]>
gitweb.pimeys.fr Git - bots/hung.git/blob - hung.py
b49fc62a8317fd6dc2e0729eab905f70026e05d3
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 class Hung(ircbot
.SingleServerIRCBot
):
65 def __init__(self
,serveur
,debug
=False):
66 temporary_pseudo
=config_irc_pseudo
+str(random
.randrange(10000,100000))
67 ircbot
.SingleServerIRCBot
.__init
__(self
, [(serveur
, 6667)],
68 temporary_pseudo
,"Bot irc pour jouer au pendu", 10)
71 self
.overops
=config_overops
72 self
.ops
=self
.overops
+config_ops
73 self
.report_bugs_to
=config_report_bugs_to
74 self
.chanlist
=config_chanlist
75 self
.stay_channels
=config_stay_channels
76 self
.play_channels
=config_play_channels
78 self
.quiet_channels
=config_quiet_channels
81 def give_me_my_pseudo(self
,serv
):
82 serv
.privmsg("NickServ","RECOVER %s %s"%(config_irc_pseudo
,config_irc_password
))
83 serv
.privmsg("NickServ","RELEASE %s %s"%(config_irc_pseudo
,config_irc_password
))
85 serv
.nick(config_irc_pseudo
)
87 def on_welcome(self
, serv
, ev
):
88 self
.give_me_my_pseudo(serv
)
89 serv
.privmsg("NickServ","IDENTIFY %s"%(config_irc_password))
90 log(self
.serveur
,"Connected")
92 self
.chanlist
=["#bot"]
93 self
.play_channels
=["#bot"]
94 for c
in self
.chanlist
:
95 log(self
.serveur
,"JOIN %s"%(c))
98 def pourmoi(self
, serv
, message
):
99 """renvoie (False,lemessage) ou (True, le message amputé de "pseudo: ")"""
100 pseudo
=serv
.get_nickname()
102 if message
[:size
]==pseudo
and len(message
)>size
and message
[size
]==":":
103 return (True,message
[size
+1:].lstrip(" "))
105 return (False,message
)
107 def on_privmsg(self
, serv
, ev
):
108 message
=ev
.arguments()[0]
109 auteur
= irclib
.nm_to_n(ev
.source())
111 test
=bot_unicode(message
)
112 except UnicodeBotError
:
114 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…")
116 message
=message
.split()
117 cmd
=message
[0].lower()
120 if auteur
in self
.ops
:
122 if message
[1] in self
.chanlist
:
123 serv
.privmsg(auteur
,"Je suis déjà sur %s"%(message
[1]))
125 serv
.join(message
[1])
126 self
.chanlist
.append(message
[1])
127 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
128 log(self
.serveur
,"priv",auteur
," ".join(message
))
130 serv
.privmsg(auteur
,"Channels : "+" ".join(self
.chanlist
))
134 if auteur
in self
.ops
and len(message
)>1:
135 if message
[1] in self
.chanlist
:
136 if not (message
[1] in self
.stay_channels
) or auteur
in self
.overops
:
137 serv
.part(message
[1])
138 self
.chanlist
.remove(message
[1])
139 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
141 serv
.privmsg(auteur
,"Non, je reste !")
142 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
144 serv
.privmsg(auteur
,"Je ne suis pas sur %s"%(message
[1]))
148 if auteur
in self
.ops
:
150 if message
[1] in self
.play_channels
:
151 serv
.privmsg(auteur
,"Je play déjà sur %s."%(message
[1]))
152 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
154 self
.play_channels
.append(message
[1])
155 self
.play_status
[message
[1]]=[[None,None,None]]
156 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
157 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
159 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
163 if auteur
in self
.ops
:
165 if message
[1] in self
.play_channels
:
166 self
.play_channels
.remove(message
[1])
167 serv
.privmsg(auteur
,"Play channels : "+" ".join(self
.play_channels
))
168 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
170 serv
.privmsg(auteur
,"Je ne play pas sur %s."%(message
[1]))
171 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
175 if auteur
in self
.overops
:
177 if message
[1] in self
.stay_channels
:
178 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
179 serv
.privmsg(auteur
,"Je stay déjà sur %s."%(message
[1]))
181 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
182 self
.stay_channels
.append(message
[1])
183 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
185 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
189 if auteur
in self
.overops
:
191 if message
[1] in self
.stay_channels
:
192 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
193 self
.stay_channels
.remove(message
[1])
194 serv
.privmsg(auteur
,"Stay channels : "+" ".join(self
.stay_channels
))
196 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
197 serv
.privmsg(auteur
,"Je ne stay pas sur %s."%(message
[1]))
201 elif cmd
in ["states","status"]:
202 if auteur
in self
.overops
:
203 for k
in self
.play_status
.keys():
204 serv
.privmsg(auteur
,"%s : %s (%s) [%s]"%(k
,"".join([str(i
[0]) for i
in self
.play_status
[k
][0]])
205 ,self
.play_status
[k
][1], self
.play_status
[k
][2]))
207 if auteur
in self
.overops
:
208 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
213 if auteur
in self
.ops
:
215 if message
[1] in self
.quiet_channels
:
216 serv
.privmsg(auteur
,"Je me la ferme déjà sur %s"%(message
[1]))
217 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
219 self
.quiet_channels
.append(message
[1])
220 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
221 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[successful]")
223 serv
.privmsg(auteur
,"Quiet channels : "+" ".join(self
.quiet_channels
))
227 if auteur
in self
.ops
:
229 if message
[1] in self
.quiet_channels
:
230 self
.quiet_channels
.remove(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
,"Je ne me la ferme pas sur %s."%(message
[1]))
235 log(self
.serveur
,"priv",auteur
," ".join(message
)+"[failed]")
239 if auteur
in self
.overops
and len(message
)>2:
240 serv
.privmsg(message
[1]," ".join(message
[2:]))
241 log(self
.serveur
,"priv",auteur
," ".join(message
))
242 elif len(message
)<=2:
243 serv
.privmsg(auteur
,"Syntaxe : SAY <channel> <message>")
247 if auteur
in self
.overops
and len(message
)>2:
248 serv
.action(message
[1]," ".join(message
[2:]))
249 log(self
.serveur
,"priv",auteur
," ".join(message
))
250 elif len(message
)<=2:
251 serv
.privmsg(auteur
,"Syntaxe : DO <channel> <action>")
254 elif cmd
in ["score","scores"]:
255 self
.send_scores(serv
,auteur
)
259 serv
.privmsg(auteur
,"Je n'ai pas compris. Essaye HELP…")
261 def affiche_mot(self
, serv
, canal
, begin
="Mot courant"):
262 if self
.play_status
.has_key(canal
):
263 mot
= self
.play_status
[canal
][0]
264 obfuskated
=" ".join([lettre
[0] if lettre
[1] else "_" for lettre
in mot
])
265 serv
.privmsg(canal
,"%s : %s"%(begin
,obfuskated
))
267 def start_partie(self
, serv
, canal
):
268 mots
=[mot
.strip() for mot
in open(config_dico_mots
).readlines()]
269 defs
=[defi
.strip() for defi
in open(config_dico_defs
).readlines()]
270 indice
= random
.randrange(0,len(mots
))
271 mot
,definition
=mots
[indice
],defs
[indice
]
272 # ' et - sont considérés comme déjà devinés
273 mot
= [(lettre
,lettre
in "'-") for lettre
in list(mot
)]
274 self
.play_status
[canal
]=[mot
,definition
,{}]
275 self
.affiche_mot(serv
, canal
, begin
="Devinez")
277 def on_pubmsg(self
, serv
, ev
):
278 auteur
= irclib
.nm_to_n(ev
.source())
280 message
= ev
.arguments()[0]
282 test
=bot_unicode(message
)
283 except UnicodeBotError
:
284 if not canal
in self
.quiet_channels
:
286 "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
288 pour_moi
,message
=self
.pourmoi(serv
,message
)
289 if pour_moi
and message
.split()!=[]:
290 cmd
=message
.split()[0].lower()
292 args
=" ".join(message
.split()[1:])
295 if cmd
in ["meurs","die","crève"]:
296 if auteur
in self
.overops
:
297 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
300 serv
.privmsg(canal
,"%s: crève !"%(auteur))
301 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
302 elif cmd
in ["part","leave","dégage"]:
303 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
304 or auteur
in self
.overops
):
305 serv
.part(canal
,message
="Éjecté par %s"%(auteur))
306 log(self
.serveur
,canal
,auteur
,message
+"[successful]")
307 if canal
in self
.chanlist
:
308 self
.chanlist
.remove(canal
)
310 serv
.privmsg(canal
,"%s: Non, je reste !"%(auteur))
311 log(self
.serveur
,canal
,auteur
,message
+"[failed]")
312 elif cmd
in ["play","jeu","encore","again","partie","pendu","game","mot","go","allez"]:
313 if not canal
in self
.quiet_channels
and canal
in self
.play_channels
:
314 if self
.play_status
.has_key(canal
):
315 if self
.play_status
[canal
]==[[None,None,None]]:
316 self
.start_partie(serv
, canal
)
318 self
.affiche_mot(serv
, canal
, begin
="%s: Rappel"%(auteur))
320 self
.play_status
[canal
]=[[None,None,None]]
321 self
.start_partie(serv
, canal
)
322 elif not canal
in self
.play_channels
:
323 serv
.privmsg(canal
,"%s: pas ici…"%(auteur))
324 elif (cmd
in list("azertyuiopqsdfghjklmwxcvbn") and canal
in self
.play_channels
325 and self
.play_status
.has_key(canal
) and self
.play_status
[canal
]!=[[None,None,None]]):
327 liste
=self
.play_status
[canal
][0]
328 listeapres
=[(lettre
[0],lettre
[1] or lettre
[0]==giv_let
) for lettre
in liste
]
329 if liste
!=listeapres
:
330 nbtrouvees
=(sum([lettre
[1] for lettre
in listeapres
if not lettre
[0] in "'-"])
331 - sum([lettre
[1] for lettre
in liste
if not lettre
[0] in "'-"]))
332 if self
.play_status
[canal
][2].has_key(auteur
):
333 self
.play_status
[canal
][2][auteur
]+= nbtrouvees
335 self
.play_status
[canal
][2][auteur
] = nbtrouvees
336 self
.play_status
[canal
][0]=listeapres
337 self
.affiche_mot(serv
, canal
, begin
="%s placé"%(giv_let))
338 if all([lettre
[1] for lettre
in listeapres
]):
339 realword
="".join([lettre
[0] for lettre
in self
.play_status
[canal
][0]])
340 definition
= self
.play_status
[canal
][1]
341 serv
.privmsg(canal
,"Bravo ! C'était %s"%(realword))
342 serv
.privmsg(canal
,definition
)
343 nlettre
=float(len(realword
.replace("'","").replace("-","")))
344 contribs
=["%s:%s%%"%(pseudo
,int(100*contrib
/nlettre
)) for pseudo
,contrib
in self
.play_status
[canal
][2].items()]
345 contribs_score
={pseudo
:int(10*contrib
/nlettre
) for pseudo
,contrib
in self
.play_status
[canal
][2].items()}
346 self
.add_score(contribs_score
)
347 serv
.privmsg(canal
,"Contributions : %s"%(" ".join(contribs
)) )
348 self
.play_status
[canal
]=[[None,None,None]]
350 elif cmd
in ["score","scores","!score","!scores"]:
351 self
.send_scores(serv
,auteur
)
352 if cmd
in ["meur", "meurt","meurre","meurres"] and not canal
in self
.quiet_channels
:
353 serv
.privmsg(canal
,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
357 def on_action(self
, serv
, ev
):
358 action
= ev
.arguments()[0]
359 auteur
= irclib
.nm_to_n(ev
.source())
360 channel
= ev
.target()
362 test
=bot_unicode(action
)
363 except UnicodeBotError
:
364 serv
.privmsg(channel
,
365 "%s : Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
367 mypseudo
=serv
.get_nickname()
369 def get_scores(self
):
370 f
=open(config_scores_file
)
371 scores
=pickle
.load(f
)
374 def save_scores(self
,scores
):
375 f
=open(config_scores_file
,'w')
376 pickle
.dump(scores
,f
)
378 def add_score(self
,dico
):
379 scores
=self
.get_scores()
380 for k
,v
in dico
.items():
381 if scores
.has_key(k
):
385 self
.save_scores(scores
)
386 def send_scores(self
, serv
, destinataire
):
387 scores
=self
.get_scores()
388 scores
=scores
.items()
389 scores
.sort(lambda x
,y
:cmp(x
[1],y
[1]))
391 serv
.privmsg(destinataire
,"Scores by score : "+" ; ".join(["%s %s"%(k
,v
) for (k
,v
) in scores
]) )
392 scores
.sort(lambda x
,y
:cmp(x
[0].lower(),y
[0].lower()))
393 serv
.privmsg(destinataire
,"Scores by pseudo : "+" ; ".join(["%s %s"%(k
,v
) for (k
,v
) in scores
]) )
396 if __name__
=="__main__":
399 print "Usage : hung.py <serveur> [--debug]"
402 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
406 serveurs
={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
407 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
409 serveur
=serveurs
[serveur
]
411 print "Server Unknown : %s"%(serveur)
413 hung
=Hung(serveur
,debug
)