From 8cce7a7c3a727d425e7a22c6cc634803b069befd Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 4 Mar 2018 17:39:56 +0200 Subject: [PATCH 1/7] Initial attempt at removing appservice bot power level requirements --- mautrix_telegram/commands/portal.py | 24 ------------------- mautrix_telegram/portal.py | 37 ++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/mautrix_telegram/commands/portal.py b/mautrix_telegram/commands/portal.py index 666baa21..5885147c 100644 --- a/mautrix_telegram/commands/portal.py +++ b/mautrix_telegram/commands/portal.py @@ -128,11 +128,6 @@ async def bridge(evt: CommandEvent): if not await _has_access_to(room_id, evt.az.intent, evt.sender, "bridge"): return await evt.reply("You do not have the permissions to bridge that room.") - levels = await evt.az.intent.get_power_levels(room_id) - power_level_error = _check_power_levels(levels, evt.az.bot_mxid) - if power_level_error: - return await evt.reply(power_level_error) - # The /id bot command provides the prefixed ID, so we assume tgid = evt.args[0] if tgid.startswith("-100"): @@ -258,21 +253,6 @@ async def _get_initial_state(evt: CommandEvent): return title, about, levels -def _check_power_levels(levels: dict, bot_mxid: str): - try: - if levels["users"][bot_mxid] < 100: - raise ValueError() - except (TypeError, KeyError, ValueError): - return (f"Please give [the bridge bot](https://matrix.to/#/{bot_mxid}) a power level of " - "100 before creating or bridging a Telegram chat.") - - for user, level in levels["users"].items(): - if level >= 100 and user != bot_mxid: - return (f"Please make sure only the bridge bot has power level above 99 before " - f"creating or bridging a Telegram chat.\n\n" - f"Use power level 95 instead of 100 for admins.") - - @command_handler() async def create(evt: CommandEvent): type = evt.args[0] if len(evt.args) > 0 else "group" @@ -287,10 +267,6 @@ async def create(evt: CommandEvent): if not title: return await evt.reply("Please set a title before creating a Telegram chat.") - power_level_error = _check_power_levels(levels, evt.az.bot_mxid) - if power_level_error: - return await evt.reply(power_level_error) - supergroup = type == "supergroup" type = { "supergroup": "channel", diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index 6111be8e..497794d2 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -284,6 +284,8 @@ class Portal: levels["users"] = { self.main_intent.mxid: 100 } + else: + levels["users"][self.main_intent.mxid] = 100 return levels @property @@ -799,7 +801,8 @@ class Portal: self.bot.add_chat(self.tgid, self.peer_type) levels = await self.main_intent.get_power_levels(self.mxid) - levels = self._get_base_power_levels(levels, entity) + if self._get_bot_level(levels) == 100: + levels = self._get_base_power_levels(levels, entity) already_saved = await self.handle_matrix_power_levels(source, levels["users"], {}) if not already_saved: await self.main_intent.set_power_levels(self.mxid, levels) @@ -1060,18 +1063,29 @@ class Portal: return 0 @staticmethod - def _participant_to_power_levels(levels, user, new_level): + def _participant_to_power_levels(levels, user, new_level, bot_level): + new_level = min(new_level, bot_level) user_level_defined = user.mxid in levels["users"] - user_has_right_level = (levels["users"][user.mxid] == new_level - if user_level_defined else new_level == 0) - if not user_has_right_level: + default_level = levels["users_default"] if "users_default" in levels else 0 + user_level = levels["users"][user.mxid] if user_level_defined else default_level + if user_level != new_level and user_level < bot_level: levels["users"][user.mxid] = new_level return True return False + def _get_bot_level(self, levels): + try: + return levels["users"][self.main_intent.mxid] + except KeyError: + try: + return levels["users_default"] + except KeyError: + return 0 + def _participants_to_power_levels(self, participants, levels): + bot_level = self._get_bot_level(levels) changed = False - admin_power_level = 75 if self.peer_type == "channel" else 50 + admin_power_level = min(75 if self.peer_type == "channel" else 50, bot_level) if levels["events"]["m.room.power_levels"] != admin_power_level: changed = True levels["events"]["m.room.power_levels"] = admin_power_level @@ -1083,10 +1097,12 @@ class Portal: if user: user.register_portal(self) - changed = self._participant_to_power_levels(levels, user, new_level) or changed + changed = self._participant_to_power_levels(levels, user, new_level, + bot_level) or changed if puppet: - changed = self._participant_to_power_levels(levels, puppet, new_level) or changed + changed = self._participant_to_power_levels(levels, puppet, new_level, + bot_level) or changed return changed async def update_telegram_participants(self, participants, levels=None): @@ -1101,7 +1117,10 @@ class Portal: levels["invite"] = level levels["events"]["m.room.name"] = level levels["events"]["m.room.avatar"] = level - await self.main_intent.set_power_levels(self.mxid, levels) + try: + await self.main_intent.set_power_levels(self.mxid, levels) + except MatrixRequestError: + pass # endregion # region Database conversion From 68648d7b5c0f503da69dc4daeba7c84272287131 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 11 Mar 2018 10:39:24 +0200 Subject: [PATCH 2/7] Improve support for portals without power levels --- mautrix_telegram/portal.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index bb29b918..7b418f58 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -865,11 +865,11 @@ class Portal: self.bot.add_chat(self.tgid, self.peer_type) levels = await self.main_intent.get_power_levels(self.mxid) - if self._get_bot_level(levels) == 100: + bot_level = self._get_bot_level(levels) + if bot_level == 100: levels = self._get_base_power_levels(levels, entity) - already_saved = await self.handle_matrix_power_levels(source, levels["users"], {}) - if not already_saved: await self.main_intent.set_power_levels(self.mxid, levels) + await self.handle_matrix_power_levels(source, levels["users"], {}) async def invite_telegram(self, source, puppet): if self.peer_type == "chat": @@ -1181,8 +1181,20 @@ class Portal: except KeyError: return 0 + @staticmethod + def _get_powerlevel_level(levels): + try: + return levels["events"]["m.room.power_levels"] + except KeyError: + try: + return levels["state_default"] + except KeyError: + return 50 + def _participants_to_power_levels(self, participants, levels): bot_level = self._get_bot_level(levels) + if bot_level < self._get_powerlevel_level(levels): + return False changed = False admin_power_level = min(75 if self.peer_type == "channel" else 50, bot_level) if levels["events"]["m.room.power_levels"] != admin_power_level: @@ -1216,10 +1228,7 @@ class Portal: levels["invite"] = level levels["events"]["m.room.name"] = level levels["events"]["m.room.avatar"] = level - try: - await self.main_intent.set_power_levels(self.mxid, levels) - except MatrixRequestError: - pass + await self.main_intent.set_power_levels(self.mxid, levels) # endregion # region Database conversion From 4448077d43332e9d9105321824c40e8d56de2d31 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 11 Mar 2018 13:06:26 +0200 Subject: [PATCH 3/7] Fix bot.add_chat() when creating Telegram chat --- mautrix_telegram/portal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index 7b418f58..cb988d41 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -861,7 +861,7 @@ class Portal: await self.update_info(source, entity) self.save() - if self.bot and self.bot.mxid in invites: + if self.bot and self.bot.tgid in invites: self.bot.add_chat(self.tgid, self.peer_type) levels = await self.main_intent.get_power_levels(self.mxid) From 54d2b4bba85e697c3ad284f395a9e1543935d9b9 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 11 Mar 2018 13:09:04 +0200 Subject: [PATCH 4/7] Make puppets leave room instead of kicking by AS bot --- mautrix_telegram/portal.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index cb988d41..0bc3ec95 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -494,10 +494,13 @@ class Portal: except MatrixRequestError: members = [] for user in members: - is_puppet = p.Puppet.get_id_from_mxid(user) - if user != intent.mxid and (not puppets_only or is_puppet): + puppet = p.Puppet.get_by_mxid(user, create=False) + if user != intent.mxid and (not puppets_only or puppet): try: - await intent.kick(room_id, user, message) + if puppet: + await puppet.intent.leave_room(room_id) + else: + await intent.kick(room_id, user, message) except (MatrixRequestError, IntentError): pass await intent.leave_room(room_id) From 88a84048989a88104705f7715ffad6ec47ccce19 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 11 Mar 2018 13:41:05 +0200 Subject: [PATCH 5/7] Fix saving created portals and use mxid as title by default --- mautrix_telegram/commands/portal.py | 4 +--- mautrix_telegram/portal.py | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/mautrix_telegram/commands/portal.py b/mautrix_telegram/commands/portal.py index 76a24375..1ee0b506 100644 --- a/mautrix_telegram/commands/portal.py +++ b/mautrix_telegram/commands/portal.py @@ -258,7 +258,7 @@ async def confirm_bridge(evt: CommandEvent): async def _get_initial_state(evt: CommandEvent): state = await evt.az.intent.get_room_state(evt.room_id) - title = None + title = evt.room_id about = None levels = None for event in state: @@ -282,8 +282,6 @@ async def create(evt: CommandEvent): return await evt.reply("This is already a portal room.") title, about, levels = await _get_initial_state(evt) - if not title: - return await evt.reply("Please set a title before creating a Telegram chat.") supergroup = type == "supergroup" type = { diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index 0bc3ec95..b1f2d1f9 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -862,6 +862,7 @@ class Portal: self.tg_receiver = self.tgid self.by_tgid[self.tgid_full] = self await self.update_info(source, entity) + self.db.add(self.db_instance) self.save() if self.bot and self.bot.tgid in invites: From 733bbb30c31cdd5b2f3952e6b18ae12647599abd Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 11 Mar 2018 13:46:02 +0200 Subject: [PATCH 6/7] Use canonical alias instead of MXID as default title --- mautrix_telegram/commands/portal.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mautrix_telegram/commands/portal.py b/mautrix_telegram/commands/portal.py index 1ee0b506..f1e01aa5 100644 --- a/mautrix_telegram/commands/portal.py +++ b/mautrix_telegram/commands/portal.py @@ -258,7 +258,7 @@ async def confirm_bridge(evt: CommandEvent): async def _get_initial_state(evt: CommandEvent): state = await evt.az.intent.get_room_state(evt.room_id) - title = evt.room_id + title = None about = None levels = None for event in state: @@ -268,6 +268,8 @@ async def _get_initial_state(evt: CommandEvent): about = event["content"]["topic"] elif event["type"] == "m.room.power_levels": levels = event["content"] + elif event["type"] == "m.room.canonical_alias": + title = title or event["content"]["alias"] return title, about, levels @@ -282,6 +284,8 @@ async def create(evt: CommandEvent): return await evt.reply("This is already a portal room.") title, about, levels = await _get_initial_state(evt) + if not title: + return await evt.reply("Please set a title before creating a Telegram chat.") supergroup = type == "supergroup" type = { From 73de61dabf3162b112b6d903a40e5638114ed6ad Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 11 Mar 2018 21:05:15 +0200 Subject: [PATCH 7/7] Fix mautrix-appservice dependency name and bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5166748e..e96746a8 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ setuptools.setup( install_requires=[ "aiohttp>=3.0.1,<4", - "mautrix-telegram>=0.1,<0.2", + "mautrix-appservice>=0.1.1,<0.2.0", "SQLAlchemy>=1.2.3,<2", "alembic>=0.9.8,<0.10", "Markdown>=2.6.11,<3",