diff --git a/mautrix_telegram/__main__.py b/mautrix_telegram/__main__.py
index 3d69241d..29d2f91d 100644
--- a/mautrix_telegram/__main__.py
+++ b/mautrix_telegram/__main__.py
@@ -31,7 +31,7 @@ from .context import Context
from .db import init as init_db
from .formatter import init as init_formatter
from .matrix import MatrixHandler
-from .portal import init as init_portal
+from .portal import Portal, init as init_portal
from .puppet import Puppet, init as init_puppet
from .sqlstatestore import SQLStateStore
from .user import User, init as init_user
@@ -97,10 +97,20 @@ class TelegramBridge(Bridge):
init_abstract_user(context)
init_formatter(context)
init_portal(context)
- puppet_startup = init_puppet(context)
- user_startup = init_user(context)
- bot_startup = [self.bot.start()] if self.bot else []
- self.startup_actions = chain(puppet_startup, user_startup, bot_startup)
+ self.add_startup_actions(init_puppet(context))
+ self.add_startup_actions(init_user(context))
+ if self.bot:
+ self.add_startup_actions(self.bot.start())
+ if self.config["bridge.resend_bridge_info"]:
+ self.add_startup_actions(self.resend_bridge_info())
+
+ async def resend_bridge_info(self) -> None:
+ self.config["bridge.resend_bridge_info"] = False
+ self.config.save()
+ self.log.info("Re-sending bridge info state event to all portals")
+ for portal in Portal.all():
+ await portal.update_bridge_info()
+ self.log.info("Finished re-sending bridge info state events")
def prepare_stop(self) -> None:
for puppet in Puppet.by_custom_mxid.values():
diff --git a/mautrix_telegram/config.py b/mautrix_telegram/config.py
index 503f6c92..5e20e9a8 100644
--- a/mautrix_telegram/config.py
+++ b/mautrix_telegram/config.py
@@ -111,6 +111,7 @@ class Config(BaseBridgeConfig):
copy("bridge.private_chat_portal_meta")
copy("bridge.delivery_receipts")
copy("bridge.delivery_error_reports")
+ copy("bridge.resend_bridge_info")
copy("bridge.initial_power_level_overrides.group")
copy("bridge.initial_power_level_overrides.user")
diff --git a/mautrix_telegram/db/portal.py b/mautrix_telegram/db/portal.py
index 8fbe1a5a..fa0fd9d1 100644
--- a/mautrix_telegram/db/portal.py
+++ b/mautrix_telegram/db/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 .
-from typing import Optional
+from typing import Optional, Iterable
from sqlalchemy import Column, Integer, String, Boolean, Text, func, sql
@@ -56,3 +56,7 @@ class Portal(Base):
@classmethod
def get_by_username(cls, username: str) -> Optional['Portal']:
return cls._select_one_or_none(func.lower(cls.c.username) == username)
+
+ @classmethod
+ def all(cls) -> Iterable['Portal']:
+ yield from cls._select_all()
diff --git a/mautrix_telegram/example-config.yaml b/mautrix_telegram/example-config.yaml
index f9eca855..283c16ed 100644
--- a/mautrix_telegram/example-config.yaml
+++ b/mautrix_telegram/example-config.yaml
@@ -219,6 +219,10 @@ bridge:
delivery_receipts: false
# Whether or not delivery errors should be reported as messages in the Matrix room.
delivery_error_reports: false
+ # Set this to true to tell the bridge to re-send m.bridge events to all rooms on the next run.
+ # This field will automatically be changed back to false after it,
+ # except if the config file is not writable.
+ resend_bridge_info: false
# Overrides for base power levels.
initial_power_level_overrides:
diff --git a/mautrix_telegram/portal/base.py b/mautrix_telegram/portal/base.py
index 127cf6fa..830ff5ca 100644
--- a/mautrix_telegram/portal/base.py
+++ b/mautrix_telegram/portal/base.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 .
-from typing import Awaitable, Dict, List, Optional, Tuple, Union, Any, Set, TYPE_CHECKING
+from typing import Awaitable, Dict, List, Optional, Tuple, Union, Any, Set, Iterable, TYPE_CHECKING
from abc import ABC, abstractmethod
import asyncio
import logging
@@ -372,6 +372,14 @@ class BasePortal(ABC):
# endregion
# region Class instance lookup
+ @classmethod
+ def all(cls) -> Iterable['Portal']:
+ for db_portal in DBPortal.all():
+ try:
+ yield cls.by_tgid[(db_portal.tgid, db_portal.tg_receiver)]
+ except KeyError:
+ yield cls.from_db(db_portal)
+
@classmethod
def get_by_mxid(cls, mxid: RoomID) -> Optional['Portal']:
try:
@@ -515,7 +523,7 @@ class BasePortal(ABC):
pass
@abstractmethod
- async def _update_bridge_info(self) -> None:
+ async def update_bridge_info(self) -> None:
pass
@abstractmethod
diff --git a/mautrix_telegram/portal/matrix.py b/mautrix_telegram/portal/matrix.py
index b0c77cee..118e0ec7 100644
--- a/mautrix_telegram/portal/matrix.py
+++ b/mautrix_telegram/portal/matrix.py
@@ -500,7 +500,7 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC):
self.title = title
self.save()
await self._send_delivery_receipt(event_id)
- await self._update_bridge_info()
+ await self.update_bridge_info()
async def handle_matrix_avatar(self, sender: 'u.User', url: ContentURI, event_id: EventID
) -> None:
@@ -533,7 +533,7 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC):
self.save()
break
await self._send_delivery_receipt(event_id)
- await self._update_bridge_info()
+ await self.update_bridge_info()
async def handle_matrix_upgrade(self, sender: UserID, new_room: RoomID, event_id: EventID
) -> None:
diff --git a/mautrix_telegram/portal/metadata.py b/mautrix_telegram/portal/metadata.py
index eced61d9..863d794e 100644
--- a/mautrix_telegram/portal/metadata.py
+++ b/mautrix_telegram/portal/metadata.py
@@ -229,7 +229,7 @@ class PortalMetadata(BasePortal, ABC):
changed = await self._update_avatar(user, entity.photo) or changed
if changed:
self.save()
- await self._update_bridge_info()
+ await self.update_bridge_info()
if self.sync_matrix_state:
await self.sync_matrix_members()
@@ -286,7 +286,7 @@ class PortalMetadata(BasePortal, ABC):
info["channel"]["external_url"] = f"https://t.me/{puppet.username}"
return info
- async def _update_bridge_info(self) -> None:
+ async def update_bridge_info(self) -> None:
try:
self.log.debug("Updating bridge info...")
await self.main_intent.send_state_event(self.mxid, StateBridge,
@@ -664,7 +664,7 @@ class PortalMetadata(BasePortal, ABC):
if changed:
self.save()
- await self._update_bridge_info()
+ await self.update_bridge_info()
async def _update_username(self, username: str, save: bool = False) -> bool:
if self.username == username:
diff --git a/mautrix_telegram/portal/telegram.py b/mautrix_telegram/portal/telegram.py
index 4da6be75..fe9ed18d 100644
--- a/mautrix_telegram/portal/telegram.py
+++ b/mautrix_telegram/portal/telegram.py
@@ -555,13 +555,13 @@ class PortalTelegram(BasePortal, ABC):
return
if isinstance(action, MessageActionChatEditTitle):
await self._update_title(action.title, sender=sender, save=True)
- await self._update_bridge_info()
+ await self.update_bridge_info()
elif isinstance(action, MessageActionChatEditPhoto):
await self._update_avatar(source, action.photo, sender=sender, save=True)
- await self._update_bridge_info()
+ await self.update_bridge_info()
elif isinstance(action, MessageActionChatDeletePhoto):
await self._update_avatar(source, ChatPhotoEmpty(), sender=sender, save=True)
- await self._update_bridge_info()
+ await self.update_bridge_info()
elif isinstance(action, MessageActionChatAddUser):
for user_id in action.users:
await self._add_telegram_user(TelegramID(user_id), source)
@@ -575,7 +575,7 @@ class PortalTelegram(BasePortal, ABC):
# TODO encrypt
await sender.intent_for(self).send_emote(self.mxid,
"upgraded this group to a supergroup.")
- await self._update_bridge_info()
+ await self.update_bridge_info()
elif isinstance(action, MessageActionGameScore):
# TODO handle game score
pass