-
Notifications
You must be signed in to change notification settings - Fork 0
/
IrcBot.py
146 lines (104 loc) · 4.06 KB
/
IrcBot.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
from __future__ import with_statement
import shelve
import sys
import time
from contextlib import closing
VERSION_NUM = "1.1"
sys.path.append(".")
from twisted.internet import protocol, reactor
from twisted.words.protocols import irc
import ChannelBot
import ConfigParser
from MicroBlogSearch import TwitterSearch, IdentiSearch
from ConfigMgr import BotConfig
def log(msg):
print "[%s] %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())), msg)
class ChannelNameError(Exception):
pass
class LogBot(irc.IRCClient):
version = "micro-bot"
versionNum = VERSION_NUM
realname = "http://github.com/CaptSolo/micro-bot"
lineRate = 6
# def _reallySendLine(self, line):
# print "[%s] %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())), line)
# irc.IRCClient._reallySendLine(self, line)
def _get_nickname(self):
return self.factory.cfg.param("nick")
nickname = property(_get_nickname)
def connectionMade(self):
# connectionMade is called first, before signedOn()
# Initialize instance variables
self._channels = {}
irc.IRCClient.connectionMade(self)
def signedOn(self):
for sect, chan in self.factory.cfg.channel_list("load"):
if chan not in self._channels:
try:
self._channels[chan] = ChannelBot.ChannelBot(self, self.factory, sect)
self.join(chan)
except ChannelBot.ChannelConfigError, e:
print "config error in section [%s]." % (sect,), self._channels
print " >>>", e
pass
else:
# Trying to join the same channe twice
raise ChannelNameError("section [%s]: trying to join same channel %s twice." % (sect, chan))
# IRCClient needs better rate control. still getting "Excess Flood" even w. lineRate=2 sec.
# self.lineRate = 5
# join all channels on the list - XXX
# (must have got a list of channels)
def joined(self, channel):
if channel in self._channels:
# ??? do we need to supply channel at all then ???
self._channels[channel].onJoined(channel)
else:
raise ChannelNameError("joined() a channel that bot was not instructed to join: %s" % (channel, ))
class LogBotFactory(protocol.ClientFactory):
protocol = LogBot
def __init__(self, cfg, memory):
self.cfg = cfg
self.memory = memory
self._check_config()
def _check_config(self):
try:
server = self.cfg.param("server")
nick = self.cfg.param("nick")
except ConfigParser.NoOptionError, e:
print "\nMandatory config parameter not found:\n %s\n" % (str(e),)
if reactor.running:
reactor.stop()
else:
sys.exit(-1)
def clientConnectionLost(self, connector, reason):
print "Lost connection (%s), reconnecting." % (reason,)
connector.connect()
def clientConnectionFailed(self, connector, reason):
print "Could not connect: %s" % (reason,)
reactor.stop()
def main(config_file):
_cfg = BotConfig(open(config_file), "irc-bot")
server = _cfg.param("server")
port = 6667
# A file to remember working info in (e.g. IDs of last messages retrieved)
MEMORY_FILE = "IrcBot.mem"
with closing(shelve.open(MEMORY_FILE, writeback=True)) as _memory:
# create factory protocol and application
f = LogBotFactory(_cfg, _memory)
from twisted.protocols.policies import TrafficLoggingFactory
f = TrafficLoggingFactory(f, "irc")
# connect factory to this host and port
reactor.connectTCP(server, port, f)
# run bot
reactor.run()
if __name__ == '__main__':
try:
config_file = sys.argv[1]
except IndexError:
print """Usage: %s config-file
For example:
1) Copy config.sample to config
2) Run "python IrcBot.py config"
""" % (sys.argv[0],)
sys.exit(-1)
main(config_file)