]> jfr.im git - erebus.git/blame_incremental - bot.py
Added a few module featuresm depends needs testing!
[erebus.git] / bot.py
... / ...
CommitLineData
1#!/usr/bin/python
2
3#TODO: error checking
4
5import socket, sys
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
12 self.user = user
13 self.realname = realname
14 self.chans = chans
15
16 self.conn = BotConnection(self, bind, server, port)
17 def connect(self):
18 if self.conn.connect():
19 self.parent.newfd(self, self.conn.socket.fileno())
20
21 def getdata(self):
22 for line in self.conn.read():
23 print self.nick, '[I]', line
24
25 if not self.conn.registered():
26 pieces = line.split()
27
28 if pieces[0] == "PING":
29 self.conn.send("PONG %s" % (pieces[1]))
30
31 elif pieces[1] == "001":
32 self.conn.registered(True)
33 for c in self.chans:
34 self.join(c)
35
36 else:
37 self.parse(line)
38 def parse(self, line):
39 pieces = line.split()
40
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)
47
48 elif pieces[0] == "PING":
49 self.conn.send("PONG %s" % (pieces[1]))
50
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
61
62 pieces = msg.split()
63 cmd = pieces[0].lower()
64
65 if self.parent.hashook(cmd):
66 self.parent.gethook(cmd)(self, user, chan, *pieces[1:])
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')
75
76 def join(self, chan):
77 self.conn.send("JOIN %s" % (chan))
78
79 def part(self, chan):
80 self.conn.send("PART %s" % (chan))
81
82 def quit(self, reason="Shutdown"):
83 self.conn.send("QUIT :%s" % (reason))
84
85 def __str__(self): return self.nick
86 def __repr__(self): return "<Bot %r>" % (self.nick)
87
88class BotConnection(object):
89 state = 0 # 0=disconnected, 1=registering, 2=connected
90
91 def __init__(self, parent, bind, server, port):
92 self.parent = parent
93 self.buffer = ''
94 self.socket = None
95
96 self.bind = bind
97 self.server = server
98 self.port = int(port)
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))
104 self.send("NICK %s" % (self.parent.nick))
105 self.send("USER %s 0 * :%s" % (self.parent.user, self.parent.realname))
106 self.state = 1
107 return True
108
109 def registered(self, done=False):
110 if done: self.state = 2
111 return self.state == 2
112
113 #TODO: rewrite send() to queue
114 def send(self, line):
115 print self.parent.nick, '[O]', line
116 self.write(line)
117
118 def write(self, line):
119 self.socket.sendall(line+"\r\n")
120
121 def read(self):
122 self.buffer += self.socket.recv(8192)
123 lines = []
124
125 while '\r\n' in self.buffer:
126 pieces = self.buffer.split('\r\n', 1)
127 lines.append(pieces[0])
128 self.buffer = pieces[1]
129
130 return lines
131
132 def __str__(self): return self.nick
133 def __repr__(self): return "<BotConnection %r (%r)>" % (self.socket.fileno(), self.parent.nick)