2018-06-13 17:20:15 +03:00
|
|
|
import asyncio
|
2020-05-16 10:58:37 +03:00
|
|
|
import inspect
|
2018-06-14 23:51:57 +03:00
|
|
|
import itertools
|
2018-06-18 14:22:25 +03:00
|
|
|
import random
|
2021-01-30 15:47:28 +03:00
|
|
|
import sys
|
2018-06-18 14:22:25 +03:00
|
|
|
import time
|
2021-01-30 15:47:28 +03:00
|
|
|
import traceback
|
2019-05-03 22:37:27 +03:00
|
|
|
import typing
|
2021-01-30 15:47:28 +03:00
|
|
|
import logging
|
2022-01-22 15:27:00 +03:00
|
|
|
from collections import deque
|
2018-06-10 14:58:21 +03:00
|
|
|
|
2021-09-24 21:07:34 +03:00
|
|
|
from ..errors._rpcbase import RpcError
|
2021-09-24 22:11:50 +03:00
|
|
|
from .._events.common import EventBuilder, EventCommon
|
|
|
|
from .._events.raw import Raw
|
|
|
|
from .._events.base import StopPropagation, _get_handlers
|
2021-09-26 20:58:42 +03:00
|
|
|
from .._misc import utils
|
|
|
|
from .. import _tl
|
2019-05-03 22:37:27 +03:00
|
|
|
|
|
|
|
if typing.TYPE_CHECKING:
|
|
|
|
from .telegramclient import TelegramClient
|
2018-06-10 14:58:21 +03:00
|
|
|
|
|
|
|
|
2021-08-03 19:33:46 +03:00
|
|
|
Callback = typing.Callable[[typing.Any], typing.Any]
|
|
|
|
|
2018-06-10 14:58:21 +03:00
|
|
|
|
2021-09-11 14:33:27 +03:00
|
|
|
async def set_receive_updates(self: 'TelegramClient', receive_updates):
|
|
|
|
self._no_updates = not receive_updates
|
|
|
|
if receive_updates:
|
2021-09-12 13:16:02 +03:00
|
|
|
await self(_tl.fn.updates.GetState())
|
2018-06-25 14:32:31 +03:00
|
|
|
|
2021-09-11 15:05:24 +03:00
|
|
|
async def run_until_disconnected(self: 'TelegramClient'):
|
2021-09-18 16:41:04 +03:00
|
|
|
# Make a high-level request to notify that we want updates
|
|
|
|
await self(_tl.fn.updates.GetState())
|
2022-01-16 15:59:43 +03:00
|
|
|
await self._sender.wait_disconnected()
|
2021-09-11 14:33:27 +03:00
|
|
|
|
|
|
|
def on(self: 'TelegramClient', event: EventBuilder):
|
|
|
|
def decorator(f):
|
|
|
|
self.add_event_handler(f, event)
|
|
|
|
return f
|
2019-05-20 12:38:26 +03:00
|
|
|
|
2021-09-11 14:33:27 +03:00
|
|
|
return decorator
|
2019-05-20 12:38:26 +03:00
|
|
|
|
2021-09-11 14:33:27 +03:00
|
|
|
def add_event_handler(
|
|
|
|
self: 'TelegramClient',
|
|
|
|
callback: Callback,
|
|
|
|
event: EventBuilder = None):
|
2021-09-24 22:11:50 +03:00
|
|
|
builders = _get_handlers(callback)
|
2021-09-11 14:33:27 +03:00
|
|
|
if builders is not None:
|
|
|
|
for event in builders:
|
|
|
|
self._event_builders.append((event, callback))
|
|
|
|
return
|
2019-05-20 12:38:26 +03:00
|
|
|
|
2021-09-11 14:33:27 +03:00
|
|
|
if isinstance(event, type):
|
|
|
|
event = event()
|
|
|
|
elif not event:
|
2021-09-24 22:11:50 +03:00
|
|
|
event = Raw()
|
2019-05-20 12:38:26 +03:00
|
|
|
|
2021-09-11 14:33:27 +03:00
|
|
|
self._event_builders.append((event, callback))
|
2019-05-20 12:38:26 +03:00
|
|
|
|
2021-09-11 14:33:27 +03:00
|
|
|
def remove_event_handler(
|
|
|
|
self: 'TelegramClient',
|
|
|
|
callback: Callback,
|
|
|
|
event: EventBuilder = None) -> int:
|
|
|
|
found = 0
|
|
|
|
if event and not isinstance(event, type):
|
|
|
|
event = type(event)
|
|
|
|
|
|
|
|
i = len(self._event_builders)
|
|
|
|
while i:
|
|
|
|
i -= 1
|
|
|
|
ev, cb = self._event_builders[i]
|
|
|
|
if cb == callback and (not event or isinstance(ev, event)):
|
|
|
|
del self._event_builders[i]
|
|
|
|
found += 1
|
|
|
|
|
|
|
|
return found
|
|
|
|
|
|
|
|
def list_event_handlers(self: 'TelegramClient')\
|
|
|
|
-> 'typing.Sequence[typing.Tuple[Callback, EventBuilder]]':
|
|
|
|
return [(callback, event) for event, callback in self._event_builders]
|
2019-04-23 21:15:27 +03:00
|
|
|
|
2021-09-11 14:33:27 +03:00
|
|
|
async def catch_up(self: 'TelegramClient'):
|
2022-01-18 21:46:19 +03:00
|
|
|
pass
|
2021-09-11 14:33:27 +03:00
|
|
|
|
|
|
|
async def _update_loop(self: 'TelegramClient'):
|
2022-01-22 15:27:00 +03:00
|
|
|
try:
|
|
|
|
updates_to_dispatch = deque()
|
|
|
|
while self.is_connected():
|
|
|
|
if updates_to_dispatch:
|
|
|
|
# TODO dispatch
|
|
|
|
updates_to_dispatch.popleft()
|
|
|
|
continue
|
|
|
|
|
|
|
|
get_diff = self._message_box.get_difference()
|
|
|
|
if get_diff:
|
|
|
|
self._log[__name__].info('Getting difference for account updates')
|
|
|
|
diff = await self(get_diff)
|
|
|
|
updates, users, chats = self._message_box.apply_difference(diff, self._entity_cache)
|
|
|
|
updates_to_dispatch.extend(updates)
|
|
|
|
continue
|
|
|
|
|
|
|
|
get_diff = self._message_box.get_channel_difference(self._entity_cache)
|
|
|
|
if get_diff:
|
|
|
|
self._log[__name__].info('Getting difference for channel updates')
|
|
|
|
diff = await self(get_diff)
|
|
|
|
updates, users, chats = self._message_box.apply_channel_difference(diff, self._entity_cache)
|
|
|
|
updates_to_dispatch.extend(updates)
|
|
|
|
continue
|
|
|
|
|
|
|
|
deadline = self._message_box.check_deadlines()
|
|
|
|
try:
|
|
|
|
updates = await asyncio.wait_for(
|
|
|
|
self._updates_queue.get(),
|
|
|
|
deadline - asyncio.get_running_loop().time()
|
|
|
|
)
|
|
|
|
except asyncio.TimeoutError:
|
|
|
|
self._log[__name__].info('Timeout waiting for updates expired')
|
|
|
|
continue
|
|
|
|
|
|
|
|
processed = []
|
|
|
|
users, chats = self._message_box.process_updates(updates, self._entity_cache, processed)
|
|
|
|
updates_to_dispatch.extend(processed)
|
|
|
|
except Exception:
|
|
|
|
self._log[__name__].exception('Fatal error handling updates (this is a bug in Telethon, please report it)')
|