diff --git a/example-config.yaml b/example-config.yaml index a07555e2..016270aa 100644 --- a/example-config.yaml +++ b/example-config.yaml @@ -325,7 +325,10 @@ telegram: logging: version: 1 formatters: - precise: + colored: + (): mautrix_telegram.util.ColorFormatter + format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s" + normal: format: "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s" handlers: file: diff --git a/mautrix_telegram/__main__.py b/mautrix_telegram/__main__.py index fe30799d..7d5c8d3a 100644 --- a/mautrix_telegram/__main__.py +++ b/mautrix_telegram/__main__.py @@ -91,9 +91,12 @@ class TelegramBridge(Bridge): init_portal(context) puppet_startup = init_puppet(context) user_startup = init_user(context) - self.startup_actions = chain(puppet_startup, user_startup, - [self.bot.start] if self.bot else []) + bot_startup = [self.bot.start()] if self.bot else [] + self.startup_actions = chain(puppet_startup, user_startup, bot_startup) async def stop(self) -> None: self.shutdown_actions = [user.stop() for user in User.by_tgid.values()] await super().stop() + + +TelegramBridge().run() diff --git a/mautrix_telegram/commands/handler.py b/mautrix_telegram/commands/handler.py index f8a1b3c0..63a6f17b 100644 --- a/mautrix_telegram/commands/handler.py +++ b/mautrix_telegram/commands/handler.py @@ -65,10 +65,10 @@ class CommandHandler(BaseCommandHandler): needs_matrix_puppeting: bool needs_admin: bool - def __init__(self, handler: Callable[[CommandEvent], Awaitable[EventID]], needs_auth: bool, - needs_puppeting: bool, needs_matrix_puppeting: bool, needs_admin: bool, + def __init__(self, handler: Callable[[CommandEvent], Awaitable[EventID]], management_only: bool, name: str, help_text: str, help_args: str, - help_section: HelpSection) -> None: + help_section: HelpSection, needs_auth: bool, needs_puppeting: bool, + needs_matrix_puppeting: bool, needs_admin: bool,) -> None: super().__init__(handler, management_only, name, help_text, help_args, help_section, needs_auth=needs_auth, needs_puppeting=needs_puppeting, needs_matrix_puppeting=needs_matrix_puppeting, needs_admin=needs_admin) diff --git a/mautrix_telegram/portal/__init__.py b/mautrix_telegram/portal/__init__.py index d0ccc839..1ec8b511 100644 --- a/mautrix_telegram/portal/__init__.py +++ b/mautrix_telegram/portal/__init__.py @@ -6,7 +6,7 @@ from .deduplication import init as init_dedup from ..context import Context -class Portal(BasePortal, PortalMatrix, PortalTelegram, PortalMetadata): +class Portal(PortalMatrix, PortalTelegram, PortalMetadata): pass diff --git a/mautrix_telegram/portal/__init__.pyi b/mautrix_telegram/portal/__init__.pyi index 0a500031..f705bfc7 100644 --- a/mautrix_telegram/portal/__init__.pyi +++ b/mautrix_telegram/portal/__init__.pyi @@ -3,5 +3,13 @@ from .base import BasePortal from .portal_matrix import PortalMatrix from .portal_metadata import PortalMetadata from .portal_telegram import PortalTelegram +from ..context import Context Portal = Union[BasePortal, PortalMatrix, PortalMetadata, PortalTelegram] + + +def init(context: Context) -> None: + pass + + +__all__ = ["Portal", "init"] diff --git a/mautrix_telegram/portal/base.py b/mautrix_telegram/portal/base.py index ec93b44e..8a0e7523 100644 --- a/mautrix_telegram/portal/base.py +++ b/mautrix_telegram/portal/base.py @@ -113,6 +113,7 @@ class BasePortal(ABC): self.photo_id = photo_id self.local_config = json.loads(local_config or "{}") self._db_instance = db_instance + self._main_intent = None self.deleted = False self.log = self.base_log.getChild(self.tgid_log) if self.tgid else self.base_log @@ -302,9 +303,9 @@ class BasePortal(ABC): config=json.dumps(self.local_config)) def save(self) -> None: - self.db_instance.update(mxid=self.mxid, username=self.username, title=self.title, - about=self.about, photo_id=self.photo_id, - config=json.dumps(self.local_config)) + self.db_instance.edit(mxid=self.mxid, username=self.username, title=self.title, + about=self.about, photo_id=self.photo_id, + config=json.dumps(self.local_config)) def delete(self) -> None: try: @@ -321,11 +322,11 @@ class BasePortal(ABC): @classmethod def from_db(cls, db_portal: DBPortal) -> 'Portal': - return Portal(tgid=db_portal.tgid, tg_receiver=db_portal.tg_receiver, - peer_type=db_portal.peer_type, mxid=db_portal.mxid, - username=db_portal.username, megagroup=db_portal.megagroup, - title=db_portal.title, about=db_portal.about, photo_id=db_portal.photo_id, - local_config=db_portal.config, db_instance=db_portal) + return cls(tgid=db_portal.tgid, tg_receiver=db_portal.tg_receiver, + peer_type=db_portal.peer_type, mxid=db_portal.mxid, + username=db_portal.username, megagroup=db_portal.megagroup, + title=db_portal.title, about=db_portal.about, photo_id=db_portal.photo_id, + local_config=db_portal.config, db_instance=db_portal) # endregion # region Class instance lookup @@ -380,7 +381,7 @@ class BasePortal(ABC): return cls.from_db(db_portal) if peer_type: - portal = Portal(tgid, peer_type=peer_type, tg_receiver=tg_receiver) + portal = cls(tgid, peer_type=peer_type, tg_receiver=tg_receiver) portal.db_instance.insert() return portal @@ -465,14 +466,14 @@ class BasePortal(ABC): def init(context: Context) -> None: global config - Portal.az, config, Portal.loop, Portal.bot = context.core - Portal.max_initial_member_sync = config["bridge.max_initial_member_sync"] - Portal.sync_channel_members = config["bridge.sync_channel_members"] - Portal.sync_matrix_state = config["bridge.sync_matrix_state"] - Portal.public_portals = config["bridge.public_portals"] - Portal.filter_mode = config["bridge.filter.mode"] - Portal.filter_list = config["bridge.filter.list"] - Portal.alias_template = config.get("bridge.alias_template", "telegram_{groupname}") - Portal.hs_domain = config["homeserver.domain"] - Portal.mx_alias_regex = re.compile( - f"#{Portal.alias_template.format(groupname='(.+)')}:{Portal.hs_domain}") + BasePortal.az, config, BasePortal.loop, BasePortal.bot = context.core + BasePortal.max_initial_member_sync = config["bridge.max_initial_member_sync"] + BasePortal.sync_channel_members = config["bridge.sync_channel_members"] + BasePortal.sync_matrix_state = config["bridge.sync_matrix_state"] + BasePortal.public_portals = config["bridge.public_portals"] + BasePortal.filter_mode = config["bridge.filter.mode"] + BasePortal.filter_list = config["bridge.filter.list"] + BasePortal.alias_template = config.get("bridge.alias_template", "telegram_{groupname}") + BasePortal.hs_domain = config["homeserver.domain"] + BasePortal.mx_alias_regex = re.compile( + f"#{BasePortal.alias_template.format(groupname='(.+)')}:{BasePortal.hs_domain}") diff --git a/mautrix_telegram/portal/portal_matrix.py b/mautrix_telegram/portal/portal_matrix.py index 3e1225b0..907c4704 100644 --- a/mautrix_telegram/portal/portal_matrix.py +++ b/mautrix_telegram/portal/portal_matrix.py @@ -491,8 +491,8 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC): if entity: break if not entity: - self.log.error( - "Failed to fully migrate to upgraded Matrix room: no Telegram user found.") + self.log.error("Failed to fully migrate to upgraded Matrix room: " + "no Telegram user found.") return await self.update_matrix_room(user, entity, direct=self.peer_type == "user") self.log.info(f"Upgraded room from {old_room} to {self.mxid}") @@ -503,7 +503,7 @@ class PortalMatrix(BasePortal, MautrixBasePortal, ABC): except KeyError: pass self.mxid = new_id - self.db_instance.update(mxid=self.mxid) + self.db_instance.edit(mxid=self.mxid) self.by_mxid[self.mxid] = self diff --git a/mautrix_telegram/portal/portal_metadata.py b/mautrix_telegram/portal/portal_metadata.py index 694477a4..d1c0c1cd 100644 --- a/mautrix_telegram/portal/portal_metadata.py +++ b/mautrix_telegram/portal/portal_metadata.py @@ -96,7 +96,7 @@ class PortalMetadata(BasePortal, ABC): existing.delete() except KeyError: pass - self.db_instance.update(tgid=new_id, tg_receiver=new_id, peer_type=self.peer_type) + self.db_instance.edit(tgid=new_id, tg_receiver=new_id, peer_type=self.peer_type) old_id = self.tgid self.tgid = new_id self.tg_receiver = new_id diff --git a/mautrix_telegram/portal/send_lock.py b/mautrix_telegram/portal/send_lock.py index 6e29834a..11a2d3ce 100644 --- a/mautrix_telegram/portal/send_lock.py +++ b/mautrix_telegram/portal/send_lock.py @@ -29,7 +29,7 @@ class FakeLock: class PortalSendLock: _send_locks: Dict[int, Lock] - _noop_lock: Lock = FakeLock + _noop_lock: Lock = FakeLock() def __init__(self) -> None: self._send_locks = {} diff --git a/mautrix_telegram/puppet.py b/mautrix_telegram/puppet.py index 1dc40728..0935d9c5 100644 --- a/mautrix_telegram/puppet.py +++ b/mautrix_telegram/puppet.py @@ -152,11 +152,11 @@ class Puppet(CustomPuppetMixin): db_puppet.disable_updates, db_instance=db_puppet) def save(self) -> None: - self.db_instance.update(access_token=self.access_token, custom_mxid=self.custom_mxid, - username=self.username, displayname=self.displayname, - displayname_source=self.displayname_source, photo_id=self.photo_id, - is_bot=self.is_bot, matrix_registered=self.is_registered, - disable_updates=self.disable_updates) + self.db_instance.edit(access_token=self.access_token, custom_mxid=self.custom_mxid, + username=self.username, displayname=self.displayname, + displayname_source=self.displayname_source, photo_id=self.photo_id, + is_bot=self.is_bot, matrix_registered=self.is_registered, + disable_updates=self.disable_updates) # endregion # region Info updating @@ -405,6 +405,6 @@ def init(context: 'Context') -> Iterable[Awaitable[Any]]: index = displayname_template.index("{displayname}") length = len("{displayname}") Puppet._displayname_prefix = displayname_template[:index] - Puppet._displayname_suffix = displayname_template[index+length:] + Puppet._displayname_suffix = displayname_template[index + length:] return (puppet.start() for puppet in Puppet.all_with_custom_mxid()) diff --git a/mautrix_telegram/user.py b/mautrix_telegram/user.py index c64fb2f3..fb5a54fb 100644 --- a/mautrix_telegram/user.py +++ b/mautrix_telegram/user.py @@ -145,8 +145,8 @@ class User(AbstractUser): saved_contacts=self.saved_contacts, portals=self.db_portals) def save(self, contacts: bool = False, portals: bool = False) -> None: - self.db_instance.update(tgid=self.tgid, tg_username=self.username, tg_phone=self.phone, - saved_contacts=self.saved_contacts) + self.db_instance.edit(tgid=self.tgid, tg_username=self.username, tg_phone=self.phone, + saved_contacts=self.saved_contacts) if contacts: self.db_instance.contacts = self.db_contacts if portals: diff --git a/mautrix_telegram/util/__init__.py b/mautrix_telegram/util/__init__.py index 5245ef9a..727224bb 100644 --- a/mautrix_telegram/util/__init__.py +++ b/mautrix_telegram/util/__init__.py @@ -1,3 +1,4 @@ from .file_transfer import transfer_file_to_matrix, convert_image from .format_duration import format_duration from .recursive_dict import recursive_del, recursive_set, recursive_get +from .color_log import ColorFormatter diff --git a/mautrix_telegram/util/color_log.py b/mautrix_telegram/util/color_log.py new file mode 100644 index 00000000..860720c2 --- /dev/null +++ b/mautrix_telegram/util/color_log.py @@ -0,0 +1,29 @@ +# mautrix-telegram - A Matrix-Telegram puppeting bridge +# Copyright (C) 2019 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.color_log import ColorFormatter as BaseColorFormatter, PREFIX, MXID_COLOR, RESET + +TELETHON_COLOR = PREFIX + "35;1m" # magenta +TELETHON_MODULE_COLOR = PREFIX + "35m" + + +class ColorFormatter(BaseColorFormatter): + def _color_name(self, module: str) -> str: + if module.startswith("telethon"): + prefix, user_id, module = module.split(".", 2) + return (f"{TELETHON_COLOR}{prefix}{RESET}." + f"{MXID_COLOR}{user_id}{RESET}." + f"{TELETHON_MODULE_COLOR}{module}{RESET}") + return super()._color_name(module)