From 8d19ddd49e6630bbc41e062a79001d14a55395bb Mon Sep 17 00:00:00 2001 From: Tulir Asokan <tulir@maunium.net> Date: Mon, 29 Apr 2019 21:02:26 +0300 Subject: [PATCH] Add fb_receiver for private chat portals --- mautrix_facebook/portal.py | 64 ++++++++++++++++++++++---------------- mautrix_facebook/user.py | 9 +++--- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/mautrix_facebook/portal.py b/mautrix_facebook/portal.py index a9cb670..e00c64c 100644 --- a/mautrix_facebook/portal.py +++ b/mautrix_facebook/portal.py @@ -13,7 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. -from typing import Dict, Optional, Union, TYPE_CHECKING +from typing import Dict, Optional, Tuple, Union, TYPE_CHECKING import aiohttp import asyncio import logging @@ -39,9 +39,10 @@ class Portal: loop: asyncio.AbstractEventLoop log: logging.Logger = logging.getLogger("mau.portal") by_mxid: Dict[RoomID, 'Portal'] = {} - by_fbid: Dict[str, 'Portal'] = {} + by_fbid: Dict[Tuple[str, str], 'Portal'] = {} fbid: str + fb_receiver: str fb_type: ThreadType mxid: Optional[RoomID] @@ -54,29 +55,34 @@ class Portal: _main_intent: Optional[IntentAPI] - def __init__(self, fbid: str, fb_type: ThreadType, mxid: Optional[RoomID] = None, - name: str = "", photo: str = "", avatar_uri: ContentURI = ""): + def __init__(self, fbid: str, fb_receiver: str, fb_type: ThreadType, + mxid: Optional[RoomID] = None, + name: str = "", photo: str = "", avatar_uri: ContentURI = "") -> None: self.fbid = fbid - self.log = self.log.getChild(fbid) + self.fb_receiver = fb_receiver self.fb_type = fb_type - self.by_fbid[fbid] = self self.mxid = mxid - if self.mxid: - self.by_mxid[self.mxid] = self + + self.name = name + self.photo = photo + self.avatar_uri = avatar_uri self._main_intent = None self.messages_by_fbid = {} self.messages_by_mxid = {} - self.name = name - self.photo = photo - self.avatar_uri = avatar_uri + self.log = self.log.getChild(self.fbid_log) + + self.by_fbid[self.fbid_full] = self + if self.mxid: + self.by_mxid[self.mxid] = self def to_dict(self) -> Dict[str, str]: return { "fbid": self.fbid, "fb_type": self.fb_type.value, + "fb_receiver": self.fb_receiver, "mxid": self.mxid, "name": self.name, "photo": self.photo, @@ -85,10 +91,21 @@ class Portal: @classmethod def from_dict(cls, data: Dict[str, str]) -> 'Portal': - return cls(fbid=data["fbid"], fb_type=ThreadType(data["fb_type"]), mxid=data["mxid"], + return cls(fbid=data["fbid"], fb_receiver=data["fb_receiver"], + fb_type=ThreadType(data["fb_type"]), mxid=RoomID(data["mxid"]), name=data["name"], photo=data["photo"], avatar_uri=ContentURI(data["avatar_uri"])) + @property + def fbid_full(self) -> Tuple[str, str]: + return self.fbid, self.fb_receiver + + @property + def fbid_log(self) -> str: + if self.is_direct: + return f"{self.fbid}<->{self.fb_receiver}" + return self.fbid + @property def is_direct(self) -> bool: return self.fb_type == ThreadType.USER @@ -134,7 +151,7 @@ class Portal: return elif not self.mxid: return - users = await source.fetchAllUsersFromThreads(info) + users = await source.fetchAllUsersFromThreads([info]) puppets = {user: p.Puppet.get(user.uid) for user in users} await asyncio.gather(*[puppet.update_info(source=source, info=user) for user, puppet in puppets.items()]) @@ -166,28 +183,20 @@ class Portal: async def handle_matrix_message(self, sender: 'u.User', message: MessageEventContent, event_id: EventID) -> None: if event_id in self.messages_by_mxid: - print(f"handle_matrix_message({event_id}) --> cancelled") return - print(f"handle_matrix_message({event_id}) --> sending") fbid = await sender.send(FBMessage(text=message.body), self.fbid, self.fb_type) - print(f"handle_matrix_message({event_id}) --> sent") self.messages_by_fbid[fbid] = event_id self.messages_by_mxid[event_id] = fbid - print(f"handle_matrix_message({event_id}) --> mapped to {fbid}") async def handle_facebook_message(self, source: 'u.User', sender: 'p.Puppet', message: FBMessage) -> None: if message.uid in self.messages_by_fbid: - print(f"handle_facebook_message({message.uid}) --> cancelled") return - print(f"handle_facebook_message({message.uid}) --> sending") if not self.mxid: await self.create_matrix_room(source) event_id = await sender.intent.send_text(self.mxid, message.text) - print(f"handle_facebook_message({message.uid}) --> sent") self.messages_by_mxid[event_id] = message.uid self.messages_by_fbid[message.uid] = event_id - print(f"handle_facebook_message({message.uid}) --> mapped to {event_id}") @classmethod def get_by_mxid(cls, mxid: RoomID) -> Optional['Portal']: @@ -198,17 +207,20 @@ class Portal: return None @classmethod - def get_by_fbid(cls, fbid: str, fb_type: Optional[ThreadType] = None) -> Optional['Portal']: + def get_by_fbid(cls, fbid: str, fb_receiver: Optional[str] = None, + fb_type: Optional[ThreadType] = None) -> Optional['Portal']: + fb_receiver = fb_receiver or fbid + fbid_full = (fbid, fb_receiver) try: - return cls.by_fbid[fbid] + return cls.by_fbid[fbid_full] except KeyError: if fb_type: - return cls(fbid=fbid, fb_type=fb_type) + return cls(fbid=fbid, fb_receiver=fb_receiver, fb_type=fb_type) return None @classmethod - def get_by_thread(cls, thread: Thread) -> 'Portal': - return cls.get_by_fbid(thread.uid, thread.type) + def get_by_thread(cls, thread: Thread, fb_receiver: Optional[str] = None) -> 'Portal': + return cls.get_by_fbid(thread.uid, fb_receiver, thread.type) def init(context: 'Context') -> None: diff --git a/mautrix_facebook/user.py b/mautrix_facebook/user.py index 6a6ebd2..5057b5d 100644 --- a/mautrix_facebook/user.py +++ b/mautrix_facebook/user.py @@ -52,8 +52,7 @@ class User(Client): self.command_status = None self.is_whitelisted, self.is_admin = config.get_permissions(mxid) self._is_logged_in = None - # Active pinging seems to throw HTTP 500's for some reason - self.setActiveStatus(False) + #self.setActiveStatus(False) # region Sessions @@ -100,7 +99,8 @@ class User(Client): threads = await self.fetchThreadList(limit=10) for thread in threads: self.log.debug(f"Syncing thread {thread.uid} {thread.name}") - portal = po.Portal.get_by_thread(thread) + fb_receiver = self.uid if thread.type == ThreadType.USER else None + portal = po.Portal.get_by_thread(thread, fb_receiver) await portal.create_matrix_room(self, thread) if isinstance(thread, FBUser): puppet = pu.Puppet.get(thread.uid, create=True) @@ -177,7 +177,8 @@ class User(Client): f"{thread_id}, {thread_type})") return self.log.debug(f"onMessage({mid}, {author_id}, {message}, {thread_id}, {thread_type})") - portal = po.Portal.get_by_fbid(thread_id, thread_type) + fb_receiver = self.uid if thread_type == ThreadType.USER else None + portal = po.Portal.get_by_fbid(thread_id, fb_receiver, thread_type) puppet = pu.Puppet.get(author_id) if not puppet.name: await puppet.update_info(self) -- GitLab