]> gitweb.pimeys.fr Git - bots/hung.git/blob - hung.py
La description du bot (ircname) était foireuse (c/c de Shadobot-hacker)
[bots/hung.git] / hung.py
1 #!/usr/bin/python
2 # -*- coding:utf8 -*-
3
4 # Codé par 20-100 le 23/04/12
5
6 # Un test de bot irc, parce que c'est cool
7
8 import irclib
9 import ircbot
10 import threading
11 import random
12 import time
13 import socket, ssl, json
14 import pickle
15 import re
16 import os
17 from commands import getstatusoutput as ex
18
19 import sys
20 config_debug_stdout=True
21 if "--quiet" in sys.argv:
22 config_debug_stdout=False
23
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]_"]
35 config_ops=[]
36 config_report_bugs_to=["[20-100]"]
37
38 config_dico_mots="mots.txt"
39 config_dico_defs="definitions.txt"
40
41 def log(serveur,channel,auteur=None,message=None):
42 f=open(get_config_logfile(serveur),"a")
43 if auteur==message==None:
44 # alors c'est que c'est pas un channel mais juste une ligne de log
45 chain="%s %s"%(time.strftime("%F %T"),channel)
46 else:
47 chain="%s [%s:%s] %s"%(time.strftime("%F %T"),channel,auteur,message)
48 f.write(chain+"\n")
49 if config_debug_stdout:
50 print chain
51 f.close()
52
53 class UnicodeBotError(Exception):
54 pass
55 def bot_unicode(chain):
56 try:
57 unicode(chain,"utf8")
58 except UnicodeDecodeError as exc:
59 raise UnicodeBotError
60
61 class Hung(ircbot.SingleServerIRCBot):
62 def __init__(self,serveur,debug=False):
63 temporary_pseudo=config_irc_pseudo+str(random.randrange(10000,100000))
64 ircbot.SingleServerIRCBot.__init__(self, [(serveur, 6667)],
65 temporary_pseudo,"Bot irc pour jouer au pendu", 10)
66 self.debug=debug
67 self.serveur=serveur
68 self.overops=config_overops
69 self.ops=self.overops+config_ops
70 self.report_bugs_to=config_report_bugs_to
71 self.chanlist=config_chanlist
72 self.stay_channels=config_stay_channels
73 self.play_channels=config_play_channels
74 self.play_status={}
75 self.quiet_channels=config_quiet_channels
76
77
78 def give_me_my_pseudo(self,serv):
79 serv.privmsg("NickServ","RECOVER %s %s"%(config_irc_pseudo,config_irc_password))
80 serv.privmsg("NickServ","RELEASE %s %s"%(config_irc_pseudo,config_irc_password))
81 time.sleep(0.3)
82 serv.nick(config_irc_pseudo)
83
84 def on_welcome(self, serv, ev):
85 self.give_me_my_pseudo(serv)
86 serv.privmsg("NickServ","IDENTIFY %s"%(config_irc_password))
87 log(self.serveur,"Connected")
88 if self.debug:
89 self.chanlist=["#bot"]
90 self.play_channels=["#bot"]
91 for c in self.chanlist:
92 log(self.serveur,"JOIN %s"%(c))
93 serv.join(c)
94
95 def pourmoi(self, serv, message):
96 """renvoie (False,lemessage) ou (True, le message amputé de "pseudo: ")"""
97 pseudo=serv.get_nickname()
98 size=len(pseudo)
99 if message[:size]==pseudo and len(message)>size and message[size]==":":
100 return (True,message[size+1:].lstrip(" "))
101 else:
102 return (False,message)
103
104 def on_privmsg(self, serv, ev):
105 message=ev.arguments()[0]
106 auteur = irclib.nm_to_n(ev.source())
107 try:
108 test=bot_unicode(message)
109 except UnicodeBotError:
110 serv.privmsg(auteur,
111 "Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…")
112 return
113 message=message.split()
114 cmd=message[0].lower()
115 notunderstood=False
116 if cmd=="join":
117 if auteur in self.ops:
118 if len(message)>1:
119 if message[1] in self.chanlist:
120 serv.privmsg(auteur,"Je suis déjà sur %s"%(message[1]))
121 else:
122 serv.join(message[1])
123 self.chanlist.append(message[1])
124 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
125 log(self.serveur,"priv",auteur," ".join(message))
126 else:
127 serv.privmsg(auteur,"Channels : "+" ".join(self.chanlist))
128 else:
129 notunderstood=True
130 elif cmd=="leave":
131 if auteur in self.ops and len(message)>1:
132 if message[1] in self.chanlist:
133 if not (message[1] in self.stay_channels) or auteur in self.overops:
134 serv.part(message[1])
135 self.chanlist.remove(message[1])
136 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
137 else:
138 serv.privmsg(auteur,"Non, je reste !")
139 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
140 else:
141 serv.privmsg(auteur,"Je ne suis pas sur %s"%(message[1]))
142 else:
143 notunderstood=True
144 elif cmd=="play":
145 if auteur in self.ops:
146 if len(message)>1:
147 if message[1] in self.play_channels:
148 serv.privmsg(auteur,"Je play déjà sur %s."%(message[1]))
149 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
150 else:
151 self.play_channels.append(message[1])
152 self.play_status[message[1]]=[[None,None]]
153 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
154 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
155 else:
156 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
157 else:
158 notunderstood=True
159 elif cmd=="noplay":
160 if auteur in self.ops:
161 if len(message)>1:
162 if message[1] in self.play_channels:
163 self.play_channels.remove(message[1])
164 serv.privmsg(auteur,"Play channels : "+" ".join(self.play_channels))
165 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
166 else:
167 serv.privmsg(auteur,"Je ne play pas sur %s."%(message[1]))
168 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
169 else:
170 notunderstood=True
171 elif cmd=="stay":
172 if auteur in self.overops:
173 if len(message)>1:
174 if message[1] in self.stay_channels:
175 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
176 serv.privmsg(auteur,"Je stay déjà sur %s."%(message[1]))
177 else:
178 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
179 self.stay_channels.append(message[1])
180 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
181 else:
182 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
183 else:
184 notunderstood=True
185 elif cmd=="nostay":
186 if auteur in self.overops:
187 if len(message)>1:
188 if message[1] in self.stay_channels:
189 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
190 self.stay_channels.remove(message[1])
191 serv.privmsg(auteur,"Stay channels : "+" ".join(self.stay_channels))
192 else:
193 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
194 serv.privmsg(auteur,"Je ne stay pas sur %s."%(message[1]))
195
196 else:
197 notunderstood=True
198 elif cmd in ["states","status"]:
199 if auteur in self.overops:
200 for k in self.play_status.keys():
201 serv.privmsg(auteur,"%s : %s (%s)"%(k,"".join([str(i[0]) for i in self.play_status[k][0]])
202 ,self.play_status[k][1]))
203 elif cmd=="die":
204 if auteur in self.overops:
205 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
206 self.die()
207 else:
208 notunderstood=True
209 elif cmd=="quiet":
210 if auteur in self.ops:
211 if len(message)>1:
212 if message[1] in self.quiet_channels:
213 serv.privmsg(auteur,"Je me la ferme déjà sur %s"%(message[1]))
214 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
215 else:
216 self.quiet_channels.append(message[1])
217 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
218 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
219 else:
220 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
221 else:
222 notunderstood=True
223 elif cmd=="noquiet":
224 if auteur in self.ops:
225 if len(message)>1:
226 if message[1] in self.quiet_channels:
227 self.quiet_channels.remove(message[1])
228 serv.privmsg(auteur,"Quiet channels : "+" ".join(self.quiet_channels))
229 log(self.serveur,"priv",auteur," ".join(message)+"[successful]")
230 else:
231 serv.privmsg(auteur,"Je ne me la ferme pas sur %s."%(message[1]))
232 log(self.serveur,"priv",auteur," ".join(message)+"[failed]")
233 else:
234 notunderstood=True
235 elif cmd=="say":
236 if auteur in self.overops and len(message)>2:
237 serv.privmsg(message[1]," ".join(message[2:]))
238 log(self.serveur,"priv",auteur," ".join(message))
239 elif len(message)<=2:
240 serv.privmsg(auteur,"Syntaxe : SAY <channel> <message>")
241 else:
242 notunderstood=True
243 elif cmd=="do":
244 if auteur in self.overops and len(message)>2:
245 serv.action(message[1]," ".join(message[2:]))
246 log(self.serveur,"priv",auteur," ".join(message))
247 elif len(message)<=2:
248 serv.privmsg(auteur,"Syntaxe : DO <channel> <action>")
249 else:
250 notunderstood=True
251 else:
252 notunderstood=True
253 if notunderstood:
254 serv.privmsg(auteur,"Je n'ai pas compris. Essaye HELP…")
255
256 def affiche_mot(self, serv, canal, begin="Mot courant"):
257 if self.play_status.has_key(canal):
258 mot = self.play_status[canal][0]
259 obfuskated=" ".join([lettre[0] if lettre[1] else "_" for lettre in mot])
260 serv.privmsg(canal,"%s : %s"%(begin,obfuskated))
261
262 def start_partie(self, serv, canal):
263 mots=[mot.strip() for mot in open(config_dico_mots).readlines()]
264 defs=[defi.strip() for defi in open(config_dico_defs).readlines()]
265 indice = random.randrange(0,len(mots))
266 mot,definition=mots[indice],defs[indice]
267 # ' et - sont considérés comme déjà devinés
268 mot = [(lettre,lettre in "'-") for lettre in list(mot)]
269 self.play_status[canal]=[mot,definition]
270 self.affiche_mot(serv, canal, begin="Devinez")
271
272 def on_pubmsg(self, serv, ev):
273 auteur = irclib.nm_to_n(ev.source())
274 canal = ev.target()
275 message = ev.arguments()[0]
276 try:
277 test=bot_unicode(message)
278 except UnicodeBotError:
279 if not canal in self.quiet_channels:
280 serv.privmsg(canal,
281 "%s: Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
282 return
283 pour_moi,message=self.pourmoi(serv,message)
284 if pour_moi and message.split()!=[]:
285 cmd=message.split()[0].lower()
286 try:
287 args=" ".join(message.split()[1:])
288 except:
289 args=""
290 if cmd in ["meurs","die","crève"]:
291 if auteur in self.overops:
292 log(self.serveur,canal,auteur,message+"[successful]")
293 self.die()
294 else:
295 serv.privmsg(canal,"%s: crève !"%(auteur))
296 log(self.serveur,canal,auteur,message+"[failed]")
297 elif cmd in ["part","leave","dégage"]:
298 if auteur in self.ops and (not (canal in self.stay_channels)
299 or auteur in self.overops):
300 serv.part(canal,message="Éjecté par %s"%(auteur))
301 log(self.serveur,canal,auteur,message+"[successful]")
302 if canal in self.chanlist:
303 self.chanlist.remove(canal)
304 else:
305 serv.privmsg(canal,"%s: Non, je reste !"%(auteur))
306 log(self.serveur,canal,auteur,message+"[failed]")
307 elif cmd in ["play","jeu","encore","again","partie","pendu","game","mot","go","allez"]:
308 if not canal in self.quiet_channels and canal in self.play_channels:
309 if self.play_status.has_key(canal):
310 if self.play_status[canal]==[[None,None]]:
311 self.start_partie(serv, canal)
312 else:
313 self.affiche_mot(serv, canal, begin="%s: Rappel"%(auteur))
314 else:
315 self.play_status[canal]=[[None,None]]
316 self.start_partie(serv, canal)
317 elif not canal in self.play_channels:
318 serv.privmsg(canal,"%s: pas ici…"%(auteur))
319 elif (cmd in list("azertyuiopqsdfghjklmwxcvbn") and canal in self.play_channels
320 and self.play_status.has_key(canal) and self.play_status[canal]!=[[None,None]]):
321 giv_let=cmd.upper()
322 liste=self.play_status[canal][0]
323 listeapres=[(lettre[0],lettre[1] or lettre[0]==giv_let) for lettre in liste]
324 if liste!=listeapres:
325 self.play_status[canal][0]=listeapres
326 self.affiche_mot(serv, canal, begin="%s placé"%(giv_let))
327 if all([lettre[1] for lettre in listeapres]):
328 realword="".join([lettre[0] for lettre in self.play_status[canal][0]])
329 definition = self.play_status[canal][1]
330 serv.privmsg(canal,"Bravo ! C'était %s"%(realword))
331 serv.privmsg(canal,definition)
332 self.play_status[canal]=[[None,None]]
333
334
335 if cmd in ["meur", "meurt","meurre","meurres"] and not canal in self.quiet_channels:
336 serv.privmsg(canal,'%s: Mourir, impératif, 2ème personne du singulier : "meurs" (de rien)'%(auteur))
337 else:
338 pass
339
340 def on_action(self, serv, ev):
341 action = ev.arguments()[0]
342 auteur = irclib.nm_to_n(ev.source())
343 channel = ev.target()
344 try:
345 test=bot_unicode(action)
346 except UnicodeBotError:
347 serv.privmsg(channel,
348 "%s : Euh, tu fais de la merde avec ton encodage là, j'ai failli crasher…"%(auteur))
349 return
350 mypseudo=serv.get_nickname()
351
352 if __name__=="__main__":
353 import sys
354 if len(sys.argv)==1:
355 print "Usage : hung.py <serveur> [--debug]"
356 exit(1)
357 serveur=sys.argv[1]
358 if "debug" in sys.argv or "--debug" in sys.argv:
359 debug=True
360 else:
361 debug=False
362 serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org",
363 "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"}
364 try:
365 serveur=serveurs[serveur]
366 except KeyError:
367 print "Server Unknown : %s"%(serveur)
368 exit(404)
369 hung=Hung(serveur,debug)
370 hung.start()