diff --git a/mautrix_telegram/db/portal.py b/mautrix_telegram/db/portal.py index f20c504b..c410b892 100644 --- a/mautrix_telegram/db/portal.py +++ b/mautrix_telegram/db/portal.py @@ -22,7 +22,7 @@ from asyncpg import Record from attr import dataclass import attr -from mautrix.types import ContentURI, EventID, RoomID +from mautrix.types import BatchID, ContentURI, EventID, RoomID from mautrix.util.async_db import Database from ..types import TelegramID @@ -44,6 +44,8 @@ class Portal: mxid: RoomID | None avatar_url: ContentURI | None encrypted: bool + first_event_id: EventID | None + next_batch_id: BatchID | None sponsored_event_id: EventID | None sponsored_event_ts: int | None @@ -67,10 +69,28 @@ class Portal: data["local_config"] = json.loads(data.pop("config", None) or "{}") return cls(**data) - columns: ClassVar[str] = ( - "tgid, tg_receiver, peer_type, megagroup, mxid, avatar_url, encrypted, sponsored_event_id," - "sponsored_event_ts, sponsored_msg_random_id, username, title, about, photo_id, " - "name_set, avatar_set, config" + columns: ClassVar[str] = ", ".join( + ( + "tgid", + "tg_receiver", + "peer_type", + "megagroup", + "mxid", + "avatar_url", + "encrypted", + "first_event_id", + "next_batch_id", + "sponsored_event_id", + "sponsored_event_ts", + "sponsored_msg_random_id", + "username", + "title", + "about", + "photo_id", + "name_set", + "avatar_set", + "config", + ) ) @classmethod @@ -112,6 +132,8 @@ class Portal: self.mxid, self.avatar_url, self.encrypted, + self.first_event_id, + self.next_batch_id, self.sponsored_event_id, self.sponsored_event_ts, self.sponsored_msg_random_id, @@ -128,9 +150,10 @@ class Portal: async def save(self) -> None: q = """ UPDATE portal - SET mxid=$4, avatar_url=$5, encrypted=$6, sponsored_event_id=$7, sponsored_event_ts=$8, - sponsored_msg_random_id=$9, username=$10, title=$11, about=$12, photo_id=$13, - name_set=$14, avatar_set=$15, megagroup=$16, config=$17 + SET mxid=$4, avatar_url=$5, encrypted=$6, first_event_id=$7, next_batch_id=$8, + sponsored_event_id=$9, sponsored_event_ts=$10, sponsored_msg_random_id=$11, + username=$12, title=$13, about=$14, photo_id=$15, name_set=$16, avatar_set=$17, + megagroup=$18, config=$19 WHERE tgid=$1 AND tg_receiver=$2 AND (peer_type=$3 OR true) """ await self.db.execute(q, *self._values) @@ -148,10 +171,11 @@ class Portal: async def insert(self) -> None: q = """ INSERT INTO portal ( - tgid, tg_receiver, peer_type, mxid, avatar_url, encrypted, - sponsored_event_id, sponsored_event_ts, sponsored_msg_random_id, + tgid, tg_receiver, peer_type, mxid, avatar_url, encrypted, first_event_id, + next_batch_id, sponsored_event_id, sponsored_event_ts, sponsored_msg_random_id, username, title, about, photo_id, name_set, avatar_set, megagroup, config - ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) + ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, + $19) """ await self.db.execute(q, *self._values) diff --git a/mautrix_telegram/db/upgrade/__init__.py b/mautrix_telegram/db/upgrade/__init__.py index 2f3fe794..106e0260 100644 --- a/mautrix_telegram/db/upgrade/__init__.py +++ b/mautrix_telegram/db/upgrade/__init__.py @@ -10,4 +10,5 @@ from . import ( v05_channel_ghosts, v06_puppet_avatar_url, v07_puppet_phone_number, + v08_infinite_backfill, ) diff --git a/mautrix_telegram/db/upgrade/v08_infinite_backfill.py b/mautrix_telegram/db/upgrade/v08_infinite_backfill.py new file mode 100644 index 00000000..9fba7bc4 --- /dev/null +++ b/mautrix_telegram/db/upgrade/v08_infinite_backfill.py @@ -0,0 +1,24 @@ +# mautrix-telegram - A Matrix-Telegram puppeting bridge +# Copyright (C) 2022 Tulir Asokan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from mautrix.util.async_db import Connection + +from . import upgrade_table + + +@upgrade_table.register(description="Switch to infinite backfill with MSC2716") +async def upgrade_v8(conn: Connection) -> None: + await conn.execute("ALTER TABLE portal ADD COLUMN first_event_id TEXT") + await conn.execute("ALTER TABLE portal ADD COLUMN next_batch_id TEXT") diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index 0e59d70a..092f7bb4 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -167,6 +167,7 @@ from mautrix.appservice import DOUBLE_PUPPET_SOURCE_KEY, IntentAPI from mautrix.bridge import BasePortal, NotificationDisabler, RejectMatrixInvite, async_getter_lock from mautrix.errors import IntentError, MatrixRequestError, MForbidden from mautrix.types import ( + BatchID, ContentURI, EventID, EventType, @@ -221,6 +222,7 @@ if TYPE_CHECKING: StateBridge = EventType.find("m.bridge", EventType.Class.STATE) StateHalfShotBridge = EventType.find("uk.half-shot.bridge", EventType.Class.STATE) +DummyPortalCreated = EventType.find("fi.mau.dummy.portal_created", EventType.Class.MESSAGE) BEEPER_LINK_PREVIEWS_KEY = "com.beeper.linkpreviews" BEEPER_IMAGE_ENCRYPTION_KEY = "beeper:image:encryption" @@ -304,6 +306,8 @@ class Portal(DBPortal, BasePortal): mxid: RoomID | None = None, avatar_url: ContentURI | None = None, encrypted: bool = False, + first_event_id: EventID | None = None, + next_batch_id: BatchID | None = None, sponsored_event_id: EventID | None = None, sponsored_event_ts: int | None = None, sponsored_msg_random_id: bytes | None = None, @@ -323,6 +327,8 @@ class Portal(DBPortal, BasePortal): mxid=mxid, avatar_url=avatar_url, encrypted=encrypted, + first_event_id=first_event_id, + next_batch_id=next_batch_id, sponsored_event_id=sponsored_event_id, sponsored_event_ts=sponsored_event_ts, sponsored_msg_random_id=sponsored_msg_random_id, @@ -890,7 +896,11 @@ class Portal(DBPortal, BasePortal): self.mxid = room_id self.by_mxid[self.mxid] = self + self.first_event_id = await self.main_intent.send_message_event( + self.mxid, DummyPortalCreated, {} + ) await self.save() + self.log.debug(f"Matrix room created: {self.mxid}") await self.az.state_store.set_power_levels(self.mxid, power_levels) await user.register_portal(self) @@ -2211,6 +2221,8 @@ class Portal(DBPortal, BasePortal): except KeyError: pass self.mxid = new_id + self.next_batch_id = None + self.first_event_id = None self.by_mxid[self.mxid] = self await self.save() @@ -3546,6 +3558,8 @@ class Portal(DBPortal, BasePortal): self.name_set = False self.avatar_set = False self.about = None + self.next_batch_id = None + self.first_event_id = None self.sponsored_event_id = None self.sponsored_event_ts = None self.sponsored_msg_random_id = None