This repository has been archived by the owner on Oct 18, 2023. It is now read-only.
forked from stenyak/breakbot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
irc_bot.py
executable file
·148 lines (143 loc) · 5.31 KB
/
irc_bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/python
# Copyright 2012 Bruno Gonzalez
# This software is released under the GNU AFFERO GENERAL PUBLIC LICENSE (see agpl-3.0.txt or www.gnu.org/licenses/agpl-3.0.html)
import threading
import time
from log import info, error
from catch_them_all import catch_them_all
from Queue import Queue
from oyoyo.client import IRCClient
from oyoyo.cmdhandler import DefaultCommandHandler
from message import Message
import binascii
class Handler(DefaultCommandHandler):
# Handle messages (the PRIVMSG command, note lower case)
@catch_them_all
def privmsg(self, nick_full, chan, msg):
try:
msg = unicode(msg, "utf-8")
except UnicodeDecodeError:
try:
msg = unicode(msg, "latin-1")
except UnicodeDecodeError:
hexa = binascii.hexlify(msg)
error("Could not decode message: binascii.unhexlify(\"%s\")" %hexa)
raise
m = Message("irc", nick_full, chan, msg)
self.irc_interface.msg_handler(m)
def set_irc_interface(self, irc_interface):
self.irc_interface = irc_interface
@catch_them_all
def join(self, nick_full, channel):
self.irc_interface.joined(channel)
@catch_them_all
def part(self, nick_full, channel):
self.irc_interface.parted(channel)
@catch_them_all
def kick(self, kicker, channel, nick, reason):
self.irc_interface.parted(channel)
class IRCInterface(threading.Thread):
def __init__(self, server, port, nick, channels, msg_handler, stopped_handler):
threading.Thread.__init__(self)
self.must_run = True
self.connected = False
self.msg_handler = msg_handler
self.stopped_handler = stopped_handler
self.nick = nick
self.host = server
self.port = port
self.channels = channels
self.send_queue = Queue()
self.channels_joined = {}
for c in self.channels:
self.channels_joined[c] = False
self.cli = IRCClient(Handler, host=self.host, port=self.port, nick=self.nick, connect_cb=self.connect_callback)
self.cli.command_handler.set_irc_interface(self)
@catch_them_all
def connect_callback(self, cli):
self.server_connected = True
def pending_channels(self):
result = True
for k,v in self.channels_joined.items():
if not v:
result = False
break
return result
def joined(self, channel):
self.channels_joined[channel] = True
info("Joined channel %s" %channel)
def parted(self, channel):
self.channels_joined[channel] = False
info("Left channel %s" %channel)
if self.must_run:
self.join_channels()
def connect(self):
info("Connecting to server")
self.server_connected = False
self.conn = self.cli.connect()
while not self.server_connected:
if not self.must_run:
raise Exception("Must stop")
try:
self.conn.next()
except Exception, e:
error("Problems while connecting to IRC server: %s" %e)
self.stop()
self.disconnected()
info("Connected to server")
def next(self):
try:
self.conn.next()
except Exception, e:
time.sleep(0.05)
error("Couldn't process connection: %s" %e)
del self.conn
self.connect()
def join_channels(self):
for c in self.channels:
if not c in self.channels_joined or self.channels_joined[c] == False:
info("Joining channel %s" %c)
self.cli.send("JOIN", c)
while self.pending_channels():
if not self.must_run:
raise Exception("Must stop")
self.conn.next()
@catch_them_all
def run(self):
self.must_run = True
info("%s connecting to %s:%s" %(self.nick, self.host, self.port))
self.connect()
self.join_channels()
while not self.pending_channels():
if not self.must_run:
raise Exception("Must stop")
self.next()
self.connected = True
info("%s connected to %s:%s" %(self.nick, self.host, self.port))
while self.must_run:
self.next()
time.sleep(0.1)
if not self.send_queue.empty():
text = self.send_queue.get()
info((" >>> IRC %s" %text).encode("utf-8"))
self.cli.send(text)
time.sleep(0.5) #throttle message sending in order to avoid excess flood kick
self.cli.send("QUIT :a la mieeerrrrda")
info("%s disconnected from %s:%s" %(self.nick, self.host, self.port))
self.disconnected()
def disconnected(self):
self.connected = False
del self.conn
self.stopped_handler()
self.must_run = False
def stop(self):
self.must_run = False
def send(self, channel, text):
info((" ->- IRC %s: %s" %(channel, text)).encode("utf-8"))
msg = "PRIVMSG %s :%s" %(channel, text)
self.send_queue.put(msg)
def wait_connected(self):
while not self.connected:
if not self.must_run:
raise Exception("IRC: bot does not intend to connect")
time.sleep(0.1)