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