]> jfr.im git - erebus.git/blame - bot.py
SQL dump added
[erebus.git] / bot.py
CommitLineData
f4f6442e
JR
1#!/usr/bin/python
2
3#TODO: error checking
4
9c935294 5import socket, sys
f4f6442e
JR
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
82696467
JR
12 self.user = user
13 self.realname = realname
f4f6442e
JR
14 self.chans = chans
15
82696467 16 self.conn = BotConnection(self, bind, server, port)
f4f6442e 17 def connect(self):
9c935294
JR
18 if self.conn.connect():
19 self.parent.newfd(self, self.conn.socket.fileno())
20
f4f6442e
JR
21 def getdata(self):
22 for line in self.conn.read():
9c935294 23 print self.nick, '[I]', line
ab7c0c0b 24
9c935294
JR
25 if not self.conn.registered():
26 pieces = line.split()
ab7c0c0b 27
9c935294
JR
28 if pieces[0] == "PING":
29 self.conn.send("PONG %s" % (pieces[1]))
ab7c0c0b 30
9c935294
JR
31 elif pieces[1] == "001":
32 self.conn.registered(True)
33 for c in self.chans:
34 self.join(c)
f9767f79 35
9c935294
JR
36 else:
37 self.parse(line)
f4f6442e
JR
38 def parse(self, line):
39 pieces = line.split()
ab7c0c0b 40
9c935294
JR
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)
ab7c0c0b 47
9c935294
JR
48 elif pieces[0] == "PING":
49 self.conn.send("PONG %s" % (pieces[1]))
ab7c0c0b 50
9c935294
JR
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:]
ab7c0c0b 59
9c935294
JR
60 else:
61 return
ab7c0c0b 62
9c935294
JR
63 pieces = msg.split()
64 cmd = pieces[0].upper()
ab7c0c0b 65
9c935294
JR
66 if cmd == "EVAL":
67 try: ret = eval(' '.join(pieces[1:]))
68 except: self.msg(chan, "Error: %s %s" % (sys.exc_info()[0], sys.exc_info()[1]))
69 else: self.msg(chan, "Done: %r" % (ret))
ab7c0c0b 70
9c935294
JR
71 elif cmd == "EXEC":
72 try: exec ' '.join(pieces[1:])
73 except: self.msg(chan, "Error: %s %s" % (sys.exc_info()[0], sys.exc_info()[1]))
74 else: self.msg(chan, "Done.")
ab7c0c0b 75
9c935294
JR
76 #TODO
77
78 def msg(self, target, msg):
79 if isinstance(target, self.parent.User): self.conn.send("NOTICE %s :%s" % (target.nick, msg))
80 elif isinstance(target, self.parent.Channel): self.conn.send("PRIVMSG %s :%s" % (target.name, msg))
81 elif isinstance(target, basestring):
82 if target[0] == '#': self.conn.send("PRIVMSG %s :%s" % (target, msg))
83 else: self.conn.send("NOTICE %s :%s" % (target, msg))
84 else: raise TypeError('Bot.msg() "target" must be Erebus.User, Erebus.Channel, or string')
ab7c0c0b 85
9c935294
JR
86 def join(self, chan):
87 self.conn.send("JOIN %s" % (chan))
ab7c0c0b 88
9c935294
JR
89 def part(self, chan):
90 self.conn.send("PART %s" % (chan))
ab7c0c0b 91
9c935294
JR
92 def quit(self, reason="Shutdown"):
93 self.conn.send("QUIT :%s" % (reason))
f4f6442e 94
82696467
JR
95 def __str__(self): return self.nick
96 def __repr__(self): return "<Bot %r>" % (self.nick)
97
f4f6442e
JR
98class BotConnection(object):
99 state = 0 # 0=disconnected, 1=registering, 2=connected
100
82696467 101 def __init__(self, parent, bind, server, port):
f4f6442e
JR
102 self.parent = parent
103 self.buffer = ''
104 self.socket = None
105
f4f6442e
JR
106 self.bind = bind
107 self.server = server
108 self.port = int(port)
f4f6442e
JR
109
110 def connect(self):
111 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
112 self.socket.bind((self.bind, 0))
113 self.socket.connect((self.server, self.port))
82696467
JR
114 self.send("NICK %s" % (self.parent.nick))
115 self.send("USER %s 0 * :%s" % (self.parent.user, self.parent.realname))
f4f6442e 116 self.state = 1
9c935294 117 return True
f4f6442e
JR
118
119 def registered(self, done=False):
120 if done: self.state = 2
121 return self.state == 2
122
f4f6442e
JR
123 #TODO: rewrite send() to queue
124 def send(self, line):
82696467 125 print self.parent.nick, '[O]', line
f4f6442e 126 self.write(line)
ab7c0c0b 127
f4f6442e 128 def write(self, line):
f4f6442e 129 self.socket.sendall(line+"\r\n")
ab7c0c0b 130
f4f6442e
JR
131 def read(self):
132 self.buffer += self.socket.recv(8192)
133 lines = []
ab7c0c0b 134
f4f6442e
JR
135 while '\r\n' in self.buffer:
136 pieces = self.buffer.split('\r\n', 1)
f4f6442e
JR
137 lines.append(pieces[0])
138 self.buffer = pieces[1]
ab7c0c0b 139
f4f6442e 140 return lines
82696467
JR
141
142 def __str__(self): return self.nick
143 def __repr__(self): return "<BotConnection %r (%r)>" % (self.socket.fileno(), self.parent.nick)