Allow adding update handlers without the need to poll updates

This commit is contained in:
Lonami Exo 2017-09-07 20:29:51 +02:00
parent b8e881b6b6
commit a24b4020fe
3 changed files with 32 additions and 11 deletions

View File

@ -59,6 +59,7 @@ class TelegramBareClient:
connection_mode=ConnectionMode.TCP_FULL, connection_mode=ConnectionMode.TCP_FULL,
proxy=None, proxy=None,
enable_updates=False, enable_updates=False,
active_updates_polling=False,
timeout=timedelta(seconds=5)): timeout=timedelta(seconds=5)):
"""Initializes the Telegram client with the specified API ID and Hash. """Initializes the Telegram client with the specified API ID and Hash.
Session must always be a Session instance, and an optional proxy Session must always be a Session instance, and an optional proxy
@ -79,7 +80,7 @@ class TelegramBareClient:
# This member will process updates if enabled. # This member will process updates if enabled.
# One may change self.updates.enabled at any later point. # 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 # These will be set later
self.dc_options = None self.dc_options = None

View File

@ -60,6 +60,7 @@ class TelegramClient(TelegramBareClient):
connection_mode=ConnectionMode.TCP_FULL, connection_mode=ConnectionMode.TCP_FULL,
proxy=None, proxy=None,
enable_updates=False, enable_updates=False,
active_updates_polling=False,
timeout=timedelta(seconds=5), timeout=timedelta(seconds=5),
**kwargs): **kwargs):
"""Initializes the Telegram client with the specified API ID and Hash. """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 This will only affect how messages are sent over the network
and how much processing is required before sending them. and how much processing is required before sending them.
If 'enable_updates' is set to True, it will by default put If 'enable_updates' is set to True, it will process incoming
all updates on self.updates. NOTE that you must manually query updates to ensure that no duplicates are received, and update
this from another thread or it will eventually fill up all your handlers will be invoked. You CANNOT invoke requests from within
memory. If you want to ignore updates, leave this set to False. these handlers.
You may change self.updates.enabled at any later point.
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 If more named arguments are provided as **kwargs, they will be
used to update the Session instance. Most common settings are: used to update the Session instance. Most common settings are:
@ -105,6 +113,7 @@ class TelegramClient(TelegramBareClient):
connection_mode=connection_mode, connection_mode=connection_mode,
proxy=proxy, proxy=proxy,
enable_updates=enable_updates, enable_updates=enable_updates,
active_updates_polling=active_updates_polling,
timeout=timeout timeout=timeout
) )

View File

@ -9,8 +9,9 @@ class UpdateState:
"""Used to hold the current state of processed updates. """Used to hold the current state of processed updates.
To retrieve an update, .pop_update() should be called. To retrieve an update, .pop_update() should be called.
""" """
def __init__(self, enabled): def __init__(self, enabled, store_updates):
self.enabled = enabled self.enabled = enabled
self._store_updates = store_updates
self.handlers = [] self.handlers = []
self._updates_lock = RLock() self._updates_lock = RLock()
self._updates_available = Event() self._updates_available = Event()
@ -23,8 +24,11 @@ class UpdateState:
"""Returns True if a call to .pop_update() won't lock""" """Returns True if a call to .pop_update() won't lock"""
return self._updates_available.is_set() return self._updates_available.is_set()
def pop(self): def poll(self):
"""Pops an update or blocks until an update object is available""" """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() self._updates_available.wait()
with self._updates_lock: with self._updates_lock:
update = self._updates.popleft() update = self._updates.popleft()
@ -33,6 +37,12 @@ class UpdateState:
return update 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): def process(self, update):
"""Processes an update object. This method is normally called by """Processes an update object. This method is normally called by
the library itself. the library itself.
@ -48,5 +58,6 @@ class UpdateState:
for handler in self.handlers: for handler in self.handlers:
handler(update) handler(update)
self._updates.append(update) if self._store_updates:
self._updates_available.set() self._updates.append(update)
self._updates_available.set()