]> jfr.im git - erebus.git/blame - bot.py
Added a few module featuresm depends needs testing!
[erebus.git] / bot.py
CommitLineData
b25d4368 1#!/usr/bin/python
2
3#TODO: error checking
4
49a455aa 5import socket, sys
b25d4368 6
7#bots = {'erebus': bot.Bot(nick='Erebus', user='erebus', bind='', server='irc.quakenet.org', port=6667, realname='Erebus')}
8class Bot(object):
9 def __init__(self, parent, nick, user, bind, server, port, realname, chans):
10 self.parent = parent
11 self.nick = nick
a12f7519 12 self.user = user
13 self.realname = realname
b25d4368 14 self.chans = chans
15
a12f7519 16 self.conn = BotConnection(self, bind, server, port)
b25d4368 17 def connect(self):
49a455aa 18 if self.conn.connect():
19 self.parent.newfd(self, self.conn.socket.fileno())
20
b25d4368 21 def getdata(self):
22 for line in self.conn.read():
49a455aa 23 print self.nick, '[I]', line
a4eacae2 24
49a455aa 25 if not self.conn.registered():
26 pieces = line.split()
a4eacae2 27
49a455aa 28 if pieces[0] == "PING":
29 self.conn.send("PONG %s" % (pieces[1]))
a4eacae2 30
49a455aa 31 elif pieces[1] == "001":
32 self.conn.registered(True)
33 for c in self.chans:
34 self.join(c)
43b98e4e 35
49a455aa 36 else:
37 self.parse(line)
b25d4368 38 def parse(self, line):
39 pieces = line.split()
a4eacae2 40
49a455aa 41 if pieces[1] == "PRIVMSG":
42 nick = pieces[0].split('!')[0][1:]
43 user = self.parent.user(nick)
44 chan = self.parent.channel(pieces[2])
45 msg = ' '.join(pieces[3:])[1:]
46 self.parsemsg(user, chan, msg)
a4eacae2 47
49a455aa 48 elif pieces[0] == "PING":
49 self.conn.send("PONG %s" % (pieces[1]))
a4eacae2 50
49a455aa 51 elif pieces[1] == "JOIN":
52 nick = pieces[0].split('!')[0][1:]
53 user = self.parent.user(nick)
54 chan = self.parent.channel(pieces[2]) #TODO TODO TODO
55
56 def parsemsg(self, user, chan, msg):
57 if msg[0] == '!': #TODO check config for trigger
58 msg = msg[1:]
59 else:
60 return
a4eacae2 61
49a455aa 62 pieces = msg.split()
db50981b 63 cmd = pieces[0].lower()
a4eacae2 64
db50981b 65 if self.parent.hashook(cmd):
66 self.parent.gethook(cmd)(self, user, chan, *pieces[1:])
49a455aa 67
68 def msg(self, target, msg):
69 if isinstance(target, self.parent.User): self.conn.send("NOTICE %s :%s" % (target.nick, msg))
70 elif isinstance(target, self.parent.Channel): self.conn.send("PRIVMSG %s :%s" % (target.name, msg))
71 elif isinstance(target, basestring):
72 if target[0] == '#': self.conn.send("PRIVMSG %s :%s" % (target, msg))
73 else: self.conn.send("NOTICE %s :%s" % (target, msg))
74 else: raise TypeError('Bot.msg() "target" must be Erebus.User, Erebus.Channel, or string')
a4eacae2 75
49a455aa 76 def join(self, chan):
77 self.conn.send("JOIN %s" % (chan))
a4eacae2 78
49a455aa 79 def part(self, chan):
80 self.conn.send("PART %s" % (chan))
a4eacae2 81
49a455aa 82 def quit(self, reason="Shutdown"):
83 self.conn.send("QUIT :%s" % (reason))
b25d4368 84
a12f7519 85 def __str__(self): return self.nick
86 def __repr__(self): return "<Bot %r>" % (self.nick)
87
b25d4368 88class BotConnection(object):
89 state = 0 # 0=disconnected, 1=registering, 2=connected
90
a12f7519 91 def __init__(self, parent, bind, server, port):
b25d4368 92 self.parent = parent
93 self.buffer = ''
94 self.socket = None
95
b25d4368 96 self.bind = bind
97 self.server = server
98 self.port = int(port)
b25d4368 99
100 def connect(self):
101 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
102 self.socket.bind((self.bind, 0))
103 self.socket.connect((self.server, self.port))
a12f7519 104 self.send("NICK %s" % (self.parent.nick))
105 self.send("USER %s 0 * :%s" % (self.parent.user, self.parent.realname))
b25d4368 106 self.state = 1
49a455aa 107 return True
b25d4368 108
109 def registered(self, done=False):
110 if done: self.state = 2
111 return self.state == 2
112
b25d4368 113 #TODO: rewrite send() to queue
114 def send(self, line):
a12f7519 115 print self.parent.nick, '[O]', line
b25d4368 116 self.write(line)
a4eacae2 117
b25d4368 118 def write(self, line):
b25d4368 119 self.socket.sendall(line+"\r\n")
a4eacae2 120
b25d4368 121 def read(self):
122 self.buffer += self.socket.recv(8192)
123 lines = []
a4eacae2 124
b25d4368 125 while '\r\n' in self.buffer:
126 pieces = self.buffer.split('\r\n', 1)
b25d4368 127 lines.append(pieces[0])
128 self.buffer = pieces[1]
a4eacae2 129
b25d4368 130 return lines
a12f7519 131
132 def __str__(self): return self.nick
133 def __repr__(self): return "<BotConnection %r (%r)>" % (self.socket.fileno(), self.parent.nick)