-
Notifications
You must be signed in to change notification settings - Fork 2
/
abpbot.py
144 lines (117 loc) · 4.41 KB
/
abpbot.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
#!/usr/bin/env python
#
# Simple IRC Bot to announce messages
#
# Code originally based on example bot and irc-bot class from
# Joel Rosdahl <joel@rosdahl.net>, author of included python-irclib.
#
"""
An IRC bot stub, it will join a particular channel on a server. All
further functionality is implemented by additional handler classes.
"""
import sys
import ConfigParser
from ircbot import SingleServerIRCBot
import irclib
from botcommon import OutputManager
import logbot
import beanbot
import decisionbot
# The message returned when someone messages the bot
HELP_MESSAGE = "I am the Adblock Plus logging bot."
def parse_host_port(hostport, default_port=None):
lis = hostport.split(":", 1)
host = lis[0]
if len(lis) == 2:
try:
port = int(lis[1])
except ValueError:
print "Error: Erroneous port."
sys.exit(1)
else:
if default_port is None:
print "Error: Port required in %s." % hostport
sys.exit(1)
port = default_port
return host, port
class Bot(SingleServerIRCBot):
def __init__(self, config):
ircaddr = parse_host_port(config.get('main', 'host'), 6667)
self.channel = config.get('main', 'channel')
self.nickname = config.get('main', 'nickname')
try:
self.nickpass = config.get('main', 'nickpass')
except ConfigParser.NoOptionError:
self.nickpass = None
try:
self.needinvite = (config.get('main', 'needinvite') == 'yes')
except ConfigParser.NoOptionError:
self.needinvite = False
SingleServerIRCBot.__init__(self, [ircaddr], self.nickname, self.nickname, 5)
self.queue = OutputManager(self.connection, .9)
self.queue.start()
self.handlers = {}
def handler_for_key(self, key):
return lambda c, e: self.execute_handlers(key, c, e)
for handler in (logbot.Logbot(config, self.queue),
beanbot.Beanbot(config, self.queue),
decisionbot.Decisionbot(config, self.queue)):
for props in handler.__dict__, handler.__class__.__dict__:
for key in props.iterkeys():
if not key.startswith('on_'):
continue
value = getattr(handler, key)
if not hasattr(value, '__call__'):
continue
if not key in self.handlers:
# Set up handling for this message
self.handlers[key] = []
if hasattr(self, key):
self.handlers[key].append(getattr(self, key))
setattr(self, key, handler_for_key(self, key))
# Add new handler for this message
self.handlers[key].append(value)
try:
self.start()
except KeyboardInterrupt:
self.connection.quit("Ctrl-C at console")
except Exception, e:
self.connection.quit("%s: %s" % (e.__class__.__name__, e.args))
raise
def execute_handlers(self, key, c, e):
for handler in self.handlers[key]:
handler(c, e)
def do_join(self, c):
if self.needinvite:
c.privmsg("chanserv", "invite %s" % self.channel)
c.join(self.channel)
def on_nicknameinuse(self, c, e):
c.nick(c.get_nickname() + "_")
def on_quit(self, c, e):
source = irclib.nm_to_n(e.source())
if source == self.nickname:
# Our desired nick just quit - take the nick back
c.nick(self.nickname)
self.do_join(c)
def on_welcome(self, c, e):
if self.nickpass and c.get_nickname() != self.nickname:
# Reclaim our desired nickname
c.privmsg('nickserv', 'ghost %s %s' % (self.nickname, self.nickpass))
else:
# Identify ourselves before joining the channel
c.privmsg("nickserv", "identify %s" % self.nickpass)
self.do_join(c)
def on_privmsg(self, c, e):
c.privmsg(irclib.nm_to_n(e.source()), HELP_MESSAGE)
def usage(exitcode=1):
print "Usage: %s <config-file>" % sys.argv[0]
sys.exit(exitcode)
def main():
if len(sys.argv) < 2:
usage()
configfile = sys.argv[1]
config = ConfigParser.ConfigParser()
config.read(configfile)
Bot(config)
if __name__ == "__main__":
main()