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'
10
from gozerbot.generic import rlog, stripident, fix_format, fromenc
11
import time, re, types, copy
15
def makeargrest(ievent):
16
""" create ievent.args and ievent.rest .. this is needed because \
17
ircevents might be created outside the parse() function """
19
ievent.args = ievent.txt.split()[1:]
23
cmnd, ievent.rest = ievent.txt.split(' ', 1)
26
ievent.command = ievent.txt.split(' ')[0]
28
class Ircevent(object):
30
""" represents an IRC event """
32
def __init__(self, ievent=None):
34
self.groupchat = False
52
self.time = time.time()
74
def copyin(self, ievent):
76
self.cmnd = cpy(ievent.cmnd)
77
self.prefix = cpy(ievent.prefix)
78
self.postfix = cpy(ievent.postfix)
79
self.target = cpy(ievent.target)
80
self.arguments = list(ievent.arguments)
81
self.nick = cpy(ievent.nick)
82
self.user = cpy(ievent.user)
83
self.ruserhost = cpy(ievent.ruserhost)
84
self.userhost = cpy(ievent.userhost)
85
self.stripped = cpy(ievent.stripped)
86
self.resource = cpy(ievent.resource)
87
self.channel = cpy(ievent.channel)
88
self.origtxt = cpy(ievent.origtxt)
89
self.txt = cpy(ievent.txt)
90
self.command = cpy(ievent.command)
91
self.alias = cpy(ievent.alias)
92
self.aliased = cpy(ievent.aliased)
93
self.time = ievent.time
94
self.msg = cpy(ievent.msg)
95
self.args = list(ievent.args)
96
self.rest = cpy(ievent.rest)
97
self.usercmnd = cpy(ievent.usercmnd)
99
self.sock = ievent.sock
100
self.printto = ievent.printto
101
self.speed = int(ievent.speed)
102
self.inqueue = ievent.inqueue
103
self.queues = list(ievent.queues)
104
self.cc = cpy(ievent.cc)
105
self.jid = ievent.jid
106
self.jidchange = ievent.jidchange
107
self.conn = ievent.conn
109
self.denied = ievent.denied
110
self.options = dict(ievent.options)
113
return "cmnd=%s prefix=%s postfix=%s arguments=%s nick=%s user=%s \
114
userhost=%s channel=%s txt='%s' command=%s args=%s rest=%s speed=%s options=%s" % \
115
(self.cmnd, self.prefix, self.postfix, self.arguments, self.nick, self.user, \
116
self.userhost, self.channel, self.txt, self.command, self.args, self.rest, \
117
self.speed, self.options)
121
self.bot.gcevents += 1
123
def parse(self, bot, rawstr):
124
""" parse raw string into ircevent """
126
rawstr = rawstr.rstrip()
127
splitted = re.split('\s+', rawstr)
128
# check if there is a prefix (: in front)
129
if not rawstr[0] == ':':
130
# no prefix .. 1st word is command
131
splitted.insert(0, ":none!none@none")
132
rawstr = ":none!none@none " + rawstr
133
self.prefix = splitted[0][1:]
135
nickuser = self.prefix.split('!')
136
if len(nickuser) == 2:
137
self.nick = nickuser[0]
138
self.userhost = nickuser[1]
139
self.cmnd = splitted[1]
140
if pfc.has_key(self.cmnd):
141
self.arguments = splitted[2:pfc[self.cmnd]+2]
142
txtsplit = re.split('\s+', rawstr, pfc[self.cmnd]+2)
143
self.txt = txtsplit[-1]
145
self.arguments = splitted[2:]
146
# 1st argument is target
148
self.target = self.arguments[0]
149
self.postfix = ' '.join(self.arguments)
150
# check if target is text
151
if self.target and self.target.startswith(':'):
152
self.txt = ' '.join(self.arguments)
153
# strip strarting ':' from txt
155
if self.txt[0] == ":":
156
self.txt = self.txt[1:]
157
rlog(0, 'ircevent',"%s %s %s" % (self.cmnd, self.arguments, self.txt))
159
if self.cmnd == 'PRIVMSG':
160
self.channel = self.arguments[0]
161
elif self.cmnd == 'JOIN' or self.cmnd == 'PART':
163
self.channel = self.arguments[0]
165
self.channel = self.txt
166
elif self.cmnd == 'MODE':
167
self.channel = self.arguments[0]
168
elif self.cmnd == 'TOPIC':
169
self.channel = self.arguments[0]
170
elif self.cmnd == 'KICK':
171
self.channel = self.arguments[0]
172
elif self.cmnd == '353':
173
self.channel = self.arguments[2]
174
elif self.cmnd == '324':
175
self.channel = self.arguments[1]
176
self.channel = self.channel.lower()
178
# userhost before possible stripident
179
self.ruserhost = self.userhost
180
self.userhost = stripident(self.userhost)
181
# jabber compat .. this is userhost on irc
182
self.stripped = self.userhost
184
self.user = self.userhost.split('@')[0]
185
self.origtxt = self.txt
186
self.channel = self.channel.strip()
187
rlog(-1, 'ircevent', self)
191
rlog(10, bot.name + '.error', '%s: %s' % (self.cmnd, self.txt))
196
def reply(self, txt, result=None, nick=None, dot=False, nritems=False, \
198
""" reply txt .. first check if queue then if DCC then /msg
199
otherwise assume channel
204
if type(result) == types.DictType:
205
for i, j in result.iteritems():
206
if type(j) == types.ListType:
210
restxt += "[%s] %s %s " % (i, z, dot)
214
if type(txt) == types.ListType and not result:
223
for i in self.queues:
233
rlog(10, 'irc', 'no bot defined in ircevent')
236
if lt and not restxt:
239
if type(i) == types.ListType or type(i) == types.TupleType:
246
pretxt += "(%s items) .. " % len(result)
256
txtlist2.append(u"%s) %s" % (teller, i))
260
restxt = ' .. '.join(txtlist)
262
restxt = dot.join(txtlist)
264
restxt = ' '.join(txtlist)
266
restxt = pretxt + restxt
267
if self.cmnd == 'DCC' and self.sock:
268
self.bot.say(self.sock, restxt, speed=self.speed)
271
self.bot.say(nick, restxt, fromm=nick, speed=self.speed)
274
self.bot.say(self.nick, restxt, fromm=self.nick, speed=self.speed)
276
# check if bot is in silent mode .. if so use /msg
278
channel = self.printto or self.channel
280
silent = self.bot.channels[channel]['silent']
281
except (KeyError, TypeError):
284
self.bot.say(self.nick, restxt, fromm=self.nick, \
288
self.bot.say(self.printto, restxt, fromm=self.nick, \
292
self.bot.say(self.channel, restxt, fromm=self.nick, \
295
def missing(self, txt):
296
""" show what arguments are missing """
298
splitted = self.origtxt.split()
299
if self.bot.nick in splitted[0]:
304
elif 'cmnd' in splitted[0]:
316
cmnd = splitted[0][1:]
317
self.reply(cmnd + ' ' + txt)
319
self.reply('missing origtxt: %s' % txt)
321
# postfix count aka how many arguments