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