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

Source Code for Module gozerbot.jabberbot

  1  # gozerbot/jabberbot.py 
  2  # 
  3  # 
  4   
  5  """ jabber bot definition """ 
  6   
  7  __copyright__ = 'this file is in the public domain' 
  8  __revision__ = '$Id: bot.py 75 2005-09-12 16:33:00Z bart $' 
  9   
 10  from gozerbot.users import users 
 11  from gozerbot.monitor import jabbermonitor 
 12  from gozerbot.wait import Jabberwait, Jabbererrorwait 
 13  from gozerbot.generic import rlog, handle_exception, lockdec, waitforqueue, \ 
 14  toenc, fromenc, jabberstrip 
 15  from gozerbot.config import config 
 16  from gozerbot.plugins import plugins 
 17  from gozerbot.jabbermsg import Jabbermsg 
 18  from gozerbot.jabberpresence import Jabberpresence 
 19  from gozerbot.pdod import Pdod 
 20  from gozerbot.dol import Dol 
 21  from gozerbot.datadir import datadir 
 22  from gozerbot.channels import Channels 
 23  from gozerbot.less import Less 
 24  from gozerbot.ignore import shouldignore 
 25  from gozerbot.callbacks import jcallbacks 
 26  from gozerbot.thr import start_new_thread 
 27  from gozerbot.fleet import fleet 
 28  from gozerbot.botbase import BotBase 
 29  from xmpp.simplexml import Node 
 30  import xmpp, time, Queue, os, threading, thread, types, xml 
 31   
 32  jabberoutlock = thread.allocate_lock() 
 33  jabberinlock = thread.allocate_lock() 
 34  outlocked = lockdec(jabberoutlock) 
 35  inlocked = lockdec(jabberinlock) 
36 37 -class Jabberbot(BotBase):
38 39 """ jabber bot class """ 40
41 - def __init__(self, name='jabbermain', owner=[]):
42 BotBase.__init__(self, name, owner) 43 self.type = 'jabber' 44 self.outqueue = Queue.Queue() 45 self.host = None 46 self.user = None 47 self.sock = None 48 self.jid = None 49 self.username = None 50 self.me = None 51 self.server = None 52 self.lastin = None 53 self.test = 0 54 self.connecttime = 0 55 self.connection = None 56 self.privwait = Jabberwait() 57 self.errorwait = Jabbererrorwait() 58 self.jabber = True 59 self.connectok = threading.Event() 60 self.jids = {} 61 self.topics = {} 62 self.timejoined = {} 63 if not self.state.has_key('ratelimit'): 64 self.state['ratelimit'] = 0.05
65
66 - def _resumedata(self): # stateful reboot request, just shutdown
67 self.exit() 68 return {self.name: [self.host, self.user, self.password, self.port]}
69
70 - def _doprocess(self):
71 """ process loop """ 72 while not self.stopped: 73 try: 74 time.sleep(0.001) 75 res = self.connection.Process() 76 if res: 77 self.lastin = time.time() 78 except xmpp.StreamError, ex: 79 if u'Disconnected' in str(ex): 80 rlog(10, self.name, str(ex)) 81 self.reconnect() 82 except xml.parsers.expat.ExpatError, ex: 83 if u'not well-formed' in str(ex): 84 rlog(10, self.name, str(ex)) 85 continue 86 except Exception, ex: 87 if not self.stopped: 88 handle_exception() 89 time.sleep(2) 90 else: 91 return
92
93 - def _outputloop(self):
94 rlog(10, self.name, 'starting outputloop') 95 while not self.stopped: 96 what = self.outqueue.get() 97 if self.stopped or what == None: 98 break 99 self.rawsend(what) 100 sleeptime = config['jabberoutsleep'] 101 if sleeptime: 102 time.sleep(sleeptime) 103 else: 104 time.sleep(0.1) 105 rlog(10, self.name, 'stopping outputloop')
106
107 - def _keepalive(self):
108 """ keepalive method .. send empty string to self every 3 minutes """ 109 nrsec = 0 110 while not self.stopped: 111 time.sleep(1) 112 nrsec += 1 113 if nrsec < 180: 114 continue 115 else: 116 nrsec = 0 117 self.say(self.me, "")
118
119 - def _keepchannelsalive(self):
120 """ channels keep alive method """ 121 nrsec = 0 122 while not self.stopped: 123 time.sleep(1) 124 nrsec += 1 125 if nrsec < 600: 126 continue 127 for i in self.state['joinedchannels']: 128 self.say(i, "")
129
130 - def _connect(self, host, user, password, port=5222):
131 """ connect to server .. start read loop """ 132 self.host = host 133 self.port = port 134 self.user = user 135 self.password = password 136 if not '@' in user: 137 rlog(100, self.name, 'user needs to be in username@host format') 138 return 139 self.username = user.split('@')[0] 140 self.me = user 141 self.jid = xmpp.JID(user) 142 self.server = self.jid.getDomain() 143 self.nick = self.username 144 self.password = password 145 rlog(10, self.name, 'connecting to %s' % self.host) 146 #self.connection = xmpp.Client(self.server, debug=['always', 'nodebuilder']) 147 self.connection = xmpp.Client(self.server, debug=[]) 148 try: 149 self.connection.connect((self.host, self.port)) 150 except AttributeError: 151 rlog(10, self.name, "can't connect to %s" % self.host) 152 return 153 if not self.connection: 154 rlog(10, self.name, "can't connect to %s" % self.host) 155 return 156 rlog(10, self.name, 'doing auth') 157 auth = self.connection.auth(self.username, self.password, \ 158 'gozerbot') 159 if not auth: 160 rlog(10, self.name, 'auth for %s failed .. trying register' \ 161 % self.username) 162 info = {'username': self.username, 'password': self.password} 163 xmpp.features.getRegInfo(self.connection, self.host, info) 164 if not xmpp.features.register(self.connection, self.host, info): 165 rlog(100, self.name, "can't register") 166 return 167 else: 168 self.connection = xmpp.Client(self.server, debug=[]) 169 self.connection.connect((self.host, self.port)) 170 auth = self.connection.auth(self.username, self.password, \ 171 'gozerbot') 172 rlog(100, self.name, "register succeded") 173 self.connecttime = time.time() 174 rlog(100, self.name, 'connected! type: %s' % \ 175 self.connection.connected) 176 self.connection.RegisterHandler('message', self.messageHandler) 177 self.connection.RegisterHandler('presence', self.presenceHandler) 178 self.connection.RegisterHandler('iq', self.iqHandler) 179 self.connection.UnregisterDisconnectHandler(\ 180 self.connection.DisconnectHandler) 181 self.connection.RegisterDisconnectHandler(self.disconnectHandler) 182 self.connection.UnregisterHandlerOnce = self.UnregisterHandlerOnce 183 self.stopped = 0 184 jabbermonitor.start() 185 start_new_thread(self._doprocess, ()) 186 start_new_thread(self._keepalive, ()) 187 start_new_thread(self._outputloop, ()) 188 #start_new_thread(self._keepchannelsalive, ()) 189 self.connection.sendInitPresence() 190 self.connection.getRoster() 191 self.connectok.set() 192 return 1
193
194 - def connect(self, host, user, password, port=5222, ipv6=None, ssl=None, \ 195 reconnect=True):
196 # ipv6 and ssl arguments are not used but are here for compat with irc 197 res = 0 198 try: 199 res = self._connect(host, user, password, port) 200 #except AttributeError: 201 # rlog(10, self.name, "%s denied the connection" % self.host) 202 # return 203 except Exception, ex: 204 if self.stopped: 205 return 0 206 rlog(10, self.name, str(ex)) 207 #handle_exception() 208 if reconnect: 209 return self.reconnect() 210 if res and not fleet.byname(self.name): 211 fleet.addbot(self) 212 return res
213
214 - def joinchannels(self):
215 """ join channels """ 216 time.sleep(5) 217 for i in self.state['joinedchannels']: 218 key = self.channels.getkey(i) 219 nick = self.channels.getnick(i) 220 result = self.join(i, key, nick) 221 if result == 1: 222 rlog(10, self.name, 'joined %s' % i) 223 else: 224 rlog(10, self.name, 'failed to join %s: %s' % (i, result))
225 226
227 - def broadcast(self, txt):
228 for i in self.state['joinedchannels']: 229 self.say(i, txt)
230
231 - def sendpresence(self, to):
232 """ send presence """ 233 presence = xmpp.Presence(to=to) 234 presence.setFrom(self.me) 235 self.send(presence)
236 237
238 - def iqHandler(self, conn, node):
239 """ handle iq stanza's """ 240 rlog(2, self.name + '-Iq', str(node)) 241 node.cmnd = 'Iq' 242 node.conn = conn 243 jcallbacks.check(self, node)
244
245 - def messageHandler(self, conn, msg):
246 """ message handler """ 247 if self.test: 248 return 249 if 'jabber:x:delay' in str(msg): 250 return 251 m = Jabbermsg(msg) 252 m.toirc(self) 253 if m.groupchat and m.getSubject(): 254 self.topiccheck(m) 255 return 256 if self.privwait.check(m): 257 return 258 if not m.txt: 259 return 260 if self.me in m.userhost: 261 return 0 262 if m.groupchat and self.nick == m.resource: 263 return 0 264 go = 1 265 try: 266 cc = self.channels[m.channel]['cc'] 267 except (TypeError, KeyError): 268 cc = config['defaultcc'] or '!' 269 try: 270 channick = self.channels[m.channel]['nick'] 271 except (TypeError, KeyError): 272 channick = self.nick 273 if m.groupchat and not m.txt[0] in cc: 274 go = 0 275 if m.txt.startswith("%s: " % channick): 276 m.txt = m.txt.replace("%s: " % channick, "") 277 go = 1 278 elif m.txt.startswith("%s, " % channick): 279 m.txt = m.txt.replace("%s, " % channick, "") 280 go = 1 281 if m.txt[0] in cc: 282 m.txt = m.txt[1:] 283 if go and not 'dojcoll' in str(m.id): 284 try: 285