Package gozerbot :: Module generic
[hide private]
[frames] | no frames]

Source Code for Module gozerbot.generic

   1  # gozerbot/generic.py 
   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   
19 -def cleanpyc():
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
40 -def getversion():
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
51 -def gethgrev():
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
62 -def getsvnrev():
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 # list of exception handled by handle_exception 82 exceptionlist = [] 83 84 # RE to dectect if string is a hostname 85 hostnamere = re.compile('^[\w\.]+$') 86 87 logging_enabled = False 88 logfile = None 89
90 -def makeoptions(ievent, options={}):
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
138 -def makeargrest(ievent):
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
151 -def enable_logging():
152 """ enable logging """ 153 global logging_enabled 154 logging_enabled = True
155 156 if config.has_key('logfile'):
157 - def openlogfile(fname, mode="a+"):
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
171 -def setdefenc(encoding):
172 import sys 173 reload(sys) 174 sys.setdefaultencoding(encoding)
175
176 -def plugfile():
177 return datadir + os.sep + calledfrom(sys._getframe())
178
179 -def cchar(bot, ievent):
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
189 -def splittxt(what, l=375):
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
206 -class istr(str):
207 """ adjustable string object """ 208 pass 209
210 -def lockdec(lock):
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 # lock for popen 230 popenlock = thread.allocate_lock() 231 popenlocked = lockdec(popenlock) 232
233 -class PopenWhitelistError(Exception):
234 235 """ exception to be raised if popen arguments contain options """ 236
237 - def __init__(self, item):
238 Exception.__init__(self) 239 self.item = item
240
241 - def __str__(self):
242 return self.item
243
244 -class PopenListError(Exception):
245 246 """ exception to tbe raised if popen argument is not a list """ 247
248 - def __init__(self, item):
249 Exception.__init__(self) 250 self.item = item
251
252 - def __str__(self):
253 return str(self.item)
254
255 -class GozerStringIO(StringIO.StringIO):
256 - def readlines(self):
257 return self.read().split('\n')
258
259 -class Gozerpopen4(Popen):
260 261 """ class providing a close method to subprocess """ 262
263 - def __init__(self, args):
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
270 - def close(self):
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 #@popenlocked
287 -def gozerpopen(args, userargs=[]):
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
301 -def die():
302 """ stop the bot """ 303 rlog(10, 'generic', 'sending kill signal') 304 os.kill(os.getpid(), 9)
305
306 -def reboot():
307 """ reboot the bot """ 308 os.execl(sys.argv[0], *sys.argv)
309
310 -def reboot_stateful(bot, ievent, fleet, partyline):
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
323 -def calledfrom(frame):
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 # directory plugin 330 name =