/src/legacy/glue.py

http://pyaimt.googlecode.com/ · Python · 734 lines · 607 code · 93 blank · 34 comment · 160 complexity · 7dcc7267abeaa25073b7c7b6d5278aee MD5 · raw file

  1. # Copyright 2004-2006 Daniel Henninger <jadestorm@nc.rr.com>
  2. # Licensed for distribution under the GPL version 2, check COPYING for details
  3. import imgmanip
  4. import utils
  5. from twisted.words.xish.domish import Element
  6. from twisted.internet import protocol, reactor, defer, task
  7. from tlib import oscar
  8. from tlib import socks5, sockserror
  9. from twisted.python import log
  10. import groupchat
  11. import aimt
  12. import config
  13. from debug import LogEvent, INFO, WARN, ERROR
  14. import sys, warnings, pprint
  15. import lang
  16. import os.path
  17. import re
  18. import time
  19. import binascii
  20. import avatar
  21. import md5
  22. # The name of the transport
  23. name = "AIM Transport"
  24. # The transport's version
  25. version = "0.8a"
  26. # URL of the transport's web site
  27. url = "http://pyaim-t.blathersource.org"
  28. # This should be set to the identity of the gateway
  29. id = "aim"
  30. if not config.disableAvatars:
  31. # Load the default AIM and ICQ avatars
  32. f = open(os.path.join("data", "defaultAIMAvatar.png"))
  33. defaultAIMAvatarData = f.read()
  34. f.close()
  35. defaultAIMAvatar = avatar.AvatarCache().setAvatar(defaultAIMAvatarData)
  36. f = open(os.path.join("data", "defaultICQAvatar.png"))
  37. defaultICQAvatarData = f.read()
  38. f.close()
  39. defaultICQAvatar = avatar.AvatarCache().setAvatar(defaultICQAvatarData)
  40. defaultAvatar = defaultAIMAvatar
  41. defaultAvatarData = defaultAIMAvatarData
  42. else:
  43. defaultAvatar = None
  44. defaultAvatarData = None
  45. # This function should return true if the JID is a group JID, false otherwise
  46. def isGroupJID(jid):
  47. #if (jid[0] == "#" or jid[0] == "%"):
  48. if jid.find(config.confjid) > 0:
  49. return True
  50. else:
  51. return False
  52. # This function translates an AIM screen name to a JID
  53. def aim2jid(aimid):
  54. if aimid:
  55. retstr = aimid.lower().replace(' ', '')
  56. return retstr.replace('@', '%') + "@" + config.jid
  57. else:
  58. return config.jid
  59. # This function translates a JID to an AIM screen name
  60. def jid2aim(jid):
  61. return unicode(jid[:jid.find('@')].replace('%','@'))
  62. # This function translates an AIM chat room to a groupchat JID
  63. def aim2jidGroup(chatid, userid=None, exchange=None):
  64. retstr = chatid.replace(' ', '_')
  65. retstr = retstr.replace('@', '')
  66. if exchange:
  67. retstr = retstr + "%" + str(exchange)
  68. retstr = retstr + "@" + config.confjid
  69. if userid:
  70. retstr = retstr + "/" + userid
  71. return retstr
  72. # This function translates a groupchat JID to an AIM chat room
  73. def jid2aimGroup(jid):
  74. exchange = 4
  75. groupid = unicode(jid[0:jid.find('@')].replace('_',' '))
  76. if groupid.find('%') != -1:
  77. exchange = int(groupid[groupid.find('%')+1:])
  78. groupid = groupid[:groupid.find('%')]
  79. if jid.find('/') != -1:
  80. userid = unicode(jid[jid.find('/'):])
  81. else:
  82. userid = None
  83. return (groupid,userid,exchange)
  84. # This function is called to handle legacy id translation to a JID
  85. translateAccount = aim2jid
  86. ############################################################################
  87. # This class handles most interaction with AIM chatrooms
  88. ############################################################################
  89. class LegacyGroupchat(groupchat.BaseGroupchat):
  90. def __init__(self, session, resource, ID=None, existing=False, switchboardSession=None):
  91. groupchat.BaseGroupchat.__init__(self, session, resource, ID)
  92. groupid,userid,exchange = jid2aimGroup(self.roomJID())
  93. LogEvent(INFO, self.session.jabberID)
  94. self.session.legacycon.createChat(groupid,exchange)
  95. def removeMe(self):
  96. groupid,userid,exchange = jid2aimGroup(self.roomJID())
  97. LogEvent(INFO, self.session.jabberID)
  98. self.session.legacycon.leaveChat(groupid)
  99. groupchat.BaseGroupchat.removeMe(self)
  100. utils.mutilateMe(self)
  101. def sendLegacyMessage(self, message, noerror):
  102. groupid,userid,exchange = jid2aimGroup(self.roomJID())
  103. LogEvent(INFO, self.session.jabberID)
  104. self.session.legacycon.sendChat(groupid, message)
  105. def sendContactInvite(self, contactJID):
  106. groupid,userid,exchange = jid2aimGroup(self.roomJID())
  107. contactid = jid2aim(contactJID)
  108. LogEvent(INFO, self.session.jabberID)
  109. self.session.legacycon.sendInvite(groupid, contactid)
  110. ############################################################################
  111. # This class handles most interaction with AIM
  112. ############################################################################
  113. class LegacyConnection:
  114. """ A glue class that connects to the legacy network """
  115. def __init__(self, username, password, session):
  116. import buddies
  117. self.username = username
  118. self.password = password
  119. self.session = session
  120. self.legacyList = buddies.BuddyList(self.session)
  121. self.savedShow = None
  122. self.savedFriendly = None
  123. self.savedURL = None
  124. self.reactor = reactor
  125. self.deferred = defer.Deferred()
  126. self.deferred.addErrback(self.errorCallback)
  127. hostport = (config.aimServer, config.aimPort)
  128. LogEvent(INFO, self.session.jabberID, "Creating")
  129. if config.socksProxyServer and config.socksProxyPort:
  130. self.oa = aimt.OA
  131. self.creator = socks5.ProxyClientCreator(self.reactor, self.oa, self.username, self.password, self, deferred=self.deferred, icq=0)
  132. LogEvent(INFO, self.session.jabberID, "Connect via socks proxy")
  133. self.creator.connectSocks5Proxy(config.aimServer, config.aimPort, config.socksProxyServer, config.socksProxyPort, "AIMCONN")
  134. else:
  135. self.oa = aimt.OA
  136. self.creator = protocol.ClientCreator(self.reactor, self.oa, self.username, self.password, self, deferred=self.deferred, icq=0)
  137. LogEvent(INFO, self.session.jabberID, "Connect via direct tcp")
  138. self.creator.connectTCP(*hostport)
  139. LogEvent(INFO, self.session.jabberID, "Created!")
  140. def removeMe(self):
  141. from glue import aim2jid
  142. LogEvent(INFO, self.session.jabberID)
  143. try:
  144. self.bos.stopKeepAlive()
  145. self.bos.disconnect()
  146. except AttributeError:
  147. pass
  148. self.legacyList.removeMe()
  149. self.legacyList = None
  150. self.session = None
  151. utils.mutilateMe(self)
  152. def jidRes(self, resource):
  153. to = self.session.jabberID
  154. if resource:
  155. to += "/" + resource
  156. return to
  157. def highestResource(self):
  158. """ Returns highest priority resource """
  159. return self.session.highestResource()
  160. def setURL(self, URL=None):
  161. LogEvent(INFO, self.session.jabberID, "setURL %s" % URL)
  162. try:
  163. self.bos.setURL(utils.utf8encode(URL))
  164. except AttributeError:
  165. #self.alertUser(lang.get("sessionnotactive", config.jid)
  166. pass
  167. def sendMessage(self, target, resource, message, noerror, xhtml, autoResponse=0):
  168. LogEvent(INFO, self.session.jabberID)
  169. from glue import jid2aim
  170. try:
  171. self.session.pytrans.serviceplugins['Statistics'].stats['OutgoingMessages'] += 1
  172. self.session.pytrans.serviceplugins['Statistics'].sessionUpdate(self.session.jabberID, 'OutgoingMessages', 1)
  173. scrnname = jid2aim(target)
  174. wantIcon = 0
  175. if self.bos.requesticon.has_key(scrnname):
  176. LogEvent(INFO, self.session.jabberID, "Going to ask for target's icon.")
  177. wantIcon = 1
  178. del self.bos.requesticon[scrnname]
  179. offline = 1
  180. try:
  181. if self.legacyList.ssicontacts[scrnname]['presence'] != "unavailable":
  182. offline = 0
  183. except:
  184. # well then they're online in some way
  185. pass
  186. iconSum = None
  187. iconLen = None
  188. iconStamp = None
  189. if hasattr(self, "myavatar"):
  190. iconSum = oscar.getIconSum(self.myavatar)
  191. iconLen = len(self.myavatar)
  192. iconStamp = time.time()
  193. LogEvent(INFO, self.session.jabberID, "Going to send info about our icon, length %d, cksum %d" % (iconLen, iconSum))
  194. LogEvent(INFO, self.session.jabberID)
  195. if scrnname[0].isdigit():
  196. encoding = "iso-8859-1"
  197. charset = "iso-8859-1"
  198. if self.legacyList.hasCapability(scrnname, "unicode"):
  199. encoding = "utf-16be"
  200. charset = "unicode"
  201. LogEvent(INFO, self.session.jabberID, "Encoding %r" % encoding)
  202. self.bos.sendMessage(scrnname, [[message,charset]], offline=offline, wantIcon=wantIcon, autoResponse=autoResponse, iconSum=iconSum, iconLen=iconLen, iconStamp=iconStamp)
  203. self.session.sendArchive(target, self.session.jabberID, message)
  204. else:
  205. if xhtml and not config.disableXHTML:
  206. xhtml = utils.xhtml_to_aimhtml(xhtml)
  207. self.bos.sendMessage(scrnname, xhtml, wantIcon=wantIcon, autoResponse=autoResponse, iconSum=iconSum, iconLen=iconLen, iconStamp=iconStamp)
  208. self.session.sendArchive(target, self.session.jabberID, message)
  209. else:
  210. htmlized = oscar.html(message)
  211. self.bos.sendMessage(scrnname, htmlized, wantIcon=wantIcon, autoResponse=autoResponse, iconSum=iconSum, iconLen=iconLen, iconStamp=iconStamp)
  212. self.session.sendArchive(target, self.session.jabberID, message)
  213. except AttributeError:
  214. self.alertUser(lang.get("sessionnotactive", config.jid))
  215. def newResourceOnline(self, resource):
  216. from glue import aim2jid
  217. LogEvent(INFO, self.session.jabberID)
  218. try:
  219. for c in self.legacyList.ssicontacts.keys( ):
  220. LogEvent(INFO, self.session.jabberID, "Resending buddy %r" % c)
  221. jid = aim2jid(c)
  222. show = self.legacyList.ssicontacts[c]['show']
  223. status = self.legacyList.ssicontacts[c]['status']
  224. ptype = self.legacyList.ssicontacts[c]['presence']
  225. url = self.legacyList.ssicontacts[c]['url']
  226. #FIXME, needs to be contact based updatePresence
  227. self.session.sendPresence(to=self.session.jabberID, fro=jid, show=show, status=status, ptype=ptype, url=url)
  228. except AttributeError:
  229. return
  230. def setAway(self, awayMessage=None):
  231. LogEvent(INFO, self.session.jabberID)
  232. try:
  233. self.bos.awayResponses = {}
  234. self.bos.setAway(utils.xmlify(awayMessage))
  235. except AttributeError:
  236. #self.alertUser(lang.get("sessionnotactive", config.jid))
  237. pass
  238. def setBack(self, backMessage=None):
  239. LogEvent(INFO, self.session.jabberID)
  240. try:
  241. self.bos.awayResponses = {}
  242. self.bos.setBack(utils.utf8encode(backMessage))
  243. except AttributeError:
  244. #self.alertUser(lang.get("sessionnotactive", config.jid))
  245. pass
  246. def sendShowStatus(self, jid=None):
  247. if not self.session: return
  248. if not jid:
  249. jid = self.jabberID
  250. self.session.sendPresence(to=jid, fro=config.jid, show=self.savedShow, status=self.savedFriendly)
  251. def setStatus(self, nickname, show, friendly, url=None):
  252. LogEvent(INFO, self.session.jabberID)
  253. if show=="away" and not friendly:
  254. friendly="Away"
  255. elif show=="dnd" and not friendly:
  256. friendly="Do Not Disturb"
  257. elif show=="xa" and not friendly:
  258. friendly="Extended Away"
  259. elif show=="chat" and not friendly:
  260. friendly="Free to Chat"
  261. self.savedShow = show
  262. self.savedFriendly = friendly
  263. self.savedURL = url
  264. if not self.session.ready:
  265. return
  266. if not show or show == "online" or show == "Online" or show == "chat":
  267. self.setBack(friendly)
  268. self.setURL(url)
  269. self.session.sendPresence(to=self.session.jabberID, fro=config.jid, show=None, url=url)
  270. else:
  271. self.setAway(friendly)
  272. self.setURL(url)
  273. self.session.sendPresence(to=self.session.jabberID, fro=config.jid, show=show, status=friendly, url=url)
  274. def setProfile(self, profileMessage=None):
  275. LogEvent(INFO, self.session.jabberID)
  276. try:
  277. self.bos.setProfile(profileMessage)
  278. except AttributeError:
  279. #self.alertUser(lang.get("sessionnotactive", config.jid))
  280. pass
  281. def buildFriendly(self, status):
  282. friendly = self.jabberID[:self.jabberID.find('@')]
  283. if status and len(status) > 0:
  284. friendly += " - "
  285. friendly += status
  286. if len(friendly) > 127:
  287. friendly = friendly[:124] + "..."
  288. return friendly
  289. def sendTypingNotify(self, type, dest):
  290. from tlib.oscar import MTN_FINISH, MTN_IDLE, MTN_BEGIN
  291. from glue import jid2aim
  292. try:
  293. username = jid2aim(dest)
  294. LogEvent(INFO, self.session.jabberID)
  295. if type == "begin":
  296. self.bos.sendTypingNotification(username, MTN_BEGIN)
  297. elif type == "idle":
  298. self.bos.sendTypingNotification(username, MTN_IDLE)
  299. elif type == "finish":
  300. self.bos.sendTypingNotification(username, MTN_FINISH)
  301. except AttributeError:
  302. self.alertUser(lang.get("sessionnotactive", config.jid))
  303. def userTypingNotification(self, dest, resource, composing):
  304. LogEvent(INFO, self.session.jabberID)
  305. if composing:
  306. self.sendTypingNotify("begin", dest)
  307. else:
  308. self.sendTypingNotify("finish", dest)
  309. def chatStateNotification(self, dest, resource, state):
  310. LogEvent(INFO, self.session.jabberID)
  311. if state == "composing":
  312. self.sendTypingNotify("begin", dest)
  313. elif state == "paused" or state == "inactive":
  314. self.sendTypingNotify("idle", dest)
  315. elif state == "active" or state == "gone":
  316. self.sendTypingNotify("finish", dest)
  317. def jabberVCardRequest(self, vcard, user):
  318. LogEvent(INFO, self.session.jabberID)
  319. return self.getvCard(vcard, user)
  320. def createChat(self, chatroom, exchange):
  321. LogEvent(INFO, self.session.jabberID)
  322. try:
  323. self.bos.createChat(chatroom, exchange).addCallback(self.bos.createdRoom)
  324. except AttributeError:
  325. self.alertUser(lang.get("sessionnotactive", config.jid))
  326. def leaveChat(self, chatroom):
  327. LogEvent(INFO, self.session.jabberID)
  328. try:
  329. for c in self.bos.chats:
  330. if c.name == chatroom:
  331. c.leaveChat()
  332. self.bos.chats.remove(c)
  333. break
  334. except AttributeError:
  335. self.alertUser(lang.get("sessionnotactive", config.jid))
  336. def sendChat(self, chatroom, message):
  337. LogEvent(INFO, self.session.jabberID)
  338. try:
  339. for c in self.bos.chats:
  340. #debug.log("Checking chat %s" % (c.name))
  341. if c.name.lower() == chatroom.lower():
  342. c.sendMessage(message)
  343. #debug.log("Found chat and sent message.")
  344. break
  345. except AttributeError:
  346. self.alertUser(lang.get("sessionnotactive", config.jid))
  347. def sendInvite(self, chatroom, contact):
  348. LogEvent(INFO, self.session.jabberID)
  349. try:
  350. for c in self.bos.chats:
  351. if c.name.lower() == chatroom.lower():
  352. self.bos.sendInvite(contact, c)
  353. except AttributeError:
  354. self.alertUser(lang.get("sessionnotactive", config.jid))
  355. def resourceOffline(self, resource):
  356. from glue import aim2jid
  357. LogEvent(INFO, self.session.jabberID)
  358. try:
  359. show = None
  360. status = None
  361. ptype = "unavailable"
  362. for c in self.legacyList.ssicontacts.keys( ):
  363. LogEvent(INFO, self.session.jabberID, "Sending offline %r" % c)
  364. jid = aim2jid(c)
  365. self.session.sendPresence(to=self.session.jabberID+"/"+resource, fro=jid, ptype=ptype, show=show, status=status)
  366. self.session.sendPresence(to=self.session.jabberID+"/"+resource, fro=config.jid, ptype=ptype, show=show, status=status)
  367. except AttributeError:
  368. return
  369. def updateAvatar(self, av=None):
  370. """ Called whenever a new avatar needs to be set. Instance of avatar.Avatar is passed """
  371. if config.disableAvatars: return
  372. imageData = ""
  373. if av:
  374. imageData = av.getImageData()
  375. else:
  376. if not config.disableDefaultAvatar:
  377. global defaultAvatarData
  378. imageData = defaultAvatarData
  379. else:
  380. imageData = None
  381. self.changeAvatar(imageData)
  382. def changeAvatar(self, imageData):
  383. if config.disableAvatars: return
  384. if imageData:
  385. try:
  386. self.myavatar = imgmanip.convertToJPG(imageData)
  387. self.myavatarlen = len(self.myavatar)
  388. m=md5.new()
  389. m.update(self.myavatar)
  390. self.myavatarsum = m.digest()
  391. self.myavatarstamp = time.time()
  392. except:
  393. LogEvent(INFO, self.session.jabberID, "Unable to convert avatar to JPEG")
  394. return
  395. if hasattr(self, "bos") and self.session.ready:
  396. if not imageData:
  397. if hasattr(self, "myavatar"):
  398. del self.myavatar
  399. if len(self.bos.ssiiconsum) > 0:
  400. self.bos.startModifySSI()
  401. for i in self.bos.ssiiconsum:
  402. LogEvent(INFO, self.session.jabberID, "Removing icon %s (u:%d g:%d)" % (i.name, i.buddyID, i.groupID))
  403. de = self.bos.delItemSSI(i)
  404. self.bos.endModifySSI()
  405. return
  406. if len(self.bos.ssiiconsum) > 0 and self.bos.ssiiconsum[0]:
  407. LogEvent(INFO, self.session.jabberID, "Replacing existing icon")
  408. self.bos.ssiiconsum[0].updateIcon(imageData)
  409. self.bos.startModifySSI()
  410. self.bos.modifyItemSSI(self.bos.ssiiconsum[0])
  411. self.bos.endModifySSI()
  412. else:
  413. LogEvent(INFO, self.session.jabberID, "Adding new icon")
  414. newBuddySum = oscar.SSIIconSum()
  415. newBuddySum.updateIcon(imageData)
  416. self.bos.startModifySSI()
  417. self.bos.addItemSSI(newBuddySum)
  418. self.bos.endModifySSI()
  419. def doSearch(self, form, iq):
  420. LogEvent(INFO, self.session.jabberID)
  421. #TEST self.bos.sendInterestsRequest()
  422. email = utils.getDataFormValue(form, "email")
  423. first = utils.getDataFormValue(form, "first")
  424. middle = utils.getDataFormValue(form, "middle")
  425. last = utils.getDataFormValue(form, "last")
  426. maiden = utils.getDataFormValue(form, "maiden")
  427. nick = utils.getDataFormValue(form, "nick")
  428. address = utils.getDataFormValue(form, "address")
  429. city = utils.getDataFormValue(form, "city")
  430. state = utils.getDataFormValue(form, "state")
  431. zip = utils.getDataFormValue(form, "zip")
  432. country = utils.getDataFormValue(form, "country")
  433. interest = utils.getDataFormValue(form, "interest")
  434. try:
  435. d = defer.Deferred()
  436. self.bos.sendDirectorySearch(email=email, first=first, middle=middle, last=last, maiden=maiden, nickname=nick, address=address, city=city, state=state, zip=zip, country=country, interest=interest).addCallback(self.gotSearchResults, iq, d).addErrback(self.gotSearchError, d)
  437. return d
  438. except AttributeError:
  439. self.alertUser(lang.get("sessionnotactive", config.jid))
  440. def gotSearchResults(self, results, iq, d):
  441. LogEvent(INFO, self.session.jabberID)
  442. from glue import aim2jid
  443. x = None
  444. for query in iq.elements():
  445. if query.name == "query":
  446. for child in query.elements():
  447. if child.name == "x":
  448. x = child
  449. break
  450. break
  451. if x:
  452. for r in results:
  453. if r.has_key("screenname"):
  454. r["jid"] = aim2jid(r["screenname"])
  455. else:
  456. r["jid"] = "Unknown"
  457. item = x.addElement("item")
  458. for k in ["jid","first","middle","last","maiden","nick","email","address","city","state","country","zip","region"]:
  459. item.addChild(utils.makeDataFormElement(None, k, value=r.get(k,None)))
  460. d.callback(iq)
  461. def gotSearchError(self, error, d):
  462. LogEvent(INFO, self.session.jabberID)
  463. #d.callback(vcard)
  464. def getvCard(self, vcard, user):
  465. LogEvent(INFO, self.session.jabberID)
  466. try:
  467. d = defer.Deferred()
  468. self.bos.getProfile(user).addCallback(self.gotvCard, user, vcard, d).addErrback(self.gotnovCard, user, vcard, d)
  469. return d
  470. except AttributeError:
  471. self.alertUser(lang.get("sessionnotactive", config.jid))
  472. def gotvCard(self, profile, user, vcard, d):
  473. from glue import aim2jid
  474. LogEvent(INFO, self.session.jabberID)
  475. cutprofile = oscar.dehtml(profile)
  476. nickname = vcard.addElement("NICKNAME")
  477. nickname.addContent(utils.xmlify(user))
  478. jabberid = vcard.addElement("JABBERID")
  479. jabberid.addContent(aim2jid(user))
  480. desc = vcard.addElement("DESC")
  481. desc.addContent(utils.xmlify(cutprofile))
  482. d.callback(vcard)
  483. def gotnovCard(self, profile, user, vcard, d):
  484. from glue import aim2jid
  485. LogEvent(INFO, self.session.jabberID)
  486. nickname = vcard.addElement("NICKNAME")
  487. nickname.addContent(user)
  488. jabberid = vcard.addElement("JABBERID")
  489. jabberid.addContent(aim2jid(user))
  490. desc = vcard.addElement("DESC")
  491. desc.addContent("User is not online.")
  492. d.callback(vcard)
  493. def aim2uhandle(self, aimid):
  494. retstr = aimid.replace(' ','')
  495. return retstr.lower()
  496. def updatePresence(self, userHandle, ptype): # Convenience
  497. from glue import aim2jid
  498. to = aim2jid(userHandle)
  499. self.session.sendPresence(to=self.session.jabberID, fro=to, ptype=ptype)
  500. def addContact(self, userHandle):
  501. LogEvent(INFO, self.session.jabberID)
  502. def cb(arg=None):
  503. self.updatePresence(userHandle, "subscribed")
  504. try:
  505. for g in self.bos.ssigroups:
  506. for u in g.users:
  507. aimHandle = self.aim2uhandle(u.name)
  508. if aimHandle == userHandle:
  509. if not u.authorizationRequestSent and not u.authorized:
  510. self.bos.sendAuthorizationRequest(userHandle, "Please authorize me!")
  511. u.authorizationRequestSent = True
  512. return
  513. else:
  514. cb()
  515. return
  516. savethisgroup = None
  517. groupName = "PyAIM-t Buddies"
  518. for g in self.bos.ssigroups:
  519. if g.name == groupName:
  520. LogEvent(INFO, self.session.jabberID, "Located group %s" % (g.name))
  521. savethisgroup = g
  522. if savethisgroup is None:
  523. LogEvent(INFO, self.session.jabberID, "Adding new group")
  524. newGroupID = self.generateGroupID()
  525. newGroup = oscar.SSIGroup(groupName, newGroupID, 0)
  526. self.bos.startModifySSI()
  527. self.bos.addItemSSI(newGroup)
  528. self.bos.endModifySSI()
  529. savethisgroup = newGroup
  530. self.bos.ssigroups.append(newGroup)
  531. group = self.findGroupByName(groupName)
  532. newUserID = self.generateBuddyID(group.groupID)
  533. newUser = oscar.SSIBuddy(userHandle, group.groupID, newUserID)
  534. savethisgroup.addUser(newUserID, newUser)
  535. LogEvent(INFO, self.session.jabberID, "Adding item to SSI")
  536. self.bos.startModifySSI()
  537. self.bos.addItemSSI(newUser)
  538. self.bos.modifyItemSSI(savethisgroup)
  539. self.bos.endModifySSI()
  540. self.legacyList.updateSSIContact(userHandle)
  541. self.updatePresence(userHandle, "subscribe")
  542. except AttributeError:
  543. self.alertUser(lang.get("sessionnotactive", config.jid))
  544. def removeContact(self, userHandle):
  545. LogEvent(INFO, self.session.jabberID)
  546. try:
  547. def cb(arg=None):
  548. self.updatePresence(userHandle, "unsubscribed")
  549. savetheseusers = []
  550. if userHandle in self.bos.authorizationRequests:
  551. self.bos.sendAuthorizationResponse(userHandle, False, "")
  552. self.bos.authorizationRequests.remove(userHandle)
  553. for g in self.bos.ssigroups:
  554. for u in g.users:
  555. aimHandle = self.aim2uhandle(u.name)
  556. LogEvent(INFO, self.session.jabberID, "Comparing %s and %s" % (aimHandle, userHandle))
  557. if aimHandle == userHandle:
  558. LogEvent(INFO, self.session.jabberID, "Located user %s" % (u.name))
  559. savetheseusers.append(u)
  560. if len(savetheseusers) == 0:
  561. LogEvent(INFO, self.session.jabberID, "Did not find user")
  562. return
  563. self.bos.startModifySSI()
  564. for u in savetheseusers:
  565. LogEvent(INFO, self.session.jabberID, "Removing %s (u:%d g:%d) from group %s"%(u.name, u.buddyID, u.groupID, u.group.name))
  566. de = self.bos.delItemSSI(u)
  567. de.addCallback(self.SSIItemDeleted, u)
  568. de.addCallback(cb)
  569. self.bos.endModifySSI()
  570. except AttributeError:
  571. self.alertUser(lang.get("sessionnotactive", config.jid))
  572. def authContact(self, userHandle):
  573. LogEvent(INFO, self.session.jabberID)
  574. try:
  575. if userHandle in self.bos.authorizationRequests:
  576. self.bos.sendAuthorizationResponse(userHandle, True, "OK")
  577. self.bos.authorizationRequests.remove(userHandle)
  578. except AttributeError:
  579. self.alertUser(lang.get("sessionnotactive", config.jid))
  580. def deauthContact(self, userHandle):
  581. LogEvent(INFO, self.session.jabberID)
  582. # I don't recall why these are the same
  583. self.authContact(userHandle)
  584. def SSIItemDeleted(self, x, user):
  585. c = 0
  586. for g in self.bos.ssigroups:
  587. c += 1
  588. for u in g.users:
  589. if u.buddyID == user.buddyID and u.groupID == user.groupID:
  590. g.users.remove(u)
  591. del g.usersToID[u]
  592. def errorCallback(self, result):
  593. try:
  594. LogEvent(INFO, self.session.jabberID)
  595. errmsg = result.getErrorMessage()
  596. errmsgs = errmsg.split("'")
  597. message = "Authentication Error!"
  598. if errmsgs[1]:
  599. message = message+"\n"+errmsgs[1]
  600. if errmsgs[3]:
  601. message = message+"\n"+errmsgs[3]
  602. self.alertUser(message)
  603. self.session.removeMe()
  604. except:
  605. pass
  606. def findGroupByID(self, groupID):
  607. for x in self.bos.ssigroups:
  608. if x.groupID == groupID:
  609. return x
  610. def findGroupByName(self, groupName):
  611. for x in self.bos.ssigroups:
  612. if x.name == groupName:
  613. return x
  614. def generateGroupID(self):
  615. pGroupID = len(self.bos.ssigroups)
  616. while True:
  617. pGroupID += 1
  618. found = False
  619. for x in self.bos.ssigroups:
  620. if pGroupID == x.groupID:
  621. found = True
  622. break
  623. if not found: break
  624. return pGroupID
  625. def generateBuddyID(self, groupID):
  626. group = self.findGroupByID(groupID)
  627. pBuddyID = len(group.users)
  628. while True: # If all integers are taken we got a bigger problems
  629. pBuddyID += 1
  630. found = False
  631. for x in group.users:
  632. if pBuddyID == x.buddyID:
  633. found = True
  634. break
  635. if not found: break
  636. return pBuddyID
  637. def alertUser(self, message):
  638. tmpjid = config.jid
  639. if self.session.registeredmunge:
  640. tmpjid = tmpjid + "/registered"
  641. self.session.sendMessage(to=self.session.jabberID, fro=tmpjid, body=message, mtype="error")