Add option to update m.direct with double puppeting
This commit is contained in:
@@ -130,5 +130,8 @@ class TelegramBridge(Bridge):
|
|||||||
async def get_double_puppet(self, user_id: UserID) -> Puppet:
|
async def get_double_puppet(self, user_id: UserID) -> Puppet:
|
||||||
return await Puppet.get_by_custom_mxid(user_id)
|
return await Puppet.get_by_custom_mxid(user_id)
|
||||||
|
|
||||||
|
def is_bridge_ghost(self, user_id: UserID) -> bool:
|
||||||
|
return bool(Puppet.get_id_from_mxid(user_id))
|
||||||
|
|
||||||
|
|
||||||
TelegramBridge().run()
|
TelegramBridge().run()
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ class Config(BaseBridgeConfig):
|
|||||||
super().do_update(helper)
|
super().do_update(helper)
|
||||||
copy, copy_dict, base = helper
|
copy, copy_dict, base = helper
|
||||||
|
|
||||||
|
copy("homeserver.asmux")
|
||||||
|
|
||||||
if "appservice.protocol" in self and "appservice.address" not in self:
|
if "appservice.protocol" in self and "appservice.address" not in self:
|
||||||
protocol, hostname, port = (self["appservice.protocol"], self["appservice.hostname"],
|
protocol, hostname, port = (self["appservice.protocol"], self["appservice.hostname"],
|
||||||
self["appservice.port"])
|
self["appservice.port"])
|
||||||
@@ -102,6 +104,7 @@ class Config(BaseBridgeConfig):
|
|||||||
copy("bridge.plaintext_highlights")
|
copy("bridge.plaintext_highlights")
|
||||||
copy("bridge.public_portals")
|
copy("bridge.public_portals")
|
||||||
copy("bridge.sync_with_custom_puppets")
|
copy("bridge.sync_with_custom_puppets")
|
||||||
|
copy("bridge.sync_direct_chat_list")
|
||||||
copy("bridge.login_shared_secret")
|
copy("bridge.login_shared_secret")
|
||||||
copy("bridge.telegram_link_preview")
|
copy("bridge.telegram_link_preview")
|
||||||
copy("bridge.inline_images")
|
copy("bridge.inline_images")
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ class Portal(Base):
|
|||||||
def get_by_tgid(cls, tgid: TelegramID, tg_receiver: TelegramID) -> Optional['Portal']:
|
def get_by_tgid(cls, tgid: TelegramID, tg_receiver: TelegramID) -> Optional['Portal']:
|
||||||
return cls._select_one_or_none(cls.c.tgid == tgid, cls.c.tg_receiver == tg_receiver)
|
return cls._select_one_or_none(cls.c.tgid == tgid, cls.c.tg_receiver == tg_receiver)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def find_private_chats(cls, tg_receiver: TelegramID) -> Iterable['Portal']:
|
||||||
|
yield from cls._select_all(cls.c.tg_receiver == tg_receiver, cls.c.peer_type == "user")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by_mxid(cls, mxid: RoomID) -> Optional['Portal']:
|
def get_by_mxid(cls, mxid: RoomID) -> Optional['Portal']:
|
||||||
return cls._select_one_or_none(cls.c.mxid == mxid)
|
return cls._select_one_or_none(cls.c.mxid == mxid)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ homeserver:
|
|||||||
# Whether or not to verify the SSL certificate of the homeserver.
|
# Whether or not to verify the SSL certificate of the homeserver.
|
||||||
# Only applies if address starts with https://
|
# Only applies if address starts with https://
|
||||||
verify_ssl: true
|
verify_ssl: true
|
||||||
|
asmux: false
|
||||||
|
|
||||||
# Application service host/registration related details
|
# Application service host/registration related details
|
||||||
# Changing these values requires regeneration of the registration.
|
# Changing these values requires regeneration of the registration.
|
||||||
@@ -163,9 +164,13 @@ bridge:
|
|||||||
plaintext_highlights: false
|
plaintext_highlights: false
|
||||||
# Whether or not to make portals of publicly joinable channels/supergroups publicly joinable on Matrix.
|
# Whether or not to make portals of publicly joinable channels/supergroups publicly joinable on Matrix.
|
||||||
public_portals: true
|
public_portals: true
|
||||||
# Whether or not to use /sync to get presence, read receipts and typing notifications when using
|
# Whether or not to use /sync to get presence, read receipts and typing notifications
|
||||||
# your own Matrix account as the Matrix puppet for your Telegram account.
|
# when double puppeting is enabled
|
||||||
sync_with_custom_puppets: true
|
sync_with_custom_puppets: true
|
||||||
|
# Whether or not to update the m.direct account data event when double puppeting is enabled.
|
||||||
|
# Note that updating the m.direct event is not atomic (except with mautrix-asmux)
|
||||||
|
# and is therefore prone to race conditions.
|
||||||
|
sync_direct_chat_list: 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
|
||||||
#
|
#
|
||||||
# If set, custom puppets will be enabled automatically for local users
|
# If set, custom puppets will be enabled automatically for local users
|
||||||
|
|||||||
@@ -220,7 +220,9 @@ class PortalMetadata(BasePortal, ABC):
|
|||||||
puppet = await p.Puppet.get_by_custom_mxid(user.mxid)
|
puppet = await p.Puppet.get_by_custom_mxid(user.mxid)
|
||||||
if puppet:
|
if puppet:
|
||||||
try:
|
try:
|
||||||
await puppet.intent.ensure_joined(self.mxid)
|
did_join = await puppet.intent.ensure_joined(self.mxid)
|
||||||
|
if isinstance(user, u.User) and did_join and self.peer_type == "user":
|
||||||
|
await user.update_direct_chats({self.main_intent.mxid: [self.mxid]})
|
||||||
except Exception:
|
except Exception:
|
||||||
self.log.exception("Failed to ensure %s is joined to portal", user.mxid)
|
self.log.exception("Failed to ensure %s is joined to portal", user.mxid)
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ from telethon.tl.functions.account import UpdateStatusRequest
|
|||||||
|
|
||||||
from mautrix.client import Client
|
from mautrix.client import Client
|
||||||
from mautrix.errors import MatrixRequestError
|
from mautrix.errors import MatrixRequestError
|
||||||
from mautrix.types import UserID
|
from mautrix.types import UserID, RoomID
|
||||||
from mautrix.bridge import BaseUser
|
from mautrix.bridge import BaseUser
|
||||||
from mautrix.util.logging import TraceLogger
|
from mautrix.util.logging import TraceLogger
|
||||||
|
|
||||||
from .types import TelegramID
|
from .types import TelegramID
|
||||||
from .db import User as DBUser
|
from .db import User as DBUser, Portal as DBPortal
|
||||||
from .abstract_user import AbstractUser
|
from .abstract_user import AbstractUser
|
||||||
from . import portal as po, puppet as pu
|
from . import portal as po, puppet as pu
|
||||||
|
|
||||||
@@ -79,6 +79,7 @@ class User(AbstractUser, BaseUser):
|
|||||||
self.db_portals = db_portals or []
|
self.db_portals = db_portals or []
|
||||||
self._db_instance = db_instance
|
self._db_instance = db_instance
|
||||||
self._ensure_started_lock = asyncio.Lock()
|
self._ensure_started_lock = asyncio.Lock()
|
||||||
|
self.dm_update_lock = asyncio.Lock()
|
||||||
|
|
||||||
self.command_status = None
|
self.command_status = None
|
||||||
|
|
||||||
@@ -340,6 +341,13 @@ class User(AbstractUser, BaseUser):
|
|||||||
except Exception:
|
except Exception:
|
||||||
self.log.exception(f"Error while {action}")
|
self.log.exception(f"Error while {action}")
|
||||||
|
|
||||||
|
async def get_direct_chats(self) -> Dict[UserID, List[RoomID]]:
|
||||||
|
return {
|
||||||
|
pu.Puppet.get_mxid_from_id(portal.tgid): [portal.mxid]
|
||||||
|
for portal in DBPortal.find_private_chats(self.tgid)
|
||||||
|
if portal.mxid
|
||||||
|
}
|
||||||
|
|
||||||
async def sync_dialogs(self) -> None:
|
async def sync_dialogs(self) -> None:
|
||||||
if self.is_bot:
|
if self.is_bot:
|
||||||
return
|
return
|
||||||
@@ -378,6 +386,7 @@ class User(AbstractUser, BaseUser):
|
|||||||
index += 1
|
index += 1
|
||||||
await self.save(portals=True)
|
await self.save(portals=True)
|
||||||
await asyncio.gather(*creators)
|
await asyncio.gather(*creators)
|
||||||
|
await self.update_direct_chats()
|
||||||
self.log.debug("Dialog syncing complete")
|
self.log.debug("Dialog syncing complete")
|
||||||
|
|
||||||
async def register_portal(self, portal: po.Portal) -> None:
|
async def register_portal(self, portal: po.Portal) -> None:
|
||||||
@@ -482,6 +491,7 @@ class User(AbstractUser, BaseUser):
|
|||||||
def init(context: 'Context') -> Iterable[Awaitable['User']]:
|
def init(context: 'Context') -> Iterable[Awaitable['User']]:
|
||||||
global config
|
global config
|
||||||
config = context.config
|
config = context.config
|
||||||
|
User.bridge = context.bridge
|
||||||
|
|
||||||
return (User.from_db(db_user).try_ensure_started()
|
return (User.from_db(db_user).try_ensure_started()
|
||||||
for db_user in DBUser.all_with_tgid())
|
for db_user in DBUser.all_with_tgid())
|
||||||
|
|||||||
+1
-1
@@ -4,6 +4,6 @@ ruamel.yaml>=0.15.35,<0.17
|
|||||||
python-magic>=0.4,<0.5
|
python-magic>=0.4,<0.5
|
||||||
commonmark>=0.8,<0.10
|
commonmark>=0.8,<0.10
|
||||||
aiohttp>=3,<4
|
aiohttp>=3,<4
|
||||||
mautrix==0.7.0rc1
|
mautrix==0.7.0rc2
|
||||||
telethon>=1.16,<1.17
|
telethon>=1.16,<1.17
|
||||||
telethon-session-sqlalchemy>=0.2.14,<0.3
|
telethon-session-sqlalchemy>=0.2.14,<0.3
|
||||||
|
|||||||
Reference in New Issue
Block a user