1
2
3
4
5 """ generic functions """
6
7 __copyright__ = 'this file is in the public domain'
8
9 from gozerbot.datadir import datadir
10 from gozerbot.config import config
11 from stat import ST_UID, ST_MODE, S_IMODE
12 from subprocess import Popen, PIPE
13 import time, sys, re, traceback, Queue, urllib, urllib2, urlparse, socket
14 import random, os, sgmllib, thread, types, calendar, httplib, string, StringIO
15 import glob, htmlentitydefs, tempfile, pickle, getopt, cgi
16
17 debuglog = False
18
20 removed = []
21 try:
22 files = os.listdir('myplugs')
23 for file in files:
24 if file.endswith('.pyc'):
25 os.unlink('myplugs' + os.sep + file)
26 removed.append(file)
27 except:
28 pass
29 try:
30 files = os.listdir('gozerplugs/plugs')
31 for file in files:
32 if file.endswith('.pyc'):
33 os.unlink('gozerplugs/plugs' + os.sep + file)
34 removed.append(file)
35 except:
36 pass
37 rlog(10, 'generic', 'cleaned %s .pyc files' % len(removed))
38 return removed
39
41 version = config['version']
42 rev = gethgrev()
43 if rev:
44 version += " HG revision %s" % rev
45 else:
46 rev = getsvnrev()
47 if rev:
48 version += " SVN revision %s" % rev
49 return version
50
52 """ get mercurial revision """
53 rev = None
54 try:
55 proces = gozerpopen(['hg', 'tip'])
56 rev = int(proces.fromchild.readlines()[0].split(':')[1].strip())
57 proces.close()
58 except Exception, ex:
59 pass
60 return rev
61
63 """ get subversion revision """
64 rev = None
65 try:
66 proces = gozerpopen(['svn', 'info'])
67 lines = proces.fromchild.readlines()
68 proces.close()
69 for line in lines:
70 if line.startswith('Revision'):
71 rev = int(line.split()[1])
72 except Exception, ex:
73 pass
74 return rev
75
76 try:
77 import chardet
78 except ImportError:
79 chardet = None
80
81
82 exceptionlist = []
83
84
85 hostnamere = re.compile('^[\w\.]+$')
86
87 logging_enabled = False
88 logfile = None
89
91 options = dict(options)
92 try:
93 optargs = ""
94 optlist = []
95 if not options.has_key('--filter'):
96 options['--filter'] = ""
97 if not options.has_key('--speed'):
98 options['--speed'] = str(ievent.speed)
99 for i,j in options.iteritems():
100 if '--' in i:
101 optlist.append("%s=" % i[2:])
102 if j:
103 optlist.append(j)
104 continue
105 if '-' in i:
106 if j:
107 optargs += ":%s" % i[1:]
108 else:
109 optargs += i[1:]
110 args = ievent.txt.split()
111 try:
112 (opts, rest) = getopt.getopt(args[1:], optargs, optlist)
113 except getopt.GetoptError, ex:
114 return 0
115 if opts:
116 for item in opts:
117 ievent.optionset.append(item[0])
118 o = dict(options)
119 o.update(dict(opts))
120 try:
121 filter = o['--filter']
122 ievent.filter.append(filter)
123 except KeyError:
124 pass
125 try:
126 speed = o['--speed']
127 ievent.speed = int(speed)
128 except KeyError:
129 pass
130 ievent.options = o
131 ievent.txt = args[0] + ' ' + ' '.join(rest)
132 makeargrest(ievent)
133 except Exception, ex:
134 handle_exception()
135 return 0
136 return 1
137
139 """ create ievent.args and ievent.rest .. this is needed because \
140 ircevents might be created outside the parse() function """
141 try:
142 ievent.args = ievent.txt.split()[1:]
143 except ValueError:
144 ievent.args = []
145 try:
146 cmnd, ievent.rest = ievent.txt.split(' ', 1)
147 except ValueError:
148 ievent.rest = ""
149 ievent.command = ievent.txt.split(' ')[0]
150
155
156 if config.has_key('logfile'):
158 """ open log file """
159 try:
160 f = open(fname, mode)
161 except IOError, e:
162 sys.stderr.write("[%s] (%s) %s" % \
163 (time.strftime("%H:%M:%S"), "logfile", str(e)))
164 return None
165 else:
166 return f
167 fname = os.path.join(datadir, config['logfile'])
168 logfile = openlogfile(fname)
169
170
172 import sys
173 reload(sys)
174 sys.setdefaultencoding(encoding)
175
178
180 """ return control char of bot/ievent's channel """
181 try:
182 cchar = bot.channels[ievent.channel]['cc']
183 except LookupError:
184 cchar = config['defaultcc'] or '!'
185 except TypeError:
186 cchar = config['defaultcc'] or '!'
187 return cchar
188
190 """ split text into <l> char portions """
191 txtlist = []
192 start = 0
193 end = l
194 length = len(what)
195 for i in range(length/end+1):
196 endword = what.find(' ', end)
197 if endword == -1:
198 endword = length
199 res = what[start:endword]
200 if res:
201 txtlist.append(res)
202 start = endword
203 end = start + l
204 return txtlist
205
207 """ adjustable string object """
208 pass
209
211 """ return locking descriptor locking on the provided lock """
212 def locked(func):
213 """ lock function func """
214 def lockedfunc(*args, **kwargs):
215 """ the locked function """
216 if lock.locked():
217 rlog(-1, 'generic', 'locking on %s .. %s' % (str(func), \
218 str(args)))
219 lock.acquire()
220 res = None
221 try:
222 res = func(*args, **kwargs)
223 finally:
224 lock.release()
225 return res
226 return lockedfunc
227 return locked
228
229
230 popenlock = thread.allocate_lock()
231 popenlocked = lockdec(popenlock)
232
234
235 """ exception to be raised if popen arguments contain options """
236
238 Exception.__init__(self)
239 self.item = item
240
243
245
246 """ exception to tbe raised if popen argument is not a list """
247
249 Exception.__init__(self)
250 self.item = item
251
253 return str(self.item)
254
257 return self.read().split('\n')
258
260
261 """ class providing a close method to subprocess """
262
264 Popen.__init__(self, args, shell=False, stdin=PIPE, stdout=PIPE, \
265 stderr=PIPE, close_fds=True)
266 self.fromchild = self.stdout
267 self.tochild = self.stdin
268 self.errors = self.stderr
269
271 self.wait()
272 try:
273 self.stdin.close()
274 except:
275 pass
276 try:
277 self.stdout.close()
278 except:
279 pass
280 try:
281 self.errors.close()
282 except:
283 pass
284 return self.returncode
285
286
288 """ function to use to run a subprocess .. enforces list argument and checks
289 for options passed
290 """
291 if type(args) != types.ListType:
292 raise PopenListError(args)
293 if type(userargs) != types.ListType:
294 raise PopenListError(args)
295 for i in userargs:
296 if i.startswith('-'):
297 raise PopenWhitelistError(i)
298 proces = Gozerpopen4(args + userargs)
299 return proces
300
302 """ stop the bot """
303 rlog(10, 'generic', 'sending kill signal')
304 os.kill(os.getpid(), 9)
305
307 """ reboot the bot """
308 os.execl(sys.argv[0], *sys.argv)
309
311 """ reboot the bot, but keep the connections """
312 config.reload()
313 session = {'bots': {}, 'name': bot.name, 'channel': ievent.channel, \
314 'partyline': []}
315 for i in fleet.bots:
316 session['bots'].update(i._resumedata())
317 session['partyline'] = partyline._resumedata()
318 sessionfile = tempfile.mkstemp('-session', 'gozerbot-')[1]
319 pickle.dump(session, open(sessionfile, 'w'))
320 fleet.save()
321 os.execl(sys.argv[0], sys.argv[0], '-r', sessionfile)
322
324 """ return plugin from which function is called """
325 try:
326 plugname = frame.f_back.f_code.co_filename
327 name = plugname.split(os.sep)[-1][:-3]
328 if name == '__init__':
329
330 name =