Labo

Sign in or create your account | Project List | Help

Labo Commit Details

Date:2008-11-26 16:57:21 (1 year 9 months ago)
Author:naps
Commit:ea56eee3a68807e65ba77373331e55d3249bda88
Message:Import of pynspircd (old svn-revisions lost)

Files: pynspircd/inspircdlib.py (1 diff)
pynspircd/pynspircd.py (1 diff)

Change Details

pynspircd/inspircdlib.py
1# -*- coding: utf-8 -*-
2# inspircd-lib.py - a part of pynspircd project
3#
4# Copyright 2007 Antoine 'NaPs' Millet <antoine@inaps.org>
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19# MA 02110-1301, USA.
20
21import socket
22import time
23import re
24import sys
25import threading
26from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
27import BaseHTTPServer
28from urlparse import urlparse
29import datetime
30
31
32class Pynspircd(object):
33    '''Manage fake-ircd, bots and other things'''
34
35    def __init__(self, hub, password, hostname, description='Pynspircd server', hops=0, bots=[], httpd_prefix_length=0, httpd_ip='', httpd_port=8081, debug=False):
36        self.bots = BotsManager(self)
37        self.bots.initialBots = bots
38        self.users = UsersManager(self)
39        self.chans = ChansManager(self)
40        self.connection = ConnectionManager(self, hub, password, hostname, description, hops)
41        self.externalController = HTTPServer(self, httpd_ip, httpd_port)
42        self.externalController.start()
43        self.hostname = hostname
44        self.hub = hub
45        self.httpd_prefix_length = httpd_prefix_length
46        self.debug = debug
47
48    def run(self):
49        while 1:
50            if self.connection.connect():
51                self.connection.messageManager()
52            self.debugMessage('Connection lost, new try in 5 seconds...', type='error')
53            time.sleep(5)
54
55    def debugMessage(self, message, type='global', cont=False):
56        '''Print a debug message on stdout'''
57        if type == 'in': prefix = '\033[0;31m--> '
58        elif type == 'out': prefix = '\033[0;32m<-- '
59        elif type == 'error': prefix = '\033[1;31m!!! '
60        else: prefix = '\033[1m*** '
61
62        if self.debug:
63            if cont and type != 'continue':
64                sys.stdout.write('%s%s' % (prefix, message))
65            elif cont and type == 'continue':
66                sys.stdout.write('%s' % message)
67            elif not(cont) and type == 'continue':
68                sys.stdout.write('%s\033[0m\n' % message)
69            else:
70                sys.stdout.write('%s%s\033[0m\n' % (prefix, message))
71
72    def cmd_ping(self, emitter, cmd, arg):
73        if self.hostname in arg.split(' '):
74            self.connection.sendMSG(':%s PONG %s' % (self.hostname, emitter))
75
76    def cmd_kill(self, emitter, cmd, arg):
77        nick = arg.split(' ')[0]
78        bot = self.bots.searchBotWithNick(nick)
79        if bot: self.bots.unregisterBot(bot)
80
81    def cmd_nick(self, emitter, cmd, args):
82        if len(args.split(' ')) == 1: # Mode changement de nick
83            user = self.users.searchUserByNick(emitter)
84            if user == None:
85                self.debugMessage('Utilisateur non trouvé dans la base', type='error')
86            else:
87                self.users.changeUserNick(user, args)
88        else:
89            timestamp, nick, hostname, displayed_hostname, ident, modes, ip, gecos = args.split(' ', 7)
90
91            modes = list(modes[1:])
92            gecos = gecos[1:]
93
94            self.users.addUser(User(nick, hostname, displayed_hostname, ident, ip, modes, gecos))
95
96    def cmd_away(self, emitter, cmd, args):
97        user = self.users.searchUserByNick(emitter)
98        if user == None: return
99        if args:
100            user.away = args[1:]
101        else:
102            user.away = None
103
104    def cmd_metadata(self, emitter, cmd, args):
105        targer, key, value = args.split(' ', 2)
106        value = value[1:]
107
108        if targer[0] == '#':
109            # Channel mode
110            pass
111        else:
112            # Nick mode
113            user = self.users.searchUserByNick(emitter)
114            if user == None: return
115
116            user.metadata[key] = value
117
118    def cmd_fjoin(self, emitter, cmd, args):
119        channelname, timestamp, nicks = args.split(' ', 2)
120        nicks = nicks.split(' ')
121
122        chan = self.chans.addChannel(channelname)
123        for nick in nicks:
124            right, nick = nick.split(',')
125            user = self.users.searchUserByNick(nick)
126            if user == None: continue
127
128            self.chans.addUserOnChannel(chan, user)
129
130    def cmd_join(self, emitter, cmd, args):
131        channelname = args.split(' ')[0]
132        user = self.users.searchUserByNick(emitter)
133        if user == None: return
134        chan = self.chans.searchChanByName(channelname)
135        if chan == None: return
136        self.chans.addUserOnChannel(chan, user)
137
138    def cmd_part(self, emitter, cmd, args):
139        channelname = args.split(' ')[0]
140        user = self.users.searchUserByNick(emitter)
141        if user == None: return
142        chan = self.chans.searchChanByName(channelname)
143        if chan == None: return
144        self.chans.removeUserOnChannel(chan, user)
145
146    def cmd_quit(self, emitter, cmd, arg):
147        self.users.removeUser(self.users.searchUserByNick(emitter))
148
149    def scmd_endburst(self, command, raw_command):
150        self.connection.lastPing = datetime.datetime.now()
151        for bot in self.bots.initialBots:
152            self.bots.registerBot(bot)
153        self.bots.initialBots = []
154        self.connection.online = True
155
156class ChansManager(object):
157    '''Manage all channels existing on the IRC network'''
158
159    def __init__(self, pynspircd):
160        self.pynspircd = pynspircd
161        self.channels = {}
162
163    def addChannel(self, channelname):
164        '''Add a channel to the database'''
165        for chan in self.channels.keys():
166            if chan.channelname == channelname:
167                # Channel already exist !
168                return chan
169        chan = Chan(channelname)
170        self.channels[chan] = []
171        return chan
172
173    def addUserOnChannel(self, channel, user):
174        '''Add an user to the channel database'''
175        if user in self.channels[channel]:
176            # User already exist on channel !
177            return False
178        self.channels[channel].append(user)
179        return True
180
181    def removeUserOnChannel(self, channel, user):
182        '''Remove an user to the channel database'''
183        while self.channels[channel].count(user) != 0:
184            self.channels[channel].remove(user)
185
186    def removeUserOnAllChannels(self, user):
187        '''Remove an user of all the channels databases'''
188        for users in self.channels.values():
189            while users.count(user) != 0:
190                users.remove(user)
191
192    def searchChanByName(self, channelname):
193        '''Return the channel object of a channel'''
194        for chan in self.channels.keys():
195            if chan.channelname == channelname:
196                return chan
197        return None
198
199class Chan(object):
200    def __init__(self, channelname):
201        self.channelname = channelname
202
203    def __str__(self):
204        return self.channelname
205
206class UsersManager(object):
207    '''Manage all users connected to the IRC network'''
208
209    def __init__(self, pynspircd):
210        self.pynspircd = pynspircd
211
212        self.users = []
213
214    def addUser(self, user):
215        for u in self.users:
216            if u.nick == user.nick:
217                return False
218        self.users.append(user)
219        self.pynspircd.debugMessage('Un nouvel utilisateur à été detecté : %s' % user.nick)
220        return True
221
222    def removeUser(self, user):
223        if user in self.users:
224            self.users.remove(user)
225            self.pynspircd.chans.removeUserOnAllChannels(user)
226            self.pynspircd.debugMessage('Un utilisateur s\'est déconnecté : %s' % user.nick)
227            return True
228        else:
229            return False
230
231    def searchUserByNick(self, nick):
232        for user in self.users:
233            if user.nick == nick:
234                return user
235        return None
236
237    def changeUserNick(self, user, newnick):
238        for u in self.users:
239            if u.nick == newnick:
240                return False
241        self.pynspircd.debugMessage('%s à changé son nick en %s' % (user.nick, newnick))
242        user.nick = newnick
243
244class User(object):
245    def __init__(self, nick, hostname, displayed_hostname, ident, ip, modes=[], gecos=''):
246        self.nick = nick
247        self.hostname = hostname,
248        self.displayed_hostname = displayed_hostname
249        self.ident = ident
250        self.modes = modes
251        self.ip = ip
252        self.gecos = gecos
253        self.away = None
254        self.metadata = {}
255
256    def __str__(self):
257        return self.nick
258
259class ConnectionManager(object):
260
261    re_rawmessage = re.compile(r'^:(?P<emitter>.*?) (?P<command>[A-Z]*) ?(?P<arguments>.*)$')
262
263    def __init__(self, pynspircd, hub, password, hostname, description, hops):
264        self.pynspircd = pynspircd
265        self.hostname = hostname
266        self.hub = hub
267        self.password = password
268        self.hops = hops
269        self.description = description
270        self.maxLastPingTime = 120
271        self.online = False
272        self.buffer = ''
273        self.lastPing = datetime.datetime.now()
274
275    def connect(self):
276        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
277        hub_host, hub_port = self.hub.split(':')
278        self.pynspircd.debugMessage('Connecting to %s on port %s...' % (hub_host, hub_port))
279        try:
280            self.socket.connect((hub_host, int(hub_port)))
281        except Exception, error:
282            self.online = False
283            self.pynspircd.debugMessage('Error while connecting to hub', type='error')
284            self.pynspircd.debugMessage('Error was : %s' % error, type='error')
285            return False
286        self.pynspircd.debugMessage('Connected to %s !' % hub_host)
287        self._waitFor('CAPAB END')
288        self.sendMSG('SERVER %s %s %s :%s' % (self.hostname, self.password, self.hops, self.description))
289        self.myburst() # <- Send my state
290        return True
291
292    def messageManager(self):
293        self.socket.settimeout(1.0)
294        buffer = ''
295        while 1:
296            try: buffer += self.socket.recv(1024)
297            except socket.timeout: pass
298            else:
299                if buffer == '':
300                    self.online = False
301                    return
302            deltaping = datetime.datetime.now() - self.lastPing
303            if deltaping.seconds > self.maxLastPingTime:
304                self.disconnect('Ping timeout (>%s)' % self.maxLastPingTime)
305                return
306            lines = buffer.split('\n')
307            buffer = lines.pop()
308            for raw_message in lines:
309                self.lastPing = datetime.datetime.now()
310                raw_message = raw_message.rstrip()
311                if raw_message == '': continue
312                self.pynspircd.debugMessage(raw_message, type='in')
313
314                # Parsing messages & calling server and bots methods
315                if raw_message[0] == ':': # Normal message
316                    try: emitter, command, args = self.re_rawmessage.findall(raw_message)[0]
317                    except: continue
318                    if hasattr(self.pynspircd, 'cmd_'+command.lower()):
319                        try:
320                            getattr(self.pynspircd, 'cmd_'+command.lower())(emitter, command, args)
321                        except Exception, error:
322                            self.pynspircd.debugMessage('Error while calling cmd_%s()' % command.lower(), type='error')
323                            self.pynspircd.debugMessage('Raw message was : "%s"' % raw_message, type='error')
324                            self.pynspircd.debugMessage('Error was : "%s"' % error, type='error')
325                    for bot in self.pynspircd.bots.bots:
326                        if bot.registeredCmds.has_key(command.lower()):
327                            if hasattr(bot, bot.registeredCmds[command.lower()]):
328                                try:
329                                    getattr(bot, bot.registeredCmds[command.lower()])(emitter, command, args)
330                                except Exception, error:
331                                    self.pynspircd.debugMessage('Error while calling %s.%s()' % (bot, bot.registeredCmds[command.lower()]), type='error')
332                                    self.pynspircd.debugMessage('Raw message was : "%s"' % raw_message, type='error')
333                                    self.pynspircd.debugMessage('Error was : "%s"' % error, type='error')
334                        if hasattr(bot, 'catchAllCmds'):
335                            try:
336                                getattr(bot, 'catchAllCmds')(emitter, command, args)
337                            except Exception, error:
338                                self.pynspircd.debugMessage('Error while calling %s.catchAllCmds()' % bot, type='error')
339                                self.pynspircd.debugMessage('Raw message was : "%s"' % raw_message, type='error')
340                                self.pynspircd.debugMessage('Error was : "%s"' % error, type='error')
341
342                else: # Server message
343                    command = raw_message.split(' ', 1)[0]
344                    if hasattr(self.pynspircd, 'scmd_'+command.lower()):
345                        try:
346                            getattr(self.pynspircd, 'scmd_'+command.lower())(command, raw_message)
347                        except Exception, error:
348                            self.pynspircd.debugMessage('Error while calling scmd_%s()' % command.lower(), type='error')
349                            self.pynspircd.debugMessage('Raw message was : "%s"' % raw_message, type='error')
350                            self.pynspircd.debugMessage('Error was : "%s"' % error, type='error')
351
352    def myburst(self):
353        burstTimestamp = int(time.time())
354        self.sendMSG('BURST %s' % burstTimestamp)
355        self.sendMSG(':%s VERSION :pynspircd alpha %s :nobuild' % (self.hostname, self.hostname))
356        for bot in self.pynspircd.bots.bots:
357            self.sendMSG(':%s NICK %s %s %s %s %s %s %s :%s' % (
358                self.hostname,
359                burstTimestamp,
360                bot.nick,
361                bot.hostname,
362                bot.displayed_hostname,
363                bot.ident,
364                '+%s' % ''.join(bot.modes),
365                bot.ip,
366                bot.gecos)) # :<local server> NICK <timestamp> <nick> <hostname> <displayed-hostname> <ident> +<modes> <ip> :<gecos>
367        for chan, bots in self.pynspircd.bots.chanList.items():
368            bots_join = []
369            for bot in bots:
370                bots_join.append('@,'+bot.nick)
371            self.sendMSG(':%s FJOIN %s %s :%s' % (self.hostname, chan, burstTimestamp, ' '.join(bots_join)))
372
373    def disconnect(self, message):
374        self.sendMSG(':%s SQUIT %s :%s' % (self.hostname, self.hostname, message))
375        self.pynspircd.debugMessage('Server disconnected: ping timeout.', type='error')
376
377    def sendMSG(self, message):
378        self.socket.send(message+' \n')
379        self.pynspircd.debugMessage(message.rstrip(), type='out')
380
381    def _waitFor(self, message):
382        '''Wait while 'message' isn't received'''
383
384        self.pynspircd.debugMessage('Waiting for "%s"' % message, cont=True)
385        self.socket.settimeout(1.0)
386        buffer = ''
387
388        while 1:
389            try: buffer += self.socket.recv(1024)
390            except socket.timeout: pass
391
392            lines = buffer.split('\n')
393            buffer = lines.pop()
394            for line in lines:
395                self.pynspircd.debugMessage('.', type='continue', cont=True)
396                if line.rstrip() == message:
397                    self.pynspircd.debugMessage('[Received] !', type='continue')
398                    self.socket.settimeout(None)
399                    return True
400
401class BotsManager(object):
402    '''Manage bots connected to the fake IRCD'''
403
404    def __init__(self, pynspircd):
405        self.bots = []
406        self.chanList = {}
407        self.pynspircd = pynspircd
408
409    def joinChan(self, bot, channel):
410        '''Join a bot on channel'''
411        if not(channel in bot.chanList):
412            if self.chanList.has_key(channel):
413                self.chanList[channel].append(bot)
414            else:
415                self.chanList[channel] = [bot]
416            bot.chanList.append(channel)
417            self.pynspircd.connection.sendMSG(':%s JOIN %s %s' % (bot.nick, channel, int(time.time())))
418            self.pynspircd.debugMessage('%s has join %s' % (bot.nick, channel))
419
420    def searchBotWithNick(self, nick):
421        '''Return bot who have specified nick or None'''
422        for bot in self.bots:
423            if bot.nick.lower() == nick.lower():
424                return bot
425        return None
426
427    def registerBot(self, bot_class, *args, **kwarg):
428        '''Register a new bot on server'''
429        bot = bot_class(self.pynspircd, *args, **kwarg)
430        bot.firstTime()
431        if self.searchBotWithNick(bot.nick):
432            self.pynspircd.debugMessage('Failed to register bot, a bot with same nick is already managed', type='error')
433            return False
434        self.pynspircd.debugMessage('Registering new bot %s' % bot.nick)
435        self.bots.append(bot)
436        self.pynspircd.connection.sendMSG(':%s NICK %s %s %s %s %s %s %s :%s' % (
437                self.pynspircd.hostname,
438                int(time.time()),
439                bot.nick,
440                bot.hostname,
441                bot.displayed_hostname,
442                bot.ident,
443                '+%s' % ''.join(bot.modes),
444                bot.ip,
445                bot.gecos)) # :<local server> NICK <timestamp> <nick> <hostname> <displayed-hostname> <ident> +<modes> <ip> :<gecos>
446        bot.secondTime()
447        return True
448
449    def unregisterBot(self, bot):
450        bot.lastTime()
451        for chan, bots in self.chanList.items():
452            if bot in bots:
453                self.pynspircd.connection.sendMSG(':%s PART %s :Unregistering bot' % (bot.nick, chan))
454                bots.remove(bot)
455        self.bots.remove(bot)
456        self.pynspircd.debugMessage('Unregistered bot %s.' % bot.nick)
457
458
459class Bot(object):
460    '''Represent a bot connected on pynspircd server'''
461
462    def __init__(self, pynspircd, *args, **kwarg):
463        self.pynspircd = pynspircd
464        self.nick = 'Bot'
465        self.realname = 'Pynspircd fake-bot'
466        self.ident = self.nick
467        self.ip = '127.0.0.1'
468        self.gecos = 'lol'
469        self.http_id = ''
470        self.chanList = []
471        self.modes = ['w', 's', 'i', 'x', 'b']
472        self.registeredCmds = dict()
473        self.hostname = pynspircd.hostname
474        self.displayed_hostname = pynspircd.hostname
475
476    def changeNick(self, newNick):
477        self.pynspircd.connection.sendMSG(':%s NICK %s' % (self.nick, newNick))
478        self.nick = newNick
479
480    def firstTime(self):
481        pass
482
483    def secondTime(self):
484        pass
485
486    def lastTime(self):
487        pass
488
489    def __str__(self):
490        return '<%s@%s>' % (self.nick, self.ip)
491
492class HTTPServer(threading.Thread):
493    def __init__(self, pynspircd, ip='', port=8081):
494        threading.Thread.__init__(self)
495        self.pynspircd = pynspircd
496        self.ip = ip
497        self.port = port
498
499    def run(self):
500        HTTPServerURLHandler.pynspircd = self.pynspircd
501        httpd = BaseHTTPServer.HTTPServer((self.ip, self.port), HTTPServerURLHandler)
502        httpd.serve_forever()
503
504class HTTPServerURLHandler(BaseHTTPServer.BaseHTTPRequestHandler):
505
506    BAD_REQUEST = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
507<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
508    <head>
509        <title>400 - Bad Request</title>
510    </head>
511
512    <body>
513        <h1>Error 400 - Bad Request</h1>
514        <p>Sorry, this HTTP daemon only accepts GET requests such as <strong>/http_group/method_to_call?param1=value&param2=value</strong>.</p>
515    </body>
516</html>'''
517
518    SERVICE_UNAVAILABLE = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
519<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
520    <head>
521        <title>503 - Bad Request</title>
522    </head>
523
524    <body>
525        <h1>Error 503 - Service Unavailable</h1>
526        <p>Sorry, but this http daemon is not available ATM.<br />Retry again later...</p>
527    </body>
528</html>'''
529
530    INTERNAL_SERVER_ERROR = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
531<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
532    <head>
533        <title>500 - Internal Server Error</title>
534    </head>
535
536    <body>
537        <h1>Error 500 - Internal Server Error</h1>
538        <p>Fail.</p>
539    </body>
540</html>'''
541
542    NOT_FOUND = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
543<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
544    <head>
545        <title>404 - Not Found</title>
546    </head>
547
548    <body>
549        <h1>Error 404 - Not Found</h1>
550        <p>Sorry, but this http daemon can't found the answer which you hoped to find</p>
551    </body>
552</html>'''
553
554    def do_GET(self):
555        if not(self.pynspircd.connection.online):
556            self.send_response(503, 'Service Unavailable')
557            self.send_header('Content-type', 'text/html')
558            self.end_headers()
559            self.wfile.write(self.SERVICE_UNAVAILABLE)
560            return
561        url = urlparse(self.path)
562        path = url.path.rstrip('/').lstrip('/').split('/')
563        if len(path) < 2+self.pynspircd.httpd_prefix_length:
564            self.send_response(400, 'Bad Request')
565            self.send_header('Content-type', 'text/html')
566            self.end_headers()
567            self.wfile.write(self.BAD_REQUEST)
568            return
569        path = path[self.pynspircd.httpd_prefix_length:]
570        http_id, action = path
571        # Parsing parameters :
572        kwarg = dict()
573        for arg in url.query.split('&'):
574            if arg != '':
575                arg = arg.split('=')
576                kwarg[arg[0]] = arg[1]
577
578        # Bot method calling :
579        for bot in self.pynspircd.bots.bots:
580            if bot.http_id == http_id:
581                break
582        else:
583            self.send_response(404, 'Not Found')
584            self.send_header('Content-type', 'text/html')
585            self.end_headers()
586            self.wfile.write(self.NOT_FOUND)
587            return
588
589        if hasattr(bot, 'act_'+action.lower()):
590            try:
591                returning = getattr(bot, 'act_'+action.lower())(**kwarg)
592                self.send_response(200, 'OK')
593                self.send_header('Content-type', 'text/html')
594                self.end_headers()
595                self.wfile.write(returning)
596            except Exception, error:
597                self.pynspircd.debugMessage('Error while calling act_%s()' % action.lower(), type='error')
598                self.pynspircd.debugMessage('Raw http path was : "%s"' % self.path, type='error')
599                self.pynspircd.debugMessage('Error was : "%s"' % error, type='error')
600                self.send_response(500, 'Internal Server Error')
601                self.send_header('Content-type', 'text/html')
602                self.end_headers()
603                self.wfile.write(self.INTERNAL_SERVER_ERROR)
604        else:
605            self.send_response(404, 'Not Found')
606            self.send_header('Content-type', 'text/html')
607            self.end_headers()
608            self.wfile.write(self.NOT_FOUND)
609
pynspircd/pynspircd.py
1# -*- coding: utf-8 -*-
2# pynspircd.py
3#
4# Copyright 2007 Antoine 'NaPs' Millet <antoine@inaps.org>
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19# MA 02110-1301, USA.
20
21from inspircdlib import Pynspircd, Bot
22import sys
23
24class Killer(Bot):
25    def firstTime(self):
26        self.nick = 'KillZor' # On définit le nom du bot (c'est le minimum)
27        self.http_id = 'killer'
28
29    def act_kill(self, **kwarg):
30        bot = self.pynspircd.bots.searchBotWithNick(kwarg['nick'])
31        self.pynspircd.bots.unregisterBot(bot)
32
33class Logs(Bot):
34    '''Bot d'enregistrement des conversations'''
35    def firstTime(self):
36        self.nick = 'Logs' # On définit le nom du bot (c'est le minimum)
37        self.registeredCmds = dict(privmsg='logging') # On définit la méthode à appelé pour la commande PRIVMSG
38        self.http_id = 'Conversations'
39        self.logs = []
40
41    def secondTime(self):
42        self.pynspircd.debugMessage("Le bot d'enregistement des conversations est actif !")
43        # debugMessage() permet d'afficher du texte sur la sortie standard en mode debug
44        self.pynspircd.bots.joinChan(self, '#test')
45        self.pynspircd.bots.joinChan(self, '#20speak')
46        # pynspircd.bots.joinChan() permet de faire joindre un bot sur un canal
47
48    def lastTime(self):
49        self.pynspircd.debugMessage('OMG, Je vais mourrir :(')
50
51    def logging(self, emitter, command, args):
52        '''Enregistrement des messages'''
53        target, message = args.split(' ', 1)
54        message = message[1:]
55        self.logs.append((target, emitter, message))
56
57    def act_view(self, **kwarg):
58        '''Affichage des messages via l'interface web.
59        Nous verrons plus en détail sur fonctionnement du
60        serveur web dans la partie consacrée.'''
61        logs = '<ul>\n'
62        for line in self.logs:
63            logs += '<li>%s &lt;-- &lt;%s&gt; %s</li>\n' % (line)
64        logs += '</ul>'
65        return logs
66
67    def act_users(self, **kwarg):
68        r = '<ul>\n'
69        for user in self.pynspircd.users.users:
70            r += '<li>%s (%s)</li>' % (user.nick, user.ip)
71        r += '</ul>\n'
72        return r
73
74    def act_chans(self, **kwarg):
75        r = '<ul>\n'
76        for name, users in self.pynspircd.chans.channels.items():
77            u = '<ul>'
78            for user in users: u += '<li>%s</li>' % user.nick
79            u += '</ul>'
80            r += '<li>%s -> %s</li>' % (name.channelname, u)
81        r += '</ul>\n'
82        return r
83
84if __name__ == '__main__':
85    ircd = Pynspircd('serveur', 'pw', 'hostname', bots=[Logs, Killer], debug=True)
86    try:
87        ircd.run()
88    except:
89        sys.exit()

Archive Download the corresponding diff file

Branches:
master