]>
gitweb.pimeys.fr Git - bots/hung.git/blob - hung.py
4 # Codé par 20-100 le 23/04/12
6 # Un test de bot irc, parce que c'est cool
13 import socket
, ssl
, json
17 from commands
import getstatusoutput
as ex
20 config_debug_stdout
= True
21 if "--quiet" in sys
. argv
:
22 config_debug_stdout
= False
24 config_irc_password
= "I'mAHungMan"
25 config_irc_pseudo
= "Hung"
26 config_chanlist
=[ "#bot" , "#flood" ]
27 config_stay_channels
=[ "#bot" , "#flood" ]
28 config_play_channels
=[ "#flood" ]
29 config_quiet_channels
=[]
30 config_logfile_template
= "hung. %s .log"
31 def get_config_logfile ( serveur
):
32 serveurs
={ "acoeur.crans.org" : "acoeur" , "irc.crans.org" : "crans" }
33 return config_logfile_template
%( serveurs
[ serveur
])
34 config_overops
=[ "[20-100]" , "[20-100]_" ]
36 config_report_bugs_to
=[ "[20-100]" ]
38 config_dico_mots
= "mots.txt"
39 config_dico_defs
= "definitions.txt"
41 config_scores_file
= "scores.pickle"
44 def log ( serveur
, channel
, auteur
= None , message
= None ):
45 f
= open ( get_config_logfile ( serveur
), "a" )
46 if auteur
== message
== None :
47 # alors c'est que c'est pas un channel mais juste une ligne de log
48 chain
= " %s %s " %( time
. strftime ( " %F %T" ), channel
)
50 chain
= " %s [ %s : %s ] %s " %( time
. strftime ( " %F %T" ), channel
, auteur
, message
)
52 if config_debug_stdout
:
56 class UnicodeBotError ( Exception ):
58 def bot_unicode ( chain
):
61 except UnicodeDecodeError as exc
:
64 def remplace_accents ( chaine
):
66 remplacements
= { u
"á" : u
"a" , u
"à" : u
"a" , u
"â" : u
"a" , u
"ä" : u
"a" , u
"é" : u
"e" , u
"è" : u
"e" , u
"ê" : u
"e" , u
"ë" : u
"e" , u
"í" : u
"i" , u
"ì" : u
"i" , u
"î" : u
"i" , u
"ï" : u
"i" , u
"ó" : u
"o" , u
"ò" : u
"o" , u
"ô" : u
"o" , u
"ö" : u
"o" , u
"ú" : u
"u" , u
"ù" : u
"u" , u
"û" : u
"u" , u
"ü" : u
"u" , u
"ý" : u
"y" , u
"ỳ" : u
"y" , u
"ŷ" : u
"y" , u
"ÿ" : u
"y" , u
"œ" : u
"oe" , u
"æ" : u
"ae" }
67 for avant
, apres
in remplacements
. items ():
68 chaine
= chaine
. replace ( avant
, apres
)
72 class Hung ( ircbot
. SingleServerIRCBot
):
73 def __init__ ( self
, serveur
, debug
= False ):
74 temporary_pseudo
= config_irc_pseudo
+ str ( random
. randrange ( 10000 , 100000 ))
75 ircbot
. SingleServerIRCBot
.__ init
__ ( self
, [( serveur
, 6667 )],
76 temporary_pseudo
, "Bot irc pour jouer au pendu" , 10 )
79 self
. overops
= config_overops
80 self
. ops
= self
. overops
+ config_ops
81 self
. report_bugs_to
= config_report_bugs_to
82 self
. chanlist
= config_chanlist
83 self
. stay_channels
= config_stay_channels
84 self
. play_channels
= config_play_channels
86 self
. quiet_channels
= config_quiet_channels
89 def give_me_my_pseudo ( self
, serv
):
90 serv
. privmsg ( "NickServ" , "RECOVER %s %s " %( config_irc_pseudo
, config_irc_password
))
91 serv
. privmsg ( "NickServ" , "RELEASE %s %s " %( config_irc_pseudo
, config_irc_password
))
93 serv
. nick ( config_irc_pseudo
)
95 def on_welcome ( self
, serv
, ev
):
96 self
. give_me_my_pseudo ( serv
)
97 serv
. privmsg ( "NickServ" , "IDENTIFY %s " %(config_irc_password))
98 log ( self
. serveur
, "Connected" )
100 self
. chanlist
=[ "#bot" ]
101 self
. play_channels
=[ "#bot" ]
102 for c
in self
. chanlist
:
103 log ( self
. serveur
, "JOIN %s " %(c))
106 def pourmoi ( self
, serv
, message
):
107 """renvoie (False,lemessage) ou (True, le message amputé de "pseudo: ")"""
108 pseudo
= serv
. get_nickname ()
110 if message
[: size
]== pseudo
and len ( message
)> size
and message
[ size
]== ":" :
111 return ( True , message
[ size
+ 1 :]. lstrip ( " " ))
113 return ( False , message
)
115 def on_privmsg ( self
, serv
, ev
):
116 message
= ev
. arguments ()[ 0 ]
117 auteur
= irclib
. nm_to_n ( ev
. source ())
119 test
= bot_unicode ( message
)
120 except UnicodeBotError
:
122 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…" )
124 message
= message
. split ()
125 cmd
= message
[ 0 ]. lower ()
128 if auteur
in self
. ops
:
130 if message
[ 1 ] in self
. chanlist
:
131 serv
. privmsg ( auteur
, "Je suis déjà sur %s " %( message
[ 1 ]))
133 serv
. join ( message
[ 1 ])
134 self
. chanlist
. append ( message
[ 1 ])
135 serv
. privmsg ( auteur
, "Channels : " + " " . join ( self
. chanlist
))
136 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
))
138 serv
. privmsg ( auteur
, "Channels : " + " " . join ( self
. chanlist
))
142 if auteur
in self
. ops
and len ( message
)> 1 :
143 if message
[ 1 ] in self
. chanlist
:
144 if not ( message
[ 1 ] in self
. stay_channels
) or auteur
in self
. overops
:
145 serv
. part ( message
[ 1 ])
146 self
. chanlist
. remove ( message
[ 1 ])
147 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[successful]" )
149 serv
. privmsg ( auteur
, "Non, je reste !" )
150 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[failed]" )
152 serv
. privmsg ( auteur
, "Je ne suis pas sur %s " %( message
[ 1 ]))
156 if auteur
in self
. ops
:
158 if message
[ 1 ] in self
. play_channels
:
159 serv
. privmsg ( auteur
, "Je play déjà sur %s ." %( message
[ 1 ]))
160 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[failed]" )
162 self
. play_channels
. append ( message
[ 1 ])
163 self
. play_status
[ message
[ 1 ]]=[ None , None , None ]
164 serv
. privmsg ( auteur
, "Play channels : " + " " . join ( self
. play_channels
))
165 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[successful]" )
167 serv
. privmsg ( auteur
, "Play channels : " + " " . join ( self
. play_channels
))
171 if auteur
in self
. ops
:
173 if message
[ 1 ] in self
. play_channels
:
174 self
. play_channels
. remove ( message
[ 1 ])
175 serv
. privmsg ( auteur
, "Play channels : " + " " . join ( self
. play_channels
))
176 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[successful]" )
178 serv
. privmsg ( auteur
, "Je ne play pas sur %s ." %( message
[ 1 ]))
179 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[failed]" )
183 if auteur
in self
. overops
:
185 if message
[ 1 ] in self
. stay_channels
:
186 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[failed]" )
187 serv
. privmsg ( auteur
, "Je stay déjà sur %s ." %( message
[ 1 ]))
189 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[successful]" )
190 self
. stay_channels
. append ( message
[ 1 ])
191 serv
. privmsg ( auteur
, "Stay channels : " + " " . join ( self
. stay_channels
))
193 serv
. privmsg ( auteur
, "Stay channels : " + " " . join ( self
. stay_channels
))
197 if auteur
in self
. overops
:
199 if message
[ 1 ] in self
. stay_channels
:
200 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[successful]" )
201 self
. stay_channels
. remove ( message
[ 1 ])
202 serv
. privmsg ( auteur
, "Stay channels : " + " " . join ( self
. stay_channels
))
204 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[failed]" )
205 serv
. privmsg ( auteur
, "Je ne stay pas sur %s ." %( message
[ 1 ]))
209 elif cmd
in [ "states" , "status" ]:
210 if auteur
in self
. overops
:
211 for k
in self
. play_status
. keys ():
212 if self
. play_status
[ k
]==[ None , None , None ]:
213 serv
. privmsg ( auteur
, "None" )
215 serv
. privmsg ( auteur
, " %s : %s ( %s ) [ %s ]" %( k
, "" . join ([ str ( i
[ 0 ]) for i
in self
. play_status
[ k
][ 0 ]])
216 , self
. play_status
[ k
][ 1 ], self
. play_status
[ k
][ 2 ]))
218 if auteur
in self
. overops
:
219 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[successful]" )
224 if auteur
in self
. ops
:
226 if message
[ 1 ] in self
. quiet_channels
:
227 serv
. privmsg ( auteur
, "Je me la ferme déjà sur %s " %( message
[ 1 ]))
228 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[failed]" )
230 self
. quiet_channels
. append ( message
[ 1 ])
231 serv
. privmsg ( auteur
, "Quiet channels : " + " " . join ( self
. quiet_channels
))
232 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[successful]" )
234 serv
. privmsg ( auteur
, "Quiet channels : " + " " . join ( self
. quiet_channels
))
238 if auteur
in self
. ops
:
240 if message
[ 1 ] in self
. quiet_channels
:
241 self
. quiet_channels
. remove ( message
[ 1 ])
242 serv
. privmsg ( auteur
, "Quiet channels : " + " " . join ( self
. quiet_channels
))
243 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[successful]" )
245 serv
. privmsg ( auteur
, "Je ne me la ferme pas sur %s ." %( message
[ 1 ]))
246 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
)+ "[failed]" )
250 if auteur
in self
. overops
and len ( message
)> 2 :
251 serv
. privmsg ( message
[ 1 ], " " . join ( message
[ 2 :]))
252 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
))
253 elif len ( message
)<= 2 :
254 serv
. privmsg ( auteur
, "Syntaxe : SAY <channel> <message>" )
258 if auteur
in self
. overops
and len ( message
)> 2 :
259 serv
. action ( message
[ 1 ], " " . join ( message
[ 2 :]))
260 log ( self
. serveur
, "priv" , auteur
, " " . join ( message
))
261 elif len ( message
)<= 2 :
262 serv
. privmsg ( auteur
, "Syntaxe : DO <channel> <action>" )
265 elif cmd
in [ "score" , "scores" ]:
266 self
. send_scores ( serv
, auteur
)
270 serv
. privmsg ( auteur
, "Je n'ai pas compris. Essaye HELP…" )
272 def affiche_mot ( self
, serv
, canal
, begin
= "Mot courant" ):
273 if self
. play_status
. has_key ( canal
):
274 mot
= self
. play_status
[ canal
][ 0 ]
275 obfuskated
= " " . join ([ lettre
[ 0 ] if lettre
[ 1 ] else "_" for lettre
in mot
])
276 serv
. privmsg ( canal
, " %s : %s " %( begin
, obfuskated
))
278 def start_partie ( self
, serv
, canal
):
279 mots
=[ mot
. strip () for mot
in open ( config_dico_mots
). readlines ()]
280 defs
=[ defi
. strip () for defi
in open ( config_dico_defs
). readlines ()]
281 indice
= random
. randrange ( 0 , len ( mots
))
282 mot
, definition
= mots
[ indice
], defs
[ indice
]
283 # ' et - sont considérés comme déjà devinés
284 mot
= [( lettre
, lettre
in "'-" ) for lettre
in list ( mot
)]
285 self
. play_status
[ canal
]=[ mot
, definition
,{}]
286 self
. affiche_mot ( serv
, canal
, begin
= "Devinez" )
288 def on_pubmsg ( self
, serv
, ev
):
289 auteur
= irclib
. nm_to_n ( ev
. source ())
291 message
= ev
. arguments ()[ 0 ]
293 test
= bot_unicode ( message
)
294 except UnicodeBotError
:
295 if not canal
in self
. quiet_channels
:
297 " %s : Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…" %(auteur))
299 pour_moi
, message
= self
. pourmoi ( serv
, message
)
300 if pour_moi
and message
. split ()!=[]:
301 cmd
= message
. split ()[ 0 ]. lower ()
303 args
= " " . join ( message
. split ()[ 1 :])
306 if cmd
in [ "meurs" , "die" , "crève" ]:
307 if auteur
in self
. overops
:
308 log ( self
. serveur
, canal
, auteur
, message
+ "[successful]" )
311 serv
. privmsg ( canal
, " %s : crève !" %(auteur))
312 log ( self
. serveur
, canal
, auteur
, message
+ "[failed]" )
313 elif cmd
in [ "part" , "leave" , "dégage" ]:
314 if auteur
in self
. ops
and ( not ( canal
in self
. stay_channels
)
315 or auteur
in self
. overops
):
316 serv
. part ( canal
, message
= "Éjecté par %s " %(auteur))
317 log ( self
. serveur
, canal
, auteur
, message
+ "[successful]" )
318 if canal
in self
. chanlist
:
319 self
. chanlist
. remove ( canal
)
321 serv
. privmsg ( canal
, " %s : Non, je reste !" %(auteur))
322 log ( self
. serveur
, canal
, auteur
, message
+ "[failed]" )
323 elif cmd
in [ "play" , "jeu" , "encore" , "again" , "partie" , "pendu" , "game" , "mot" , "go" , "allez" ]:
324 if not canal
in self
. quiet_channels
and canal
in self
. play_channels
:
325 if self
. play_status
. has_key ( canal
):
326 if self
. play_status
[ canal
]==[ None , None , None ]:
327 self
. start_partie ( serv
, canal
)
329 self
. affiche_mot ( serv
, canal
, begin
= " %s : Rappel" %(auteur))
331 self
. play_status
[ canal
]=[ None , None , None ]
332 self
. start_partie ( serv
, canal
)
333 elif not canal
in self
. play_channels
:
334 serv
. privmsg ( canal
, " %s : pas ici…" %(auteur))
335 elif ( cmd
in list ( "azertyuiopqsdfghjklmwxcvbn" ) and canal
in self
. play_channels
336 and self
. play_status
. has_key ( canal
) and self
. play_status
[ canal
]!=[ None , None , None ]):
338 liste
= self
. play_status
[ canal
][ 0 ]
339 listeapres
=[( lettre
[ 0 ], lettre
[ 1 ] or lettre
[ 0 ]== giv_let
) for lettre
in liste
]
340 if liste
!= listeapres
:
341 nbtrouvees
=( sum ([ lettre
[ 1 ] for lettre
in listeapres
if not lettre
[ 0 ] in "'-" ])
342 - sum ([ lettre
[ 1 ] for lettre
in liste
if not lettre
[ 0 ] in "'-" ]))
343 if self
. play_status
[ canal
][ 2 ]. has_key ( auteur
):
344 self
. play_status
[ canal
][ 2 ][ auteur
]+= nbtrouvees
346 self
. play_status
[ canal
][ 2 ][ auteur
] = nbtrouvees
347 self
. play_status
[ canal
][ 0 ]= listeapres
348 self
. affiche_mot ( serv
, canal
, begin
= " %s placé" %(giv_let))
349 if all ([ lettre
[ 1 ] for lettre
in listeapres
]):
350 self
. gagne ( serv
, canal
)
352 elif cmd
in [ "score" , "scores" , "!score" , "!scores" ]:
353 self
. send_scores ( serv
, auteur
)
354 if cmd
in [ "meur" , "meurt" , "meurre" , "meurres" ] and not canal
in self
. quiet_channels
:
355 serv
. privmsg ( canal
, ' %s : Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)' %(auteur))
356 # on essaye de voir si le mot fourni matche la partie en cours
358 # bon, ce teste merde et j'arrive pas à trouver pourquoi, alors j'ai craqué, je l'ai mis dans un try
359 # bouh ! beurk ! pas bien ! promis, j'irai me flageller…
361 if remplace_accents ( mot
)==( "" . join ([ i
[ 0 ] for i
in self
. play_status
[ canal
][ 0 ]])). lower ():
363 # on regarde combien de lettre il manquait
364 manquait
= sum ([ not lettre
[ 1 ] for lettre
in self
. play_status
[ canal
][ 0 ]])
365 self
. add_score ({ auteur
: manquait
})
366 if self
. play_status
[ canal
][ 2 ]. has_key ( auteur
):
367 self
. play_status
[ canal
][ 2 ][ auteur
]+= manquait
369 self
. play_status
[ canal
][ 2 ][ auteur
]= manquait
370 self
. gagne ( serv
, canal
, bonus
= auteur
, bonusvalue
= manquait
)
377 def on_action ( self
, serv
, ev
):
378 action
= ev
. arguments ()[ 0 ]
379 auteur
= irclib
. nm_to_n ( ev
. source ())
380 channel
= ev
. target ()
382 test
= bot_unicode ( action
)
383 except UnicodeBotError
:
384 serv
. privmsg ( channel
,
385 " %s : Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…" %(auteur))
387 mypseudo
= serv
. get_nickname ()
389 def get_scores ( self
):
390 f
= open ( config_scores_file
)
391 scores
= pickle
. load ( f
)
394 def save_scores ( self
, scores
):
395 f
= open ( config_scores_file
, 'w' )
396 pickle
. dump ( scores
, f
)
398 def add_score ( self
, dico
):
399 scores
= self
. get_scores ()
400 for k
, v
in dico
. items ():
401 if scores
. has_key ( k
):
405 self
. save_scores ( scores
)
406 def send_scores ( self
, serv
, destinataire
):
407 scores
= self
. get_scores ()
408 scores
= scores
. items ()
409 scores
. sort ( lambda x
, y
: cmp ( x
[ 1 ], y
[ 1 ]))
411 serv
. privmsg ( destinataire
, "Scores by score : " + " ; " . join ([ " %s %s " %( k
, v
) for ( k
, v
) in scores
]) )
412 scores
. sort ( lambda x
, y
: cmp ( x
[ 0 ]. lower (), y
[ 0 ]. lower ()))
413 serv
. privmsg ( destinataire
, "Scores by pseudo : " + " ; " . join ([ " %s %s " %( k
, v
) for ( k
, v
) in scores
]) )
415 def gagne ( self
, serv
, canal
, bonus
= None , bonusvalue
= 2 ):
416 realword
= "" . join ([ lettre
[ 0 ] for lettre
in self
. play_status
[ canal
][ 0 ]])
417 definition
= self
. play_status
[ canal
][ 1 ]
418 serv
. privmsg ( canal
, "Bravo ! C'était %s " %(realword))
419 serv
. privmsg ( canal
, definition
)
420 nlettre
= float ( len ( realword
. replace ( "'" , "" ). replace ( "-" , "" )))
421 contribs
=[ " %s : %s%% " %( pseudo
, str ( int ( 100 * contrib
/ nlettre
))+( "+bonus( %s )" %(bonusvalue))*( bonus
== pseudo
)) for pseudo
, contrib
in self
. play_status
[ canal
][ 2 ]. items ()]
422 contribs_score
={ pseudo
: int ( 10 * contrib
/ nlettre
) for pseudo
, contrib
in self
. play_status
[ canal
][ 2 ]. items ()}
423 self
. add_score ( contribs_score
)
424 serv
. privmsg ( canal
, "Contributions : %s " %( " " . join ( contribs
)) )
425 self
. play_status
[ canal
]=[ None , None , None ]
428 if __name__
== "__main__" :
431 print "Usage : hung.py <serveur> [--debug]"
434 if "debug" in sys
. argv
or "--debug" in sys
. argv
:
438 serveurs
={ "a♡" : "acoeur.crans.org" , "acoeur" : "acoeur.crans.org" , "acoeur.crans.org" : "acoeur.crans.org" ,
439 "irc" : "irc.crans.org" , "crans" : "irc.crans.org" , "irc.crans.org" : "irc.crans.org" }
441 serveur
= serveurs
[ serveur
]
443 print "Server Unknown : %s " %(serveur)
445 hung
= Hung ( serveur
, debug
)