passportbot.py

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

HTML Page

 1<!DOCTYPE html>
 2<html lang="en">
 3<head>
 4    <title>Telegram passport test!</title>
 5    <meta charset="utf-8">
 6    <meta content="IE=edge" http-equiv="X-UA-Compatible">
 7    <meta content="width=device-width, initial-scale=1" name="viewport">
 8</head>
 9<body>
10<h1>Telegram passport test</h1>
11
12<div id="telegram_passport_auth"></div>
13</body>
14
15<!--- Needs file from https://github.com/TelegramMessenger/TGPassportJsSDK downloaded --->
16<script src="telegram-passport.js"></script>
17<script>
18    "use strict";
19
20    Telegram.Passport.createAuthButton('telegram_passport_auth', {
21        bot_id: 1234567890, // YOUR BOT ID
22        scope: {
23            data: [{
24                type: 'id_document',
25                selfie: true
26            }, 'address_document', 'phone_number', 'email'], v: 1
27        }, // WHAT DATA YOU WANT TO RECEIVE
28        public_key: '-----BEGIN PUBLIC KEY-----\n', // YOUR PUBLIC KEY
29        nonce: 'thisisatest', // YOUR BOT WILL RECEIVE THIS DATA WITH THE REQUEST
30        callback_url: 'https://example.org' // TELEGRAM WILL SEND YOUR USER BACK TO THIS URL
31    });
32
33</script>
34</html>