diff options
author | John Smith <mrdoctorwho@gmail.com> | 2016-12-25 14:27:34 +0300 |
---|---|---|
committer | John Smith <mrdoctorwho@gmail.com> | 2016-12-25 14:27:34 +0300 |
commit | a5354a9f365dd3e18f10314d25dd36609671d640 (patch) | |
tree | 73ffaa31150b01a659c949f78662be8b456f387d | |
parent | 291eadf050602bc27ff9addbdf89bcc6d90e4304 (diff) |
Make roster check xmpp-based
-rw-r--r-- | gateway.py | 29 | ||||
-rw-r--r-- | library/utils.py | 36 | ||||
-rw-r--r-- | modules/mod_prs_main.py | 52 |
3 files changed, 89 insertions, 28 deletions
@@ -194,7 +194,7 @@ def getGatewayRev(): """ Gets gateway revision using git or custom revision number """ - number, hash = 317, 0 + number, hash = 360, 0 shell = os.popen("git describe --always &" "& git log --pretty=format:''").readlines() if shell: @@ -208,9 +208,9 @@ def vk2xmpp(id): Args: id: a Jabber or VK id Returns: - id@TransportID if parameter id is a number - id if parameter "id" is id@TransportID - TransportID if the given id is equal to TransportID + id@TransportID if parameter id is a number (String) + id if parameter "id" is id@TransportID (Integer) + TransportID if the given id is equal to TransportID (String) """ if not utils.isNumber(id) and "@" in id: id = id.split("@")[0] @@ -835,11 +835,9 @@ class User(object): del self.typing[user] sendMessage(self.source, vk2xmpp(user), typ="paused") - def updateFriends(self, cTime): + def updateStatus(self, cTime): """ - Updates friends list. - Compares the current friends list to the new list - Takes a corresponding action if any difference found + Updates user's status """ if (cTime - self.last_udate) > 300 and not self.vk.engine.captcha: if self.settings.keep_online: @@ -847,19 +845,6 @@ class User(object): else: self.vk.setOffline() self.last_udate = cTime - friends = self.vk.getFriends() - if not friends: - logger.error("updateFriends: no friends received (jid: %s).", - self.source) - return None - - for uid in friends: - if uid not in self.friends: - self.sendSubPresence({uid: friends[uid]}) - for uid in self.friends: - if uid not in friends: - sendPresence(self.source, vk2xmpp(uid), "unsubscribe") - self.friends = friends def reauth(self): """ @@ -979,7 +964,7 @@ def updateCron(): for user in Users.values(): cTime = time.time() user.updateTypingUsers(cTime) - user.updateFriends(cTime) + user.updateStatus(cTime) time.sleep(2) def calcStats(): diff --git a/library/utils.py b/library/utils.py index ef00d39..42d0711 100644 --- a/library/utils.py +++ b/library/utils.py @@ -200,4 +200,40 @@ def TimeMachine(text): time += int(current[:-1]) * TIME_VALUES[x] return time + +class ExpiringObject(object): + def __init__(self, obj, lifetime): + self.obj = obj + self.created = time.time() + self.lifetime = lifetime + + def hasExpired(self): + return (time.time() >= (self.created + self.lifetime)) + + def __getattr__(self, attr): + try: + result = object.__getattribute__(self, attr) + except AttributeError: + result = getattr(self.obj, attr) + return result + + def __iter__(self): + if hasattr(self.obj, "__iter__"): + return self.obj.__iter__() + raise TypeError("Not iterable") + + def next(self): + if hasattr(self.obj, "next"): + return self.obj.next() + raise TypeError("Not iterable") + + # TODO what if our object isn't iterable? + def __str__(self): + result = "" + for num, i in enumerate(self.obj): + result += str(i) + if num < (len(self.obj) -1): + result += ", " + return result + # Yay! diff --git a/modules/mod_prs_main.py b/modules/mod_prs_main.py index 9c9da11..b832880 100644 --- a/modules/mod_prs_main.py +++ b/modules/mod_prs_main.py @@ -8,8 +8,36 @@ Module purpose is to receive and handle presences from __main__ import * from __main__ import _ +from utils import * -USERS_ON_INIT = set([]) +# keeps the user's roster +USERS_ON_INIT = {} +EXPIRING_OBJECT_LIFETIME = 600 +UPDATE_FRIENDS_DELAY = 60 + + +def updateFriends(user, local): + """ + Compares the local (xmpp) and remote (vk) list of friends + """ + if TransportID in local: + local.remove(TransportID) + if not user.vk.online: + return None + + friends = user.friends or user.vk.getFriends() + if not friends or not local: + logger.error("updateFriends: no friends received (local: %s, remote: %s) (jid: %s).", + str(local), str(friends), user.source) + return None + + for uid in friends: + if uid not in local: + user.sendSubPresence({uid: friends[uid]}) + # TODO + # for uid in self.friends: + # if uid not in friends: + # sendPresence(self.source, vk2xmpp(uid), "unsubscribe") def initializeUser(source, resource, prs): @@ -30,10 +58,12 @@ def initializeUser(source, resource, prs): report(crashLog("user.connect")) else: user.initialize(send=True, resource=resource) # probably we need to know resource a bit earlier than this time + utils.runThread(updateFriends, (user, list(USERS_ON_INIT[source])), # making a copy so we can remote it safely + delay=UPDATE_FRIENDS_DELAY) utils.runThread(executeHandlers, ("prs01", (source, prs))) if source in USERS_ON_INIT: - USERS_ON_INIT.remove(source) + del USERS_ON_INIT[source] def presence_handler(cl, prs): @@ -50,6 +80,8 @@ def presence_handler(cl, prs): logger.debug("Received presence %s from user. Calling sendInitPresence() (jid: %s)" % (pType, source)) user.resources.add(resource) utils.runThread(user.sendInitPresence) + elif source in USERS_ON_INIT: + USERS_ON_INIT[source].add(vk2xmpp(destination)) elif pType == "unavailable": if destination == TransportID and resource in user.resources: @@ -85,11 +117,19 @@ def presence_handler(cl, prs): removeUser(user, True, False) executeHandlers("evt09", (source,)) - elif pType in ("available", None) and destination == TransportID: + # when user becomes online, we get subscribe as we don't have both subscription + elif pType not in ("error", "unavailable"): # It's possible to receive more than one presence from @gmail.com - if source not in USERS_ON_INIT: - utils.runThread(initializeUser, args=(source, resource, prs)) - USERS_ON_INIT.add(source) + if source in USERS_ON_INIT: + roster = USERS_ON_INIT[source] + if destination == TransportID and TransportID not in roster and pType in ("available", "probe", None): + utils.runThread(initializeUser, args=(source, resource, prs)) + else: + __set = set([]) + USERS_ON_INIT[source] = ExpiringObject(__set, EXPIRING_OBJECT_LIFETIME) + if destination == TransportID: + utils.runThread(initializeUser, args=(source, resource, prs)) + USERS_ON_INIT[source].add(vk2xmpp(destination)) utils.runThread(executeHandlers, ("prs01", (source, prs))) |