diff --git a/telethon/telegram_bare_client.py b/telethon/telegram_bare_client.py index 1685d849..1ca4a6d9 100644 --- a/telethon/telegram_bare_client.py +++ b/telethon/telegram_bare_client.py @@ -59,6 +59,7 @@ class TelegramBareClient: connection_mode=ConnectionMode.TCP_FULL, proxy=None, enable_updates=False, + active_updates_polling=False, timeout=timedelta(seconds=5)): """Initializes the Telegram client with the specified API ID and Hash. Session must always be a Session instance, and an optional proxy @@ -79,7 +80,7 @@ class TelegramBareClient: # This member will process updates if enabled. # One may change self.updates.enabled at any later point. - self.updates = UpdateState(enabled=enable_updates) + self.updates = UpdateState(enable_updates, active_updates_polling) # These will be set later self.dc_options = None diff --git a/telethon/telegram_client.py b/telethon/telegram_client.py index 73ebcdbf..f0add2d4 100644 --- a/telethon/telegram_client.py +++ b/telethon/telegram_client.py @@ -60,6 +60,7 @@ class TelegramClient(TelegramBareClient): connection_mode=ConnectionMode.TCP_FULL, proxy=None, enable_updates=False, + active_updates_polling=False, timeout=timedelta(seconds=5), **kwargs): """Initializes the Telegram client with the specified API ID and Hash. @@ -73,11 +74,18 @@ class TelegramClient(TelegramBareClient): This will only affect how messages are sent over the network and how much processing is required before sending them. - If 'enable_updates' is set to True, it will by default put - all updates on self.updates. NOTE that you must manually query - this from another thread or it will eventually fill up all your - memory. If you want to ignore updates, leave this set to False. - You may change self.updates.enabled at any later point. + If 'enable_updates' is set to True, it will process incoming + updates to ensure that no duplicates are received, and update + handlers will be invoked. You CANNOT invoke requests from within + these handlers. + + In order to invoke requests upon receiving an update, you must + have your own thread (or use the main thread) and enable set + 'active_updates_polling' to True. You must call self.updates.poll() + or you'll memory will be filled with unhandled updates. + + You can also modify 'self.updates.enabled' and + 'self.updates.set_polling()' at any later point. If more named arguments are provided as **kwargs, they will be used to update the Session instance. Most common settings are: @@ -105,6 +113,7 @@ class TelegramClient(TelegramBareClient): connection_mode=connection_mode, proxy=proxy, enable_updates=enable_updates, + active_updates_polling=active_updates_polling, timeout=timeout ) diff --git a/telethon/update_state.py b/telethon/update_state.py index 6d0b40cd..5ad17ab3 100644 --- a/telethon/update_state.py +++ b/telethon/update_state.py @@ -9,8 +9,9 @@ class UpdateState: """Used to hold the current state of processed updates. To retrieve an update, .pop_update() should be called. """ - def __init__(self, enabled): + def __init__(self, enabled, store_updates): self.enabled = enabled + self._store_updates = store_updates self.handlers = [] self._updates_lock = RLock() self._updates_available = Event() @@ -23,8 +24,11 @@ class UpdateState: """Returns True if a call to .pop_update() won't lock""" return self._updates_available.is_set() - def pop(self): - """Pops an update or blocks until an update object is available""" + def poll(self): + """Polls an update or blocks until an update object is available""" + if not self._store_updates: + raise ValueError('Polling updates is not enabled.') + self._updates_available.wait() with self._updates_lock: update = self._updates.popleft() @@ -33,6 +37,12 @@ class UpdateState: return update + def set_polling(self, store): + self._store_updates = store + if not store: + with self._updates_lock: + self._updates.clear() + def process(self, update): """Processes an update object. This method is normally called by the library itself. @@ -48,5 +58,6 @@ class UpdateState: for handler in self.handlers: handler(update) - self._updates.append(update) - self._updates_available.set() + if self._store_updates: + self._updates.append(update) + self._updates_available.set()