Telethon/telethon/errors.py
2017-05-29 16:46:17 +02:00

252 lines
11 KiB
Python

import re
class ReadCancelledError(Exception):
"""Occurs when a read operation was cancelled"""
def __init__(self):
super().__init__(self, 'The read operation was cancelled.')
class InvalidParameterError(Exception):
"""Occurs when an invalid parameter is given, for example,
when either A or B are required but none is given"""
class TypeNotFoundError(Exception):
"""Occurs when a type is not found, for example,
when trying to read a TLObject with an invalid constructor code"""
def __init__(self, invalid_constructor_id):
super().__init__(
self, 'Could not find a matching Constructor ID for the TLObject '
'that was supposed to be read with ID {}. Most likely, a TLObject '
'was trying to be read when it should not be read.'
.format(hex(invalid_constructor_id)))
self.invalid_constructor_id = invalid_constructor_id
class InvalidDCError(Exception):
def __init__(self, rpc_error):
self.new_dc = rpc_error.__dict__.pop('additional_data')
self.__dict__.update(rpc_error.__dict__)
class InvalidChecksumError(Exception):
def __init__(self, checksum, valid_checksum):
super().__init__(
self,
'Invalid checksum ({} when {} was expected). This packet should be skipped.'
.format(checksum, valid_checksum))
self.checksum = checksum
self.valid_checksum = valid_checksum
class FloodWaitError(Exception):
def __init__(self, seconds):
super().__init__(
self,
'Too many requests were made too fast. Must wait {} seconds.'
.format(seconds)
)
self.seconds = seconds
class RPCError(Exception):
CodeMessages = {
303:
('ERROR_SEE_OTHER',
'The request must be repeated, but directed to a different data center.'
),
400:
('BAD_REQUEST',
'The query contains errors. In the event that a request was created using a '
'form and contains user generated data, the user should be notified that the '
'data must be corrected before the query is repeated.'),
401:
('UNAUTHORIZED',
'There was an unauthorized attempt to use functionality available only to '
'authorized users.'),
403:
('FORBIDDEN',
'Privacy violation. For example, an attempt to write a message to someone who '
'has blacklisted the current user.'),
404: ('NOT_FOUND',
'An attempt to invoke a non-existent object, such as a method.'),
420:
('FLOOD',
'The maximum allowed number of attempts to invoke the given method with '
'the given input parameters has been exceeded. For example, in an attempt '
'to request a large number of text messages (SMS) for the same phone number.'
),
500:
('INTERNAL',
'An internal server error occurred while a request was being processed; '
'for example, there was a disruption while accessing a database or file storage.'
)
}
ErrorMessages = {
# 303 ERROR_SEE_OTHER
'FILE_MIGRATE_(\d+)':
'The file to be accessed is currently stored in a different data center (#{}).',
'PHONE_MIGRATE_(\d+)':
'The phone number a user is trying to use for authorization is associated '
'with a different data center (#{}).',
'NETWORK_MIGRATE_(\d+)':
'The source IP address is associated with a different data center (#{}, '
'for registration).',
'USER_MIGRATE_(\d+)':
'The user whose identity is being used to execute queries is associated with '
'a different data center (#{} for registration).',
# 400 BAD_REQUEST
'FIRSTNAME_INVALID': 'The first name is invalid.',
'LASTNAME_INVALID': 'The last name is invalid.',
'PHONE_NUMBER_INVALID': 'The phone number is invalid.',
'PHONE_CODE_HASH_EMPTY': 'The phone code hash is missing.',
'PHONE_CODE_EMPTY': 'The phone code is missing.',
'PHONE_CODE_INVALID': 'The phone code entered was invalid.',
'PHONE_CODE_EXPIRED': 'The confirmation code has expired.',
'API_ID_INVALID': 'The api_id/api_hash combination is invalid.',
'PHONE_NUMBER_OCCUPIED': 'The phone number is already in use.',
'PHONE_NUMBER_UNOCCUPIED': 'The phone number is not yet being used.',
'USERS_TOO_FEW': 'Not enough users (to create a chat, for example).',
'USERS_TOO_MUCH':
'The maximum number of users has been exceeded (to create a chat, for example).',
'TYPE_CONSTRUCTOR_INVALID': 'The type constructor is invalid.',
'FILE_PART_INVALID': 'The file part number is invalid.',
'FILE_PARTS_INVALID': 'The number of file parts is invalid.',
'FILE_PART_(\d+)_MISSING':
'Part {} of the file is missing from storage.',
'MD5_CHECKSUM_INVALID': 'The MD5 check-sums do not match.',
'PHOTO_INVALID_DIMENSIONS': 'The photo dimensions are invalid.',
'FIELD_NAME_INVALID': 'The field with the name FIELD_NAME is invalid.',
'FIELD_NAME_EMPTY': 'The field with the name FIELD_NAME is missing.',
'MSG_WAIT_FAILED': 'A waiting call returned an error.',
'CHAT_ADMIN_REQUIRED':
'Chat admin privileges are required to do that in the specified chat '
'(for example, to send a message in a channel which is not yours).',
'PASSWORD_HASH_INVALID':
'The password (and thus its hash value) you entered is invalid.',
'BOT_METHOD_INVALID':
'The API access for bot users is restricted. The method you tried '
'to invoke cannot be executed as a bot.',
'PEER_ID_INVALID':
'An invalid Peer was used. Make sure to pass the right peer type.',
'MESSAGE_EMPTY': 'Empty or invalid UTF-8 message was sent.',
'MESSAGE_TOO_LONG':
'Message was too long. Current maximum length is 4096 UTF-8 characters.',
'USERNAME_INVALID':
'Unacceptable username. Must match r"[a-zA-Z][\w\d]{4,32}"',
'USERNAME_OCCUPIED': 'The username is already taken.',
'USERNAME_NOT_MODIFIED':
'The username is not different from the current username',
'USER_ID_INVALID':
'Invalid object ID for an user. Make sure to pass the right types.',
'CHAT_ID_INVALID':
'Invalid object ID for a chat. Make sure to pass the right types.',
'CHANNEL_INVALID':
'Invalid channel object. Make sure to pass the right types.',
'MESSAGE_ID_INVALID': 'The specified message ID is invalid.',
'CONNECTION_LAYER_INVALID':
'The very first request must always be InvokeWithLayerRequest.',
'INPUT_METHOD_INVALID':
'The invoked method does not exist anymore or has never existed.',
# 401 UNAUTHORIZED
'AUTH_KEY_UNREGISTERED': 'The key is not registered in the system.',
'AUTH_KEY_INVALID': 'The key is invalid.',
'USER_DEACTIVATED': 'The user has been deleted/deactivated.',
'SESSION_REVOKED':
'The authorization has been invalidated, because of the user terminating all sessions.',
'SESSION_EXPIRED': 'The authorization has expired.',
'ACTIVE_USER_REQUIRED':
'The method is only available to already activated users.',
'AUTH_KEY_PERM_EMPTY':
'The method is unavailable for temporary authorization key, not bound to permanent.',
'SESSION_PASSWORD_NEEDED':
'Two-steps verification is enabled and a password is required.',
# 420 FLOOD
'FLOOD_WAIT_(\d+)': 'A wait of {} seconds is required.'
}
def __init__(self, code, message):
self.code = code
self.code_meaning = RPCError.CodeMessages[code]
self.message = message
self.must_resend = code == 303 # ERROR_SEE_OTHER, "The request must be repeated"
called_super = False
for key, error_msg in RPCError.ErrorMessages.items():
match = re.match(key, message)
if match:
# Get additional_data, if any
if match.groups():
self.additional_data = int(match.group(1))
super().__init__(self,
error_msg.format(self.additional_data))
else:
self.additional_data = None
super().__init__(self, error_msg)
# Add another field to easily determine whether this error
# should be handled as a password-required error
self.password_required = message == 'SESSION_PASSWORD_NEEDED'
called_super = True
break
if not called_super:
super().__init__(
self, 'Unknown error message with code {}: {}'.format(code,
message))
class BadMessageError(Exception):
"""Occurs when handling a bad_message_notification"""
ErrorMessages = {
16:
'msg_id too low (most likely, client time is wrong it would be worthwhile to '
'synchronize it using msg_id notifications and re-send the original message '
'with the "correct" msg_id or wrap it in a container with a new msg_id if the '
'original message had waited too long on the client to be transmitted).',
17:
'msg_id too high (similar to the previous case, the client time has to be '
'synchronized, and the message re-sent with the correct msg_id).',
18:
'Incorrect two lower order msg_id bits (the server expects client message msg_id '
'to be divisible by 4).',
19:
'Container msg_id is the same as msg_id of a previously received message '
'(this must never happen).',
20:
'Message too old, and it cannot be verified whether the server has received a '
'message with this msg_id or not.',
32:
'msg_seqno too low (the server has already received a message with a lower '
'msg_id but with either a higher or an equal and odd seqno).',
33:
'msg_seqno too high (similarly, there is a message with a higher msg_id but with '
'either a lower or an equal and odd seqno).',
34:
'An even msg_seqno expected (irrelevant message), but odd received.',
35: 'Odd msg_seqno expected (relevant message), but even received.',
48:
'Incorrect server salt (in this case, the bad_server_salt response is received with '
'the correct salt, and the message is to be re-sent with it).',
64: 'Invalid container.'
}
def __init__(self, code):
super().__init__(self, BadMessageError.ErrorMessages.get(
code,
'Unknown error code (this should not happen): {}.'.format(code)))
self.code = code