Skip to main content

ask_phone_bot/
ask-phone-bot.rs

1//! Бот, запрашивающий контактные данные через inline-кнопку.
2//! При получении контакта разбирает vCard и отвечает с извлечённой информацией.
3
4use maxbot::{Dispatcher, MaxClient, Attachment, InlineKeyboardButton, InlineKeyboardBuilder, SendMessageParamsBuilder};
5use maxbot::vcard::parse_vcard;
6use std::env;
7
8#[tokio::main]
9async fn main() -> Result<(), Box<dyn std::error::Error>> {
10    let token = env::var("MAXBOT_TOKEN").expect("MAXBOT_TOKEN not set");
11    let real_token = env::var("MAXBOT_REAL_TOKEN").unwrap_or_else(|_| token.clone());
12
13    let mut check_hash = true;
14    let mut client = MaxClient::new(token);
15    if let Ok(proxy_url) = env::var("MAXBOT_PROXY") {
16        client.set_base_url(proxy_url);
17        if real_token.starts_with("Basic ") {
18            check_hash = false;
19        }
20    }
21
22    if !check_hash {
23        println!("Токен бота подменён. Требуется указать MAXBOT_REAL_TOKEN для проверки номера телефона.");
24    }
25
26    let bot = client;
27    let mut dp = Dispatcher::new(bot);
28
29    // Команда /start – отправляем кнопку запроса контакта
30    dp.on_command("/start", |ctx| async move {
31        let chat_id = ctx.chat_id().unwrap();
32        let keyboard = InlineKeyboardBuilder::new()
33            .button(InlineKeyboardButton::request_contact("Передать 🔀"))
34            .build()?;
35        let body = SendMessageParamsBuilder::new()
36            .text("Предоставьте свои данные")
37            .chat_id(chat_id)
38            .attachment(Attachment::inline_keyboard(keyboard))
39            .build();
40        ctx.bot().send_message(body).await?;
41        Ok(())
42    });
43
44    // Подготовка токена проверки для передачи в замыкание
45    let check_bytes = real_token.into_bytes();
46
47    // Обработка входящего контакта
48    dp.on_message(move |ctx| {
49        let token_bytes = check_bytes.clone();
50        async move {
51            let msg = match ctx.message() {
52                Some(m) => m,
53                None => return Ok(()),
54            };
55            let attachments = match &msg.body {
56                Some(b) => &b.attachments,
57                None => return Ok(()),
58            };
59            for att in attachments {
60                if let maxbot::AttachmentData::Contact { payload } = att {
61                    let mut response = String::from("Вы предоставили следующую информацию:\n");
62                    let mut has_phone = false;
63
64                    // Разбор vCard, если есть
65                    if let Some(vcf) = &payload.vcf_info {
66                        match parse_vcard(vcf) {
67                            Ok(card) => {
68                                if let Some(fn_) = card.get_formatted_name() {
69                                    response.push_str(&format!("Имя: {}\n", fn_));
70                                }
71                                for phone in card.get_phone_numbers() {
72                                    response.push_str(&format!("Телефон: {}\n", phone));
73                                    has_phone = !phone.is_empty();
74                                }
75                                for email in card.get_emails() {
76                                    response.push_str(&format!("Email: {}\n", email));
77                                }
78                            }
79                            Err(e) => response.push_str(&format!("Ошибка чтения vCard: {}\n", e)),
80                        }
81                    } else {
82                        if let Some(name) = &payload.name {
83                            response.push_str(&format!("Имя: {}\n", name));
84                        }
85                        if let Some(phone) = &payload.vcf_phone {
86                            response.push_str(&format!("Телефон: {}\n", phone));
87                            has_phone = !phone.is_empty();
88                        }
89                    }
90
91                    // Проверка контрольной суммы
92                    if check_hash && has_phone {
93                        if payload.verify_hash(&token_bytes) {
94                            response.push_str("✅ Номер телефона подтверждён.\n");
95                        } else {
96                            response.push_str("❌ Номер телефона не подтверждён.\n");
97                        }
98                    }
99
100                    ctx.reply_text(&response).await?;
101                    return Ok(());
102                }
103            }
104            Ok(())
105        }
106    });
107
108    println!("Бот запущен. Отправьте команду /start для запроса контактных данных.");
109    dp.start_polling().await;
110    Ok(())
111}