Sync mute status even if portal is created outside dialog sync

Closes #897
This commit is contained in:
Tulir Asokan
2023-03-10 13:35:25 +02:00
parent 6eda8bd165
commit 233468b37b
2 changed files with 70 additions and 15 deletions
+42 -2
View File
@@ -23,6 +23,7 @@ from sqlite3 import IntegrityError
from string import Template from string import Template
import asyncio import asyncio
import base64 import base64
import itertools
import random import random
import time import time
@@ -36,6 +37,7 @@ from telethon.errors import (
ReactionInvalidError, ReactionInvalidError,
RPCError, RPCError,
) )
from telethon.tl.custom import Dialog
from telethon.tl.functions.channels import ( from telethon.tl.functions.channels import (
CreateChannelRequest, CreateChannelRequest,
EditPhotoRequest, EditPhotoRequest,
@@ -54,6 +56,7 @@ from telethon.tl.functions.messages import (
ExportChatInviteRequest, ExportChatInviteRequest,
GetMessageReactionsListRequest, GetMessageReactionsListRequest,
GetMessagesReactionsRequest, GetMessagesReactionsRequest,
GetPeerDialogsRequest,
MigrateChatRequest, MigrateChatRequest,
SendReactionRequest, SendReactionRequest,
SetTypingRequest, SetTypingRequest,
@@ -66,6 +69,7 @@ from telethon.tl.types import (
ChannelFull, ChannelFull,
Chat, Chat,
ChatBannedRights, ChatBannedRights,
ChatEmpty,
ChatFull, ChatFull,
ChatPhoto, ChatPhoto,
ChatPhotoEmpty, ChatPhotoEmpty,
@@ -76,6 +80,7 @@ from telethon.tl.types import (
GeoPoint, GeoPoint,
InputChannel, InputChannel,
InputChatUploadedPhoto, InputChatUploadedPhoto,
InputDialogPeer,
InputMediaUploadedDocument, InputMediaUploadedDocument,
InputMediaUploadedPhoto, InputMediaUploadedPhoto,
InputPeerChannel, InputPeerChannel,
@@ -136,11 +141,13 @@ from telethon.tl.types import (
UpdatePhoneCall, UpdatePhoneCall,
UpdateUserTyping, UpdateUserTyping,
User, User,
UserEmpty,
UserFull, UserFull,
UserProfilePhoto, UserProfilePhoto,
UserProfilePhotoEmpty, UserProfilePhotoEmpty,
) )
from telethon.utils import encode_waveform from telethon.tl.types.messages import PeerDialogs
from telethon.utils import encode_waveform, get_peer_id
import attr import attr
from mautrix.appservice import DOUBLE_PUPPET_SOURCE_KEY, IntentAPI from mautrix.appservice import DOUBLE_PUPPET_SOURCE_KEY, IntentAPI
@@ -725,6 +732,7 @@ class Portal(DBPortal, BasePortal):
entity: TypeChat | User = None, entity: TypeChat | User = None,
invites: InviteList = None, invites: InviteList = None,
update_if_exists: bool = True, update_if_exists: bool = True,
from_dialog_sync: bool = False,
client: MautrixTelegramClient | None = None, client: MautrixTelegramClient | None = None,
) -> RoomID | None: ) -> RoomID | None:
if self.mxid: if self.mxid:
@@ -741,7 +749,9 @@ class Portal(DBPortal, BasePortal):
return self.mxid return self.mxid
async with self._room_create_lock: async with self._room_create_lock:
try: try:
return await self._create_matrix_room(user, entity, invites, client=client) return await self._create_matrix_room(
user, entity, invites, client=client, from_dialog_sync=from_dialog_sync
)
except Exception: except Exception:
self.log.exception("Fatal error creating Matrix room") self.log.exception("Fatal error creating Matrix room")
@@ -796,6 +806,7 @@ class Portal(DBPortal, BasePortal):
user: au.AbstractUser, user: au.AbstractUser,
entity: TypeChat | User, entity: TypeChat | User,
invites: InviteList, invites: InviteList,
from_dialog_sync: bool,
client: MautrixTelegramClient | None = None, client: MautrixTelegramClient | None = None,
) -> RoomID | None: ) -> RoomID | None:
if self.mxid: if self.mxid:
@@ -807,6 +818,31 @@ class Portal(DBPortal, BasePortal):
invites = invites or [] invites = invites or []
dialog = None
if not from_dialog_sync and not user.is_bot:
self.log.debug("Fetching dialog info for new portal")
dialogs: PeerDialogs = await user.client(
GetPeerDialogsRequest(peers=[InputDialogPeer(await self.get_input_entity(user))])
)
if dialogs.chats and dialogs.chats[0].id == self.tgid:
entity = dialogs.chats[0]
self.log.debug("Got entity info from get dialogs request")
elif self.is_direct and dialogs.users:
for user in dialogs.users:
if user.id == self.tgid:
entity = user
self.log.debug("Got user entity info from get dialogs request")
break
if dialogs.dialogs:
entities = {
get_peer_id(x): x
for x in itertools.chain(dialogs.users, dialogs.chats)
if not isinstance(x, (UserEmpty, ChatEmpty))
}
msg = dialogs.messages[0] if len(dialogs.messages) == 1 else None
dialog = Dialog(user.client, dialogs.dialogs[0], entities, msg)
self.log.debug("Got dialog info for new portal: %s", dialog)
if not entity: if not entity:
entity = await self.get_entity(user, client) entity = await self.get_entity(user, client)
self.log.trace("Fetched data: %s", entity) self.log.trace("Fetched data: %s", entity)
@@ -959,6 +995,10 @@ class Portal(DBPortal, BasePortal):
self.log.debug(f"Matrix room created: {self.mxid}") self.log.debug(f"Matrix room created: {self.mxid}")
await self.az.state_store.set_power_levels(self.mxid, power_levels) await self.az.state_store.set_power_levels(self.mxid, power_levels)
await user.register_portal(self) await user.register_portal(self)
if dialog and isinstance(user, u.User):
await user.post_sync_dialog(
self, puppet=None, was_created=True, **user.dialog_to_sync_args(dialog)
)
if not autojoin_invites or not self.is_direct: if not autojoin_invites or not self.is_direct:
await self.invite_to_matrix(invites) await self.invite_to_matrix(invites)
+28 -13
View File
@@ -490,13 +490,16 @@ class User(DBUser, AbstractUser, BaseUser):
self.log.info(f"Creating portal for {portal.tgid_log} as part of backfill loop") self.log.info(f"Creating portal for {portal.tgid_log} as part of backfill loop")
try: try:
await portal.create_matrix_room( await portal.create_matrix_room(
self, client=client, update_if_exists=False, invites=[self.mxid] self,
client=client,
update_if_exists=False,
invites=[self.mxid],
from_dialog_sync=True,
) )
except Exception: except Exception:
self.log.exception(f"Error while creating {portal.tgid_log}") self.log.exception(f"Error while creating {portal.tgid_log}")
else: else:
puppet = await pu.Puppet.get_by_custom_mxid(self.mxid) await self.post_sync_dialog(portal, puppet=None, was_created=True, **post_sync_args)
await self._post_sync_dialog(portal, puppet, was_created=True, **post_sync_args)
async def update(self, update: TypeUpdate) -> bool: async def update(self, update: TypeUpdate) -> bool:
if not self.is_bot: if not self.is_bot:
@@ -746,12 +749,12 @@ class User(DBUser, AbstractUser, BaseUser):
) )
await self._mute_room(puppet, portal, update.notify_settings.mute_until.timestamp()) await self._mute_room(puppet, portal, update.notify_settings.mute_until.timestamp())
async def _sync_dialog( @staticmethod
self, portal: po.Portal, dialog: Dialog, should_create: bool, puppet: pu.Puppet | None def dialog_to_sync_args(dialog: Dialog) -> dict:
) -> None: return {
was_created = False "last_message_ts": (
post_sync_args = { cast(datetime, dialog.date).timestamp() if dialog.date else time.time()
"last_message_ts": cast(datetime, dialog.date).timestamp(), ),
"unread_count": dialog.unread_count, "unread_count": dialog.unread_count,
"max_read_id": dialog.dialog.read_inbox_max_id, "max_read_id": dialog.dialog.read_inbox_max_id,
"mute_until": ( "mute_until": (
@@ -762,6 +765,12 @@ class User(DBUser, AbstractUser, BaseUser):
"pinned": dialog.pinned, "pinned": dialog.pinned,
"archived": dialog.archived, "archived": dialog.archived,
} }
async def _sync_dialog(
self, portal: po.Portal, dialog: Dialog, should_create: bool, puppet: pu.Puppet | None
) -> None:
was_created = False
post_sync_args = self.dialog_to_sync_args(dialog)
if portal.mxid: if portal.mxid:
self.log.debug(f"Backfilling and updating {portal.tgid_log} (dialog sync)") self.log.debug(f"Backfilling and updating {portal.tgid_log} (dialog sync)")
try: try:
@@ -775,7 +784,9 @@ class User(DBUser, AbstractUser, BaseUser):
elif should_create: elif should_create:
self.log.debug(f"Creating portal for {portal.tgid_log} immediately (dialog sync)") self.log.debug(f"Creating portal for {portal.tgid_log} immediately (dialog sync)")
try: try:
await portal.create_matrix_room(self, dialog.entity, invites=[self.mxid]) await portal.create_matrix_room(
self, dialog.entity, invites=[self.mxid], from_dialog_sync=True
)
was_created = True was_created = True
except Exception: except Exception:
self.log.exception(f"Error while creating {portal.tgid_log}") self.log.exception(f"Error while creating {portal.tgid_log}")
@@ -788,7 +799,7 @@ class User(DBUser, AbstractUser, BaseUser):
extra_data=post_sync_args, extra_data=post_sync_args,
) )
if portal.mxid and puppet and puppet.is_real_user: if portal.mxid and puppet and puppet.is_real_user:
await self._post_sync_dialog( await self.post_sync_dialog(
portal=portal, portal=portal,
puppet=puppet, puppet=puppet,
was_created=was_created, was_created=was_created,
@@ -796,10 +807,10 @@ class User(DBUser, AbstractUser, BaseUser):
) )
self.log.debug(f"_sync_dialog finished for {portal.tgid_log}") self.log.debug(f"_sync_dialog finished for {portal.tgid_log}")
async def _post_sync_dialog( async def post_sync_dialog(
self, self,
portal: po.Portal, portal: po.Portal,
puppet: pu.Puppet, puppet: pu.Puppet | None,
was_created: bool, was_created: bool,
max_read_id: int, max_read_id: int,
last_message_ts: float, last_message_ts: float,
@@ -808,6 +819,10 @@ class User(DBUser, AbstractUser, BaseUser):
pinned: bool, pinned: bool,
archived: bool, archived: bool,
) -> None: ) -> None:
if puppet is None:
puppet = await pu.Puppet.get_by_custom_mxid(self.mxid)
if not puppet or not puppet.is_real_user:
return
self.log.debug( self.log.debug(
f"Running dialog post-sync for {portal.tgid_log} with args " f"Running dialog post-sync for {portal.tgid_log} with args "
f"{was_created=}, {max_read_id=}, {last_message_ts=}, {unread_count=}, " f"{was_created=}, {max_read_id=}, {last_message_ts=}, {unread_count=}, "