From bc62b3f6aefdd491027d2c0de4de58e46370a741 Mon Sep 17 00:00:00 2001 From: Dan <14043624+delivrance@users.noreply.github.com> Date: Sat, 22 Aug 2020 09:22:14 +0200 Subject: [PATCH] Implement a way to deal with failing inline requests This is due to Telegram raising an error in case bots not in DC4 try to communicate with chats that live in DC4. --- .../methods/messages/edit_inline_media.py | 10 ++- .../messages/edit_inline_reply_markup.py | 11 ++- pyrogram/methods/messages/edit_inline_text.py | 10 ++- pyrogram/methods/messages/inline_session.py | 75 +++++++++++++++++++ 4 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 pyrogram/methods/messages/inline_session.py diff --git a/pyrogram/methods/messages/edit_inline_media.py b/pyrogram/methods/messages/edit_inline_media.py index 76b716f1..a6a893ae 100644 --- a/pyrogram/methods/messages/edit_inline_media.py +++ b/pyrogram/methods/messages/edit_inline_media.py @@ -22,6 +22,7 @@ from pyrogram import raw from pyrogram import types from pyrogram import utils from pyrogram.scaffold import Scaffold +from .inline_session import get_session class EditInlineMedia(Scaffold): @@ -105,9 +106,14 @@ class EditInlineMedia(Scaffold): else: media = utils.get_input_media_from_file_id(media.media, media.file_ref, 5) - return await self.send( + unpacked = utils.unpack_inline_message_id(inline_message_id) + dc_id = unpacked.dc_id + + session = get_session(self, dc_id) + + return await session.send( raw.functions.messages.EditInlineBotMessage( - id=utils.unpack_inline_message_id(inline_message_id), + id=unpacked, media=media, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(caption, parse_mode) diff --git a/pyrogram/methods/messages/edit_inline_reply_markup.py b/pyrogram/methods/messages/edit_inline_reply_markup.py index 5d1b2463..9905bcf5 100644 --- a/pyrogram/methods/messages/edit_inline_reply_markup.py +++ b/pyrogram/methods/messages/edit_inline_reply_markup.py @@ -20,6 +20,7 @@ from pyrogram import raw from pyrogram import types from pyrogram import utils from pyrogram.scaffold import Scaffold +from .inline_session import get_session class EditInlineReplyMarkup(Scaffold): @@ -51,9 +52,15 @@ class EditInlineReplyMarkup(Scaffold): InlineKeyboardMarkup([[ InlineKeyboardButton("New button", callback_data="new_data")]])) """ - return await self.send( + + unpacked = utils.unpack_inline_message_id(inline_message_id) + dc_id = unpacked.dc_id + + session = get_session(self, dc_id) + + return await session.send( raw.functions.messages.EditInlineBotMessage( - id=utils.unpack_inline_message_id(inline_message_id), + id=unpacked, reply_markup=reply_markup.write() if reply_markup else None, ) ) diff --git a/pyrogram/methods/messages/edit_inline_text.py b/pyrogram/methods/messages/edit_inline_text.py index ebb2f91a..c1363181 100644 --- a/pyrogram/methods/messages/edit_inline_text.py +++ b/pyrogram/methods/messages/edit_inline_text.py @@ -22,6 +22,7 @@ from pyrogram import raw from pyrogram import types from pyrogram import utils from pyrogram.scaffold import Scaffold +from .inline_session import get_session class EditInlineText(Scaffold): @@ -72,9 +73,14 @@ class EditInlineText(Scaffold): disable_web_page_preview=True) """ - return await self.send( + unpacked = utils.unpack_inline_message_id(inline_message_id) + dc_id = unpacked.dc_id + + session = get_session(self, dc_id) + + return await session.send( raw.functions.messages.EditInlineBotMessage( - id=utils.unpack_inline_message_id(inline_message_id), + id=unpacked, no_webpage=disable_web_page_preview or None, reply_markup=reply_markup.write() if reply_markup else None, **await self.parser.parse(text, parse_mode) diff --git a/pyrogram/methods/messages/inline_session.py b/pyrogram/methods/messages/inline_session.py new file mode 100644 index 00000000..681ea14f --- /dev/null +++ b/pyrogram/methods/messages/inline_session.py @@ -0,0 +1,75 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2020 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +from asyncio import Lock + +import pyrogram +from pyrogram import raw +from pyrogram.errors import AuthBytesInvalid +from pyrogram.session import Session +from pyrogram.session.auth import Auth + +lock = Lock() +session = None +dest_dc_id = 4 + + +async def get_session(client: "pyrogram.Client", dc_id: int): + if dc_id != dest_dc_id: + return client + + if dc_id == await client.storage.dc_id(): + return client + + async with lock: + global session + + if session is not None: + return session + + session = Session( + client, dest_dc_id, + await Auth(client, dest_dc_id, False).create(), + False, is_media=True + ) + + await session.start() + + for _ in range(3): + exported_auth = await session.send( + raw.functions.auth.ExportAuthorization( + dc_id=dest_dc_id + ) + ) + + try: + await session.send( + raw.functions.auth.ImportAuthorization( + id=exported_auth.id, + bytes=exported_auth.bytes + ) + ) + except AuthBytesInvalid: + continue + else: + break + else: + await session.stop() + raise AuthBytesInvalid + + return session