diff --git a/telebot/async_telebot.py b/telebot/async_telebot.py index 9f24d90..e7221bc 100644 --- a/telebot/async_telebot.py +++ b/telebot/async_telebot.py @@ -97,16 +97,15 @@ class AsyncTeleBot: def __init__(self, token: str, parse_mode: Optional[str]=None, offset=None, - exception_handler=None,suppress_middleware_excepions=False) -> None: # TODO: ADD TYPEHINTS + exception_handler=None) -> None: # TODO: ADD TYPEHINTS self.token = token self.offset = offset self.token = token self.parse_mode = parse_mode self.update_listener = [] - self.suppress_middleware_excepions = suppress_middleware_excepions - self.exc_info = None + self.exception_handler = exception_handler @@ -234,13 +233,23 @@ class AsyncTeleBot: try: updates = await self.get_updates(offset=self.offset, allowed_updates=allowed_updates, timeout=timeout, request_timeout=request_timeout) + if updates: + self.offset = updates[-1].update_id + 1 + self._loop_create_task(self.process_new_updates(updates)) # Seperate task for processing updates + if interval: await asyncio.sleep(interval) + + except KeyboardInterrupt: + return except asyncio.CancelledError: return except asyncio_helper.ApiTelegramException as e: logger.error(str(e)) - continue + if non_stop: + continue + else: + break except Exception as e: logger.error('Cause exception while getting updates.') if non_stop: @@ -249,10 +258,6 @@ class AsyncTeleBot: continue else: raise e - if updates: - self.offset = updates[-1].update_id + 1 - self._loop_create_task(self.process_new_updates(updates)) # Seperate task for processing updates - if interval: await asyncio.sleep(interval) finally: self._polling = False @@ -297,7 +302,12 @@ class AsyncTeleBot: break except Exception as e: handler_error = e - logger.info(str(e)) + + if not middleware: + if self.exception_handler: + return self.exception_handler.handle(e) + logging.error(str(e)) + return if middleware: await middleware.post_process(message, data, handler_error) @@ -448,7 +458,7 @@ class AsyncTeleBot: if len(self.update_listener) == 0: return for listener in self.update_listener: - self._loop_create_task(listener, new_messages) + self._loop_create_task(listener(new_messages)) async def _test_message_handler(self, message_handler, message): """ @@ -466,6 +476,9 @@ class AsyncTeleBot: return True + def set_update_listener(self, func): + self.update_listener.append(func) + def add_custom_filter(self, custom_filter): """ Create custom filter. diff --git a/telebot/asyncio_helper.py b/telebot/asyncio_helper.py index 3d1189d..3a765de 100644 --- a/telebot/asyncio_helper.py +++ b/telebot/asyncio_helper.py @@ -8,7 +8,7 @@ try: import ujson as json except ImportError: import json - +import os API_URL = 'https://api.telegram.org/bot{0}/{1}' from datetime import datetime @@ -42,14 +42,55 @@ RETRY_TIMEOUT = 2 MAX_RETRIES = 15 async def _process_request(token, url, method='get', params=None, files=None, request_timeout=None): + params = compose_data(params, files) async with await session_manager._get_new_session() as session: - async with session.get(API_URL.format(token, url), params=params, data=files, timeout=request_timeout) as response: + async with session.request(method=method, url=API_URL.format(token, url), data=params, timeout=request_timeout) as response: logger.debug("Request: method={0} url={1} params={2} files={3} request_timeout={4}".format(method, url, params, files, request_timeout).replace(token, token.split(':')[0] + ":{TOKEN}")) json_result = await _check_result(url, response) if json_result: return json_result['result'] +def guess_filename(obj): + """ + Get file name from object + + :param obj: + :return: + """ + name = getattr(obj, 'name', None) + if name and isinstance(name, str) and name[0] != '<' and name[-1] != '>': + return os.path.basename(name) + + +def compose_data(params=None, files=None): + """ + Prepare request data + + :param params: + :param files: + :return: + """ + data = aiohttp.formdata.FormData(quote_fields=False) + + if params: + for key, value in params.items(): + data.add_field(key, str(value)) + + if files: + for key, f in files.items(): + if isinstance(f, tuple): + if len(f) == 2: + filename, fileobj = f + else: + raise ValueError('Tuple must have exactly 2 elements: filename, fileobj') + else: + filename, fileobj = guess_filename(f) or key, f + + data.add_field(key, fileobj, filename=filename) + + return data + async def _convert_markup(markup): if isinstance(markup, types.JsonSerializable): return markup.to_json() @@ -731,7 +772,7 @@ async def send_audio(token, chat_id, audio, caption=None, duration=None, perform async def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_markup=None, parse_mode=None, disable_notification=None, timeout=None, caption=None, thumb=None, caption_entities=None, allow_sending_without_reply=None, disable_content_type_detection=None, visible_file_name=None): - method_url = get_method_by_type(data_type) + method_url = await get_method_by_type(data_type) payload = {'chat_id': chat_id} files = None if not util.is_string(data):