diff --git a/external/messenger.py b/external/messenger.py index 6af2ec2..6b954d4 100755 --- a/external/messenger.py +++ b/external/messenger.py @@ -79,16 +79,17 @@ class MessengerBridgeClient(fbchat.Client): # ---- SEPARATE THREADS FOR INITIAL SYNC & CLIENT LISTEN ---- class InitialSyncThread(threading.Thread): - def __init__(self, client, bridge, *args, **kwargs): + def __init__(self, client, bridge, threads, *args, **kwargs): super(InitialSyncThread, self).__init__(*args, **kwargs) self.client = client self.bridge = bridge + self.threads = threads def run(self): - threads = self.client.fetchThreadList() sys.stderr.write("fb thread list: {}\n".format(threads)) - for thread in threads: + + for thread in self.threads: sys.stderr.write("fb thread: {}\n".format(thread)) if thread.type == ThreadType.GROUP: members = self.client.fetchAllUsersFromThreads([thread]) @@ -100,8 +101,6 @@ class InitialSyncThread(threading.Thread): self.send_room_info(thread, members) self.send_room_members(thread, members) - elif thread.type == ThreadType.USER: - self.bridge.getUserId(thread) self.backlog_room(thread) @@ -134,25 +133,7 @@ class InitialSyncThread(threading.Thread): def send_room_members(self, thread, members): for member in members: sys.stderr.write("fb thread member: {}\n".format(member)) - self.bridge.write({ - "_type": EVENT, - "data": { - "type": EVENT_JOIN, - "author": self.bridge.getUserId(member), - "room": thread.uid, - } - }) - - user_info = { - "display_name": member.name, - } - if member.photo is not None: - user_info["avatar"] = mediaObjectOfURL(member.photo) - self.bridge.write({ - "_type": USER_INFO_UPDATED, - "user": self.bridge.getUserId(member), - "data": user_info, - }) + self.bridge.ensureJoined(self.bridge.getUserId(member), thread.uid) def backlog_room(self, thread): prev_last_seen = self.bridge.cache_get("last_seen_%s"%thread.uid) @@ -194,16 +175,32 @@ class MessengerBridge: def __init__(self): self.rev_uid = {} self.uid_map = {} + self.joined_map = {} def getUserId(self, user): + retval = None if user.url is not None and not "?" in user.url: user_id = user.url.split("/")[-1] self.rev_uid[user_id] = user.uid - self.uid_map[user.uid] = user_id + retval = user_id else: - self.uid_map[user.uid] = user.uid + retval = user.uid - return self.uid_map[user.uid] + if user.uid not in self.uid_map: + self.uid_map[user.uid] = retval + + user_info = { + "display_name": user.name, + } + if user.photo is not None: + user_info["avatar"] = mediaObjectOfURL(user.photo) + self.bridge.write({ + "_type": USER_INFO_UPDATED, + "user": self.bridge.getUserId(user), + "data": user_info, + }) + + return retval def getUserIdFromUid(self, uid): if uid in self.uid_map: @@ -218,7 +215,6 @@ class MessengerBridge: else: return user_id - def getUserShortName(self, user): if user.first_name != None: return user.first_name @@ -281,17 +277,27 @@ class MessengerBridge: email, password = cmd["data"]["email"], cmd["data"]["password"] self.client = MessengerBridgeClient(email=email, password=password, max_tries=1) - if self.client.isLoggedIn(): - try: - f = open(client_file, "wb") - pickle.dump(self.client, f) - f.close() - except: - pass + if not self.client.isLoggedIn(): + return {"_type": "ret_error", "error": "Unable to login (?)"} - self.client.setBridge(self) - InitialSyncThread(self.client, self).start() - ClientListenThread(self.client).start() + try: + f = open(client_file, "wb") + pickle.dump(self.client, f) + f.close() + except: + pass + + self.client.setBridge(self) + + threads = self.client.fetchThreadList() + # ensure we have a correct mapping for bridged user IDs to fb uids + # (this should be fast) + for thread in threads: + if thread.type == ThreadType.GROUP: + self.getUserId(thread) + + InitialSyncThread(self.client, self, threads).start() + ClientListenThread(self.client).start() elif ty == CLOSE: self.close() @@ -344,6 +350,19 @@ class MessengerBridge: def cache_put(self, key, value): self.write({"_type": CACHE_PUT, "key": key, "value": value}) + def ensureJoined(self, userId, room): + key = "{}--{}".format(userId, room) + if not key in self.joined_map: + self.bridge.write({ + "_type": EVENT, + "data": { + "type": EVENT_JOIN, + "author": userId, + "room": room, + } + }) + self.joined_map[key] = true + def onMessage(self, thread_id, thread_type, message_object, **kwargs): if message_object.author == self.client.uid: # Ignore our own messages @@ -358,6 +377,8 @@ class MessengerBridge: } if thread_type == ThreadType.GROUP: event["room"] = thread_id + self.ensureJoined(author, thread_id) + self.write({"_type": EVENT, "data": event}) self.cache_put("last_seen_%s"%thread_id, message_object.uid) @@ -369,7 +390,6 @@ class MessengerBridge: def onTitleChange(self, *args, **kwargs): pass - if __name__ == "__main__": bridge = MessengerBridge() bridge.run()