From 9c6fbb8bc57d52214414bf530a8706941102d513 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sat, 27 Jan 2018 14:22:14 +0200 Subject: [PATCH] Add supergroup migrate support --- README.md | 2 +- mautrix_appservice/intent_api.py | 12 +++++++++--- mautrix_telegram/__main__.py | 6 +++--- mautrix_telegram/commands.py | 2 +- mautrix_telegram/db.py | 12 +++++------- mautrix_telegram/portal.py | 13 +++++++++++++ mautrix_telegram/user.py | 5 +++++ 7 files changed, 37 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 589f9f5f..fffbcdbc 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ does not do this automatically. * [x] Chat metadata changes * [ ] Public channel username changes * [x] Initial chat metadata - * [ ] Supergroup upgrade + * [x] Supergroup upgrade * Initiating chats * [x] Automatic portal creation for groups/channels at startup * [ ] Automatic portal creation for groups/channels when receiving invite/message diff --git a/mautrix_appservice/intent_api.py b/mautrix_appservice/intent_api.py index 9b4a8435..e8971b24 100644 --- a/mautrix_appservice/intent_api.py +++ b/mautrix_appservice/intent_api.py @@ -205,18 +205,24 @@ class IntentAPI: self._ensure_joined(room_id) return self.client.set_typing(room_id, is_typing, timeout) - def send_text(self, room_id, text, html=None, notice=False): + def send_notice(self, room_id, text, html=None): + self.send_text(room_id, text, html, "m.notice") + + def send_emote(self, room_id, text, html=None): + self.send_text(room_id, text, html, "m.emote") + + def send_text(self, room_id, text, html=None, type="m.text"): if html: return self.send_message(room_id, { "body": text, - "msgtype": "m.notice" if notice else "m.text", + "msgtype": type, "format": "org.matrix.custom.html", "formatted_body": html or text, }) else: return self.send_message(room_id, { "body": text, - "msgtype": "m.notice" if notice else "m.text", + "msgtype": type, }) def send_message(self, room_id, body): diff --git a/mautrix_telegram/__main__.py b/mautrix_telegram/__main__.py index 8909a818..58345b5b 100644 --- a/mautrix_telegram/__main__.py +++ b/mautrix_telegram/__main__.py @@ -64,18 +64,18 @@ if config["appservice.debug"]: db_engine = sql.create_engine(config.get("appservice.database", "sqlite:///mautrix-telegram.db")) db_factory = orm.sessionmaker(bind=db_engine) -db = db_factory() +db_session = orm.scoping.scoped_session(db_factory) Base.metadata.bind = db_engine Base.metadata.create_all() appserv = AppService(config["homeserver.address"], config["homeserver.domain"], config["appservice.as_token"], config["appservice.hs_token"], config["appservice.bot_username"], log=log.getChild("as")) -context = (appserv, db, log, config) +context = (appserv, db_session, log, config) with appserv.run(config["appservice.hostname"], config["appservice.port"]) as start: - init_db(db_factory) + init_db(db_session) init_formatter(context) init_portal(context) init_puppet(context) diff --git a/mautrix_telegram/commands.py b/mautrix_telegram/commands.py index 819b79b7..b10e1d72 100644 --- a/mautrix_telegram/commands.py +++ b/mautrix_telegram/commands.py @@ -68,7 +68,7 @@ class CommandHandler: html = markdown.markdown(message, safe_mode="escape" if allow_html else False) elif allow_html: html = message - self.az.intent.send_text(self._room_id, message, html=html, notice=True) + self.az.intent.send_notice(self._room_id, message, html=html) @command_handler def register(self, sender, args): diff --git a/mautrix_telegram/db.py b/mautrix_telegram/db.py index a4135c24..60ef1369 100644 --- a/mautrix_telegram/db.py +++ b/mautrix_telegram/db.py @@ -14,7 +14,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . from sqlalchemy import Column, ForeignKey, UniqueConstraint, Integer, String -from sqlalchemy.orm.scoping import scoped_session from .base import Base @@ -62,9 +61,8 @@ class Puppet(Base): photo_id = Column(String, nullable=True) -def init(db_factory): - db = scoped_session(db_factory) - Portal.query = db.query_property() - Message.query = db.query_property() - User.query = db.query_property() - Puppet.query = db.query_property() +def init(db_session): + Portal.query = db_session.query_property() + Message.query = db_session.query_property() + User.query = db_session.query_property() + Puppet.query = db_session.query_property() diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index 8dcd46c0..776a480c 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -246,6 +246,10 @@ class Portal: elif action_type == MessageActionChatDeleteUser: # TODO show kick message if user was kicked self.delete_telegram_user(action.user_id) + elif action_type == MessageActionChatMigrateTo: + self.peer_type = "channel" + self.migrate_and_save(action.channel_id) + sender.intent.send_emote(self.mxid, "upgraded this group to a supergroup.") else: self.log.debug("Unhandled Telegram action in %s: %s", self.title, action) @@ -257,6 +261,15 @@ class Portal: username=self.username, title=self.title, photo_id=self.photo_id)) + def migrate_and_save(self, new_id): + existing = DBPortal.query.get(self.tgid) + if existing: + self.db.object_session(existing).delete(existing) + self.by_tgid[self.tgid] = None + self.tgid = new_id + self.by_tgid[self.tgid] = self + self.save() + def save(self): self.to_db() self.db.commit() diff --git a/mautrix_telegram/user.py b/mautrix_telegram/user.py index 14e796b6..48130f5f 100644 --- a/mautrix_telegram/user.py +++ b/mautrix_telegram/user.py @@ -146,6 +146,8 @@ class User: continue elif isinstance(entity, Chat) and entity.deactivated: continue + elif isinstance(entity, ChannelForbidden): + continue portal = po.Portal.get_by_entity(entity) portal.create_room(self, entity, invites=[self.mxid]) @@ -208,6 +210,9 @@ class User: update, sender, portal = self.get_message_details(update) if isinstance(update, MessageService): + if isinstance(update.action, MessageActionChannelMigrateFrom): + self.log.debug("Ignoring action %s to %d by %d", update.action, portal.tgid, sender.id) + return self.log.debug("Handling action %s to %d by %d", update.action, portal.tgid, sender.id) portal.handle_telegram_action(self, sender, update.action) else: