]>
gitweb.pimeys.fr Git - bots/bbc.git/blob - skeleton.py
2 # -*- encoding: utf-8 -*-
6 Un bot IRC qui ne fait rien. Base pour en coder un vrai.
14 from commands
import getstatusoutput
as ex
16 # on récupère la config
20 def get_config_logfile(serveur
):
21 """Renvoie le nom du fichier de log en fonction du serveur."""
22 serveurs
= {"acoeur.crans.org" : "acoeur", "irc.crans.org" : "crans"}
23 return config
.logfile_template
% (serveurs
[serveur
])
25 def log(serveur
, channel
, auteur
=None, message
=None):
26 f
= open(get_config_logfile(serveur
), "a")
27 if auteur
== message
== None:
28 # alors c'est que c'est pas un channel mais juste une ligne de log
29 chain
= "%s %s" % (time
.strftime("%F %T"), channel
)
31 chain
= "%s [%s:%s] %s" % (time
.strftime("%F %T"), channel
, auteur
, message
)
33 if config
.debug_stdout
:
37 class UnicodeBotError(Exception):
39 def bot_unicode(chain
):
41 unicode(chain
, "utf8")
42 except UnicodeDecodeError as exc
:
45 class Skeleton(ircbot
.SingleServerIRCBot
):
46 def __init__(self
, serveur
, debug
=False):
47 temporary_pseudo
= config
.irc_pseudo
+ str(random
.randrange(10000, 100000))
48 ircbot
.SingleServerIRCBot
.__init
__(self
, [(serveur
, 6667)],
49 temporary_pseudo
, config
.ircname
, 10)
51 self
.serveur
= serveur
52 self
.overops
= config
.overops
53 self
.ops
= self
.overops
+ config
.ops
54 self
.chanlist
= config
.chanlist
55 self
.stay_channels
= config
.stay_channels
56 self
.quiet_channels
= config
.quiet_channels
59 def give_me_my_pseudo(self
, serv
):
60 serv
.privmsg("NickServ", "RECOVER %s %s" % (config
.irc_pseudo
, config
.irc_password
))
61 serv
.privmsg("NickServ", "RELEASE %s %s" % (config
.irc_pseudo
, config
.irc_password
))
63 serv
.nick(config
.irc_pseudo
)
65 def on_welcome(self
, serv
, ev
):
66 self
.serv
= serv
# ça serv ira :)
67 self
.give_me_my_pseudo(serv
)
68 serv
.privmsg("NickServ", "identify %s" % (config
.irc_password
))
69 log(self
.serveur
, "Connected")
71 self
.chanlist
= ["#bot"]
72 for c
in self
.chanlist
:
73 log(self
.serveur
, "JOIN %s" % (c
))
76 def pourmoi(self
, serv
, message
):
77 """renvoie (False, lemessage) ou (True, le message amputé de "pseudo: ")"""
80 if message
[:size
] == pseudo
and len(message
) > size
and message
[size
] == ":":
81 return (True, message
[size
+ 1:].lstrip(" "))
83 return (False, message
)
85 def on_privmsg(self
, serv
, ev
):
86 message
= ev
.arguments()[0]
87 auteur
= irclib
.nm_to_n(ev
.source())
90 except UnicodeBotError
:
91 if config
.utf8_trigger
:
92 serv
.privmsg(auteur
, random
.choice(config
.utf8_fail_answers
).encode("utf8"))
94 message
= message
.split()
95 cmd
= message
[0].lower()
98 helpdico
= {"help" : ["""HELP <commande>
99 Affiche de l'aide sur la commande""", None, None],
100 "join" : [None, """JOIN <channel>
101 Me fait rejoindre le channel""", None],
102 "leave" : [None, """LEAVE <channel>
103 Me fait quitter le channel (sauf s'il est dans ma stay_list).""", None],
104 "quiet" : [None, """QUIET <channel>
105 Me rend silencieux sur le channel.""", None],
106 "noquiet" : [None, """NOQUIET <channel>
107 Me rend la parole sur le channel.""", None],
108 "say" : [None, None, """SAY <channel> <message>
109 Me fait parler sur le channel."""],
110 "do" : [None, None, """DO <channel> <action>
111 Me fait faitre une action (/me) sur le channel."""],
112 "stay" : [None, None, """STAY <channel>
113 Ajoute le channel à ma stay_list."""],
114 "nostay" : [None, None, """NOSTAY <channel>
115 Retire le channel de ma stay_list."""],
116 "ops" : [None, None, """OPS
117 Affiche la liste des ops."""],
118 "overops" : [None, None, """OVEROPS
119 Affiche la liste des overops."""],
120 "kick" : [None, None, """KICK <channel> <pseudo> [<raison>]
121 Kicke <pseudo> du channel (Il faut bien entendu que j'y sois op)."""],
122 "die" : [None, None, """DIE
123 Me déconnecte du serveur IRC."""]
125 helpmsg_default
= "Liste des commandes disponibles :\nHELP"
126 helpmsg_ops
= " JOIN LEAVE QUIET NOQUIET LOST RECONNECT"
127 helpmsg_overops
= " SAY DO STAY NOSTAY OPS OVEROPS KICK DIE"
128 op
, overop
= auteur
in self
.ops
, auteur
in self
.overops
129 if len(message
) == 1:
130 helpmsg
= helpmsg_default
132 helpmsg
+= helpmsg_ops
134 helpmsg
+= helpmsg_overops
136 helpmsgs
= helpdico
.get(message
[1].lower(), ["Commande inconnue.", None, None])
137 helpmsg
= helpmsgs
[0]
138 if op
and helpmsgs
[1]:
140 helpmsg
+= "\n" + helpmsgs
[1]
142 helpmsg
= helpmsgs
[1]
143 if overop
and helpmsgs
[2]:
145 helpmsg
+= "\n" + helpmsgs
[2]
147 helpmsg
= helpmsgs
[2]
148 for ligne
in helpmsg
.split("\n"):
149 serv
.privmsg(auteur
, ligne
)
151 if auteur
in self
.ops
:
153 if message
[1] in self
.chanlist
:
154 serv
.privmsg(auteur
, "Je suis déjà sur %s" % (message
[1]))
156 serv
.join(message
[1])
157 self
.chanlist
.append(message
[1])
158 serv
.privmsg(auteur
, "Channels : " + " ".join(self
.chanlist
))
159 log(self
.serveur
, "priv", auteur
, " ".join(message
))
161 serv
.privmsg(auteur
, "Channels : " + " ".join(self
.chanlist
))
165 if auteur
in self
.ops
and len(message
) > 1:
166 if message
[1] in self
.chanlist
:
167 if not (message
[1] in self
.stay_channels
) or auteur
in self
.overops
:
168 self
.quitter(message
[1], " ".join(message
[2:]))
169 self
.chanlist
.remove(message
[1])
170 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[successful]")
172 serv
.privmsg(auteur
, "Non, je reste !")
173 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[failed]")
175 serv
.privmsg(auteur
, "Je ne suis pas sur %s" % (message
[1]))
179 if auteur
in self
.overops
:
181 if message
[1] in self
.stay_channels
:
182 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[failed]")
183 serv
.privmsg(auteur
, "Je stay déjà sur %s." % (message
[1]))
185 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[successful]")
186 self
.stay_channels
.append(message
[1])
187 serv
.privmsg(auteur
, "Stay channels : " + " ".join(self
.stay_channels
))
189 serv
.privmsg(auteur
, "Stay channels : " + " ".join(self
.stay_channels
))
192 elif cmd
== "nostay":
193 if auteur
in self
.overops
:
195 if message
[1] in self
.stay_channels
:
196 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[successful]")
197 self
.stay_channels
.remove(message
[1])
198 serv
.privmsg(auteur
, "Stay channels : " + " ".join(self
.stay_channels
))
200 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[failed]")
201 serv
.privmsg(auteur
, "Je ne stay pas sur %s." % (message
[1]))
206 if auteur
in self
.overops
:
207 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[successful]")
212 if auteur
in self
.ops
:
214 if message
[1] in self
.quiet_channels
:
215 serv
.privmsg(auteur
, "Je me la ferme déjà sur %s" % (message
[1]))
216 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[failed]")
218 self
.quiet_channels
.append(message
[1])
219 serv
.privmsg(auteur
, "Quiet channels : " + " ".join(self
.quiet_channels
))
220 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[successful]")
222 serv
.privmsg(auteur
, "Quiet channels : " + " ".join(self
.quiet_channels
))
225 elif cmd
== "noquiet":
226 if auteur
in self
.ops
:
228 if message
[1] in self
.quiet_channels
:
229 self
.quiet_channels
.remove(message
[1])
230 serv
.privmsg(auteur
, "Quiet channels : " + " ".join(self
.quiet_channels
))
231 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[successful]")
233 serv
.privmsg(auteur
, "Je ne me la ferme pas sur %s." % (message
[1]))
234 log(self
.serveur
, "priv", auteur
, " ".join(message
) + "[failed]")
238 if auteur
in self
.overops
and len(message
) > 2:
239 serv
.privmsg(message
[1], " ".join(message
[2:]))
240 log(self
.serveur
, "priv", auteur
, " ".join(message
))
241 elif len(message
) <= 2:
242 serv
.privmsg(auteur
, "Syntaxe : SAY <channel> <message>")
246 if auteur
in self
.overops
and len(message
) > 2:
247 serv
.action(message
[1], " ".join(message
[2:]))
248 log(self
.serveur
, "priv", auteur
, " ".join(message
))
249 elif len(message
) <= 2:
250 serv
.privmsg(auteur
, "Syntaxe : DO <channel> <action>")
254 if auteur
in self
.overops
and len(message
) > 2:
255 serv
.kick(message
[1], message
[2], " ".join(message
[3:]))
256 log(self
.serveur
, "priv", auteur
, " ".join(message
))
257 elif len(message
) <= 2:
258 serv
.privmsg(auteur
, "Syntaxe : KICK <channel> <pseudo> [<raison>]")
262 if auteur
in self
.overops
:
263 serv
.privmsg(auteur
, " ".join(self
.ops
))
266 elif cmd
== "overops":
267 if auteur
in self
.overops
:
268 serv
.privmsg(auteur
, " ".join(self
.overops
))
274 serv
.privmsg(auteur
, "Je n'ai pas compris. Essayez HELP…")
276 def on_pubmsg(self
, serv
, ev
):
277 auteur
= irclib
.nm_to_n(ev
.source())
279 message
= ev
.arguments()[0]
282 except UnicodeBotError
:
283 if config
.utf8_trigger
and not canal
in self
.quiet_channels
:
284 serv
.privmsg(canal
, (u
"%s: %s" % (auteur
, random
.choice(config
.utf8_fail_answers
))).encode("utf8"))
286 pour_moi
, message
= self
.pourmoi(serv
, message
)
287 if pour_moi
and message
.split() != []:
288 cmd
= message
.split()[0].lower()
290 args
= " ".join(message
.split()[1:])
293 if cmd
in ["meurs", "die", "crève"]:
294 if auteur
in self
.overops
:
295 log(self
.serveur
, canal
, auteur
, message
+ "[successful]")
298 serv
.privmsg(canal
, ("%s: %s" % (auteur
, random
.choice(config
.quit_fail_messages
))).encode("utf8"))
299 log(self
.serveur
, canal
, auteur
, message
+ "[failed]")
301 elif cmd
in ["part", "leave", "dégage", "va-t-en", "tut'tiresailleurs, c'estmesgalets"]:
302 if auteur
in self
.ops
and (not (canal
in self
.stay_channels
)
303 or auteur
in self
.overops
):
305 log(self
.serveur
, canal
, auteur
, message
+ "[successful]")
306 if canal
in self
.chanlist
:
307 self
.chanlist
.remove(canal
)
309 serv
.privmsg(canal
, ("%s: %s" % (auteur
, random
.choice(config
.leave_fail_messages
))).encode("utf8"))
310 log(self
.serveur
, canal
, auteur
, message
+ "[failed]")
312 elif cmd
in ["deviens", "pseudo"]:
313 if auteur
in self
.ops
:
316 log(self
.serveur
, canal
, auteur
, message
+ "[successful]")
318 elif cmd
in ["ping"] and not canal
in self
.quiet_channels
:
319 serv
.privmsg(canal
, "%s: pong" % (auteur
))
321 if not canal
in self
.quiet_channels
:
324 def on_action(self
, serv
, ev
):
325 action
= ev
.arguments()[0]
326 auteur
= irclib
.nm_to_n(ev
.source())
327 channel
= ev
.target()
330 except UnicodeBotError
:
331 if config
.utf8_trigger
and not channel
in self
.quiet_channels
:
332 serv
.privmsg(channel
, (u
"%s: %s" % (auteur
, random
.choice(config
.utf8_fail_answers
))).encode("utf8"))
336 def on_kick(self
, serv
, ev
):
337 auteur
= irclib
.nm_to_n(ev
.source())
338 channel
= ev
.target()
339 victime
= ev
.arguments()[0]
340 raison
= ev
.arguments()[1]
341 if victime
== self
.nick
:
342 log(self
.serveur
, "%s kické de %s par %s (raison : %s)" % (victime
, channel
, auteur
, raison
))
346 l1
, l2
= config
.kick_answers
, config
.kick_actions
347 n1
, n2
= len(l1
), len(l2
)
348 i
= random
.randrange(n1
+ n2
)
350 serv
.action(channel
, l2
[i
- n1
].format(auteur
).encode("utf8"))
352 serv
.privmsg(channel
, l1
[i
].format(auteur
).encode("utf8"))
354 def quitter(self
, chan
, leave_message
=None):
355 if leave_message
== None:
356 leave_message
= random
.choice(config
.leave_messages
)
357 self
.serv
.part(chan
, message
=leave_message
.encode("utf8"))
360 quit_message
= random
.choice(config
.quit_messages
)
361 self
.die(msg
=quit_message
.encode("utf8"))
364 return self
.serv
.get_nickname()
365 nick
= property(_getnick
)
368 if __name__
== "__main__":
370 if len(sys
.argv
) == 1:
371 print "Usage : bbc.py <serveur> [--debug]"
373 serveur
= sys
.argv
[1]
374 if "debug" in sys
.argv
or "--debug" in sys
.argv
:
378 if "--quiet" in sys
.argv
:
379 config
.debug_stdout
= False
380 serveurs
= {"irc" : "irc.crans.org", "crans" : "irc.crans.org", "irc.crans.org" : "irc.crans.org"}
382 serveur
= serveurs
[serveur
]
384 print "Server Unknown : %s" % (serveur
)
386 bot
= Skeleton(serveur
, debug
)