mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2026-06-28 04:05:01 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 259a1faedc | |||
| 09bdb88822 |
+15
@@ -2,6 +2,21 @@
|
||||
Changes
|
||||
=======
|
||||
|
||||
**2018-09-01**
|
||||
*Released 11.1.0*
|
||||
|
||||
Fixes and updates for Telegram Passport: (`#1198`_)
|
||||
|
||||
- Fix passport decryption failing at random times
|
||||
- Added support for middle names.
|
||||
- Added support for translations for documents
|
||||
- Add errors for translations for documents
|
||||
- Added support for requesting names in the language of the user's country of residence
|
||||
- Replaced the payload parameter with the new parameter nonce
|
||||
- Add hash to EncryptedPassportElement
|
||||
|
||||
.. _`#1198`: https://github.com/python-telegram-bot/python-telegram-bot/pull/1198
|
||||
|
||||
**2018-08-29**
|
||||
*Released 11.0.0*
|
||||
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ make the development of bots easy and straightforward. These classes are contain
|
||||
Telegram API support
|
||||
====================
|
||||
|
||||
All types and methods of the Telegram Bot API **4.0** are supported.
|
||||
All types and methods of the Telegram Bot API **4.1** are supported.
|
||||
|
||||
==========
|
||||
Installing
|
||||
|
||||
+2
-2
@@ -58,9 +58,9 @@ author = u'Leandro Toledo'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '11.0' # telegram.__version__[:3]
|
||||
version = '11.1' # telegram.__version__[:3]
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '11.0.0' # telegram.__version__
|
||||
release = '11.1.0' # telegram.__version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
+13
-4
@@ -24,9 +24,9 @@ def msg(bot, update):
|
||||
# If we received any passport data
|
||||
passport_data = update.message.passport_data
|
||||
if passport_data:
|
||||
# If our payload doesn't match what we think, this Update did not originate from us
|
||||
# Ideally you would randomize the payload on the server
|
||||
if passport_data.decrypted_credentials.payload != 'thisisatest':
|
||||
# If our nonce doesn't match what we think, this Update did not originate from us
|
||||
# Ideally you would randomize the nonce on the server
|
||||
if passport_data.decrypted_credentials.nonce != 'thisisatest':
|
||||
return
|
||||
|
||||
# Print the decrypted credential data
|
||||
@@ -39,7 +39,7 @@ def msg(bot, update):
|
||||
elif data.type == 'email':
|
||||
print('Email: ', data.email)
|
||||
if data.type in ('personal_details', 'passport', 'driver_license', 'identity_card',
|
||||
'identity_passport', 'address'):
|
||||
'internal_passport', 'address'):
|
||||
print(data.type, data.data)
|
||||
if data.type in ('utility_bill', 'bank_statement', 'rental_agreement',
|
||||
'passport_registration', 'temporary_registration'):
|
||||
@@ -65,6 +65,15 @@ def msg(bot, update):
|
||||
file = data.selfie.get_file()
|
||||
print(data.type, file)
|
||||
file.download()
|
||||
if data.type in ('passport', 'driver_license', 'identity_card',
|
||||
'internal_passport', 'utility_bill', 'bank_statement',
|
||||
'rental_agreement', 'passport_registration',
|
||||
'temporary_registration'):
|
||||
print(data.type, len(data.translation), 'translation')
|
||||
for file in data.translation:
|
||||
actual_file = file.get_file()
|
||||
print(actual_file)
|
||||
actual_file.download()
|
||||
|
||||
|
||||
def error(bot, update, error):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
''#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2018
|
||||
@@ -109,7 +109,10 @@ from .passport.passportelementerrors import (PassportElementError,
|
||||
PassportElementErrorFiles,
|
||||
PassportElementErrorFrontSide,
|
||||
PassportElementErrorReverseSide,
|
||||
PassportElementErrorSelfie)
|
||||
PassportElementErrorSelfie,
|
||||
PassportElementErrorTranslationFile,
|
||||
PassportElementErrorTranslationFiles,
|
||||
PassportElementErrorUnspecified)
|
||||
from .passport.credentials import (Credentials,
|
||||
DataCredentials,
|
||||
SecureData,
|
||||
@@ -148,5 +151,6 @@ __all__ = [
|
||||
'Credentials', 'DataCredentials', 'SecureData', 'FileCredentials', 'IdDocumentData',
|
||||
'PersonalDetails', 'ResidentialAddress', 'InputMediaVideo', 'InputMediaAnimation',
|
||||
'InputMediaAudio', 'InputMediaDocument', 'TelegramDecryptionError',
|
||||
'PassportElementErrorSelfie'
|
||||
'PassportElementErrorSelfie', 'PassportElementErrorTranslationFile',
|
||||
'PassportElementErrorTranslationFiles', 'PassportElementErrorUnspecified'
|
||||
]
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram File."""
|
||||
from base64 import b64decode
|
||||
from os.path import basename
|
||||
|
||||
from future.backports.urllib import parse as urllib_parse
|
||||
@@ -107,7 +108,9 @@ class File(TelegramObject):
|
||||
if out:
|
||||
buf = self.bot.request.retrieve(url)
|
||||
if self._credentials:
|
||||
buf = decrypt(self._credentials.secret, self._credentials.hash, buf, file=True)
|
||||
buf = decrypt(b64decode(self._credentials.secret),
|
||||
b64decode(self._credentials.hash),
|
||||
buf)
|
||||
out.write(buf)
|
||||
return out
|
||||
else:
|
||||
@@ -118,7 +121,9 @@ class File(TelegramObject):
|
||||
|
||||
buf = self.bot.request.retrieve(url, timeout=timeout)
|
||||
if self._credentials:
|
||||
buf = decrypt(self._credentials.secret, self._credentials.hash, buf, file=True)
|
||||
buf = decrypt(b64decode(self._credentials.secret),
|
||||
b64decode(self._credentials.hash),
|
||||
buf)
|
||||
with open(filename, 'wb') as fobj:
|
||||
fobj.write(buf)
|
||||
return filename
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
import binascii
|
||||
try:
|
||||
import ujson as json
|
||||
except ImportError:
|
||||
@@ -44,7 +43,7 @@ class TelegramDecryptionError(TelegramError):
|
||||
"{}".format(message))
|
||||
|
||||
|
||||
def decrypt(secret, hash, data, file=False):
|
||||
def decrypt(secret, hash, data):
|
||||
"""
|
||||
Decrypt per telegram docs at https://core.telegram.org/passport.
|
||||
|
||||
@@ -65,20 +64,6 @@ def decrypt(secret, hash, data, file=False):
|
||||
:obj:`bytes`: The decrypted data as bytes.
|
||||
|
||||
"""
|
||||
# First make sure that if secret, hash, or data was base64 encoded, to decode it into bytes
|
||||
try:
|
||||
secret = b64decode(secret)
|
||||
except (binascii.Error, TypeError):
|
||||
pass
|
||||
try:
|
||||
hash = b64decode(hash)
|
||||
except (binascii.Error, TypeError):
|
||||
pass
|
||||
if not file:
|
||||
try:
|
||||
data = b64decode(data)
|
||||
except (binascii.Error, TypeError):
|
||||
pass
|
||||
# Make a SHA512 hash of secret + update
|
||||
digest = Hash(SHA512(), backend=default_backend())
|
||||
digest.update(secret + hash)
|
||||
@@ -113,14 +98,14 @@ class EncryptedCredentials(TelegramObject):
|
||||
|
||||
Attributes:
|
||||
data (:class:`telegram.Credentials` or :obj:`str`): Decrypted data with unique user's
|
||||
payload, data hashes and secrets used for EncryptedPassportElement decryption and
|
||||
nonce, data hashes and secrets used for EncryptedPassportElement decryption and
|
||||
authentication or base64 encrypted data.
|
||||
hash (:obj:`str`): Base64-encoded data hash for data authentication.
|
||||
secret (:obj:`str`): Decrypted or encrypted secret used for decryption.
|
||||
|
||||
Args:
|
||||
data (:class:`telegram.Credentials` or :obj:`str`): Decrypted data with unique user's
|
||||
payload, data hashes and secrets used for EncryptedPassportElement decryption and
|
||||
nonce, data hashes and secrets used for EncryptedPassportElement decryption and
|
||||
authentication or base64 encrypted data.
|
||||
hash (:obj:`str`): Base64-encoded data hash for data authentication.
|
||||
secret (:obj:`str`): Decrypted or encrypted secret used for decryption.
|
||||
@@ -184,8 +169,8 @@ class EncryptedCredentials(TelegramObject):
|
||||
def decrypted_data(self):
|
||||
"""
|
||||
:class:`telegram.Credentials`: Lazily decrypt and return credentials data. This object
|
||||
also contains the user specified payload as
|
||||
`decrypted_data.payload`.
|
||||
also contains the user specified nonce as
|
||||
`decrypted_data.nonce`.
|
||||
|
||||
Raises:
|
||||
telegram.TelegramDecryptionError: Decryption failed. Usually due to bad
|
||||
@@ -193,8 +178,8 @@ class EncryptedCredentials(TelegramObject):
|
||||
"""
|
||||
if self._decrypted_data is None:
|
||||
self._decrypted_data = Credentials.de_json(decrypt_json(self.decrypted_secret,
|
||||
self.hash,
|
||||
self.data),
|
||||
b64decode(self.hash),
|
||||
b64decode(self.data)),
|
||||
self.bot)
|
||||
return self._decrypted_data
|
||||
|
||||
@@ -203,13 +188,13 @@ class Credentials(TelegramObject):
|
||||
"""
|
||||
Attributes:
|
||||
secure_data (:class:`telegram.SecureData`): Credentials for encrypted data
|
||||
payload (:obj:`str`): Bot-specified payload
|
||||
nonce (:obj:`str`): Bot-specified nonce
|
||||
"""
|
||||
|
||||
def __init__(self, secure_data, payload, bot=None, **kwargs):
|
||||
def __init__(self, secure_data, nonce, bot=None, **kwargs):
|
||||
# Required
|
||||
self.secure_data = secure_data
|
||||
self.payload = payload
|
||||
self.nonce = nonce
|
||||
|
||||
self.bot = bot
|
||||
|
||||
@@ -319,7 +304,11 @@ class SecureValue(TelegramObject):
|
||||
selfie (:class:`telegram.FileCredentials`, optional): Credentials for encrypted selfie
|
||||
of the user with a document. Can be available for "passport", "driver_license",
|
||||
"identity_card" and "internal_passport".
|
||||
files (:class:`telegram.Array of FileCredentials`, optional): Credentials for encrypted
|
||||
translation (List[:class:`telegram.FileCredentials`], optional): Credentials for an
|
||||
encrypted translation of the document. Available for "passport", "driver_license",
|
||||
"identity_card", "internal_passport", "utility_bill", "bank_statement",
|
||||
"rental_agreement", "passport_registration" and "temporary_registration".
|
||||
files (List[:class:`telegram.FileCredentials`], optional): Credentials for encrypted
|
||||
files. Available for "utility_bill", "bank_statement", "rental_agreement",
|
||||
"passport_registration" and "temporary_registration" types.
|
||||
|
||||
@@ -331,6 +320,7 @@ class SecureValue(TelegramObject):
|
||||
reverse_side=None,
|
||||
selfie=None,
|
||||
files=None,
|
||||
translation=None,
|
||||
bot=None,
|
||||
**kwargs):
|
||||
self.data = data
|
||||
@@ -338,6 +328,7 @@ class SecureValue(TelegramObject):
|
||||
self.reverse_side = reverse_side
|
||||
self.selfie = selfie
|
||||
self.files = files
|
||||
self.translation = translation
|
||||
|
||||
self.bot = bot
|
||||
|
||||
@@ -351,6 +342,7 @@ class SecureValue(TelegramObject):
|
||||
data['reverse_side'] = FileCredentials.de_json(data.get('reverse_side'), bot=bot)
|
||||
data['selfie'] = FileCredentials.de_json(data.get('selfie'), bot=bot)
|
||||
data['files'] = FileCredentials.de_list(data.get('files'), bot=bot)
|
||||
data['translation'] = FileCredentials.de_list(data.get('translation'), bot=bot)
|
||||
|
||||
return cls(bot=bot, **data)
|
||||
|
||||
@@ -358,6 +350,7 @@ class SecureValue(TelegramObject):
|
||||
data = super(SecureValue, self).to_dict()
|
||||
|
||||
data['files'] = [p.to_dict() for p in self.files]
|
||||
data['translation'] = [p.to_dict() for p in self.translation]
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@@ -25,23 +25,33 @@ class PersonalDetails(TelegramObject):
|
||||
|
||||
Attributes:
|
||||
first_name (:obj:`str`): First Name.
|
||||
middle_name (:obj:`str`): Optional. First Name.
|
||||
last_name (:obj:`str`): Last Name.
|
||||
birth_date (:obj:`str`): Date of birth in DD.MM.YYYY format.
|
||||
gender (:obj:`str`): Gender, male or female.
|
||||
country_code (:obj:`str`): Citizenship (ISO 3166-1 alpha-2 country code).
|
||||
residence_country_code (:obj:`str`): Country of residence (ISO 3166-1 alpha-2 country
|
||||
code).
|
||||
first_name (:obj:`str`): First Name in the language of the user's country of residence.
|
||||
middle_name (:obj:`str`): Optional. Middle Name in the language of the user's country of
|
||||
residence.
|
||||
last_name (:obj:`str`): Last Name in the language of the user's country of residence.
|
||||
"""
|
||||
|
||||
def __init__(self, first_name, last_name, birth_date, gender, country_code,
|
||||
residence_country_code, bot=None, **kwargs):
|
||||
residence_country_code, first_name_native, last_name_native, middle_name=None,
|
||||
middle_name_native=None, bot=None, **kwargs):
|
||||
# Required
|
||||
self.first_name = first_name
|
||||
self.last_name = last_name
|
||||
self.middle_name = middle_name
|
||||
self.birth_date = birth_date
|
||||
self.gender = gender
|
||||
self.country_code = country_code
|
||||
self.residence_country_code = residence_country_code
|
||||
self.first_name_native = first_name_native
|
||||
self.last_name_native = last_name_native
|
||||
self.middle_name_native = middle_name_native
|
||||
|
||||
self.bot = bot
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
"""This module contains an object that represents a Telegram EncryptedPassportElement."""
|
||||
from base64 import b64decode
|
||||
|
||||
from telegram import (TelegramObject, PassportFile, PersonalDetails, IdDocumentData,
|
||||
ResidentialAddress)
|
||||
@@ -43,15 +44,22 @@ class EncryptedPassportElement(TelegramObject):
|
||||
files (List[:class:`telegram.PassportFile`]): Optional. Array of encrypted/decrypted files
|
||||
with documents provided by the user, available for "utility_bill", "bank_statement",
|
||||
"rental_agreement", "passport_registration" and "temporary_registration" types.
|
||||
front_side (:class:`PassportFile`): Optional. Encrypted/decrypted file with the front side
|
||||
of the document, provided by the user. Available for "passport", "driver_license",
|
||||
"identity_card" and "internal_passport".
|
||||
reverse_side (:class:`PassportFile`): Optional. Encrypted/decrypted file with the reverse
|
||||
side of the document, provided by the user. Available for "driver_license" and
|
||||
"identity_card".
|
||||
selfie (:class:`PassportFile`): Optional. Encrypted/decrypted file with the selfie of the
|
||||
user holding a document, provided by the user; available for "passport",
|
||||
front_side (:class:`telegram.PassportFile`): Optional. Encrypted/decrypted file with the
|
||||
front side of the document, provided by the user. Available for "passport",
|
||||
"driver_license", "identity_card" and "internal_passport".
|
||||
reverse_side (:class:`telegram.PassportFile`): Optional. Encrypted/decrypted file with the
|
||||
reverse side of the document, provided by the user. Available for "driver_license" and
|
||||
"identity_card".
|
||||
selfie (:class:`telegram.PassportFile`): Optional. Encrypted/decrypted file with the
|
||||
selfie of the user holding a document, provided by the user; available for "passport",
|
||||
"driver_license", "identity_card" and "internal_passport".
|
||||
translation (List[:class:`telegram.PassportFile`]): Optional. Array of encrypted/decrypted
|
||||
files with translated versions of documents provided by the user. Available if
|
||||
requested for "passport", "driver_license", "identity_card", "internal_passport",
|
||||
"utility_bill", "bank_statement", "rental_agreement", "passport_registration" and
|
||||
"temporary_registration" types.
|
||||
hash (:obj:`str`): Base64-encoded element hash for using in
|
||||
:class:`telegram.PassportElementErrorUnspecified`.
|
||||
bot (:class:`telegram.Bot`): Optional. The Bot to use for instance methods.
|
||||
|
||||
Args:
|
||||
@@ -69,15 +77,22 @@ class EncryptedPassportElement(TelegramObject):
|
||||
files (List[:class:`telegram.PassportFile`], optional): Array of encrypted/decrypted files
|
||||
with documents provided by the user, available for "utility_bill", "bank_statement",
|
||||
"rental_agreement", "passport_registration" and "temporary_registration" types.
|
||||
front_side (:class:`PassportFile`, optional): Encrypted/decrypted file with the front side
|
||||
of the document, provided by the user. Available for "passport", "driver_license",
|
||||
"identity_card" and "internal_passport".
|
||||
reverse_side (:class:`PassportFile`, optional): Encrypted/decrypted file with the reverse
|
||||
side of the document, provided by the user. Available for "driver_license" and
|
||||
"identity_card".
|
||||
selfie (:class:`PassportFile`, optional): Encrypted/decrypted file with the selfie of the
|
||||
user holding a document, provided by the user; available for "passport",
|
||||
front_side (:class:`telegram.PassportFile`, optional): Encrypted/decrypted file with the
|
||||
front side of the document, provided by the user. Available for "passport",
|
||||
"driver_license", "identity_card" and "internal_passport".
|
||||
reverse_side (:class:`telegram.PassportFile`, optional): Encrypted/decrypted file with the
|
||||
reverse side of the document, provided by the user. Available for "driver_license" and
|
||||
"identity_card".
|
||||
selfie (:class:`telegram.PassportFile`, optional): Encrypted/decrypted file with the
|
||||
selfie of the user holding a document, provided by the user; available for "passport",
|
||||
"driver_license", "identity_card" and "internal_passport".
|
||||
translation (List[:class:`telegram.PassportFile`], optional): Array of encrypted/decrypted
|
||||
files with translated versions of documents provided by the user. Available if
|
||||
requested for "passport", "driver_license", "identity_card", "internal_passport",
|
||||
"utility_bill", "bank_statement", "rental_agreement", "passport_registration" and
|
||||
"temporary_registration" types.
|
||||
hash (:obj:`str`): Base64-encoded element hash for using in
|
||||
:class:`telegram.PassportElementErrorUnspecified`.
|
||||
bot (:class:`telegram.Bot`, optional): The Bot to use for instance methods.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
@@ -95,6 +110,8 @@ class EncryptedPassportElement(TelegramObject):
|
||||
front_side=None,
|
||||
reverse_side=None,
|
||||
selfie=None,
|
||||
translation=None,
|
||||
hash=None,
|
||||
bot=None,
|
||||
credentials=None,
|
||||
**kwargs):
|
||||
@@ -108,6 +125,8 @@ class EncryptedPassportElement(TelegramObject):
|
||||
self.front_side = front_side
|
||||
self.reverse_side = reverse_side
|
||||
self.selfie = selfie
|
||||
self.translation = translation
|
||||
self.hash = hash
|
||||
|
||||
self._id_attrs = (self.type, self.data, self.phone_number, self.email, self.files,
|
||||
self.front_side, self.reverse_side, self.selfie)
|
||||
@@ -125,6 +144,7 @@ class EncryptedPassportElement(TelegramObject):
|
||||
data['front_side'] = PassportFile.de_json(data.get('front_side'), bot)
|
||||
data['reverse_side'] = PassportFile.de_json(data.get('reverse_side'), bot)
|
||||
data['selfie'] = PassportFile.de_json(data.get('selfie'), bot)
|
||||
data['translation'] = PassportFile.de_list(data.get('translation'), bot) or None
|
||||
|
||||
return cls(bot=bot, **data)
|
||||
|
||||
@@ -141,9 +161,9 @@ class EncryptedPassportElement(TelegramObject):
|
||||
if secure_data.data is not None:
|
||||
# If not already decrypted
|
||||
if not isinstance(data['data'], dict):
|
||||
data['data'] = decrypt_json(secure_data.data.secret,
|
||||
secure_data.data.hash,
|
||||
data['data'])
|
||||
data['data'] = decrypt_json(b64decode(secure_data.data.secret),
|
||||
b64decode(secure_data.data.hash),
|
||||
b64decode(data['data']))
|
||||
if data['type'] == 'personal_details':
|
||||
data['data'] = PersonalDetails.de_json(data['data'], bot=bot)
|
||||
elif data['type'] in ('passport', 'internal_passport',
|
||||
@@ -153,13 +173,15 @@ class EncryptedPassportElement(TelegramObject):
|
||||
data['data'] = ResidentialAddress.de_json(data['data'], bot=bot)
|
||||
|
||||
data['files'] = PassportFile.de_list_decrypted(data.get('files'), bot,
|
||||
secure_data) or None
|
||||
secure_data.files) or None
|
||||
data['front_side'] = PassportFile.de_json_decrypted(data.get('front_side'), bot,
|
||||
secure_data.front_side)
|
||||
data['reverse_side'] = PassportFile.de_json_decrypted(data.get('reverse_side'), bot,
|
||||
secure_data.reverse_side)
|
||||
data['selfie'] = PassportFile.de_json_decrypted(data.get('selfie'), bot,
|
||||
secure_data.selfie)
|
||||
data['translation'] = PassportFile.de_list_decrypted(data.get('translation'), bot,
|
||||
secure_data.translation) or None
|
||||
|
||||
return cls(bot=bot, **data)
|
||||
|
||||
@@ -179,5 +201,7 @@ class EncryptedPassportElement(TelegramObject):
|
||||
|
||||
if self.files:
|
||||
data['files'] = [p.to_dict() for p in self.files]
|
||||
if self.translation:
|
||||
data['translation'] = [p.to_dict() for p in self.translation]
|
||||
|
||||
return data
|
||||
|
||||
@@ -250,3 +250,108 @@ class PassportElementErrorSelfie(PassportElementError):
|
||||
self.file_hash = file_hash
|
||||
|
||||
self._id_attrs = (self.source, self.type, self.file_hash, self.message)
|
||||
|
||||
|
||||
class PassportElementErrorTranslationFile(PassportElementError):
|
||||
"""
|
||||
Represents an issue with one of the files that constitute the translation of a document.
|
||||
The error is considered resolved when the file changes.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): Type of element of the user's Telegram Passport which has the issue,
|
||||
one of "passport", "driver_license", "identity_card", "internal_passport",
|
||||
"utility_bill", "bank_statement", "rental_agreement", "passport_registration",
|
||||
"temporary_registration".
|
||||
file_hash (:obj:`str`): Base64-encoded hash of the file.
|
||||
message (:obj:`str`): Error message.
|
||||
|
||||
Args:
|
||||
type (:obj:`str`): Type of element of the user's Telegram Passport which has the issue,
|
||||
one of "passport", "driver_license", "identity_card", "internal_passport",
|
||||
"utility_bill", "bank_statement", "rental_agreement", "passport_registration",
|
||||
"temporary_registration".
|
||||
file_hash (:obj:`str`): Base64-encoded hash of the file.
|
||||
message (:obj:`str`): Error message.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
type,
|
||||
file_hash,
|
||||
message,
|
||||
**kwargs):
|
||||
# Required
|
||||
super(PassportElementErrorTranslationFile, self).__init__('translation_file',
|
||||
type, message)
|
||||
self.file_hash = file_hash
|
||||
|
||||
self._id_attrs = (self.source, self.type, self.file_hash, self.message)
|
||||
|
||||
|
||||
class PassportElementErrorTranslationFiles(PassportElementError):
|
||||
"""
|
||||
Represents an issue with the translated version of a document. The error is considered
|
||||
resolved when a file with the document translation change.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): Type of element of the user's Telegram Passport which has the issue,
|
||||
one of "passport", "driver_license", "identity_card", "internal_passport",
|
||||
"utility_bill", "bank_statement", "rental_agreement", "passport_registration",
|
||||
"temporary_registration"
|
||||
file_hash (:obj:`str`): Base64-encoded file hash.
|
||||
message (:obj:`str`): Error message.
|
||||
|
||||
Args:
|
||||
type (:obj:`str`): Type of element of the user's Telegram Passport which has the issue,
|
||||
one of "passport", "driver_license", "identity_card", "internal_passport",
|
||||
"utility_bill", "bank_statement", "rental_agreement", "passport_registration",
|
||||
"temporary_registration"
|
||||
file_hashes (List[:obj:`str`]): List of base64-encoded file hashes.
|
||||
message (:obj:`str`): Error message.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
type,
|
||||
file_hashes,
|
||||
message,
|
||||
**kwargs):
|
||||
# Required
|
||||
super(PassportElementErrorTranslationFiles, self).__init__('translation_files',
|
||||
type, message)
|
||||
self.file_hashes = file_hashes
|
||||
|
||||
self._id_attrs = ((self.source, self.type, self.message) +
|
||||
tuple([file_hash for file_hash in file_hashes]))
|
||||
|
||||
|
||||
class PassportElementErrorUnspecified(PassportElementError):
|
||||
"""
|
||||
Represents an issue in an unspecified place. The error is considered resolved when new
|
||||
data is added.
|
||||
|
||||
Attributes:
|
||||
type (:obj:`str`): Type of element of the user's Telegram Passport which has the issue.
|
||||
element_hash (:obj:`str`): Base64-encoded element hash.
|
||||
message (:obj:`str`): Error message.
|
||||
|
||||
Args:
|
||||
type (:obj:`str`): Type of element of the user's Telegram Passport which has the issue.
|
||||
element_hash (:obj:`str`): Base64-encoded element hash.
|
||||
message (:obj:`str`): Error message.
|
||||
**kwargs (:obj:`dict`): Arbitrary keyword arguments.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
type,
|
||||
element_hash,
|
||||
message,
|
||||
**kwargs):
|
||||
# Required
|
||||
super(PassportElementErrorUnspecified, self).__init__('unspecified', type, message)
|
||||
self.element_hash = element_hash
|
||||
|
||||
self._id_attrs = (self.source, self.type, self.element_hash, self.message)
|
||||
|
||||
@@ -84,7 +84,7 @@ class PassportFile(TelegramObject):
|
||||
if not data:
|
||||
return []
|
||||
|
||||
return [cls.de_json_decrypted(passport_file, bot, credentials.files[i])
|
||||
return [cls.de_json_decrypted(passport_file, bot, credentials[i])
|
||||
for i, passport_file in enumerate(data)]
|
||||
|
||||
def get_file(self, timeout=None, **kwargs):
|
||||
|
||||
+1
-1
@@ -17,4 +17,4 @@
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
__version__ = '11.0.0'
|
||||
__version__ = '11.1.0'
|
||||
|
||||
+103
-44
@@ -22,29 +22,63 @@ import pytest
|
||||
|
||||
from telegram import (PassportData, PassportFile, Bot, File, PassportElementErrorSelfie,
|
||||
PassportElementErrorDataField, Credentials, TelegramDecryptionError)
|
||||
|
||||
RAW_PASSPORT_DATA = {'data': [{'type': 'personal_details',
|
||||
'data': 'tj3pNwOpN+ZHsyb6F3aJcNmEyPxrOtGTbu3waBlCQDNaQ9oJlkbXpw+HI3y9faq/+TCeB/WsS/2TxRXTKZw4zXvGP2UsfdRkJ2SQq6x+Ffe/oTF9/q8sWp2BwU3hHUOz7ec1/QrdPBhPJjbwSykEBNggPweiBVDZ0x/DWJ0guCkGT9smYGqog1vqlqbIWG7AWcxVy2fpUy9w/zDXjxj5WQ3lRpHJmi46s9xIHobNGGBvWw6/bGBCInMoovgqRCEu1sgz2QXF3wNiUzGFycEzLz7o+1htLys5n8Pdi9MG4RY='},
|
||||
{'type': 'driver_license',
|
||||
'data': 'hOXQ/iHSGRDFXqql3yETA4AiP0mdlwmo9RtGS+Qg9E5okrN/yTcPNtBKb2fLA0posk35bvevN53cyJMHZnxErEFTSw/FQjPyRFdJUyjGNPeu4yOI73uk5eRVLTAlA2G0eN2azzfS/QOBGL19N3pHk9hMTZYPCBTDt89MHhRQS7Z3YWRSzFcFiEhktHv/ezgcg3EWtsUQ8K4J2445uoZzbB8wsQ6RM4ibn08RfjV6dNyVrj8jBGUpCBlA6iY60rFQM+LZ9ByI3OeS53bnIAMQC2rHHbV/wkzS6PbufOzjZgJq26aCLmC5YDomrpcrdvk0fvi6aEuBJEI3zcteh2fh/Q==',
|
||||
'selfie': {'file_id': 'DgADBAADEQQAAkopgFNr6oi-wISRtAI',
|
||||
'file_date': 1534074942},
|
||||
'reverse_side': {'file_id': 'DgADBAADNQQAAtoagFPf4wwmFZdmyQI',
|
||||
'file_date': 1534074942},
|
||||
'front_side': {'file_id': 'DgADBAADxwMAApnQgVPK2-ckL2eXVAI',
|
||||
'file_date': 1534074942}},
|
||||
{'type': 'address',
|
||||
'data': 'j9SksVkSj128DBtZA+3aNjSFNirzv+R97guZaMgae4Gi0oDVNAF7twPR7j9VSmPedfJrEwL3O889Ei+a5F1xyLLyEI/qEBljvL70GFIhYGitS0JmNabHPHSZrjOl8b4s/0Z0Px2GpLO5siusTLQonimdUvu4UPjKquYISmlKEKhtmGATy+h+JDjNCYuOkhakeNw0Rk0BHgj0C3fCb7WZNQSyVb+2GTu6caR6eXf/AFwFp0TV3sRz3h0WIVPW8bna'},
|
||||
{'type': 'utility_bill', 'files': [
|
||||
{'file_id': 'DgADBAADLAMAAhwfgVMyfGa5Nr0LvAI',
|
||||
'file_date': 1534074988},
|
||||
{'file_id': 'DgADBAADaQQAAsFxgVNVfLZuT-_3ZQI',
|
||||
'file_date': 1534074988}]},
|
||||
{'type': 'email', 'email': 'fb3e3i47zt@dispostable.com'}],
|
||||
'credentials': {
|
||||
'data': 'uI/g4fJLVO6132t+yuBvKExTpTubinscH8KLVc8YPuo1SiXaBg4A6AaVdv60CPViMw8n+ShVWOTL6oN5Ye0+CC2/URZ0eeTMJcKkvJYRI0Q6YJ3aeeEzslwORKho0mGk5xSWpPV5LHXhRIlgUMA32NkbNuzzoij7OhqxvuDE50/0pAUKtxy69h+heAzxFj8+jYjgnOwgwNa6FGUG59oUozgpB98XrEeWGW+JIGE9fux8dSGkFhF2SjkmdW6b2Gexuq94TVGDgFigSvqMOgZj9slZI4UEdZBIGldPHrc8/+EuqWv+WKWU8hdj1dxfY/pNvonb8MwrQLrUyNafdLq5QD4Kmg3XPnZTI9bsYUf6xO9oKU42JezDcRbaCqKkUn6UceCkV2hHMJP4aVVI9Bad1k/rXlaDh8PUV19n6tct5UH8JfkBbGlj2uASI5lPasIvnWg9s1vsZ4ynE2YAuU4iotMkgmJkj1+JCl8Ul9uqzfiK0IbYfu57V82gUEjn6c4br49pY+Cvo9od9Lx8fSJCiXq+DdmDTfIZxpeFqEYeJi6/v0CjJni4CtS6LJGo9JUR2MlqOAiyOLomadlrZyzC2eLm8X6ouIXTxtbUqzxcTiH/r23NQ44YwJpMdDiulNuPg0tEyio8TokHj9APORiW+QIw4zLZFyBEorT1DSALm4AV3A1lIg0svOncDkOqa3ZydQ0tdysoXOq5Zsu+Qu/DQZQz5IGEHb7N9QW6KZDGfBOP5Ok04OxlXO8UaTZr6mysmu8jDOlqtitLKSCGDy0LPfITzehTqfEu0KrtmxI91zJtiNyE4g+oBzQsLwQ7vSp1xl7YNViDi8ea/upZdRavh3NthVD5TxyNJedt4Xp8q5/H5kSV/EFhumONPwBwOuN4KrsCQEaNtHZfYB8SH1v0rWbiFw3/owxCrCPqgEwMGnx+JTqsAplurIZfxsNz+57O4Hq10VVt7yhroq9UpIAR8C8hW58dcZBflWyQwG8HalYAaPJ/teSLP9o6MyiqrUkADbNBOFsUhIerq6Q0BnQ941sWg10BkG8oQSU6JdnZ1Ygml2gpFabBRXeeF5ijD0Y9Bq8D3vDnHKx/GziAK0aKlwSqfTmJ+C1hm7AxBekjtDavkBeq5bIOtxYaXqrtunQFAZRCrcnQEg0DPY6dYw+jmOR0NuHRMU5KeZ0994Jn0TRGiUoJtLp1MHJ2D1MCWG3Fp9Ps7vB46a9XiGYHJUdJjHsavvQRQjhB1FvA/kxXNubCjAOPLUz1j+BEkUUgwi65l8+pViHUCIhBdLJn7S0J9HbMsc3jXOFusfvXfyvf2SZMqyhEscs/2HzYgbCWVSxQ//6eimZqvW4an1JIEfH1xUH3zS0HvS7NWChtX1Cj+jJ2vw+lyom6a84wJ2mjSRVcaV6JZa2mIf2IuXfX8EMZwKMDJagkQ7effV3MrnCNrXUXJYn8wVm6l+uP+R9mCn9qbGlvWToCID0YM8MTxJ0LgzC0n93m46OxxCI1p1hPzVrmDCcKt3OASe0zVat415/sz9TTU7Rm8oNSAVUVNo7FRg2XwEb9VupGMjlscu4cJKLCtUpImSKDKlVLH2KYy6s4NdPjOjqtjQLRoaCxbYHmNXXE+vVwPiNBK/bBVT3XJgdmbkXa/PDnMjhAmn0huuxBu8GsTOs+bBdyDCbr6mY6EzN9lCPspEoOPs7nmREpjrvGmEqEddRteyAebpVqZQhqklyT3RVl8AmfoF7QgTi0NYqFb50Lgou3hFrMg7isG5EKU+IKI5WfzyWONlHNSpvO',
|
||||
'hash': 'qyi5vQ2HCVjVMHb+l6HQ4krmvwwEkvm6Qmdf5GJcohM=',
|
||||
'secret': 'kgJE0VLB9enOq5fhhX8gOv0xoaMIcskmRPOG1eMbiC/Q8slr7kur12H/YIoOfd7/DQ0ggE7TAAe34PypFvtmwt5fDVtqtPl9YoCeAOCFWxHxLgTCLbzoJ0lTJXoJkdHjlvR2lKaP+rMtaU1w8WOpYOGiNXyblQoWwFRrWNTHmHnmwBfGBFCj/vp89+C1viEYHeWPPUkBhf1vT31L70BEoe8hxORJEDg+jY+80W2nFdIWNBF+o9GSmbMWFtd7UFiuLPp2JUBCy8XuHozk8xFk/PN6m6DgSu32rC4YBJv/sWGUo/MmH0nxR3gaiEkj+9rWIybCNAwgfdQpk/KH2RCF8g=='}}
|
||||
# Generated using the scope:
|
||||
# {
|
||||
# data: [
|
||||
# {
|
||||
# type: 'personal_details',
|
||||
# native_names: true
|
||||
# },
|
||||
# {
|
||||
# type: 'id_document',
|
||||
# selfie: true,
|
||||
# translation: true
|
||||
# },
|
||||
# {
|
||||
# type: 'address_document',
|
||||
# translation: true
|
||||
# },
|
||||
# 'address',
|
||||
# 'email'
|
||||
# ],
|
||||
# v: 1
|
||||
# }
|
||||
RAW_PASSPORT_DATA = {'credentials': {'hash': 'qB4hz2LMcXYhglwz6EvXMMyI3PURisWLXl/iCmCXcSk=',
|
||||
'secret': 'O6x3X2JrLO1lUIhw48os1gaenDuZLhesoZMKXehZwtM3vsxOdtxHKWQyLNwtbyy4snYpARXDwf8f1QHNmQ/M1PwBQvk1ozrZBXb4a6k/iYj+P4v8Xw2M++CRHqZv0LaxFtyHOXnNYZ6dXpNeF0ZvYYTmm0FsYvK+/3/F6VDB3Oe6xWlXFLwaCCP/jA9i2+dKp6iq8NLOo4VnxenPKWWYz20RZ50MdAbS3UR+NCx4AHM2P5DEGrHNW0tMXJ+FG3jpVrit5BuCbB/eRgKxNGRWNxEGV5hun5MChdxKCEHCimnUA97h7MZdoTgYxkrfvDSZ/V89BnFXLdr87t/NLvVE0Q==',
|
||||
'data': 'MjHCHQT277BgJMxq5PfkPUl9p9h/5GbWtR0lcEi9MvtmQ9ONW8DZ3OmddaaVDdEHwh6Lfcr/0mxyMKhttm9QyACA1+oGBdw/KHRzLKS4a0P+rMyCcgctO6Q/+P9o6xs66hPFJAsN+sOUU4d431zaQN/RuHYuGM2s14A1K4YNRvNlp5/0JiS7RrV6SH6LC/97CvgGUnBOhLISmJXiMqwyVgg+wfS5SnOy2hQ5Zt/XdzxFyuehE3W4mHyY5W09I+MB/IafM4HcEvaqfFkWPmXNTkgBk9C2EJU9Lqc0PLmrXZn4LKeHVjuY7iloes/JecYKPMWmNjXwZQg/duIXvWL5icUaNrfjEcT5oljwZsrAc6NyyZwIp4w/+cb98jFwFAJ5uF81lRkZbeC3iw84mdpSVVYEzJSWSkSRs6JydfRCOYki0BNX9RnjgGqPYT+hNtUpEix2vHvJTIyvceflLF5vu+ol/axusirRiBVgNjKMfhs+x5bwBj5nDEE1XtEVrKtRq8/Ss96p0Tlds8eKulCDtPv/YujHVIErEhgUxDCGhr7OShokAFs/RwLmj6IBYQwnVbo0zIsq5qmCn/+1ogxJK+e934cDcwJAs8pnpgp7JPeFN9wBdmXSTpkO3KZt5Lgl3V86Rv5qv8oExQoJIUH5pKoXM+H2GB3QdfHLc/KpCeedG8RjateuIXKL2EtVe3JDMGBeI56eP9bTlW8+G1zVcpUuw/YEV14q4yiPlIRuWzrxXMvC1EtSzfGeY899trZBMCI00aeSpJyanf1f7B7nlQu6UbtMyN/9/GXbnjQjdP15CCQnmUK3PEWGtGV4XmK4iXIjBJELDD3T86RJyX/JAhJbT6funMt05w0bTyKFUDXdOcMyw2upj+wCsWTVMRNkw9yM63xL5TEfOc24aNi4pc4/LARSvwaNI/iBStqZEpG3KkYBQ2KutA022jRWzQ+xHIIz3mgA8z4PmXhcAU2RrTDGjGZUfbcX9LysZ/HvCHo/EB5njRISn3Yr1Ewu1pLX+Z4mERs+PCBXbpqBrZjY6dSWJ1QhggVJTPpWHya4CTGhkpyeFIc+D35t4kgt3U5ib61IaO9ABq0fUnB6dsvTGiN/i7KM8Ie1RUvPFBoVbz9x5YU9IT/ai8ln+1kfFfhiy8Ku4MnczthOUIjdr8nGUo4r3y0iEd5JEmqEcEsNx+/ZVMb7NEhpqXG8GPUxmwFTaHekldENxqTylv6qIxodhch6SLs/+iMat86DeCk1/+0u2fGmqZpxEEd9B89iD0+Av3UZC/C1rHn5FhC+o89RQAFWnH245rOHSbrTXyAtVBu2s1R0eIGadtAZYOI8xjULkbp52XyznZKCKaMKmr3UYah4P4VnUmhddBy+Mp/Bvxh8N3Ma8VSltO1n+3lyQWeUwdlCjt/3q3UpjAmilIKwEfeXMVhyjRlae1YGi/k+vgn+9LbFogh3Pl+N/kuyNqsTqPlzei2RXgpkX2qqHdF8WfkwQJpjXRurQN5LYaBfalygrUT+fCCpyaNkByxdDljKIPq6EibqtFA5jprAVDWGTTtFCKsPDJKFf9vc2lFy+7zyJxe8kMP1Wru8GrzF5z+pbfNp1tB80NqOrqJUbRnPB2I9Fb47ab76L8RBu2MROUNGcKJ62imQtfPH2I0f8zpbqqTZQwr3AmZ+PS9df2hHp2dYR9gFpMyR9u+bJ7HbpiKbYhh7mEFYeB/pQHsQRqM2OU5Bxk8XzxrwsdnzYO6tVcn8xr3Q4P9kZNXA6X5H0vJPpzClWoCPEr3ZGGWGl5DOhfsAmmst47vdAA1Cbl5k3pUW7/T3LWnMNwRnP8OdDOnsm06/v1nxIDjH08YlzLj4GTeXphSnsXSRNKFmz+M7vsOZPhWB8Y/WQmpJpOIj6IRstLxJk0h47TfYC7/RHBr4y7HQ8MLHODoPz/FM+nZtm2MMpB+u0qFNBvZG+Tjvlia7ZhX0n0OtivLWhnqygx3jZX7Ffwt5Es03wDP39ru4IccVZ9Jly/YUriHZURS6oDGycH3+DKUn5gRAxgOyjAwxGRqJh/YKfPt14d4iur0H3VUuLwFCbwj5hSvHVIv5cNapitgINU+0qzIlhyeE0HfRKstO7nOQ9A+nclqbOikYgurYIe0z70WZyJ3qSiHbOMMqQqcoKOJ6M9v2hDdJo9MDQ13dF6bl4+BfX4mcF0m7nVUBkzCRiSOQWWFUMgLX7CxSdmotT+eawKLjrCpSPmq9sicWyrFtVlq/NYLDGhT0jUUau6Mb5ksT+/OBVeMzqoezUcly29L1/gaeWAc8zOApVEjAMT48U63NXK5o8GrANeqqAt3TB36S5yeIjMf194nXAAzsJZ+s/tXprLn2M5mA1Iag4RbVPTarEsMp10JYag=='},
|
||||
'data': [
|
||||
{
|
||||
'data': 'QRfzWcCN4WncvRO3lASG+d+c5gzqXtoCinQ1PgtYiZMKXCksx9eB9Ic1bOt8C/un9/XaX220PjJSO7Kuba+nXXC51qTsjqP9rnLKygnEIWjKrfiDdklzgcukpRzFSjiOAvhy86xFJZ1PfPSrFATy/Gp1RydLzbrBd2ZWxZqXrxcMoA0Q2UTTFXDoCYerEAiZoD69i79tB/6nkLBcUUvN5d52gKd/GowvxWqAAmdO6l1N7jlo6aWjdYQNBAK1KHbJdbRZMJLxC1MqMuZXAYrPoYBRKr5xAnxDTmPn/LEZKLc3gwwZyEgR5x7e9jp5heM6IEMmsv3O/6SUeEQs7P0iVuRSPLMJLfDdwns8Tl3fF2M4IxKVovjCaOVW+yHKsADDAYQPzzH2RcrWVD0TP5I64mzpK64BbTOq3qm3Hn51SV9uA/+LvdGbCp7VnzHx4EdUizHsVyilJULOBwvklsrDRvXMiWmh34ZSR6zilh051tMEcRf0I+Oe7pIxVJd/KKfYA2Z/eWVQTCn5gMuAInQNXFSqDIeIqBX+wca6kvOCUOXB7J2uRjTpLaC4DM9s/sNjSBvFixcGAngt+9oap6Y45rQc8ZJaNN/ALqEJAmkphW8=',
|
||||
'type': 'personal_details'
|
||||
}, {
|
||||
'reverse_side': {'file_date': 1534074942,
|
||||
'file_id': 'DgADBAADNQQAAtoagFPf4wwmFZdmyQI'},
|
||||
'translation': [{'file_size': 28640, 'file_date': 1535630933,
|
||||
'file_id': 'DgADBAADswMAAisqQVAmooP-kVgLgAI'},
|
||||
{'file_size': 28672, 'file_date': 1535630933,
|
||||
'file_id': 'DgADBAAD1QMAAnrpQFBMZsT3HysjwwI'}],
|
||||
'front_side': {'file_size': 28624, 'file_date': 1534074942,
|
||||
'file_id': 'DgADBAADxwMAApnQgVPK2-ckL2eXVAI'},
|
||||
'type': 'driver_license',
|
||||
'selfie': {'file_size': 28592, 'file_date': 1534074942,
|
||||
'file_id': 'DgADBAADEQQAAkopgFNr6oi-wISRtAI'},
|
||||
'data': 'eJUOFuY53QKmGqmBgVWlLBAQCUQJ79n405SX6M5aGFIIodOPQqnLYvMNqTwTrXGDlW+mVLZcbu+y8luLVO8WsJB/0SB7q5WaXn/IMt1G9lz5G/KMLIZG/x9zlnimsaQLg7u8srG6L4KZzv+xkbbHjZdETrxU8j0N/DoS4HvLMRSJAgeFUrY6v2YW9vSRg+fSxIqQy1jR2VKpzAT8OhOz7A=='
|
||||
}, {
|
||||
'translation': [{'file_size': 28480, 'file_date': 1535630939,
|
||||
'file_id': 'DgADBAADyQUAAqyqQVC_eoX_KwNjJwI'},
|
||||
{'file_size': 28528, 'file_date': 1535630939,
|
||||
'file_id': 'DgADBAADsQQAAubTQVDRO_FN3lOwWwI'}],
|
||||
'files': [{'file_size': 28640, 'file_date': 1534074988,
|
||||
'file_id': 'DgADBAADLAMAAhwfgVMyfGa5Nr0LvAI'},
|
||||
{'file_size': 28480, 'file_date': 1534074988,
|
||||
'file_id': 'DgADBAADaQQAAsFxgVNVfLZuT-_3ZQI'}],
|
||||
'type': 'utility_bill'
|
||||
}, {
|
||||
'data': 'j9SksVkSj128DBtZA+3aNjSFNirzv+R97guZaMgae4Gi0oDVNAF7twPR7j9VSmPedfJrEwL3O889Ei+a5F1xyLLyEI/qEBljvL70GFIhYGitS0JmNabHPHSZrjOl8b4s/0Z0Px2GpLO5siusTLQonimdUvu4UPjKquYISmlKEKhtmGATy+h+JDjNCYuOkhakeNw0Rk0BHgj0C3fCb7WZNQSyVb+2GTu6caR6eXf/AFwFp0TV3sRz3h0WIVPW8bna',
|
||||
'type': 'address'
|
||||
}, {
|
||||
'email': 'fb3e3i47zt@dispostable.com', 'type': 'email'
|
||||
}]}
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
@@ -54,33 +88,42 @@ def all_passport_data():
|
||||
{'type': 'passport',
|
||||
'data': RAW_PASSPORT_DATA['data'][1]['data'],
|
||||
'front_side': RAW_PASSPORT_DATA['data'][1]['front_side'],
|
||||
'selfie': RAW_PASSPORT_DATA['data'][1]['selfie']},
|
||||
'selfie': RAW_PASSPORT_DATA['data'][1]['selfie'],
|
||||
'translation': RAW_PASSPORT_DATA['data'][1]['translation']},
|
||||
{'type': 'internal_passport',
|
||||
'data': RAW_PASSPORT_DATA['data'][1]['data'],
|
||||
'front_side': RAW_PASSPORT_DATA['data'][1]['front_side'],
|
||||
'selfie': RAW_PASSPORT_DATA['data'][1]['selfie']},
|
||||
'selfie': RAW_PASSPORT_DATA['data'][1]['selfie'],
|
||||
'translation': RAW_PASSPORT_DATA['data'][1]['translation']},
|
||||
{'type': 'driver_license',
|
||||
'data': RAW_PASSPORT_DATA['data'][1]['data'],
|
||||
'front_side': RAW_PASSPORT_DATA['data'][1]['front_side'],
|
||||
'reverse_side': RAW_PASSPORT_DATA['data'][1]['reverse_side'],
|
||||
'selfie': RAW_PASSPORT_DATA['data'][1]['selfie']},
|
||||
'selfie': RAW_PASSPORT_DATA['data'][1]['selfie'],
|
||||
'translation': RAW_PASSPORT_DATA['data'][1]['translation']},
|
||||
{'type': 'identity_card',
|
||||
'data': RAW_PASSPORT_DATA['data'][1]['data'],
|
||||
'front_side': RAW_PASSPORT_DATA['data'][1]['front_side'],
|
||||
'reverse_side': RAW_PASSPORT_DATA['data'][1]['reverse_side'],
|
||||
'selfie': RAW_PASSPORT_DATA['data'][1]['selfie']},
|
||||
{'type': 'address',
|
||||
'data': RAW_PASSPORT_DATA['data'][2]['data']},
|
||||
'selfie': RAW_PASSPORT_DATA['data'][1]['selfie'],
|
||||
'translation': RAW_PASSPORT_DATA['data'][1]['translation']},
|
||||
{'type': 'utility_bill',
|
||||
'files': RAW_PASSPORT_DATA['data'][3]['files']},
|
||||
'files': RAW_PASSPORT_DATA['data'][2]['files'],
|
||||
'translation': RAW_PASSPORT_DATA['data'][2]['translation']},
|
||||
{'type': 'bank_statement',
|
||||
'files': RAW_PASSPORT_DATA['data'][3]['files']},
|
||||
'files': RAW_PASSPORT_DATA['data'][2]['files'],
|
||||
'translation': RAW_PASSPORT_DATA['data'][2]['translation']},
|
||||
{'type': 'rental_agreement',
|
||||
'files': RAW_PASSPORT_DATA['data'][3]['files']},
|
||||
'files': RAW_PASSPORT_DATA['data'][2]['files'],
|
||||
'translation': RAW_PASSPORT_DATA['data'][2]['translation']},
|
||||
{'type': 'passport_registration',
|
||||
'files': RAW_PASSPORT_DATA['data'][3]['files']},
|
||||
'files': RAW_PASSPORT_DATA['data'][2]['files'],
|
||||
'translation': RAW_PASSPORT_DATA['data'][2]['translation']},
|
||||
{'type': 'temporary_registration',
|
||||
'files': RAW_PASSPORT_DATA['data'][3]['files']},
|
||||
'files': RAW_PASSPORT_DATA['data'][2]['files'],
|
||||
'translation': RAW_PASSPORT_DATA['data'][2]['translation']},
|
||||
{'type': 'address',
|
||||
'data': RAW_PASSPORT_DATA['data'][3]['data']},
|
||||
{'type': 'email',
|
||||
'email': 'fb3e3i47zt@dispostable.com'},
|
||||
{'type': 'phone_number',
|
||||
@@ -96,8 +139,12 @@ class TestPassport(object):
|
||||
driver_license_selfie_file_id = 'DgADBAADEQQAAkopgFNr6oi-wISRtAI'
|
||||
driver_license_front_side_file_id = 'DgADBAADxwMAApnQgVPK2-ckL2eXVAI'
|
||||
driver_license_reverse_side_file_id = 'DgADBAADNQQAAtoagFPf4wwmFZdmyQI'
|
||||
driver_license_translation_1_file_id = 'DgADBAADswMAAisqQVAmooP-kVgLgAI'
|
||||
driver_license_translation_2_file_id = 'DgADBAAD1QMAAnrpQFBMZsT3HysjwwI'
|
||||
utility_bill_1_file_id = 'DgADBAADLAMAAhwfgVMyfGa5Nr0LvAI'
|
||||
utility_bill_2_file_id = 'DgADBAADaQQAAsFxgVNVfLZuT-_3ZQI'
|
||||
utility_bill_translation_1_file_id = 'DgADBAADyQUAAqyqQVC_eoX_KwNjJwI'
|
||||
utility_bill_translation_2_file_id = 'DgADBAADsQQAAubTQVDRO_FN3lOwWwI'
|
||||
driver_license_selfie_credentials_file_hash = 'Cila/qLXSBH7DpZFbb5bRZIRxeFW2uv/ulL0u0JNsYI='
|
||||
driver_license_selfie_credentials_secret = 'tivdId6RNYNsvXYPppdzrbxOBuBOr9wXRPDcCvnXU7E='
|
||||
|
||||
@@ -105,7 +152,7 @@ class TestPassport(object):
|
||||
assert isinstance(passport_data, PassportData)
|
||||
|
||||
def test_expected_encrypted_values(self, passport_data):
|
||||
personal_details, driver_license, address, utility_bill, email = passport_data.data
|
||||
personal_details, driver_license, utility_bill, address, email = passport_data.data
|
||||
|
||||
assert personal_details.type == 'personal_details'
|
||||
assert personal_details.data == RAW_PASSPORT_DATA['data'][0]['data']
|
||||
@@ -118,29 +165,41 @@ class TestPassport(object):
|
||||
assert driver_license.front_side.file_id == self.driver_license_front_side_file_id
|
||||
assert isinstance(driver_license.reverse_side, PassportFile)
|
||||
assert driver_license.reverse_side.file_id == self.driver_license_reverse_side_file_id
|
||||
|
||||
assert address.type == 'address'
|
||||
assert address.data == RAW_PASSPORT_DATA['data'][2]['data']
|
||||
assert isinstance(driver_license.translation[0], PassportFile)
|
||||
assert driver_license.translation[0].file_id == self.driver_license_translation_1_file_id
|
||||
assert isinstance(driver_license.translation[1], PassportFile)
|
||||
assert driver_license.translation[1].file_id == self.driver_license_translation_2_file_id
|
||||
|
||||
assert utility_bill.type == 'utility_bill'
|
||||
assert isinstance(utility_bill.files[0], PassportFile)
|
||||
assert utility_bill.files[0].file_id == self.utility_bill_1_file_id
|
||||
assert isinstance(utility_bill.files[1], PassportFile)
|
||||
assert utility_bill.files[1].file_id == self.utility_bill_2_file_id
|
||||
assert isinstance(utility_bill.translation[0], PassportFile)
|
||||
assert utility_bill.translation[0].file_id == self.utility_bill_translation_1_file_id
|
||||
assert isinstance(utility_bill.translation[1], PassportFile)
|
||||
assert utility_bill.translation[1].file_id == self.utility_bill_translation_2_file_id
|
||||
|
||||
assert address.type == 'address'
|
||||
assert address.data == RAW_PASSPORT_DATA['data'][3]['data']
|
||||
|
||||
assert email.type == 'email'
|
||||
assert email.email == 'fb3e3i47zt@dispostable.com'
|
||||
|
||||
def test_expected_decrypted_values(self, passport_data):
|
||||
(personal_details, driver_license, address,
|
||||
utility_bill, email) = passport_data.decrypted_data
|
||||
(personal_details, driver_license, utility_bill, address,
|
||||
email) = passport_data.decrypted_data
|
||||
|
||||
assert personal_details.type == 'personal_details'
|
||||
assert personal_details.data.to_dict() == {'gender': 'female',
|
||||
assert personal_details.data.to_dict() == {'first_name': 'FIRSTNAME',
|
||||
'middle_name': 'MIDDLENAME',
|
||||
'first_name_native': 'FIRSTNAMENATIVE',
|
||||
'residence_country_code': 'DK',
|
||||
'country_code': 'DK',
|
||||
'birth_date': '01.01.2001',
|
||||
'first_name': 'FIRSTNAME',
|
||||
'last_name_native': 'LASTNAMENATIVE',
|
||||
'gender': 'female',
|
||||
'middle_name_native': 'MIDDLENAMENATIVE',
|
||||
'country_code': 'DK',
|
||||
'last_name': 'LASTNAME'}
|
||||
|
||||
assert driver_license.type == 'driver_license'
|
||||
@@ -210,7 +269,7 @@ class TestPassport(object):
|
||||
|
||||
def test_wrong_hash(self, bot):
|
||||
data = deepcopy(RAW_PASSPORT_DATA)
|
||||
data['credentials']['hash'] = b'notcorrecthash'
|
||||
data['credentials']['hash'] = 'bm90Y29ycmVjdGhhc2g=' # Not correct hash
|
||||
passport_data = PassportData.de_json(data, bot=bot)
|
||||
with pytest.raises(TelegramDecryptionError):
|
||||
assert passport_data.decrypted_data
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2018
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
import pytest
|
||||
|
||||
from telegram import PassportElementErrorTranslationFile, PassportElementErrorDataField
|
||||
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def passport_element_error_translation_file():
|
||||
return PassportElementErrorTranslationFile(TestPassportElementErrorTranslationFile.type,
|
||||
TestPassportElementErrorTranslationFile.file_hash,
|
||||
TestPassportElementErrorTranslationFile.message)
|
||||
|
||||
|
||||
class TestPassportElementErrorTranslationFile(object):
|
||||
source = 'translation_file'
|
||||
type = 'test_type'
|
||||
file_hash = 'file_hash'
|
||||
message = 'Error message'
|
||||
|
||||
def test_expected_values(self, passport_element_error_translation_file):
|
||||
assert passport_element_error_translation_file.source == self.source
|
||||
assert passport_element_error_translation_file.type == self.type
|
||||
assert passport_element_error_translation_file.file_hash == self.file_hash
|
||||
assert passport_element_error_translation_file.message == self.message
|
||||
|
||||
def test_to_dict(self, passport_element_error_translation_file):
|
||||
passport_element_error_translation_file_dict = \
|
||||
passport_element_error_translation_file.to_dict()
|
||||
|
||||
assert isinstance(passport_element_error_translation_file_dict, dict)
|
||||
assert (passport_element_error_translation_file_dict['source'] ==
|
||||
passport_element_error_translation_file.source)
|
||||
assert (passport_element_error_translation_file_dict['type'] ==
|
||||
passport_element_error_translation_file.type)
|
||||
assert (passport_element_error_translation_file_dict['file_hash'] ==
|
||||
passport_element_error_translation_file.file_hash)
|
||||
assert (passport_element_error_translation_file_dict['message'] ==
|
||||
passport_element_error_translation_file.message)
|
||||
|
||||
def test_equality(self):
|
||||
a = PassportElementErrorTranslationFile(self.type, self.file_hash, self.message)
|
||||
b = PassportElementErrorTranslationFile(self.type, self.file_hash, self.message)
|
||||
c = PassportElementErrorTranslationFile(self.type, '', '')
|
||||
d = PassportElementErrorTranslationFile('', self.file_hash, '')
|
||||
e = PassportElementErrorTranslationFile('', '', self.message)
|
||||
f = PassportElementErrorDataField(self.type, '', '', self.message)
|
||||
|
||||
assert a == b
|
||||
assert hash(a) == hash(b)
|
||||
assert a is not b
|
||||
|
||||
assert a != c
|
||||
assert hash(a) != hash(c)
|
||||
|
||||
assert a != d
|
||||
assert hash(a) != hash(d)
|
||||
|
||||
assert a != e
|
||||
assert hash(a) != hash(e)
|
||||
|
||||
assert a != f
|
||||
assert hash(a) != hash(f)
|
||||
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2018
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
import pytest
|
||||
|
||||
from telegram import PassportElementErrorTranslationFiles, PassportElementErrorSelfie
|
||||
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def passport_element_error_translation_files():
|
||||
return PassportElementErrorTranslationFiles(TestPassportElementErrorTranslationFiles.type,
|
||||
TestPassportElementErrorTranslationFiles.file_hashes, # flake8: noqa
|
||||
TestPassportElementErrorTranslationFiles.message)
|
||||
|
||||
|
||||
class TestPassportElementErrorTranslationFiles(object):
|
||||
source = 'translation_files'
|
||||
type = 'test_type'
|
||||
file_hashes = ['hash1', 'hash2']
|
||||
message = 'Error message'
|
||||
|
||||
def test_expected_values(self, passport_element_error_translation_files):
|
||||
assert passport_element_error_translation_files.source == self.source
|
||||
assert passport_element_error_translation_files.type == self.type
|
||||
assert isinstance(passport_element_error_translation_files.file_hashes, list)
|
||||
assert passport_element_error_translation_files.file_hashes == self.file_hashes
|
||||
assert passport_element_error_translation_files.message == self.message
|
||||
|
||||
def test_to_dict(self, passport_element_error_translation_files):
|
||||
passport_element_error_translation_files_dict = \
|
||||
passport_element_error_translation_files.to_dict()
|
||||
|
||||
assert isinstance(passport_element_error_translation_files_dict, dict)
|
||||
assert (passport_element_error_translation_files_dict['source'] ==
|
||||
passport_element_error_translation_files.source)
|
||||
assert (passport_element_error_translation_files_dict['type'] ==
|
||||
passport_element_error_translation_files.type)
|
||||
assert (passport_element_error_translation_files_dict['file_hashes'] ==
|
||||
passport_element_error_translation_files.file_hashes)
|
||||
assert (passport_element_error_translation_files_dict['message'] ==
|
||||
passport_element_error_translation_files.message)
|
||||
|
||||
def test_equality(self):
|
||||
a = PassportElementErrorTranslationFiles(self.type, self.file_hashes, self.message)
|
||||
b = PassportElementErrorTranslationFiles(self.type, self.file_hashes, self.message)
|
||||
c = PassportElementErrorTranslationFiles(self.type, '', '')
|
||||
d = PassportElementErrorTranslationFiles('', self.file_hashes, '')
|
||||
e = PassportElementErrorTranslationFiles('', '', self.message)
|
||||
f = PassportElementErrorSelfie(self.type, '', self.message)
|
||||
|
||||
assert a == b
|
||||
assert hash(a) == hash(b)
|
||||
assert a is not b
|
||||
|
||||
assert a != c
|
||||
assert hash(a) != hash(c)
|
||||
|
||||
assert a != d
|
||||
assert hash(a) != hash(d)
|
||||
|
||||
assert a != e
|
||||
assert hash(a) != hash(e)
|
||||
|
||||
assert a != f
|
||||
assert hash(a) != hash(f)
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# A library that provides a Python interface to the Telegram Bot API
|
||||
# Copyright (C) 2015-2018
|
||||
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
|
||||
import pytest
|
||||
|
||||
from telegram import PassportElementErrorUnspecified, PassportElementErrorDataField
|
||||
|
||||
|
||||
@pytest.fixture(scope='class')
|
||||
def passport_element_error_unspecified():
|
||||
return PassportElementErrorUnspecified(TestPassportElementErrorUnspecified.type,
|
||||
TestPassportElementErrorUnspecified.element_hash,
|
||||
TestPassportElementErrorUnspecified.message)
|
||||
|
||||
|
||||
class TestPassportElementErrorUnspecified(object):
|
||||
source = 'unspecified'
|
||||
type = 'test_type'
|
||||
element_hash = 'element_hash'
|
||||
message = 'Error message'
|
||||
|
||||
def test_expected_values(self, passport_element_error_unspecified):
|
||||
assert passport_element_error_unspecified.source == self.source
|
||||
assert passport_element_error_unspecified.type == self.type
|
||||
assert passport_element_error_unspecified.element_hash == self.element_hash
|
||||
assert passport_element_error_unspecified.message == self.message
|
||||
|
||||
def test_to_dict(self, passport_element_error_unspecified):
|
||||
passport_element_error_unspecified_dict = passport_element_error_unspecified.to_dict()
|
||||
|
||||
assert isinstance(passport_element_error_unspecified_dict, dict)
|
||||
assert (passport_element_error_unspecified_dict['source'] ==
|
||||
passport_element_error_unspecified.source)
|
||||
assert (passport_element_error_unspecified_dict['type'] ==
|
||||
passport_element_error_unspecified.type)
|
||||
assert (passport_element_error_unspecified_dict['element_hash'] ==
|
||||
passport_element_error_unspecified.element_hash)
|
||||
assert (passport_element_error_unspecified_dict['message'] ==
|
||||
passport_element_error_unspecified.message)
|
||||
|
||||
def test_equality(self):
|
||||
a = PassportElementErrorUnspecified(self.type, self.element_hash, self.message)
|
||||
b = PassportElementErrorUnspecified(self.type, self.element_hash, self.message)
|
||||
c = PassportElementErrorUnspecified(self.type, '', '')
|
||||
d = PassportElementErrorUnspecified('', self.element_hash, '')
|
||||
e = PassportElementErrorUnspecified('', '', self.message)
|
||||
f = PassportElementErrorDataField(self.type, '', '', self.message)
|
||||
|
||||
assert a == b
|
||||
assert hash(a) == hash(b)
|
||||
assert a is not b
|
||||
|
||||
assert a != c
|
||||
assert hash(a) != hash(c)
|
||||
|
||||
assert a != d
|
||||
assert hash(a) != hash(d)
|
||||
|
||||
assert a != e
|
||||
assert hash(a) != hash(e)
|
||||
|
||||
assert a != f
|
||||
assert hash(a) != hash(f)
|
||||
Reference in New Issue
Block a user