1
# Copyright (c) 2001-2009 Twisted Matrix Laboratories.
2
# See LICENSE for details.
6
An example IRC log bot - logs a channel's events to a file.
8
If someone says the bot's name in the channel followed by a ':',
15
<logbot> foo: I am a log bot
17
Run this script with two arguments, the channel name the bot should
18
connect to, and file to log to, e.g.:
20
$ python ircLogBot.py test test.log
22
will log channel #test to the file 'test.log'.
27
from twisted.words.protocols import irc
28
from twisted.internet import reactor, protocol
29
from twisted.python import log
37
An independent logger class (because separation of application
38
and protocol logic is a good thing).
40
def __init__(self, file):
43
def log(self, message):
44
"""Write a message to the file."""
45
timestamp = time.strftime("[%H:%M:%S]", time.localtime(time.time()))
46
self.file.write('%s %s\n' % (timestamp, message))
53
class LogBot(irc.IRCClient):
54
"""A logging IRC bot."""
56
nickname = "twistedbot"
58
def connectionMade(self):
59
irc.IRCClient.connectionMade(self)
60
self.logger = MessageLogger(open(self.factory.filename, "a"))
61
self.logger.log("[connected at %s]" %
62
time.asctime(time.localtime(time.time())))
64
def connectionLost(self, reason):
65
irc.IRCClient.connectionLost(self, reason)
66
self.logger.log("[disconnected at %s]" %
67
time.asctime(time.localtime(time.time())))
71
# callbacks for events
74
"""Called when bot has succesfully signed on to server."""
75
self.join(self.factory.channel)
77
def joined(self, channel):
78
"""This will get called when the bot joins the channel."""
79
self.logger.log("[I have joined %s]" % channel)
81
def privmsg(self, user, channel, msg):
82
"""This will get called when the bot receives a message."""
83
user = user.split('!', 1)[0]
84
self.logger.log("<%s> %s" % (user, msg))
86
# Check to see if they're sending me a private message
87
if channel == self.nickname:
88
msg = "It isn't nice to whisper! Play nice with the group."
92
# Otherwise check to see if it is a message directed at me
93
if msg.startswith(self.nickname + ":"):
94
msg = "%s: I am a log bot" % user
95
self.msg(channel, msg)
96
self.logger.log("<%s> %s" % (self.nickname, msg))
98
def action(self, user, channel, msg):
99
"""This will get called when the bot sees someone do an action."""
100
user = user.split('!', 1)[0]
101
self.logger.log("* %s %s" % (user, msg))
105
def irc_NICK(self, prefix, params):
106
"""Called when an IRC user changes their nickname."""
107
old_nick = prefix.split('!')[0]
109
self.logger.log("%s is now known as %s" % (old_nick, new_nick))
112
# For fun, override the method that determines how a nickname is changed on
113
# collisions. The default method appends an underscore.
114
def alterCollidedNick(self, nickname):
116
Generate an altered version of a nickname that caused a collision in an
117
effort to create an unused related name for subsequent registration.
119
return nickname + '^'
123
class LogBotFactory(protocol.ClientFactory):
124
"""A factory for LogBots.
126
A new protocol instance will be created each time we connect to the server.
129
# the class of the protocol to build when new connection is made
132
def __init__(self, channel, filename):
133
self.channel = channel
134
self.filename = filename
136
def clientConnectionLost(self, connector, reason):
137
"""If we get disconnected, reconnect to server."""
140
def clientConnectionFailed(self, connector, reason):
141
print "connection failed:", reason
145
if __name__ == '__main__':
147
log.startLogging(sys.stdout)
149
# create factory protocol and application
150
f = LogBotFactory(sys.argv[1], sys.argv[2])
152
# connect factory to this host and port
153
reactor.connectTCP("irc.freenode.net", 6667, f)