mirror of
				https://github.com/LonamiWebs/Telethon.git
				synced 2025-11-04 01:47:27 +03:00 
			
		
		
		
	Get rid of client.loop
Instead, use the asyncio-intended way of implicit loop.
This commit is contained in:
		
							parent
							
								
									6eadc8aed8
								
							
						
					
					
						commit
						a62627534e
					
				| 
						 | 
					@ -8,14 +8,15 @@ use these if possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. code-block:: python
 | 
					.. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    import asyncio
 | 
				
			||||||
    from telethon import TelegramClient
 | 
					    from telethon import TelegramClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Remember to use your own values from my.telegram.org!
 | 
					    # Remember to use your own values from my.telegram.org!
 | 
				
			||||||
    api_id = 12345
 | 
					    api_id = 12345
 | 
				
			||||||
    api_hash = '0123456789abcdef0123456789abcdef'
 | 
					    api_hash = '0123456789abcdef0123456789abcdef'
 | 
				
			||||||
    client = TelegramClient('anon', api_id, api_hash)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def main():
 | 
					    async def main():
 | 
				
			||||||
 | 
					        async with TelegramClient('anon', api_id, api_hash).start() as client:
 | 
				
			||||||
            # Getting information about yourself
 | 
					            # Getting information about yourself
 | 
				
			||||||
            me = await client.get_me()
 | 
					            me = await client.get_me()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,8 +71,7 @@ use these if possible.
 | 
				
			||||||
                    path = await message.download_media()
 | 
					                    path = await message.download_media()
 | 
				
			||||||
                    print('File saved to', path)  # printed after download is done
 | 
					                    print('File saved to', path)  # printed after download is done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with client:
 | 
					    asyncio.run(main())
 | 
				
			||||||
        client.loop.run_until_complete(main())
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Here, we show how to sign in, get information about yourself, send
 | 
					Here, we show how to sign in, get information about yourself, send
 | 
				
			||||||
| 
						 | 
					@ -100,8 +100,8 @@ proceeding. We will see all the available methods later on.
 | 
				
			||||||
            # Most of your code should go here.
 | 
					            # Most of your code should go here.
 | 
				
			||||||
            # You can of course make and use your own async def (do_something).
 | 
					            # You can of course make and use your own async def (do_something).
 | 
				
			||||||
            # They only need to be async if they need to await things.
 | 
					            # They only need to be async if they need to await things.
 | 
				
			||||||
            async with client:
 | 
					            async with client.start():
 | 
				
			||||||
                me = await client.get_me()
 | 
					                me = await client.get_me()
 | 
				
			||||||
                await do_something(me)
 | 
					                await do_something(me)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        client.loop.run_until_complete(main())
 | 
					        asyncio.run(main())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,6 +49,7 @@ We can finally write some code to log into our account!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. code-block:: python
 | 
					.. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    import asyncio
 | 
				
			||||||
    from telethon import TelegramClient
 | 
					    from telethon import TelegramClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Use your own values from my.telegram.org
 | 
					    # Use your own values from my.telegram.org
 | 
				
			||||||
| 
						 | 
					@ -57,10 +58,10 @@ We can finally write some code to log into our account!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def main():
 | 
					    async def main():
 | 
				
			||||||
        # The first parameter is the .session file name (absolute paths allowed)
 | 
					        # The first parameter is the .session file name (absolute paths allowed)
 | 
				
			||||||
        async with TelegramClient('anon', api_id, api_hash) as client:
 | 
					        async with TelegramClient('anon', api_id, api_hash).start() as client:
 | 
				
			||||||
            await client.send_message('me', 'Hello, myself!')
 | 
					            await client.send_message('me', 'Hello, myself!')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    client.loop.run_until_complete(main())
 | 
					    asyncio.run(main())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
In the first line, we import the class name so we can create an instance
 | 
					In the first line, we import the class name so we can create an instance
 | 
				
			||||||
| 
						 | 
					@ -98,21 +99,19 @@ You will still need an API ID and hash, but the process is very similar:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. code-block:: python
 | 
					.. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    import asyncio
 | 
				
			||||||
    from telethon import TelegramClient
 | 
					    from telethon import TelegramClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    api_id = 12345
 | 
					    api_id = 12345
 | 
				
			||||||
    api_hash = '0123456789abcdef0123456789abcdef'
 | 
					    api_hash = '0123456789abcdef0123456789abcdef'
 | 
				
			||||||
    bot_token = '12345:0123456789abcdef0123456789abcdef'
 | 
					    bot_token = '12345:0123456789abcdef0123456789abcdef'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # We have to manually call "start" if we want an explicit bot token
 | 
					 | 
				
			||||||
    bot = TelegramClient('bot', api_id, api_hash).start(bot_token=bot_token)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async def main():
 | 
					    async def main():
 | 
				
			||||||
        # But then we can use the client instance as usual
 | 
					        # But then we can use the client instance as usual
 | 
				
			||||||
        async with bot:
 | 
					        async with TelegramClient('bot', api_id, api_hash).start(bot_token=bot_token) as bot:
 | 
				
			||||||
            ...
 | 
					            ...  # bot is your client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    client.loop.run_until_complete(main())
 | 
					    asyncio.run(main())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To get a bot account, you need to talk
 | 
					To get a bot account, you need to talk
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,7 +74,7 @@ Or we call `client.get_input_entity()
 | 
				
			||||||
    async def main():
 | 
					    async def main():
 | 
				
			||||||
        peer = await client.get_input_entity('someone')
 | 
					        peer = await client.get_input_entity('someone')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    client.loop.run_until_complete(main())
 | 
					    asyncio.run(main())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. note::
 | 
					.. note::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,8 +156,8 @@ you can save it in a variable directly:
 | 
				
			||||||
.. code-block:: python
 | 
					.. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    string = '1aaNk8EX-YRfwoRsebUkugFvht6DUPi_Q25UOCzOAqzc...'
 | 
					    string = '1aaNk8EX-YRfwoRsebUkugFvht6DUPi_Q25UOCzOAqzc...'
 | 
				
			||||||
    with TelegramClient(StringSession(string), api_id, api_hash) as client:
 | 
					    async with TelegramClient(StringSession(string), api_id, api_hash).start() as client:
 | 
				
			||||||
        client.loop.run_until_complete(client.send_message('me', 'Hi'))
 | 
					        await client.send_message('me', 'Hi')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
These strings are really convenient for using in places like Heroku since
 | 
					These strings are really convenient for using in places like Heroku since
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -759,3 +759,5 @@ they are meant to work on lists.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
also mark read only supports single now. a list would just be max anyway.
 | 
					also mark read only supports single now. a list would just be max anyway.
 | 
				
			||||||
removed max id since it's not really of much use.
 | 
					removed max id since it's not really of much use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					client loop has been removed. embrace implicit loop as asyncio does now
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,10 +20,10 @@ Each mixin has its own methods, which you all can use.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def main():
 | 
					    async def main():
 | 
				
			||||||
        # Now you can use all client methods listed below, like for example...
 | 
					        # Now you can use all client methods listed below, like for example...
 | 
				
			||||||
 | 
					        async with client.start():
 | 
				
			||||||
            await client.send_message('me', 'Hello to myself!')
 | 
					            await client.send_message('me', 'Hello to myself!')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with client:
 | 
					    asyncio.run(main())
 | 
				
			||||||
        client.loop.run_until_complete(main())
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You **don't** need to import these `AuthMethods`, `MessageMethods`, etc.
 | 
					You **don't** need to import these `AuthMethods`, `MessageMethods`, etc.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ class _ChatAction:
 | 
				
			||||||
            self._chat, self._action)
 | 
					            self._chat, self._action)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._running = True
 | 
					        self._running = True
 | 
				
			||||||
        self._task = self._client.loop.create_task(self._update())
 | 
					        self._task = asyncio.create_task(self._update())
 | 
				
			||||||
        return self
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def __aexit__(self, *args):
 | 
					    async def __aexit__(self, *args):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,6 @@ def init(
 | 
				
			||||||
        app_version: str = None,
 | 
					        app_version: str = None,
 | 
				
			||||||
        lang_code: str = 'en',
 | 
					        lang_code: str = 'en',
 | 
				
			||||||
        system_lang_code: str = 'en',
 | 
					        system_lang_code: str = 'en',
 | 
				
			||||||
        loop: asyncio.AbstractEventLoop = None,
 | 
					 | 
				
			||||||
        base_logger: typing.Union[str, logging.Logger] = None,
 | 
					        base_logger: typing.Union[str, logging.Logger] = None,
 | 
				
			||||||
        receive_updates: bool = True
 | 
					        receive_updates: bool = True
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
| 
						 | 
					@ -153,24 +152,6 @@ def init(
 | 
				
			||||||
    self.api_id = int(api_id)
 | 
					    self.api_id = int(api_id)
 | 
				
			||||||
    self.api_hash = api_hash
 | 
					    self.api_hash = api_hash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Current proxy implementation requires `sock_connect`, and some
 | 
					 | 
				
			||||||
    # event loops lack this method. If the current loop is missing it,
 | 
					 | 
				
			||||||
    # bail out early and suggest an alternative.
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # TODO A better fix is obviously avoiding the use of `sock_connect`
 | 
					 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    # See https://github.com/LonamiWebs/Telethon/issues/1337 for details.
 | 
					 | 
				
			||||||
    if not callable(getattr(self.loop, 'sock_connect', None)):
 | 
					 | 
				
			||||||
        raise TypeError(
 | 
					 | 
				
			||||||
            'Event loop of type {} lacks `sock_connect`, which is needed to use proxies.\n\n'
 | 
					 | 
				
			||||||
            'Change the event loop in use to use proxies:\n'
 | 
					 | 
				
			||||||
            '# https://github.com/LonamiWebs/Telethon/issues/1337\n'
 | 
					 | 
				
			||||||
            'import asyncio\n'
 | 
					 | 
				
			||||||
            'asyncio.set_event_loop(asyncio.SelectorEventLoop())'.format(
 | 
					 | 
				
			||||||
                self.loop.__class__.__name__
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if local_addr is not None:
 | 
					    if local_addr is not None:
 | 
				
			||||||
        if use_ipv6 is False and ':' in local_addr:
 | 
					        if use_ipv6 is False and ':' in local_addr:
 | 
				
			||||||
            raise TypeError(
 | 
					            raise TypeError(
 | 
				
			||||||
| 
						 | 
					@ -283,10 +264,6 @@ def init(
 | 
				
			||||||
    # A place to store if channels are a megagroup or not (see `edit_admin`)
 | 
					    # A place to store if channels are a megagroup or not (see `edit_admin`)
 | 
				
			||||||
    self._megagroup_cache = {}
 | 
					    self._megagroup_cache = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
def get_loop(self: 'TelegramClient') -> asyncio.AbstractEventLoop:
 | 
					 | 
				
			||||||
    return asyncio.get_event_loop()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def get_flood_sleep_threshold(self):
 | 
					def get_flood_sleep_threshold(self):
 | 
				
			||||||
    return self._flood_sleep_threshold
 | 
					    return self._flood_sleep_threshold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -382,7 +359,7 @@ async def connect(self: 'TelegramClient') -> None:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await self.session.save()
 | 
					    await self.session.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self._updates_handle = self.loop.create_task(self._update_loop())
 | 
					    self._updates_handle = asyncio.create_task(self._update_loop())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def is_connected(self: 'TelegramClient') -> bool:
 | 
					def is_connected(self: 'TelegramClient') -> bool:
 | 
				
			||||||
    sender = getattr(self, '_sender', None)
 | 
					    sender = getattr(self, '_sender', None)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,10 +148,6 @@ class TelegramClient:
 | 
				
			||||||
            "System lang code"  to be sent when creating the initial connection.
 | 
					            "System lang code"  to be sent when creating the initial connection.
 | 
				
			||||||
            Defaults to `lang_code`.
 | 
					            Defaults to `lang_code`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        loop (`asyncio.AbstractEventLoop`, optional):
 | 
					 | 
				
			||||||
            Asyncio event loop to use. Defaults to `asyncio.get_event_loop()`.
 | 
					 | 
				
			||||||
            This argument is ignored.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        base_logger (`str` | `logging.Logger`, optional):
 | 
					        base_logger (`str` | `logging.Logger`, optional):
 | 
				
			||||||
            Base logger name or instance to use.
 | 
					            Base logger name or instance to use.
 | 
				
			||||||
            If a `str` is given, it'll be passed to `logging.getLogger()`. If a
 | 
					            If a `str` is given, it'll be passed to `logging.getLogger()`. If a
 | 
				
			||||||
| 
						 | 
					@ -2666,31 +2662,11 @@ class TelegramClient:
 | 
				
			||||||
            app_version: str = None,
 | 
					            app_version: str = None,
 | 
				
			||||||
            lang_code: str = 'en',
 | 
					            lang_code: str = 'en',
 | 
				
			||||||
            system_lang_code: str = 'en',
 | 
					            system_lang_code: str = 'en',
 | 
				
			||||||
            loop: asyncio.AbstractEventLoop = None,
 | 
					 | 
				
			||||||
            base_logger: typing.Union[str, logging.Logger] = None,
 | 
					            base_logger: typing.Union[str, logging.Logger] = None,
 | 
				
			||||||
            receive_updates: bool = True
 | 
					            receive_updates: bool = True
 | 
				
			||||||
    ):
 | 
					    ):
 | 
				
			||||||
        telegrambaseclient.init(**locals())
 | 
					        telegrambaseclient.init(**locals())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					 | 
				
			||||||
    def loop(self: 'TelegramClient') -> asyncio.AbstractEventLoop:
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        Property with the ``asyncio`` event loop used by this client.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Example
 | 
					 | 
				
			||||||
            .. code-block:: python
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # Download media in the background
 | 
					 | 
				
			||||||
                task = client.loop.create_task(message.download_media())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # Do some work
 | 
					 | 
				
			||||||
                ...
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                # Join the task (wait for it to complete)
 | 
					 | 
				
			||||||
                await task
 | 
					 | 
				
			||||||
        """
 | 
					 | 
				
			||||||
        return telegrambaseclient.get_loop(**locals())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def flood_sleep_threshold(self):
 | 
					    def flood_sleep_threshold(self):
 | 
				
			||||||
        return telegrambaseclient.get_flood_sleep_threshold(**locals())
 | 
					        return telegrambaseclient.get_flood_sleep_threshold(**locals())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,14 +159,14 @@ def _process_update(self: 'TelegramClient', update, entities, others):
 | 
				
			||||||
    channel_id = self._state_cache.get_channel_id(update)
 | 
					    channel_id = self._state_cache.get_channel_id(update)
 | 
				
			||||||
    args = (update, entities, others, channel_id, self._state_cache[channel_id])
 | 
					    args = (update, entities, others, channel_id, self._state_cache[channel_id])
 | 
				
			||||||
    if self._dispatching_updates_queue is None:
 | 
					    if self._dispatching_updates_queue is None:
 | 
				
			||||||
        task = self.loop.create_task(_dispatch_update(self, *args))
 | 
					        task = asyncio.create_task(_dispatch_update(self, *args))
 | 
				
			||||||
        self._updates_queue.add(task)
 | 
					        self._updates_queue.add(task)
 | 
				
			||||||
        task.add_done_callback(lambda _: self._updates_queue.discard(task))
 | 
					        task.add_done_callback(lambda _: self._updates_queue.discard(task))
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        self._updates_queue.put_nowait(args)
 | 
					        self._updates_queue.put_nowait(args)
 | 
				
			||||||
        if not self._dispatching_updates_queue.is_set():
 | 
					        if not self._dispatching_updates_queue.is_set():
 | 
				
			||||||
            self._dispatching_updates_queue.set()
 | 
					            self._dispatching_updates_queue.set()
 | 
				
			||||||
            self.loop.create_task(_dispatch_queue_updates(self))
 | 
					            asyncio.create_task(_dispatch_queue_updates(self))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    self._state_cache.update(update)
 | 
					    self._state_cache.update(update)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,15 +37,15 @@ class AlbumHack:
 | 
				
			||||||
        # very short-lived but might as well try to do "the right thing".
 | 
					        # very short-lived but might as well try to do "the right thing".
 | 
				
			||||||
        self._client = weakref.ref(client)
 | 
					        self._client = weakref.ref(client)
 | 
				
			||||||
        self._event = event  # parent event
 | 
					        self._event = event  # parent event
 | 
				
			||||||
        self._due = client.loop.time() + _HACK_DELAY
 | 
					        self._due = asyncio.get_running_loop().time() + _HACK_DELAY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        client.loop.create_task(self.deliver_event())
 | 
					        asyncio.create_task(self.deliver_event())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def extend(self, messages):
 | 
					    def extend(self, messages):
 | 
				
			||||||
        client = self._client()
 | 
					        client = self._client()
 | 
				
			||||||
        if client:  # weakref may be dead
 | 
					        if client:  # weakref may be dead
 | 
				
			||||||
            self._event.messages.extend(messages)
 | 
					            self._event.messages.extend(messages)
 | 
				
			||||||
            self._due = client.loop.time() + _HACK_DELAY
 | 
					            self._due = asyncio.get_running_loop().time() + _HACK_DELAY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def deliver_event(self):
 | 
					    async def deliver_event(self):
 | 
				
			||||||
        while True:
 | 
					        while True:
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ class AlbumHack:
 | 
				
			||||||
            if client is None:
 | 
					            if client is None:
 | 
				
			||||||
                return  # weakref is dead, nothing to deliver
 | 
					                return  # weakref is dead, nothing to deliver
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            diff = self._due - client.loop.time()
 | 
					            diff = self._due - asyncio.get_running_loop().time()
 | 
				
			||||||
            if diff <= 0:
 | 
					            if diff <= 0:
 | 
				
			||||||
                # We've hit our due time, deliver event. It won't respect
 | 
					                # We've hit our due time, deliver event. It won't respect
 | 
				
			||||||
                # sequential updates but fixing that would just worsen this.
 | 
					                # sequential updates but fixing that would just worsen this.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
import struct
 | 
					import struct
 | 
				
			||||||
 | 
					import asyncio
 | 
				
			||||||
 | 
					import functools
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .common import EventBuilder, EventCommon, name_inner_event
 | 
					from .common import EventBuilder, EventCommon, name_inner_event
 | 
				
			||||||
from .._misc import utils
 | 
					from .._misc import utils
 | 
				
			||||||
| 
						 | 
					@ -7,6 +9,20 @@ from .. import _tl
 | 
				
			||||||
from ..types import _custom
 | 
					from ..types import _custom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def auto_answer(func):
 | 
				
			||||||
 | 
					    @functools.wraps(func)
 | 
				
			||||||
 | 
					    async def wrapped(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        if self._answered:
 | 
				
			||||||
 | 
					            return await func(*args, **kwargs)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return (await asyncio.gather(
 | 
				
			||||||
 | 
					                self._answer(),
 | 
				
			||||||
 | 
					                func(*args, **kwargs),
 | 
				
			||||||
 | 
					            ))[1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return wrapped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@name_inner_event
 | 
					@name_inner_event
 | 
				
			||||||
class CallbackQuery(EventBuilder):
 | 
					class CallbackQuery(EventBuilder):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -240,16 +256,15 @@ class CallbackQuery(EventBuilder):
 | 
				
			||||||
            if self._answered:
 | 
					            if self._answered:
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self._answered = True
 | 
					            res = await self._client(_tl.fn.messages.SetBotCallbackAnswer(
 | 
				
			||||||
            return await self._client(
 | 
					 | 
				
			||||||
                _tl.fn.messages.SetBotCallbackAnswer(
 | 
					 | 
				
			||||||
                query_id=self.query.query_id,
 | 
					                query_id=self.query.query_id,
 | 
				
			||||||
                cache_time=cache_time,
 | 
					                cache_time=cache_time,
 | 
				
			||||||
                alert=alert,
 | 
					                alert=alert,
 | 
				
			||||||
                message=message,
 | 
					                message=message,
 | 
				
			||||||
                    url=url
 | 
					                url=url,
 | 
				
			||||||
                )
 | 
					            ))
 | 
				
			||||||
            )
 | 
					            self._answered = True
 | 
				
			||||||
 | 
					            return res
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @property
 | 
					        @property
 | 
				
			||||||
        def via_inline(self):
 | 
					        def via_inline(self):
 | 
				
			||||||
| 
						 | 
					@ -266,35 +281,36 @@ class CallbackQuery(EventBuilder):
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            return isinstance(self.query, _tl.UpdateInlineBotCallbackQuery)
 | 
					            return isinstance(self.query, _tl.UpdateInlineBotCallbackQuery)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @auto_answer
 | 
				
			||||||
        async def respond(self, *args, **kwargs):
 | 
					        async def respond(self, *args, **kwargs):
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            Responds to the message (not as a reply). Shorthand for
 | 
					            Responds to the message (not as a reply). Shorthand for
 | 
				
			||||||
            `telethon.client.messages.MessageMethods.send_message` with
 | 
					            `telethon.client.messages.MessageMethods.send_message` with
 | 
				
			||||||
            ``entity`` already set.
 | 
					            ``entity`` already set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            This method also creates a task to `answer` the callback.
 | 
					            This method will also `answer` the callback if necessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            This method will likely fail if `via_inline` is `True`.
 | 
					            This method will likely fail if `via_inline` is `True`.
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            self._client.loop.create_task(self.answer())
 | 
					 | 
				
			||||||
            return await self._client.send_message(
 | 
					            return await self._client.send_message(
 | 
				
			||||||
                await self.get_input_chat(), *args, **kwargs)
 | 
					                await self.get_input_chat(), *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @auto_answer
 | 
				
			||||||
        async def reply(self, *args, **kwargs):
 | 
					        async def reply(self, *args, **kwargs):
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            Replies to the message (as a reply). Shorthand for
 | 
					            Replies to the message (as a reply). Shorthand for
 | 
				
			||||||
            `telethon.client.messages.MessageMethods.send_message` with
 | 
					            `telethon.client.messages.MessageMethods.send_message` with
 | 
				
			||||||
            both ``entity`` and ``reply_to`` already set.
 | 
					            both ``entity`` and ``reply_to`` already set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            This method also creates a task to `answer` the callback.
 | 
					            This method will also `answer` the callback if necessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            This method will likely fail if `via_inline` is `True`.
 | 
					            This method will likely fail if `via_inline` is `True`.
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            self._client.loop.create_task(self.answer())
 | 
					 | 
				
			||||||
            kwargs['reply_to'] = self.query.msg_id
 | 
					            kwargs['reply_to'] = self.query.msg_id
 | 
				
			||||||
            return await self._client.send_message(
 | 
					            return await self._client.send_message(
 | 
				
			||||||
                await self.get_input_chat(), *args, **kwargs)
 | 
					                await self.get_input_chat(), *args, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @auto_answer
 | 
				
			||||||
        async def edit(self, *args, **kwargs):
 | 
					        async def edit(self, *args, **kwargs):
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            Edits the message. Shorthand for
 | 
					            Edits the message. Shorthand for
 | 
				
			||||||
| 
						 | 
					@ -303,7 +319,7 @@ class CallbackQuery(EventBuilder):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Returns `True` if the edit was successful.
 | 
					            Returns `True` if the edit was successful.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            This method also creates a task to `answer` the callback.
 | 
					            This method will also `answer` the callback if necessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            .. note::
 | 
					            .. note::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -311,7 +327,6 @@ class CallbackQuery(EventBuilder):
 | 
				
			||||||
                `Message.edit <telethon.tl._custom.message.Message.edit>`,
 | 
					                `Message.edit <telethon.tl._custom.message.Message.edit>`,
 | 
				
			||||||
                since the message object is normally not present.
 | 
					                since the message object is normally not present.
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            self._client.loop.create_task(self.answer())
 | 
					 | 
				
			||||||
            if isinstance(self.query.msg_id, _tl.InputBotInlineMessageID):
 | 
					            if isinstance(self.query.msg_id, _tl.InputBotInlineMessageID):
 | 
				
			||||||
                return await self._client.edit_message(
 | 
					                return await self._client.edit_message(
 | 
				
			||||||
                    None, self.query.msg_id, *args, **kwargs
 | 
					                    None, self.query.msg_id, *args, **kwargs
 | 
				
			||||||
| 
						 | 
					@ -322,6 +337,7 @@ class CallbackQuery(EventBuilder):
 | 
				
			||||||
                    *args, **kwargs
 | 
					                    *args, **kwargs
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @auto_answer
 | 
				
			||||||
        async def delete(self, *args, **kwargs):
 | 
					        async def delete(self, *args, **kwargs):
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            Deletes the message. Shorthand for
 | 
					            Deletes the message. Shorthand for
 | 
				
			||||||
| 
						 | 
					@ -332,11 +348,10 @@ class CallbackQuery(EventBuilder):
 | 
				
			||||||
            this `delete` method. Use a
 | 
					            this `delete` method. Use a
 | 
				
			||||||
            `telethon.client.telegramclient.TelegramClient` instance directly.
 | 
					            `telethon.client.telegramclient.TelegramClient` instance directly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            This method also creates a task to `answer` the callback.
 | 
					            This method will also `answer` the callback if necessary.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            This method will likely fail if `via_inline` is `True`.
 | 
					            This method will likely fail if `via_inline` is `True`.
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
            self._client.loop.create_task(self.answer())
 | 
					 | 
				
			||||||
            return await self._client.delete_messages(
 | 
					            return await self._client.delete_messages(
 | 
				
			||||||
                await self.get_input_chat(), [self.query.msg_id],
 | 
					                await self.get_input_chat(), [self.query.msg_id],
 | 
				
			||||||
                *args, **kwargs
 | 
					                *args, **kwargs
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -242,6 +242,6 @@ class InlineQuery(EventBuilder):
 | 
				
			||||||
            if inspect.isawaitable(obj):
 | 
					            if inspect.isawaitable(obj):
 | 
				
			||||||
                return asyncio.ensure_future(obj)
 | 
					                return asyncio.ensure_future(obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            f = asyncio.get_event_loop().create_future()
 | 
					            f = asyncio.get_running_loop().create_future()
 | 
				
			||||||
            f.set_result(obj)
 | 
					            f.set_result(obj)
 | 
				
			||||||
            return f
 | 
					            return f
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,13 +23,15 @@ class Connection:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Establishes a connection with the server.
 | 
					        Establishes a connection with the server.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        loop = asyncio.get_event_loop()
 | 
					        loop = asyncio.get_running_loop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
					        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
				
			||||||
        sock.setblocking(False)
 | 
					        sock.setblocking(False)
 | 
				
			||||||
        if self._local_addr:
 | 
					        if self._local_addr:
 | 
				
			||||||
            sock.bind(self._local_addr)
 | 
					            sock.bind(self._local_addr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO https://github.com/LonamiWebs/Telethon/issues/1337 may be an issue again
 | 
				
			||||||
 | 
					        # perhaps we just need to ignore async connect on windows and block?
 | 
				
			||||||
        await asyncio.wait_for(loop.sock_connect(sock, (self._ip, self._port)), timeout)
 | 
					        await asyncio.wait_for(loop.sock_connect(sock, (self._ip, self._port)), timeout)
 | 
				
			||||||
        self._sock = sock
 | 
					        self._sock = sock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,14 +43,14 @@ class Connection:
 | 
				
			||||||
        if not self._sock:
 | 
					        if not self._sock:
 | 
				
			||||||
            raise ConnectionError('not connected')
 | 
					            raise ConnectionError('not connected')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        loop = asyncio.get_event_loop()
 | 
					        loop = asyncio.get_running_loop()
 | 
				
			||||||
        await loop.sock_sendall(self._sock, self._transport.pack(data))
 | 
					        await loop.sock_sendall(self._sock, self._transport.pack(data))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def recv(self):
 | 
					    async def recv(self):
 | 
				
			||||||
        if not self._sock:
 | 
					        if not self._sock:
 | 
				
			||||||
            raise ConnectionError('not connected')
 | 
					            raise ConnectionError('not connected')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        loop = asyncio.get_event_loop()
 | 
					        loop = asyncio.get_running_loop()
 | 
				
			||||||
        while True:
 | 
					        while True:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                length, body = self._transport.unpack(self._in_buffer)
 | 
					                length, body = self._transport.unpack(self._in_buffer)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ class MTProtoSender:
 | 
				
			||||||
        # pending futures should be cancelled.
 | 
					        # pending futures should be cancelled.
 | 
				
			||||||
        self._user_connected = False
 | 
					        self._user_connected = False
 | 
				
			||||||
        self._reconnecting = False
 | 
					        self._reconnecting = False
 | 
				
			||||||
        self._disconnected = asyncio.get_event_loop().create_future()
 | 
					        self._disconnected = asyncio.get_running_loop().create_future()
 | 
				
			||||||
        self._disconnected.set_result(None)
 | 
					        self._disconnected.set_result(None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # We need to join the loops upon disconnection
 | 
					        # We need to join the loops upon disconnection
 | 
				
			||||||
| 
						 | 
					@ -248,18 +248,17 @@ class MTProtoSender:
 | 
				
			||||||
            await self._disconnect(error=e)
 | 
					            await self._disconnect(error=e)
 | 
				
			||||||
            raise e
 | 
					            raise e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        loop = asyncio.get_event_loop()
 | 
					 | 
				
			||||||
        self._log.debug('Starting send loop')
 | 
					        self._log.debug('Starting send loop')
 | 
				
			||||||
        self._send_loop_handle = loop.create_task(self._send_loop())
 | 
					        self._send_loop_handle = asyncio.create_task(self._send_loop())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._log.debug('Starting receive loop')
 | 
					        self._log.debug('Starting receive loop')
 | 
				
			||||||
        self._recv_loop_handle = loop.create_task(self._recv_loop())
 | 
					        self._recv_loop_handle = asyncio.create_task(self._recv_loop())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # _disconnected only completes after manual disconnection
 | 
					        # _disconnected only completes after manual disconnection
 | 
				
			||||||
        # or errors after which the sender cannot continue such
 | 
					        # or errors after which the sender cannot continue such
 | 
				
			||||||
        # as failing to reconnect or any unexpected error.
 | 
					        # as failing to reconnect or any unexpected error.
 | 
				
			||||||
        if self._disconnected.done():
 | 
					        if self._disconnected.done():
 | 
				
			||||||
            self._disconnected = loop.create_future()
 | 
					            self._disconnected = asyncio.get_running_loop().create_future()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self._log.info('Connection to %s complete!', self._connection)
 | 
					        self._log.info('Connection to %s complete!', self._connection)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -381,7 +380,7 @@ class MTProtoSender:
 | 
				
			||||||
                self._pending_state.clear()
 | 
					                self._pending_state.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if self._auto_reconnect_callback:
 | 
					                if self._auto_reconnect_callback:
 | 
				
			||||||
                    asyncio.get_event_loop().create_task(self._auto_reconnect_callback())
 | 
					                    asyncio.create_task(self._auto_reconnect_callback())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                break
 | 
					                break
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
| 
						 | 
					@ -406,7 +405,7 @@ class MTProtoSender:
 | 
				
			||||||
            # gets stuck.
 | 
					            # gets stuck.
 | 
				
			||||||
            # TODO It still gets stuck? Investigate where and why.
 | 
					            # TODO It still gets stuck? Investigate where and why.
 | 
				
			||||||
            self._reconnecting = True
 | 
					            self._reconnecting = True
 | 
				
			||||||
            asyncio.get_event_loop().create_task(self._reconnect(error))
 | 
					            asyncio.create_task(self._reconnect(error))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _keepalive_ping(self, rnd_id):
 | 
					    def _keepalive_ping(self, rnd_id):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,7 @@ class App(tkinter.Tk):
 | 
				
			||||||
                       command=self.send_message).grid(row=3, column=2)
 | 
					                       command=self.send_message).grid(row=3, column=2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Post-init (async, connect client)
 | 
					        # Post-init (async, connect client)
 | 
				
			||||||
        self.cl.loop.create_task(self.post_init())
 | 
					        asyncio.create_task(self.post_init())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def post_init(self):
 | 
					    async def post_init(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -369,10 +369,4 @@ async def main(interval=0.05):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == "__main__":
 | 
					if __name__ == "__main__":
 | 
				
			||||||
    # Some boilerplate code to set up the main method
 | 
					    asyncio.run(main())
 | 
				
			||||||
    aio_loop = asyncio.get_event_loop()
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        aio_loop.run_until_complete(main())
 | 
					 | 
				
			||||||
    finally:
 | 
					 | 
				
			||||||
        if not aio_loop.is_closed():
 | 
					 | 
				
			||||||
            aio_loop.close()
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,9 +9,6 @@ from telethon.errors import SessionPasswordNeededError
 | 
				
			||||||
from telethon.network import ConnectionTcpAbridged
 | 
					from telethon.network import ConnectionTcpAbridged
 | 
				
			||||||
from telethon.utils import get_display_name
 | 
					from telethon.utils import get_display_name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Create a global variable to hold the loop we will be using
 | 
					 | 
				
			||||||
loop = asyncio.get_event_loop()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def sprint(string, *args, **kwargs):
 | 
					def sprint(string, *args, **kwargs):
 | 
				
			||||||
    """Safe Print (handle UnicodeEncodeErrors on some terminals)"""
 | 
					    """Safe Print (handle UnicodeEncodeErrors on some terminals)"""
 | 
				
			||||||
| 
						 | 
					@ -50,7 +47,7 @@ async def async_input(prompt):
 | 
				
			||||||
    let the loop run while we wait for input.
 | 
					    let the loop run while we wait for input.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    print(prompt, end='', flush=True)
 | 
					    print(prompt, end='', flush=True)
 | 
				
			||||||
    return (await loop.run_in_executor(None, sys.stdin.readline)).rstrip()
 | 
					    return (await asyncio.get_running_loop().run_in_executor(None, sys.stdin.readline)).rstrip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def get_env(name, message, cast=str):
 | 
					def get_env(name, message, cast=str):
 | 
				
			||||||
| 
						 | 
					@ -109,34 +106,34 @@ class InteractiveTelegramClient(TelegramClient):
 | 
				
			||||||
        # media known the message ID, for every message having media.
 | 
					        # media known the message ID, for every message having media.
 | 
				
			||||||
        self.found_media = {}
 | 
					        self.found_media = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def init(self):
 | 
				
			||||||
        # Calling .connect() may raise a connection error False, so you need
 | 
					        # Calling .connect() may raise a connection error False, so you need
 | 
				
			||||||
        # to except those before continuing. Otherwise you may want to retry
 | 
					        # to except those before continuing. Otherwise you may want to retry
 | 
				
			||||||
        # as done here.
 | 
					        # as done here.
 | 
				
			||||||
        print('Connecting to Telegram servers...')
 | 
					        print('Connecting to Telegram servers...')
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            loop.run_until_complete(self.connect())
 | 
					            await self.connect()
 | 
				
			||||||
        except IOError:
 | 
					        except IOError:
 | 
				
			||||||
            # We handle IOError and not ConnectionError because
 | 
					            # We handle IOError and not ConnectionError because
 | 
				
			||||||
            # PySocks' errors do not subclass ConnectionError
 | 
					            # PySocks' errors do not subclass ConnectionError
 | 
				
			||||||
            # (so this will work with and without proxies).
 | 
					            # (so this will work with and without proxies).
 | 
				
			||||||
            print('Initial connection failed. Retrying...')
 | 
					            print('Initial connection failed. Retrying...')
 | 
				
			||||||
            loop.run_until_complete(self.connect())
 | 
					            await self.connect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # If the user hasn't called .sign_in() or .sign_up() yet, they won't
 | 
					        # If the user hasn't called .sign_in() or .sign_up() yet, they won't
 | 
				
			||||||
        # be authorized. The first thing you must do is authorize. Calling
 | 
					        # be authorized. The first thing you must do is authorize. Calling
 | 
				
			||||||
        # .sign_in() should only be done once as the information is saved on
 | 
					        # .sign_in() should only be done once as the information is saved on
 | 
				
			||||||
        # the *.session file so you don't need to enter the code every time.
 | 
					        # the *.session file so you don't need to enter the code every time.
 | 
				
			||||||
        if not loop.run_until_complete(self.is_user_authorized()):
 | 
					        if not await self.is_user_authorized():
 | 
				
			||||||
            print('First run. Sending code request...')
 | 
					            print('First run. Sending code request...')
 | 
				
			||||||
            user_phone = input('Enter your phone: ')
 | 
					            user_phone = input('Enter your phone: ')
 | 
				
			||||||
            loop.run_until_complete(self.sign_in(user_phone))
 | 
					            await self.sign_in(user_phone)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self_user = None
 | 
					            self_user = None
 | 
				
			||||||
            while self_user is None:
 | 
					            while self_user is None:
 | 
				
			||||||
                code = input('Enter the code you just received: ')
 | 
					                code = input('Enter the code you just received: ')
 | 
				
			||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    self_user =\
 | 
					                    self_user = await self.sign_in(code=code)
 | 
				
			||||||
                        loop.run_until_complete(self.sign_in(code=code))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                # Two-step verification may be enabled, and .sign_in will
 | 
					                # Two-step verification may be enabled, and .sign_in will
 | 
				
			||||||
                # raise this error. If that's the case ask for the password.
 | 
					                # raise this error. If that's the case ask for the password.
 | 
				
			||||||
| 
						 | 
					@ -146,8 +143,7 @@ class InteractiveTelegramClient(TelegramClient):
 | 
				
			||||||
                    pw = getpass('Two step verification is enabled. '
 | 
					                    pw = getpass('Two step verification is enabled. '
 | 
				
			||||||
                                 'Please enter your password: ')
 | 
					                                 'Please enter your password: ')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    self_user =\
 | 
					                    self_user = await self.sign_in(password=pw)
 | 
				
			||||||
                        loop.run_until_complete(self.sign_in(password=pw))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def run(self):
 | 
					    async def run(self):
 | 
				
			||||||
        """Main loop of the TelegramClient, will wait for user action"""
 | 
					        """Main loop of the TelegramClient, will wait for user action"""
 | 
				
			||||||
| 
						 | 
					@ -397,9 +393,13 @@ class InteractiveTelegramClient(TelegramClient):
 | 
				
			||||||
                ))
 | 
					                ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if __name__ == '__main__':
 | 
					async def main():
 | 
				
			||||||
    SESSION = os.environ.get('TG_SESSION', 'interactive')
 | 
					    SESSION = os.environ.get('TG_SESSION', 'interactive')
 | 
				
			||||||
    API_ID = get_env('TG_API_ID', 'Enter your API ID: ', int)
 | 
					    API_ID = get_env('TG_API_ID', 'Enter your API ID: ', int)
 | 
				
			||||||
    API_HASH = get_env('TG_API_HASH', 'Enter your API hash: ')
 | 
					    API_HASH = get_env('TG_API_HASH', 'Enter your API hash: ')
 | 
				
			||||||
    client = InteractiveTelegramClient(SESSION, API_ID, API_HASH)
 | 
					    client = await InteractiveTelegramClient(SESSION, API_ID, API_HASH).init()
 | 
				
			||||||
    loop.run_until_complete(client.run())
 | 
					    await client.run()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    asyncio.run(main())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,6 @@ import os
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
loop = asyncio.get_event_loop()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
Provider token can be obtained via @BotFather. more info at https://core.telegram.org/bots/payments#getting-a-token
 | 
					Provider token can be obtained via @BotFather. more info at https://core.telegram.org/bots/payments#getting-a-token
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -180,4 +178,4 @@ if __name__ == '__main__':
 | 
				
			||||||
    if not provider_token:
 | 
					    if not provider_token:
 | 
				
			||||||
        logger.error("No provider token supplied.")
 | 
					        logger.error("No provider token supplied.")
 | 
				
			||||||
        exit(1)
 | 
					        exit(1)
 | 
				
			||||||
    loop.run_until_complete(main())
 | 
					    asyncio.run(main())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -134,12 +134,13 @@ async def main():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# By default, `Quart.run` uses `asyncio.run()`, which creates a new asyncio
 | 
					# By default, `Quart.run` uses `asyncio.run()`, which creates a new asyncio
 | 
				
			||||||
# event loop. If we create the `TelegramClient` before, `telethon` will
 | 
					# event loop. Instead, we use `asyncio.run()` manually in order to make this
 | 
				
			||||||
# use `asyncio.get_event_loop()`, which is the implicit loop in the main
 | 
					# explicit, as the client cannot be "transferred" between loops while
 | 
				
			||||||
# thread. These two loops are different, and it won't work.
 | 
					# connected due to the need to schedule work within an event loop.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# So, we have to manually pass the same `loop` to both applications to
 | 
					# In essence one needs to be careful to avoid mixing event loops, but this is
 | 
				
			||||||
# make 100% sure it works and to avoid headaches.
 | 
					# simple, as `asyncio.run` is generally only used in the entry-point of the
 | 
				
			||||||
 | 
					# program.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# To run Quart inside `async def`, we must use `hypercorn.asyncio.serve()`
 | 
					# To run Quart inside `async def`, we must use `hypercorn.asyncio.serve()`
 | 
				
			||||||
# directly.
 | 
					# directly.
 | 
				
			||||||
| 
						 | 
					@ -149,4 +150,4 @@ async def main():
 | 
				
			||||||
# won't have to worry about any of this, but it's still good to be
 | 
					# won't have to worry about any of this, but it's still good to be
 | 
				
			||||||
# explicit about the event loop.
 | 
					# explicit about the event loop.
 | 
				
			||||||
if __name__ == '__main__':
 | 
					if __name__ == '__main__':
 | 
				
			||||||
    client.loop.run_until_complete(main())
 | 
					    asyncio.run(main())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user