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