Skip to main content

subscription_chat_collector/
subscription-chat-collector.rs

1//! Сбор идентификаторов чатов через подписки (альтернатива устаревшему GET /chats).
2//!
3//! Бот подписывается на события добавления/удаления в чатах и хранит список chat_id.
4//! По команде /list выводит все сохранённые идентификаторы.
5//!
6//! # Запуск
7//! ```bash
8//! export MAXBOT_TOKEN="ваш_токен"
9//! cargo run --example subscription-chat-collector
10//! ```
11
12use maxbot::{Dispatcher, MaxClient};
13use std::collections::HashSet;
14use std::sync::Arc;
15use tokio::sync::Mutex;
16
17type ChatStore = Arc<Mutex<HashSet<i64>>>;
18
19#[tokio::main]
20async fn main() -> Result<(), Box<dyn std::error::Error>> {
21    let bot = MaxClient::from_env().expect("MAXBOT_TOKEN not set");
22    let mut dp = Dispatcher::new(bot);
23
24    // Хранилище chat_id в памяти (в реальном проекте используйте БД)
25    let store: ChatStore = Arc::new(Mutex::new(HashSet::new()));
26
27    // Обработчик добавления бота в чат (групповой чат или канал)
28    let store_clone = store.clone();
29    dp.on_bot_added(move |ctx| {
30        let store = store_clone.clone();
31        async move {
32            if let Some(chat_id) = ctx.chat_id() {
33                let mut guard = store.lock().await;
34                if guard.insert(chat_id) {
35                    println!("✅ Бот добавлен в новый чат: {}", chat_id);
36                    // Отправляем приветствие с chat_id
37                    let _ = ctx.reply_text(&format!(
38                        "Привет! Я бот. Мой ID в этом чате: `{}`",
39                        chat_id
40                    )).await;
41                }
42            }
43            Ok(())
44        }
45    });
46
47    // Обработчик запуска бота (личные сообщения или /start в группе)
48    let store_clone = store.clone();
49    dp.on_bot_started(move |ctx| {
50        let store = store_clone.clone();
51        async move {
52            if let Some(chat_id) = ctx.chat_id() {
53                let mut guard = store.lock().await;
54                if guard.insert(chat_id) {
55                    println!("✅ Бот запущен в чате: {}", chat_id);
56                }
57                // Отвечаем в личке или группе
58                let _ = ctx.reply_text(&format!(
59                    "Ваш chat_id: `{}`\nИспользуйте /list для просмотра всех сохранённых чатов.",
60                    chat_id
61                )).await;
62            }
63            Ok(())
64        }
65    });
66
67    // Обработчик удаления бота из чата
68    let store_clone = store.clone();
69    dp.on_bot_removed(move |ctx| {
70        let store = store_clone.clone();
71        async move {
72            if let Some(chat_id) = ctx.chat_id() {
73                let mut guard = store.lock().await;
74                if guard.remove(&chat_id) {
75                    println!("❌ Бот удалён из чата: {}", chat_id);
76                }
77            }
78            Ok(())
79        }
80    });
81
82    // Команда /list – выводит все сохранённые chat_id
83    let store_clone = store.clone();
84    dp.on_command("/list", move |ctx| {
85        let store = store_clone.clone();
86        async move {
87            let guard = store.lock().await;
88            if guard.is_empty() {
89                ctx.reply_text("Нет сохранённых чатов. Добавьте бота в группу или напишите /start в личку.")
90                    .await?;
91            } else {
92                let mut response = String::from("Сохранённые chat_id:\n");
93                for id in guard.iter() {
94                    response.push_str(&format!("- {}\n", id));
95                }
96                ctx.reply_text(&response).await?;
97            }
98            Ok(())
99        }
100    });
101
102    // Команда /clear – очищает хранилище (для тестирования)
103    let store_clone = store.clone();
104    dp.on_command("/clear", move |ctx| {
105        let store = store_clone.clone();
106        async move {
107            let mut guard = store.lock().await;
108            guard.clear();
109            ctx.reply_text("Хранилище очищено.").await?;
110            Ok(())
111        }
112    });
113
114    println!("🔄 Бот запущен. Собираю chat_id из событий.");
115    println!("📋 Используйте команду /list для просмотра всех сохранённых чатов.");
116    println!("   /clear для очистки списка.");
117
118    dp.start_polling().await;
119
120    Ok(())
121}