107 lines
3.8 KiB
Python
107 lines
3.8 KiB
Python
"""
|
|
Like :mod:`telepot.delegate`, this module has a bunch of seeder factories
|
|
and delegator factories.
|
|
|
|
.. autofunction:: per_chat_id
|
|
.. autofunction:: per_chat_id_in
|
|
.. autofunction:: per_chat_id_except
|
|
.. autofunction:: per_from_id
|
|
.. autofunction:: per_from_id_in
|
|
.. autofunction:: per_from_id_except
|
|
.. autofunction:: per_inline_from_id
|
|
.. autofunction:: per_inline_from_id_in
|
|
.. autofunction:: per_inline_from_id_except
|
|
.. autofunction:: per_application
|
|
.. autofunction:: per_message
|
|
.. autofunction:: per_event_source_id
|
|
.. autofunction:: per_callback_query_chat_id
|
|
.. autofunction:: per_callback_query_origin
|
|
.. autofunction:: per_invoice_payload
|
|
.. autofunction:: until
|
|
.. autofunction:: chain
|
|
.. autofunction:: pair
|
|
.. autofunction:: pave_event_space
|
|
.. autofunction:: include_callback_query_chat_id
|
|
.. autofunction:: intercept_callback_query_origin
|
|
"""
|
|
|
|
import asyncio
|
|
import traceback
|
|
from .. import exception
|
|
from . import helper
|
|
|
|
# Mirror traditional version to avoid having to import one more module
|
|
from ..delegate import (
|
|
per_chat_id, per_chat_id_in, per_chat_id_except,
|
|
per_from_id, per_from_id_in, per_from_id_except,
|
|
per_inline_from_id, per_inline_from_id_in, per_inline_from_id_except,
|
|
per_application, per_message, per_event_source_id,
|
|
per_callback_query_chat_id, per_callback_query_origin, per_invoice_payload,
|
|
until, chain, pair, pave_event_space,
|
|
include_callback_query_chat_id, intercept_callback_query_origin
|
|
)
|
|
|
|
def _ensure_coroutine_function(fn):
|
|
return fn if asyncio.iscoroutinefunction(fn) else asyncio.coroutine(fn)
|
|
|
|
def call(corofunc, *args, **kwargs):
|
|
"""
|
|
:return:
|
|
a delegator function that returns a coroutine object by calling
|
|
``corofunc(seed_tuple, *args, **kwargs)``.
|
|
"""
|
|
corofunc = _ensure_coroutine_function(corofunc)
|
|
def f(seed_tuple):
|
|
return corofunc(seed_tuple, *args, **kwargs)
|
|
return f
|
|
|
|
def create_run(cls, *args, **kwargs):
|
|
"""
|
|
:return:
|
|
a delegator function that calls the ``cls`` constructor whose arguments being
|
|
a seed tuple followed by supplied ``*args`` and ``**kwargs``, then returns
|
|
a coroutine object by calling the object's ``run`` method, which should be
|
|
a coroutine function.
|
|
"""
|
|
def f(seed_tuple):
|
|
j = cls(seed_tuple, *args, **kwargs)
|
|
return _ensure_coroutine_function(j.run)()
|
|
return f
|
|
|
|
def create_open(cls, *args, **kwargs):
|
|
"""
|
|
:return:
|
|
a delegator function that calls the ``cls`` constructor whose arguments being
|
|
a seed tuple followed by supplied ``*args`` and ``**kwargs``, then returns
|
|
a looping coroutine object that uses the object's ``listener`` to wait for
|
|
messages and invokes instance method ``open``, ``on_message``, and ``on_close``
|
|
accordingly.
|
|
"""
|
|
def f(seed_tuple):
|
|
j = cls(seed_tuple, *args, **kwargs)
|
|
|
|
async def wait_loop():
|
|
bot, msg, seed = seed_tuple
|
|
try:
|
|
handled = await helper._invoke(j.open, msg, seed)
|
|
if not handled:
|
|
await helper._invoke(j.on_message, msg)
|
|
|
|
while 1:
|
|
msg = await j.listener.wait()
|
|
await helper._invoke(j.on_message, msg)
|
|
|
|
# These exceptions are "normal" exits.
|
|
except (exception.IdleTerminate, exception.StopListening) as e:
|
|
await helper._invoke(j.on_close, e)
|
|
|
|
# Any other exceptions are accidents. **Print it out.**
|
|
# This is to prevent swallowing exceptions in the case that on_close()
|
|
# gets overridden but fails to account for unexpected exceptions.
|
|
except Exception as e:
|
|
traceback.print_exc()
|
|
await helper._invoke(j.on_close, e)
|
|
|
|
return wait_loop()
|
|
return f
|