From 6caf82e975b5b38ac14b9043f020f92d94d1e006 Mon Sep 17 00:00:00 2001 From: Tulir Asokan <tulir@maunium.net> Date: Mon, 11 May 2020 18:46:09 +0300 Subject: [PATCH] Bridge messenger member add/remove to Matrix --- ROADMAP.md | 4 ++-- mautrix_facebook/portal.py | 21 +++++++++++++++++++-- mautrix_facebook/user.py | 23 ++++++++++++++++++++--- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 44594e3..1adabe4 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -48,8 +48,8 @@ * [x] Read receipts * [ ] Admin status * [ ] Membership actions - * [ ] Add member - * [ ] Remove member + * [x] Add member + * [x] Remove member * [ ] Leave * [ ] Chat metadata changes * [x] Title diff --git a/mautrix_facebook/portal.py b/mautrix_facebook/portal.py index aa76912..bd286d5 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, Deque, Optional, Tuple, Union, Set, Iterator, TYPE_CHECKING +from typing import Dict, Deque, Optional, Tuple, Union, Set, Iterator, List, TYPE_CHECKING from collections import deque import asyncio @@ -797,13 +797,30 @@ class Portal(BasePortal): return reaction = DBReaction.get_by_fbid(message_id, self.fb_receiver, sender.fbid) if reaction: - self.log.debug(f"redacting {reaction.mxid}") try: await sender.intent_for(self).redact(reaction.mx_room, reaction.mxid) except MForbidden: await self.main_intent.redact(reaction.mx_room, reaction.mxid) reaction.delete() + async def handle_facebook_join(self, source: 'u.User', sender: 'p.Puppet', + users: List['p.Puppet']) -> None: + sender_intent = sender.intent_for(self) + for user in users: + await sender_intent.invite_user(self.mxid, user.mxid) + await user.intent_for(self).join_room_by_id(self.mxid) + + async def handle_facebook_leave(self, source: 'u.User', sender: 'p.Puppet', removed: 'p.Puppet' + ) -> None: + if sender == removed: + await removed.intent_for(self).leave_room(self.mxid) + else: + try: + await sender.intent_for(self).kick_user(self.mxid, removed.mxid) + except MForbidden: + await self.main_intent.kick_user(self.mxid, removed.mxid, + reason=f"Kicked by {sender.name}") + # endregion # region Getters diff --git a/mautrix_facebook/user.py b/mautrix_facebook/user.py index 1bfad54..8ea747c 100644 --- a/mautrix_facebook/user.py +++ b/mautrix_facebook/user.py @@ -319,6 +319,8 @@ class User: fbchat.ReactionEvent: self.on_reaction, fbchat.Presence: self.on_presence, fbchat.Typing: self.on_typing, + fbchat.PeopleAdded: self.on_members_added, + fbchat.PersonRemoved: self.on_member_removed, } self.log.debug("Starting fbchat listener") async for event in self.listener.listen(): @@ -358,9 +360,8 @@ class User: await portal.handle_facebook_message(self, puppet, evt.message) async def on_title_change(self, evt: fbchat.TitleSet) -> None: - # TODO this check is probably useless, users' titles don't change - fb_receiver = self.fbid if isinstance(evt.thread, fbchat.User) else None - portal = po.Portal.get_by_thread(evt.thread, fb_receiver) + assert isinstance(evt.thread, fbchat.Group) + portal = po.Portal.get_by_thread(evt.thread) if not portal: return sender = pu.Puppet.get_by_fbid(evt.author.id) @@ -425,6 +426,22 @@ class User: puppet = pu.Puppet.get_by_fbid(evt.author.id) await puppet.intent.set_typing(portal.mxid, is_typing=evt.status, timeout=120000) + async def on_members_added(self, evt: fbchat.PeopleAdded) -> None: + assert isinstance(evt.thread, fbchat.Group) + portal = po.Portal.get_by_thread(evt.thread) + if portal.mxid: + sender = pu.Puppet.get_by_fbid(evt.author.id) + users = [pu.Puppet.get_by_fbid(user.id) for user in evt.added] + await portal.handle_facebook_join(self, sender, users) + + async def on_member_removed(self, evt: fbchat.PersonRemoved) -> None: + assert isinstance(evt.thread, fbchat.Group) + portal = po.Portal.get_by_thread(evt.thread) + if portal.mxid: + sender = pu.Puppet.get_by_fbid(evt.author.id) + user = pu.Puppet.get_by_fbid(evt.removed.id) + await portal.handle_facebook_leave(self, sender, user) + # endregion -- GitLab