From 99129daeeee2d3bcb33e13b9cb8c1ebb16aa9b98 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Mon, 15 Oct 2018 18:35:51 +0200 Subject: [PATCH] Show the request that caused RPC errors in their messages --- telethon/errors/__init__.py | 44 ++++--------------------- telethon/errors/rpcbaseerrors.py | 34 +++++++++++-------- telethon/network/mtprotosender.py | 2 +- telethon_generator/generators/errors.py | 6 ++-- 4 files changed, 31 insertions(+), 55 deletions(-) diff --git a/telethon/errors/__init__.py b/telethon/errors/__init__.py index faf88e8d..ef327041 100644 --- a/telethon/errors/__init__.py +++ b/telethon/errors/__init__.py @@ -2,9 +2,7 @@ This module holds all the base and automatically generated errors that the Telegram API has. See telethon_generator/errors.json for more. """ -import urllib.request import re -from threading import Thread from .common import ( ReadCancelledError, TypeNotFoundError, InvalidChecksumError, @@ -17,57 +15,27 @@ from .rpcbaseerrors import * from .rpcerrorlist import * -def report_error(code, message, report_method): - """ - Reports an RPC error to pwrtelegram. - - :param code: the integer code of the error (like 400). - :param message: the message representing the error. - :param report_method: the constructor ID of the function that caused it. - """ - try: - # Ensure it's signed - report_method = int.from_bytes( - report_method.to_bytes(4, 'big'), 'big', signed=True - ) - url = urllib.request.urlopen( - 'https://rpc.pwrtelegram.xyz?code={}&error={}&method={}' - .format(code, message, report_method), - timeout=5 - ) - url.read() - url.close() - except Exception as e: - "We really don't want to crash when just reporting an error" - - -def rpc_message_to_error(rpc_error, report_method=None): +def rpc_message_to_error(rpc_error, request): """ Converts a Telegram's RPC Error to a Python error. :param rpc_error: the RpcError instance. - :param report_method: if present, the ID of the method that caused it. + :param request: the request that caused this error. :return: the RPCError as a Python exception that represents this error. """ - if report_method is not None: - Thread( - target=report_error, - args=(rpc_error.error_code, rpc_error.error_message, report_method) - ).start() - # Try to get the error by direct look-up, otherwise regex cls = rpc_errors_dict.get(rpc_error.error_message, None) if cls: - return cls() + return cls(request) for msg_regex, cls in rpc_errors_re: m = re.match(msg_regex, rpc_error.error_message) if m: capture = int(m.group(1)) if m.groups() else None - return cls(capture=capture) + return cls(request, capture=capture) cls = base_errors.get(rpc_error.error_code) if cls: - return cls(rpc_error.error_message) + return cls(request, rpc_error.error_message) - return RPCError(rpc_error.error_message, rpc_error.error_code) + return RPCError(request, rpc_error.error_message, rpc_error.error_code) diff --git a/telethon/errors/rpcbaseerrors.py b/telethon/errors/rpcbaseerrors.py index 2ff3b47f..edbab5ba 100644 --- a/telethon/errors/rpcbaseerrors.py +++ b/telethon/errors/rpcbaseerrors.py @@ -3,11 +3,17 @@ class RPCError(Exception): code = None message = None - def __init__(self, message, code=None): - super().__init__('RPCError {}: {}'.format(code or self.code, message)) + def __init__(self, request, message, code=None): + super().__init__('RPCError {}: {}{}'.format( + code or self.code, message, self._fmt_request(request))) + self.code = code self.message = message + @staticmethod + def _fmt_request(request): + return ' (caused by {})'.format(request.__class__.__name__) + def __reduce__(self): return type(self), (self.code, self.message) @@ -47,8 +53,8 @@ class ForbiddenError(RPCError): code = 403 message = 'FORBIDDEN' - def __init__(self, message): - super().__init__(message) + def __init__(self, request, message): + super().__init__(request, message) self.message = message @@ -59,8 +65,8 @@ class NotFoundError(RPCError): code = 404 message = 'NOT_FOUND' - def __init__(self, message): - super().__init__(message) + def __init__(self, request, message): + super().__init__(request, message) self.message = message @@ -72,8 +78,8 @@ class AuthKeyError(RPCError): code = 406 message = 'AUTH_KEY' - def __init__(self, message): - super().__init__(message) + def __init__(self, request, message): + super().__init__(request, message) self.message = message @@ -97,8 +103,8 @@ class ServerError(RPCError): code = 500 message = 'INTERNAL' - def __init__(self, message): - super().__init__(message) + def __init__(self, request, message): + super().__init__(request, message) self.message = message @@ -110,8 +116,8 @@ class BotTimeout(RPCError): code = -503 message = 'Timeout' - def __init__(self, message): - super().__init__(message) + def __init__(self, request, message): + super().__init__(request, message) self.message = message @@ -154,8 +160,8 @@ class BadMessageError(Exception): 'Invalid container.' } - def __init__(self, code): - super().__init__(self.ErrorMessages.get( + def __init__(self, request, code): + super().__init__(request, self.ErrorMessages.get( code, 'Unknown error code (this should not happen): {}.'.format(code))) diff --git a/telethon/network/mtprotosender.py b/telethon/network/mtprotosender.py index d0248680..e18d48a1 100644 --- a/telethon/network/mtprotosender.py +++ b/telethon/network/mtprotosender.py @@ -470,7 +470,7 @@ class MTProtoSender: return if rpc_result.error: - error = rpc_message_to_error(rpc_result.error) + error = rpc_message_to_error(rpc_result.error, state.request) self._send_queue.append( RequestState(MsgsAck([state.msg_id]), loop=self._loop)) diff --git a/telethon_generator/generators/errors.py b/telethon_generator/generators/errors.py index 4ec5ac0b..93355e15 100644 --- a/telethon_generator/generators/errors.py +++ b/telethon_generator/generators/errors.py @@ -26,14 +26,16 @@ def generate_errors(errors, f): # Error classes generation for error in errors: - f.write('\n\nclass {}({}):\n def __init__(self, **kwargs):\n' + f.write('\n\nclass {}({}):\n' + ' def __init__(self, request, **kwargs):\n' ' '.format(error.name, error.subclass)) if error.has_captures: f.write("self.{} = int(kwargs.get('capture', 0))\n " .format(error.capture_name)) - f.write('super(Exception, self).__init__({}' + f.write('super(Exception, self).__init__(' + '{} + self._fmt_request(request)' .format(repr(error.description))) if error.has_captures: