Kick own puppets when turning on double puppeting

And invite them when turning it off
This commit is contained in:
Andrew Ferrazzutti 2021-05-06 02:15:21 -04:00
parent a2a21927cd
commit baf7db73b7
3 changed files with 38 additions and 4 deletions

View File

@ -79,7 +79,8 @@ bridge:
# Set 0 to disable automatic syncing. # Set 0 to disable automatic syncing.
initial_conversation_sync: 10 initial_conversation_sync: 10
# Whether or not the LINE users of logged in Matrix users should be # Whether or not the LINE users of logged in Matrix users should be
# invited to private chats when the user sends a message from another client. # invited to rooms when the user sends a message from another client.
# NOTE: This setting is forced to "false" when custom puppets are enabled.
invite_own_puppet_to_pm: false invite_own_puppet_to_pm: false
# Shared secret for https://github.com/devture/matrix-synapse-shared-secret-auth # Shared secret for https://github.com/devture/matrix-synapse-shared-secret-auth
# #

View File

@ -29,7 +29,7 @@ from mautrix.types import (EventID, MessageEventContent, RoomID, EventType, Mess
TextMessageEventContent, MediaMessageEventContent, Membership, Format, TextMessageEventContent, MediaMessageEventContent, Membership, Format,
ContentURI, EncryptedFile, ImageInfo, ContentURI, EncryptedFile, ImageInfo,
RelatesTo, RelationType) RelatesTo, RelationType)
from mautrix.errors import MatrixError from mautrix.errors import IntentError, MatrixError
from mautrix.util.simple_lock import SimpleLock from mautrix.util.simple_lock import SimpleLock
from .db import Portal as DBPortal, Message as DBMessage, ReceiptReaction as DBReceiptReaction, Media as DBMedia from .db import Portal as DBPortal, Message as DBMessage, ReceiptReaction as DBReceiptReaction, Media as DBMedia
@ -91,6 +91,12 @@ class Portal(DBPortal, BasePortal):
def is_room(self) -> bool: def is_room(self) -> bool:
return self.chat_id[0] == "r" return self.chat_id[0] == "r"
@property
def needs_bridgebot(self) -> bool:
# TODO Ask Tulir why e2b needs the bridgebot to be in the room
# Reminder that the bridgebot's intent is used for non-DM rooms
return not self.is_direct or (self.encrypted and self.matrix.e2ee)
@property @property
def main_intent(self) -> IntentAPI: def main_intent(self) -> IntentAPI:
if not self._main_intent: if not self._main_intent:
@ -110,6 +116,7 @@ class Portal(DBPortal, BasePortal):
NotificationDisabler.config_enabled = cls.config["bridge.backfill.disable_notifications"] NotificationDisabler.config_enabled = cls.config["bridge.backfill.disable_notifications"]
async def _send_delivery_receipt(self, event_id: EventID) -> None: async def _send_delivery_receipt(self, event_id: EventID) -> None:
# TODO Also send receipt from own puppet, if it's in the room
if event_id and self.config["bridge.delivery_receipts"]: if event_id and self.config["bridge.delivery_receipts"]:
try: try:
await self.az.intent.mark_read(self.mxid, event_id) await self.az.intent.mark_read(self.mxid, event_id)
@ -187,7 +194,15 @@ class Portal(DBPortal, BasePortal):
intent = sender.intent if sender else self.az.intent intent = sender.intent if sender else self.az.intent
if self.is_direct and (sender is None or sender.mid == source.mid and not sender.is_real_user): if self.is_direct and (sender is None or sender.mid == source.mid and not sender.is_real_user):
if self.invite_own_puppet_to_pm and invite: if self.invite_own_puppet_to_pm and invite:
try:
await intent.ensure_joined(self.mxid)
except IntentError as e:
if self.main_intent != self.az.intent:
await self.main_intent.invite_user(self.mxid, intent.mxid) await self.main_intent.invite_user(self.mxid, intent.mxid)
await intent.ensure_joined(self.mxid)
else:
self.log.warning(f"Unable to invite own puppet to {self.mxid}: {e}")
intent = None
elif await self.az.state_store.get_membership(self.mxid, elif await self.az.state_store.get_membership(self.mxid,
intent.mxid) != Membership.JOIN: intent.mxid) != Membership.JOIN:
self.log.warning(f"Ignoring own {mid} in private chat because own puppet is not in" self.log.warning(f"Ignoring own {mid} in private chat because own puppet is not in"
@ -427,9 +442,16 @@ class Portal(DBPortal, BasePortal):
return return
self._last_participant_update = current_members self._last_participant_update = current_members
# TODO When supporting multiple bridge users, do this per user
forbid_own_puppets = \
not self.invite_own_puppet_to_pm or \
(await u.User.get_by_mxid(self.config["bridge.user"], False)).intent is not None
# Make sure puppets who should be here are here # Make sure puppets who should be here are here
for participant in participants: for participant in participants:
puppet = await p.Puppet.get_by_mid(participant.id) puppet = await p.Puppet.get_by_mid(participant.id)
if forbid_own_puppets and p.Puppet.is_mid_for_own_puppet(participant.id):
continue
await puppet.intent.ensure_joined(self.mxid) await puppet.intent.ensure_joined(self.mxid)
print(current_members) print(current_members)
@ -437,12 +459,18 @@ class Portal(DBPortal, BasePortal):
# Kick puppets who shouldn't be here # Kick puppets who shouldn't be here
for user_id in await self.main_intent.get_room_members(self.mxid): for user_id in await self.main_intent.get_room_members(self.mxid):
if user_id == self.az.bot_mxid: if user_id == self.az.bot_mxid:
if forbid_own_puppets and not self.needs_bridgebot:
await self.az.intent.leave_room(self.mxid)
continue continue
mid = p.Puppet.get_id_from_mxid(user_id) mid = p.Puppet.get_id_from_mxid(user_id)
if mid and mid not in current_members: if mid and mid not in current_members:
print(mid) print(mid)
await self.main_intent.kick_user(self.mxid, user_id, await self.main_intent.kick_user(self.mxid, user_id,
reason="User had left this chat") reason="User had left this chat")
elif forbid_own_puppets and p.Puppet.is_mid_for_own_puppet(mid):
await self.main_intent.kick_user(self.mxid, user_id,
reason="Kicking own puppet")
async def backfill(self, source: 'u.User') -> None: async def backfill(self, source: 'u.User') -> None:
try: try:
@ -594,7 +622,7 @@ class Portal(DBPortal, BasePortal):
if not self.mxid: if not self.mxid:
raise Exception("Failed to create room: no mxid returned") raise Exception("Failed to create room: no mxid returned")
if self.encrypted and self.matrix.e2ee and self.is_direct: if self.needs_bridgebot:
try: try:
await self.az.intent.ensure_joined(self.mxid) await self.az.intent.ensure_joined(self.mxid)
except Exception: except Exception:

View File

@ -148,6 +148,11 @@ class Puppet(DBPuppet, BasePuppet):
return None return None
# TODO When supporting multiple bridge users, this should return the user whose puppet this is
@classmethod
def is_mid_for_own_puppet(cls, mid) -> bool:
return mid.startswith("_OWN_") if mid else False
@classmethod @classmethod
async def get_by_custom_mxid(cls, mxid: UserID) -> Optional['u.User']: async def get_by_custom_mxid(cls, mxid: UserID) -> Optional['u.User']:
if mxid == cls.config["bridge.user"]: if mxid == cls.config["bridge.user"]: