mirror of
				https://github.com/LonamiWebs/Telethon.git
				synced 2025-10-30 23:47:33 +03:00 
			
		
		
		
	Completely change errors (make one class for each)
This commit is contained in:
		
							parent
							
								
									5df4716164
								
							
						
					
					
						commit
						44ab85962b
					
				
							
								
								
									
										19
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								README.rst
									
									
									
									
									
								
							|  | @ -130,13 +130,20 @@ More examples are also available under the ``telethon_examples/`` folder. | ||||||
| Common errors | Common errors | ||||||
| ------------- | ------------- | ||||||
| 
 | 
 | ||||||
| Some errors you may encounter when using Telethon can be the ``FloodWaitError``, which tells you | Errors resulting from Telegram queries all subclass the ``RPCError`` class. | ||||||
| that you've been trying to send the very same request many times, too quickly. You must wait | This class is further specialized into further errors: | ||||||
| ``flood_wait_error.seconds`` before calling ``client.connect()`` again, since this error also |  | ||||||
| disconnects the client. |  | ||||||
| 
 | 
 | ||||||
| Another common one is the ``RPCError``, which usually has descriptive information on what went wrong. | * ``InvalidDCError`` (303), the request must be repeated on another DC. | ||||||
| However, you may encounter something strange. If you don't manage to solve it, please open an issue. | * ``BadRequestError`` (400), the request contained errors. | ||||||
|  | * ``UnauthorizedError`` (401), the user is not authorized yet. | ||||||
|  | * ``ForbiddenError`` (403), privacy violation error. | ||||||
|  | * ``NotFoundError`` (404), make sure you're invoking ``Request``'s! | ||||||
|  | * ``FloodError`` (420), the same request was repeated many times. Must wait ``.seconds``. | ||||||
|  | 
 | ||||||
|  | Further specialization is also available, for instance, the ``SessionPasswordNeededError`` | ||||||
|  | when signing in means that a password must be provided to continue. | ||||||
|  | 
 | ||||||
|  | If the error is not recognised, it will only be an ``RPCError``. | ||||||
| 
 | 
 | ||||||
| Unless you know what you're doing, you should download media by always using the ``.download_file()`` | Unless you know what you're doing, you should download media by always using the ``.download_file()`` | ||||||
| function, which supports a ``str`` or a file handle as parameters. Otherwise, ``.invoke()`` may raise | function, which supports a ``str`` or a file handle as parameters. Otherwise, ``.invoke()`` may raise | ||||||
|  |  | ||||||
|  | @ -1,4 +1,3 @@ | ||||||
| from .errors import * |  | ||||||
| from .telegram_bare_client import TelegramBareClient | from .telegram_bare_client import TelegramBareClient | ||||||
| from .telegram_client import TelegramClient | from .telegram_client import TelegramClient | ||||||
| from . import tl | from . import tl | ||||||
|  |  | ||||||
|  | @ -1,266 +0,0 @@ | ||||||
| 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.', |  | ||||||
|         'PHONE_NUMBER_BANNED': |  | ||||||
|         'The used phone number has been banned from Telegram and cannot ' |  | ||||||
|         'be used anymore. Possibly check https://www.telegram.org/faq_spam.', |  | ||||||
|         '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_OCCUPIED': |  | ||||||
|         'See issue #96 for Telethon - try upgrading the library.', |  | ||||||
|         '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.', |  | ||||||
|         'DC_ID_INVALID': |  | ||||||
|         'This occurs when an authorization is tried to be exported for ' |  | ||||||
|         'the same data center one is currently connected to.', |  | ||||||
| 
 |  | ||||||
|         # 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.', |  | ||||||
|         'USER_ALREADY_PARTICIPANT': |  | ||||||
|         'The authenticated user is already a participant of the chat.', |  | ||||||
|         'INVITE_HASH_EXPIRED': |  | ||||||
|         'The chat the user tried to join has expired and is not valid anymore.', |  | ||||||
| 
 |  | ||||||
|         # 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: |  | ||||||
|                 error_msg = '{} ({}): {}'.format( |  | ||||||
|                     self.message, self.code, error_msg) |  | ||||||
| 
 |  | ||||||
|                 # 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 |  | ||||||
							
								
								
									
										43
									
								
								telethon/errors/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								telethon/errors/__init__.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | ||||||
|  | import re | ||||||
|  | 
 | ||||||
|  | from .common import ( | ||||||
|  |     ReadCancelledError, InvalidParameterError, TypeNotFoundError, | ||||||
|  |     InvalidChecksumError | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | from .rpc_errors import ( | ||||||
|  |     RPCError, InvalidDCError, BadRequestError, UnauthorizedError, | ||||||
|  |     ForbiddenError, NotFoundError, FloodError, ServerError, BadMessageError | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | from .rpc_errors_303 import * | ||||||
|  | from .rpc_errors_400 import * | ||||||
|  | from .rpc_errors_401 import * | ||||||
|  | from .rpc_errors_420 import * | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def rpc_message_to_error(code, message): | ||||||
|  |     errors = { | ||||||
|  |         303: rpc_303_errors, | ||||||
|  |         400: rpc_400_errors, | ||||||
|  |         401: rpc_401_errors, | ||||||
|  |         420: rpc_420_errors | ||||||
|  |     }.get(code, None) | ||||||
|  | 
 | ||||||
|  |     if errors is not None: | ||||||
|  |         for msg, cls in errors.items(): | ||||||
|  |             m = re.match(msg, message) | ||||||
|  |             if m: | ||||||
|  |                 extra = int(m.group(1)) if m.groups() else None | ||||||
|  |                 return cls(extra=extra) | ||||||
|  | 
 | ||||||
|  |     elif code == 403: | ||||||
|  |         return ForbiddenError() | ||||||
|  | 
 | ||||||
|  |     elif code == 404: | ||||||
|  |         return NotFoundError() | ||||||
|  | 
 | ||||||
|  |     elif code == 500: | ||||||
|  |         return ServerError() | ||||||
|  | 
 | ||||||
|  |     return RPCError('{} (code {})'.format(message, code)) | ||||||
							
								
								
									
										37
									
								
								telethon/errors/common.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								telethon/errors/common.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | ||||||
|  | """Errors not related to the Telegram API itself""" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 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 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 | ||||||
							
								
								
									
										111
									
								
								telethon/errors/rpc_errors.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								telethon/errors/rpc_errors.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,111 @@ | ||||||
|  | class RPCError(Exception): | ||||||
|  |     code = None | ||||||
|  |     message = None | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class InvalidDCError(RPCError): | ||||||
|  |     """ | ||||||
|  |         The request must be repeated, but directed to a different data center. | ||||||
|  |     """ | ||||||
|  |     code = 303 | ||||||
|  |     message = 'ERROR_SEE_OTHER' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class BadRequestError(RPCError): | ||||||
|  |     """ | ||||||
|  |         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. | ||||||
|  |     """ | ||||||
|  |     code = 400 | ||||||
|  |     message = 'BAD_REQUEST' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UnauthorizedError(RPCError): | ||||||
|  |     """ | ||||||
|  |         There was an unauthorized attempt to use functionality available only | ||||||
|  |         to authorized users. | ||||||
|  |     """ | ||||||
|  |     code = 401 | ||||||
|  |     message = 'UNAUTHORIZED' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ForbiddenError(RPCError): | ||||||
|  |     """ | ||||||
|  |         Privacy violation. For example, an attempt to write a message to | ||||||
|  |         someone who has blacklisted the current user. | ||||||
|  |     """ | ||||||
|  |     code = 403 | ||||||
|  |     message = 'FORBIDDEN' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class NotFoundError(RPCError): | ||||||
|  |     """ | ||||||
|  |         An attempt to invoke a non-existent object, such as a method. | ||||||
|  |     """ | ||||||
|  |     code = 404 | ||||||
|  |     message = 'NOT_FOUND' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FloodError(RPCError): | ||||||
|  |     """ | ||||||
|  |         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. | ||||||
|  |     """ | ||||||
|  |     code = 420 | ||||||
|  |     message = 'FLOOD' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ServerError(RPCError): | ||||||
|  |     """ | ||||||
|  |         An internal server error occurred while a request was being processed | ||||||
|  |         for example, there was a disruption while accessing a database or file | ||||||
|  |         storage. | ||||||
|  |     """ | ||||||
|  |     code = 500 | ||||||
|  |     message = 'INTERNAL' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 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, self.ErrorMessages.get( | ||||||
|  |             code, | ||||||
|  |             'Unknown error code (this should not happen): {}.'.format(code))) | ||||||
|  | 
 | ||||||
|  |         self.code = code | ||||||
							
								
								
									
										51
									
								
								telethon/errors/rpc_errors_303.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								telethon/errors/rpc_errors_303.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | ||||||
|  | from . import InvalidDCError | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FileMigrateError(InvalidDCError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         self.new_dc = kwargs['extra'] | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The file to be accessed is currently stored in DC {}.' | ||||||
|  |             .format(self.new_dc) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhoneMigrateError(InvalidDCError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         self.new_dc = kwargs['extra'] | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The phone number a user is trying to use for authorization is ' | ||||||
|  |             'associated with DC {}.' | ||||||
|  |             .format(self.new_dc) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class NetworkMigrateError(InvalidDCError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         self.new_dc = kwargs['extra'] | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The source IP address is associated with DC {}.' | ||||||
|  |             .format(self.new_dc) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UserMigrateError(InvalidDCError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         self.new_dc = kwargs['extra'] | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The user whose identity is being used to execute queries is ' | ||||||
|  |             'associated with DC {}.' | ||||||
|  |             .format(self.new_dc) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | rpc_303_errors = { | ||||||
|  |     'FILE_MIGRATE_(\d+)': FileMigrateError, | ||||||
|  |     'PHONE_MIGRATE_(\d+)': PhoneMigrateError, | ||||||
|  |     'NETWORK_MIGRATE_(\d+)': NetworkMigrateError, | ||||||
|  |     'USER_MIGRATE_(\d+)': UserMigrateError | ||||||
|  | } | ||||||
							
								
								
									
										364
									
								
								telethon/errors/rpc_errors_400.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										364
									
								
								telethon/errors/rpc_errors_400.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,364 @@ | ||||||
|  | from . import BadRequestError | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ApiIdInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The api_id/api_hash combination is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class BotMethodInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The API access for bot users is restricted. The method you ' | ||||||
|  |             'tried to invoke cannot be executed as a bot.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ChannelInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'Invalid channel object. Make sure to pass the right types.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ChatAdminRequiredError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             '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).' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ChatIdInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'Invalid object ID for a chat. Make sure to pass the right types.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ConnectionLayerInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The very first request must always be InvokeWithLayerRequest.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class DcIdInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'This occurs when an authorization is tried to be exported for ' | ||||||
|  |             'the same data center one is currently connected to.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FieldNameEmptyError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The field with the name FIELD_NAME is missing.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FieldNameInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The field with the name FIELD_NAME is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FilePartsInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The number of file parts is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FilePartMissingError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         self.which = kwargs['extra'] | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'Part {} of the file is missing from storage.'.format(self.which) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FilePartInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The file part number is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FirstNameInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The first name is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class InputMethodInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The invoked method does not exist anymore or has never existed.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class LastNameInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The last name is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Md5ChecksumInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The MD5 check-sums do not match.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class MessageEmptyError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'Empty or invalid UTF-8 message was sent.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class MessageIdInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The specified message ID is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class MessageTooLongError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'Message was too long. Current maximum length is 4096 UTF-8 ' | ||||||
|  |             'characters.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class MsgWaitFailedError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'A waiting call returned an error.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PasswordHashInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The password (and thus its hash value) you entered is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PeerIdInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'An invalid Peer was used. Make sure to pass the right peer type.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhoneCodeEmptyError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The phone code is missing.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhoneCodeExpiredError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The confirmation code has expired.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhoneCodeHashEmptyError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The phone code hash is missing.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhoneCodeInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The phone code entered was invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhoneNumberBannedError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The used phone number has been banned from Telegram and cannot ' | ||||||
|  |             'be used anymore. Maybe check https://www.telegram.org/faq_spam.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhoneNumberInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The phone number is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhoneNumberOccupiedError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The phone number is already in use.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhoneNumberUnoccupiedError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The phone number is not yet being used.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class PhotoInvalidDimensionsError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The photo dimensions are invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TypeConstructorInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The type constructor is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UsernameInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'Unacceptable username. Must match r"[a-zA-Z][\w\d]{4,32}"' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UsernameNotModifiedError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The username is not different from the current username' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UsernameNotOccupiedError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'See issue #96 for Telethon - try upgrading the library.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UsernameOccupiedError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The username is already taken.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UsersTooFewError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'Not enough users (to create a chat, for example).' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UsersTooMuchError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The maximum number of users has been exceeded (to create a ' | ||||||
|  |             'chat, for example).' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UserIdInvalidError(BadRequestError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'Invalid object ID for an user. Make sure to pass the right types.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | rpc_400_errors = { | ||||||
|  |     'API_ID_INVALID': ApiIdInvalidError, | ||||||
|  |     'BOT_METHOD_INVALID': BotMethodInvalidError, | ||||||
|  |     'CHANNEL_INVALID': ChannelInvalidError, | ||||||
|  |     'CHAT_ADMIN_REQUIRED': ChatAdminRequiredError, | ||||||
|  |     'CHAT_ID_INVALID': ChatIdInvalidError, | ||||||
|  |     'CONNECTION_LAYER_INVALID': ConnectionLayerInvalidError, | ||||||
|  |     'DC_ID_INVALID': DcIdInvalidError, | ||||||
|  |     'FIELD_NAME_EMPTY': FieldNameEmptyError, | ||||||
|  |     'FIELD_NAME_INVALID': FieldNameInvalidError, | ||||||
|  |     'FILE_PARTS_INVALID': FilePartsInvalidError, | ||||||
|  |     'FILE_PART_(\d+)_MISSING': FilePartMissingError, | ||||||
|  |     'FILE_PART_INVALID': FilePartInvalidError, | ||||||
|  |     'FIRSTNAME_INVALID': FirstNameInvalidError, | ||||||
|  |     'INPUT_METHOD_INVALID': InputMethodInvalidError, | ||||||
|  |     'LASTNAME_INVALID': LastNameInvalidError, | ||||||
|  |     'MD5_CHECKSUM_INVALID': Md5ChecksumInvalidError, | ||||||
|  |     'MESSAGE_EMPTY': MessageEmptyError, | ||||||
|  |     'MESSAGE_ID_INVALID': MessageIdInvalidError, | ||||||
|  |     'MESSAGE_TOO_LONG': MessageTooLongError, | ||||||
|  |     'MSG_WAIT_FAILED': MsgWaitFailedError, | ||||||
|  |     'PASSWORD_HASH_INVALID': PasswordHashInvalidError, | ||||||
|  |     'PEER_ID_INVALID': PeerIdInvalidError, | ||||||
|  |     'PHONE_CODE_EMPTY': PhoneCodeEmptyError, | ||||||
|  |     'PHONE_CODE_EXPIRED': PhoneCodeExpiredError, | ||||||
|  |     'PHONE_CODE_HASH_EMPTY': PhoneCodeHashEmptyError, | ||||||
|  |     'PHONE_CODE_INVALID': PhoneCodeInvalidError, | ||||||
|  |     'PHONE_NUMBER_BANNED': PhoneNumberBannedError, | ||||||
|  |     'PHONE_NUMBER_INVALID': PhoneNumberInvalidError, | ||||||
|  |     'PHONE_NUMBER_OCCUPIED': PhoneNumberOccupiedError, | ||||||
|  |     'PHONE_NUMBER_UNOCCUPIED': PhoneNumberUnoccupiedError, | ||||||
|  |     'PHOTO_INVALID_DIMENSIONS': PhotoInvalidDimensionsError, | ||||||
|  |     'TYPE_CONSTRUCTOR_INVALID': TypeConstructorInvalidError, | ||||||
|  |     'USERNAME_INVALID': UsernameInvalidError, | ||||||
|  |     'USERNAME_NOT_MODIFIED': UsernameNotModifiedError, | ||||||
|  |     'USERNAME_NOT_OCCUPIED': UsernameNotOccupiedError, | ||||||
|  |     'USERNAME_OCCUPIED': UsernameOccupiedError, | ||||||
|  |     'USERS_TOO_FEW': UsersTooFewError, | ||||||
|  |     'USERS_TOO_MUCH': UsersTooMuchError, | ||||||
|  |     'USER_ID_INVALID': UserIdInvalidError, | ||||||
|  | } | ||||||
							
								
								
									
										98
									
								
								telethon/errors/rpc_errors_401.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								telethon/errors/rpc_errors_401.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,98 @@ | ||||||
|  | from . import UnauthorizedError | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class ActiveUserRequiredError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The method is only available to already activated users.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class AuthKeyInvalidError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The key is invalid.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class AuthKeyPermEmptyError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The method is unavailable for temporary authorization key, not ' | ||||||
|  |             'bound to permanent.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class AuthKeyUnregisteredError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The key is not registered in the system.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class InviteHashExpiredError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The chat the user tried to join has expired and is not valid ' | ||||||
|  |             'anymore.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class SessionExpiredError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The authorization has expired.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class SessionPasswordNeededError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'Two-steps verification is enabled and a password is required.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class SessionRevokedError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The authorization has been invalidated, because of the user ' | ||||||
|  |             'terminating all sessions.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UserAlreadyParticipantError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The authenticated user is already a participant of the chat.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class UserDeactivatedError(UnauthorizedError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'The user has been deleted/deactivated.' | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | rpc_401_errors = { | ||||||
|  |     'ACTIVE_USER_REQUIRED': ActiveUserRequiredError, | ||||||
|  |     'AUTH_KEY_INVALID': AuthKeyInvalidError, | ||||||
|  |     'AUTH_KEY_PERM_EMPTY': AuthKeyPermEmptyError, | ||||||
|  |     'AUTH_KEY_UNREGISTERED': AuthKeyUnregisteredError, | ||||||
|  |     'INVITE_HASH_EXPIRED': InviteHashExpiredError, | ||||||
|  |     'SESSION_EXPIRED': SessionExpiredError, | ||||||
|  |     'SESSION_PASSWORD_NEEDED': SessionPasswordNeededError, | ||||||
|  |     'SESSION_REVOKED': SessionRevokedError, | ||||||
|  |     'USER_ALREADY_PARTICIPANT': UserAlreadyParticipantError, | ||||||
|  |     'USER_DEACTIVATED': UserDeactivatedError, | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								telethon/errors/rpc_errors_420.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								telethon/errors/rpc_errors_420.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | from . import FloodError | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FloodWaitError(FloodError): | ||||||
|  |     def __init__(self, **kwargs): | ||||||
|  |         self.seconds = kwargs['extra'] | ||||||
|  |         super(Exception, self).__init__( | ||||||
|  |             self, | ||||||
|  |             'A wait of {} seconds is required.' | ||||||
|  |             .format(self.seconds) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | rpc_420_errors = { | ||||||
|  |     'FLOOD_WAIT_(\d+)': FloodWaitError | ||||||
|  | } | ||||||
|  | @ -4,8 +4,7 @@ from threading import RLock | ||||||
| 
 | 
 | ||||||
| from .. import helpers as utils | from .. import helpers as utils | ||||||
| from ..crypto import AES | from ..crypto import AES | ||||||
| from ..errors import (BadMessageError, FloodWaitError, | from ..errors import BadMessageError, InvalidDCError, rpc_message_to_error | ||||||
|                       RPCError, InvalidDCError) |  | ||||||
| from ..tl.all_tlobjects import tlobjects | from ..tl.all_tlobjects import tlobjects | ||||||
| from ..tl.types import MsgsAck | from ..tl.types import MsgsAck | ||||||
| from ..extensions import BinaryReader, BinaryWriter | from ..extensions import BinaryReader, BinaryWriter | ||||||
|  | @ -106,7 +105,7 @@ class MtProtoSender: | ||||||
|                     if updates: |                     if updates: | ||||||
|                         break  # No request but one update read, exit |                         break  # No request but one update read, exit | ||||||
|                 elif request.confirm_received: |                 elif request.confirm_received: | ||||||
|                         break  # Request, and result read, exit |                     break  # Request, and result read, exit | ||||||
| 
 | 
 | ||||||
|             self._logger.info('Request result received') |             self._logger.info('Request result received') | ||||||
|         self._logger.debug('receive() released the lock') |         self._logger.debug('receive() released the lock') | ||||||
|  | @ -325,15 +324,16 @@ class MtProtoSender: | ||||||
|             request.confirm_received = True |             request.confirm_received = True | ||||||
| 
 | 
 | ||||||
|         if inner_code == 0x2144ca19:  # RPC Error |         if inner_code == 0x2144ca19:  # RPC Error | ||||||
|             error = RPCError( |             error = rpc_message_to_error( | ||||||
|                 code=reader.read_int(), message=reader.tgread_string()) |                 reader.read_int(), reader.tgread_string()) | ||||||
| 
 | 
 | ||||||
|             # Acknowledge that we received the error |             # Acknowledge that we received the error | ||||||
|             self._need_confirmation.append(request_id) |             self._need_confirmation.append(request_id) | ||||||
|             self._send_acknowledges() |             self._send_acknowledges() | ||||||
| 
 | 
 | ||||||
|             self._logger.warning('Read RPC error: %s', str(error)) |             self._logger.warning('Read RPC error: %s', str(error)) | ||||||
|             if error.must_resend: |             if isinstance(error, InvalidDCError): | ||||||
|  |                 # Must resend this request | ||||||
|                 if not request: |                 if not request: | ||||||
|                     raise ValueError( |                     raise ValueError( | ||||||
|                         'The previously sent request must be resent. ' |                         'The previously sent request must be resent. ' | ||||||
|  | @ -341,15 +341,7 @@ class MtProtoSender: | ||||||
|                         '(possibly called from a different thread).') |                         '(possibly called from a different thread).') | ||||||
|                 request.confirm_received = False |                 request.confirm_received = False | ||||||
| 
 | 
 | ||||||
|             if error.message.startswith('FLOOD_WAIT_'): |             raise error | ||||||
|                 self._updates_thread_sleep = error.additional_data |  | ||||||
|                 raise FloodWaitError(seconds=error.additional_data) |  | ||||||
| 
 |  | ||||||
|             elif '_MIGRATE_' in error.message: |  | ||||||
|                 raise InvalidDCError(error) |  | ||||||
| 
 |  | ||||||
|             else: |  | ||||||
|                 raise error |  | ||||||
|         else: |         else: | ||||||
|             if not request: |             if not request: | ||||||
|                 raise ValueError( |                 raise ValueError( | ||||||
|  |  | ||||||
|  | @ -9,15 +9,16 @@ from . import TelegramBareClient | ||||||
| 
 | 
 | ||||||
| # Import some externalized utilities to work with the Telegram types and more | # Import some externalized utilities to work with the Telegram types and more | ||||||
| from . import helpers as utils | from . import helpers as utils | ||||||
| from .errors import (RPCError, InvalidDCError, InvalidParameterError, | from .errors import (RPCError, UnauthorizedError, InvalidParameterError, | ||||||
|                      ReadCancelledError) |                      ReadCancelledError, FileMigrateError, PhoneMigrateError, | ||||||
| from .network import authenticator, MtProtoSender, TcpTransport |                      NetworkMigrateError, UserMigrateError, PhoneCodeEmptyError, | ||||||
|  |                      PhoneCodeExpiredError, PhoneCodeHashEmptyError, | ||||||
|  |                      PhoneCodeInvalidError) | ||||||
|  | 
 | ||||||
| from .parser.markdown_parser import parse_message_entities | from .parser.markdown_parser import parse_message_entities | ||||||
| 
 | 
 | ||||||
| # For sending and receiving requests | # For sending and receiving requests | ||||||
| from .tl import MTProtoRequest, Session, JsonSession | from .tl import MTProtoRequest, Session, JsonSession | ||||||
| from .tl.all_tlobjects import layer |  | ||||||
| from .tl.functions import (InitConnectionRequest, InvokeWithLayerRequest) |  | ||||||
| 
 | 
 | ||||||
| # Required to get the password salt | # Required to get the password salt | ||||||
| from .tl.functions.account import GetPasswordRequest | from .tl.functions.account import GetPasswordRequest | ||||||
|  | @ -251,18 +252,13 @@ class TelegramClient(TelegramBareClient): | ||||||
|             # TODO Retry if 'result' is None? |             # TODO Retry if 'result' is None? | ||||||
|             return result |             return result | ||||||
| 
 | 
 | ||||||
|         except InvalidDCError as e: |         except (PhoneMigrateError, NetworkMigrateError, UserMigrateError) as e: | ||||||
|             if not e.message.startswith('FILE_MIGRATE_'): |             self._logger.info('DC error when invoking request, ' | ||||||
|                 # Only reconnect unless we're trying to download media, |                               'attempting to reconnect at DC {}' | ||||||
|                 # this is, on login (user migrate, phone migrate, etc.) |                               .format(e.new_dc)) | ||||||
|                 self._logger.info('DC error when invoking request, ' |  | ||||||
|                                   'attempting to reconnect at DC {}' |  | ||||||
|                                   .format(e.new_dc)) |  | ||||||
| 
 | 
 | ||||||
|                 self.reconnect(new_dc=e.new_dc) |             self.reconnect(new_dc=e.new_dc) | ||||||
|                 return self.invoke(request, timeout=timeout) |             return self.invoke(request, timeout=timeout) | ||||||
|             else: |  | ||||||
|                 raise |  | ||||||
| 
 | 
 | ||||||
|         finally: |         finally: | ||||||
|             self._lock.release() |             self._lock.release() | ||||||
|  | @ -326,11 +322,9 @@ class TelegramClient(TelegramBareClient): | ||||||
|                 result = self.invoke(SignInRequest( |                 result = self.invoke(SignInRequest( | ||||||
|                     phone_number, self._phone_code_hashes[phone_number], code)) |                     phone_number, self._phone_code_hashes[phone_number], code)) | ||||||
| 
 | 
 | ||||||
|             except RPCError as error: |             except (PhoneCodeEmptyError, PhoneCodeExpiredError, | ||||||
|                 if error.message.startswith('PHONE_CODE_'): |                     PhoneCodeHashEmptyError, PhoneCodeInvalidError): | ||||||
|                     return None |                 return None | ||||||
|                 else: |  | ||||||
|                     raise |  | ||||||
| 
 | 
 | ||||||
|         elif password: |         elif password: | ||||||
|             salt = self.invoke(GetPasswordRequest()).current_salt |             salt = self.invoke(GetPasswordRequest()).current_salt | ||||||
|  | @ -386,11 +380,8 @@ class TelegramClient(TelegramBareClient): | ||||||
|            or None if the request fails (hence, not authenticated).""" |            or None if the request fails (hence, not authenticated).""" | ||||||
|         try: |         try: | ||||||
|             return self.invoke(GetUsersRequest([InputUserSelf()]))[0] |             return self.invoke(GetUsersRequest([InputUserSelf()]))[0] | ||||||
|         except RPCError as e: |         except UnauthorizedError: | ||||||
|             if e.code == 401:  # 401 UNAUTHORIZED |             return None | ||||||
|                 return None |  | ||||||
|             else: |  | ||||||
|                 raise |  | ||||||
| 
 | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def list_sessions(): |     def list_sessions(): | ||||||
|  | @ -743,7 +734,7 @@ class TelegramClient(TelegramBareClient): | ||||||
|                     file_size=file_size, |                     file_size=file_size, | ||||||
|                     progress_callback=progress_callback |                     progress_callback=progress_callback | ||||||
|                 ) |                 ) | ||||||
|             except InvalidDCError as e: |             except FileMigrateError as e: | ||||||
|                 on_dc = e.new_dc |                 on_dc = e.new_dc | ||||||
| 
 | 
 | ||||||
|         if on_dc is not None: |         if on_dc is not None: | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ import shutil | ||||||
| from getpass import getpass | from getpass import getpass | ||||||
| 
 | 
 | ||||||
| from telethon import TelegramClient | from telethon import TelegramClient | ||||||
| from telethon.errors import RPCError | from telethon.errors import SessionPasswordNeededError | ||||||
| from telethon.tl.types import UpdateShortChatMessage, UpdateShortMessage | from telethon.tl.types import UpdateShortChatMessage, UpdateShortMessage | ||||||
| from telethon.utils import get_display_name | from telethon.utils import get_display_name | ||||||
| 
 | 
 | ||||||
|  | @ -76,14 +76,11 @@ class InteractiveTelegramClient(TelegramClient): | ||||||
|                     self_user = self.sign_in(user_phone, code) |                     self_user = self.sign_in(user_phone, code) | ||||||
| 
 | 
 | ||||||
|                 # Two-step verification may be enabled |                 # Two-step verification may be enabled | ||||||
|                 except RPCError as e: |                 except SessionPasswordNeededError as e: | ||||||
|                     if e.password_required: |                     pw = getpass('Two step verification is enabled. ' | ||||||
|                         pw = getpass('Two step verification is enabled. ' |                                  'Please enter your password: ') | ||||||
|                                      'Please enter your password: ') |  | ||||||
| 
 | 
 | ||||||
|                         self_user = self.sign_in(password=pw) |                     self_user = self.sign_in(password=pw) | ||||||
|                     else: |  | ||||||
|                         raise |  | ||||||
| 
 | 
 | ||||||
|     def run(self): |     def run(self): | ||||||
|         # Listen for updates |         # Listen for updates | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user