4
# http://www.irchelp.org/irchelp/rfc/rfc2812.txt
6
""" an ircevent is extracted from the IRC string received from the server. """
8
__copyright__ = 'this file is in the public domain'
11
from gozerbot.utils.log import rlog
12
from gozerbot.utils.generic import fix_format, toenc, fromenc, stripident
13
from gozerbot.eventbase import EventBase, makeargrest
14
from gozerbot.stats import stats
15
from gozerbot.config import config
18
import time, re, types, copy
23
dotchars = config['dotchars']
29
def makeargrest(ievent):
31
""" create ievent.args and ievent.rest .. this is needed because \
32
ircevents might be created outside the parse() function.
36
ievent.args = ievent.txt.split()[1:]
41
cmnd, ievent.rest = ievent.txt.split(' ', 1)
45
ievent.command = ievent.txt.split(' ')[0]
47
class Ircevent(EventBase):
49
""" represents an IRC event. """
54
def __deepcopy__(self, bla):
60
def parse(self, bot, rawstr):
62
""" parse raw string into ircevent. """
65
stats.up('events', bot.name)
67
rawstr = rawstr.rstrip()
68
splitted = re.split('\s+', rawstr)
70
# check if there is a prefix (: in front)
71
if not rawstr[0] == ':':
72
# no prefix .. 1st word is command
73
splitted.insert(0, ":none!none@none")
74
rawstr = ":none!none@none " + rawstr
76
self.prefix = splitted[0][1:]
79
nickuser = self.prefix.split('!')
80
if len(nickuser) == 2:
81
self.nick = nickuser[0]
82
stats.up('events', self.nick)
83
if self.bot.cfg['stripident'] or config['stripident']:
84
self.userhost = stripident(nickuser[1])
86
self.userhost = nickuser[1]
89
self.cmnd = splitted[1]
90
self.cbtype = self.cmnd
91
stats.up('events', self.cmnd)
93
# split string based of postfix count .. nr of items ater the command
94
if pfc.has_key(self.cmnd):
95
self.arguments = splitted[2:pfc[self.cmnd]+2]
96
txtsplit = re.split('\s+', rawstr, pfc[self.cmnd]+2)
97
self.txt = txtsplit[-1]
99
self.arguments = splitted[2:]
101
# 1st argument is target
103
self.target = self.arguments[0]
104
self.postfix = ' '.join(self.arguments)
106
# check if target is text
107
if self.target and self.target.startswith(':'):
108
self.txt = ' '.join(self.arguments)
110
# strip strarting ':' from txt
112
if self.txt[0] == ":":
113
self.txt = self.txt[1:]
114
rlog(0, 'ircevent',"%s %s %s" % (self.cmnd, self.arguments, self.txt))
116
# set ircevent attributes
117
if self.cmnd == 'PING':
119
if self.cmnd == 'PRIVMSG':
120
self.channel = self.arguments[0]
121
if '\001' in self.txt:
123
elif self.cmnd == 'JOIN' or self.cmnd == 'PART':
125
self.channel = self.arguments[0]
127
self.channel = self.txt
128
elif self.cmnd == 'MODE':
129
self.channel = self.arguments[0]
130
elif self.cmnd == 'TOPIC':
131
self.channel = self.arguments[0]
132
elif self.cmnd == 'KICK':
133
self.channel = self.arguments[0]
134
elif self.cmnd == '353':
135
self.channel = self.arguments[2]
136
elif self.cmnd == '324':
137
self.channel = self.arguments[1]
139
# userhost before possible stripident
140
self.ruserhost = self.userhost
141
# jabber compat .. this is userhost on irc
142
self.stripped = self.userhost
144
self.user = stripident(self.userhost).split('@')[0]
146
self.origtxt = self.txt
147
self.channel = self.channel.strip()
148
stats.up('events', self.channel)
149
self.origchannel = self.channel
150
rlog(-1, 'ircevent', self)
156
rlog(10, bot.name + '.error', '%s: %s %s' % (self.cmnd, \
157
self.arguments, self.txt))
163
def reply(self, txt, result=None, nick=None, dot=False, nritems=False, nr=False, fromm=None, private=False, how=''):
165
# don't replu is result is empty list
170
stats.up('events', 'replies')
173
how = self.options['--how']
181
# make reply if result is a dict
182
if type(result) == types.DictType:
183
for i, j in result.iteritems():
184
if type(j) == types.ListType:
191
res = "%s: %s" % (i, z)
194
restxt += "%s%s" % (res, dotchars)
196
restxt += "%s %s" % (dot or ' ', res)
201
restxt = restxt[:-len(dot)]
203
lt = False # set if result is list
205
# set vars if result is a list
206
if type(txt) == types.ListType and not result:
216
# if queues are set write output to them
218
for i in self.queues:
220
for item in splitted:
232
# check if bot is set in event
234
rlog(10, 'event', 'no bot defined in event')
239
if lt and not restxt:
242
# check if there are list in list
244
if type(i) == types.ListType or type(i) == types.TupleType:
246
res.append(dotchars.join(i))
252
# if nritems is set ..
256
pretxt += "(%s items) .. " % len(result)
259
# prepend item number for results
268
txtlist2.append(u"%s) %s" % (teller, i))
272
# convert results to encoding
275
txtl.append(toenc(item))
278
# join result with dot
280
restxt = dotchars.join(txtlist)
282
restxt = dot.join(txtlist)
284
restxt = ' '.join(txtlist)
286
# see if txt needs to be prepended
289
restxt = pretxt + restxt
291
rlog(10, 'eventbase', "can't add %s and %s" % (str(pretxt), str(restxt)))
293
# if txt in result is filtered ignore the reuslt
294
if self.filtered(restxt):
297
# if event is DCC based write result directly to socket
298
if self.cmnd == 'DCC' and self.sock:
299
self.bot.say(self.sock, restxt, speed=self.speed, how=how)
302
# if nick is set write result to nick in question
304
self.bot.say(nick, restxt, fromm=nick, speed=self.speed, how=how)
307
# if originatiog event is a private message or private flaf is set
308
if self.msg or private:
309
self.bot.say(self.nick, restxt, fromm=self.nick, speed=self.speed, how=how)
312
# check if bot is in silent mode .. if so use /msg
314
channel = self.printto or self.channel
316
silent = self.bot.channels[channel]['silent']
317
except (KeyError, TypeError):
319
fromm = fromm or self.nick
321
# check if notice needs to be used
325
notice = self.bot.channels[channel]['notice']
326
except (KeyError, TypeError):
329
self.bot.say(self.nick, restxt, how='notice', fromm=fromm, speed=self.speed)
331
self.bot.say(self.nick, restxt, fromm=fromm, speed=self.speed, how=how)
334
# if printto is set used that as the target
336
self.bot.say(self.printto, restxt, fromm=fromm, speed=self.speed, how=how)
339
self.bot.say(self.channel, restxt, fromm=fromm, speed=self.speed, how=how)
342
# postfix count aka how many arguments
483
# default event used to initialise events
484
defaultevent = EventBase()