Initial import to Tizen
[profile/ivi/python-twisted.git] / doc / words / examples / ircLogBot.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4
5 """
6 An example IRC log bot - logs a channel's events to a file.
7
8 If someone says the bot's name in the channel followed by a ':',
9 e.g.
10
11   <foo> logbot: hello!
12
13 the bot will reply:
14
15   <logbot> foo: I am a log bot
16
17 Run this script with two arguments, the channel name the bot should
18 connect to, and file to log to, e.g.:
19
20   $ python ircLogBot.py test test.log
21
22 will log channel #test to the file 'test.log'.
23 """
24
25
26 # twisted imports
27 from twisted.words.protocols import irc
28 from twisted.internet import reactor, protocol
29 from twisted.python import log
30
31 # system imports
32 import time, sys
33
34
35 class MessageLogger:
36     """
37     An independent logger class (because separation of application
38     and protocol logic is a good thing).
39     """
40     def __init__(self, file):
41         self.file = file
42
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))
47         self.file.flush()
48
49     def close(self):
50         self.file.close()
51
52
53 class LogBot(irc.IRCClient):
54     """A logging IRC bot."""
55     
56     nickname = "twistedbot"
57     
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())))
63
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())))
68         self.logger.close()
69
70
71     # callbacks for events
72
73     def signedOn(self):
74         """Called when bot has succesfully signed on to server."""
75         self.join(self.factory.channel)
76
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)
80
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))
85         
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."
89             self.msg(user, msg)
90             return
91
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))
97
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))
102
103     # irc callbacks
104
105     def irc_NICK(self, prefix, params):
106         """Called when an IRC user changes their nickname."""
107         old_nick = prefix.split('!')[0]
108         new_nick = params[0]
109         self.logger.log("%s is now known as %s" % (old_nick, new_nick))
110
111
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):
115         """
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.
118         """
119         return nickname + '^'
120
121
122
123 class LogBotFactory(protocol.ClientFactory):
124     """A factory for LogBots.
125
126     A new protocol instance will be created each time we connect to the server.
127     """
128
129     def __init__(self, channel, filename):
130         self.channel = channel
131         self.filename = filename
132
133     def buildProtocol(self, addr):
134         p = LogBot()
135         p.factory = self
136         return p
137
138     def clientConnectionLost(self, connector, reason):
139         """If we get disconnected, reconnect to server."""
140         connector.connect()
141
142     def clientConnectionFailed(self, connector, reason):
143         print "connection failed:", reason
144         reactor.stop()
145
146
147 if __name__ == '__main__':
148     # initialize logging
149     log.startLogging(sys.stdout)
150     
151     # create factory protocol and application
152     f = LogBotFactory(sys.argv[1], sys.argv[2])
153
154     # connect factory to this host and port
155     reactor.connectTCP("irc.freenode.net", 6667, f)
156
157     # run bot
158     reactor.run()