1#!/usr/bin/env python
2# pylint: disable=unused-argument
3# This program is dedicated to the public domain under the CC0 license.
4
5"""
6Simple Bot to print/download all incoming passport data
7
8See https://telegram.org/blog/passport for info about what telegram passport is.
9
10See https://github.com/python-telegram-bot/python-telegram-bot/wiki/Telegram-Passport
11 for how to use Telegram Passport properly with python-telegram-bot.
12
13Note:
14To use Telegram Passport, you must install PTB via
15`pip install "python-telegram-bot[passport]"`
16"""
17import logging
18from pathlib import Path
19
20from telegram import Update
21from telegram.ext import Application, ContextTypes, MessageHandler, filters
22
23# Enable logging
24
25logging.basicConfig(
26 format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
27)
28
29# set higher logging level for httpx to avoid all GET and POST requests being logged
30logging.getLogger("httpx").setLevel(logging.WARNING)
31
32logger = logging.getLogger(__name__)
33
34
35async def msg(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
36 """Downloads and prints the received passport data."""
37 # Retrieve passport data
38 passport_data = update.message.passport_data
39 # If our nonce doesn't match what we think, this Update did not originate from us
40 # Ideally you would randomize the nonce on the server
41 if passport_data.decrypted_credentials.nonce != "thisisatest":
42 return
43
44 # Print the decrypted credential data
45 # For all elements
46 # Print their decrypted data
47 # Files will be downloaded to current directory
48 for data in passport_data.decrypted_data: # This is where the data gets decrypted
49 if data.type == "phone_number":
50 logger.info("Phone: %s", data.phone_number)
51 elif data.type == "email":
52 logger.info("Email: %s", data.email)
53 if data.type in (
54 "personal_details",
55 "passport",
56 "driver_license",
57 "identity_card",
58 "internal_passport",
59 "address",
60 ):
61 logger.info(data.type, data.data)
62 if data.type in (
63 "utility_bill",
64 "bank_statement",
65 "rental_agreement",
66 "passport_registration",
67 "temporary_registration",
68 ):
69 logger.info(data.type, len(data.files), "files")
70 for file in data.files:
71 actual_file = await file.get_file()
72 logger.info(actual_file)
73 await actual_file.download_to_drive()
74 if (
75 data.type in ("passport", "driver_license", "identity_card", "internal_passport")
76 and data.front_side
77 ):
78 front_file = await data.front_side.get_file()
79 logger.info(data.type, front_file)
80 await front_file.download_to_drive()
81 if data.type in ("driver_license" and "identity_card") and data.reverse_side:
82 reverse_file = await data.reverse_side.get_file()
83 logger.info(data.type, reverse_file)
84 await reverse_file.download_to_drive()
85 if (
86 data.type in ("passport", "driver_license", "identity_card", "internal_passport")
87 and data.selfie
88 ):
89 selfie_file = await data.selfie.get_file()
90 logger.info(data.type, selfie_file)
91 await selfie_file.download_to_drive()
92 if data.translation and data.type in (
93 "passport",
94 "driver_license",
95 "identity_card",
96 "internal_passport",
97 "utility_bill",
98 "bank_statement",
99 "rental_agreement",
100 "passport_registration",
101 "temporary_registration",
102 ):
103 logger.info(data.type, len(data.translation), "translation")
104 for file in data.translation:
105 actual_file = await file.get_file()
106 logger.info(actual_file)
107 await actual_file.download_to_drive()
108
109
110def main() -> None:
111 """Start the bot."""
112 # Create the Application and pass it your token and private key
113 private_key = Path("private.key")
114 application = (
115 Application.builder().token("TOKEN").private_key(private_key.read_bytes()).build()
116 )
117
118 # On messages that include passport data call msg
119 application.add_handler(MessageHandler(filters.PASSPORT_DATA, msg))
120
121 # Run the bot until the user presses Ctrl-C
122 application.run_polling(allowed_updates=Update.ALL_TYPES)
123
124
125if __name__ == "__main__":
126 main()