maxbot 0.7.4

Автоматизация работы с чат-ботами на платформе MAX (max.ru)
Documentation
//! Демонстрация возможностей отправки текста:
//! - простой текст
//! - форматирование Markdown и HTML
//! - вложения (изображение, видео, аудио, файл)
//! - пересылка сообщения
//! - ответ на сообщение
//!
//! # Запуск
//! ```bash
//! export MAXBOT_TOKEN="ваш_токен"
//! export CHAT_ID=-1234567890
//! # опционально: MENTION_USER_ID=12345
//! cargo run --example full-demo
//! ```

use maxbot::{MaxClient, SendMessageParamsBuilder, Attachment};
use std::env;
use std::time::Duration;

/// Получает ID первого пользователя (не бота) в чате.
async fn get_first_non_bot_user_id(client: &MaxClient, chat_id: i64) -> Option<i64> {
    match client.get_chat_members(chat_id, None, Some(10)).await {
        Ok((members, _)) => members.into_iter().find(|m| !m.user.is_bot).map(|m| m.user.user_id),
        Err(_) => None,
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let token = std::env::var("MAXBOT_TOKEN").expect("Missing MAXBOT_TOKEN");
    let chat_id = std::env::var("CHAT_ID")
        .expect("Missing CHAT_ID")
        .parse::<i64>()?;
    let mention_user_id = match std::env::var("MENTION_USER_ID") {
        Ok(s) => match s.parse::<i64>() {
            Ok(id) => Some(id),
            Err(_) => {
                eprintln!("Warning: MENTION_USER_ID contains invalid number '{}', ignoring", s);
                None
            }
        },
        Err(_) => None,
    };
    if let Ok(proxy_url) = env::var("MAXBOT_PROXY") {
        maxbot::set_global_base_url(proxy_url);
    }

    let client = MaxClient::new(token);

    // -----------------------------------------------------------------
    // 1. Простое текстовое сообщение
    // -----------------------------------------------------------------
    println!("1. Sending plain text message...");
    let builder = SendMessageParamsBuilder::new()
        .text("Hello! This is a plain text message from maxbot demo.")
        .chat_id(chat_id);
    let ids = client.send_message_builder(builder).await?;
    println!("   Sent, message ID: {:?}", ids.first().unwrap());
    tokio::time::sleep(Duration::from_secs(1)).await;

    // -----------------------------------------------------------------
    // 2. Форматирование Markdown
    // -----------------------------------------------------------------
    println!("2. Sending Markdown formatted message...");
    let user_id = if let Some(uid) = mention_user_id {
        uid
    } else {
        match get_first_non_bot_user_id(&client, chat_id).await {
            Some(uid) => uid,
            None => {
                eprintln!("Warning: Could not find a non-bot user in chat, using bot's own ID.");
                client.get_me().await?.user.user_id
            }
        }
    };

    let markdown_text = format!(
        "**Bold** text, *italic* text, ~~strikethrough~~, ++underline++,\n\
         `monospace code`\n\
         [Inline link](https://dev.max.ru/)\n\
         User mention: [Demo User](max://user/{})\n",
        user_id
    );
    let builder = SendMessageParamsBuilder::new()
        .text(markdown_text)
        .chat_id(chat_id)
        .format_markdown();
    let ids = client.send_message_builder(builder).await?;
    println!("   Sent, message ID: {:?}", ids.first().unwrap());
    tokio::time::sleep(Duration::from_secs(1)).await;

    // -----------------------------------------------------------------
    // 3. Форматирование HTML
    // -----------------------------------------------------------------
    println!("3. Sending HTML formatted message...");
    let html_text = format!(
        "<b>Bold</b> text, <i>italic</i> text, <del>strikethrough</del>, <ins>underline</ins>,<br/>\
         <pre>monospace code</pre>\n\
         <a href=\"https://dev.max.ru/\">HTML link</a><br/>\n\
         User mention: <a href=\"max://user/{}\">Demo User</a>\n",
        user_id
    );
    let builder = SendMessageParamsBuilder::new()
        .text(html_text)
        .chat_id(chat_id)
        .format_html();
    let ids = client.send_message_builder(builder).await?;
    println!("   Sent, message ID: {:?}", ids.first().unwrap());
    tokio::time::sleep(Duration::from_secs(1)).await;

    // -----------------------------------------------------------------
    // 4. Вложения
    // -----------------------------------------------------------------
    // 4a. Изображение
    println!("4a. Sending message with image attachment...");
    let builder = SendMessageParamsBuilder::new()
        .text("Image attachment:")
        .chat_id(chat_id)
        .attachment(Attachment::image_local("examples/files/hello.webp"));
    let ids = client.send_message_builder(builder).await?;
    println!("   Sent, message ID: {:?}", ids.first().unwrap());
    tokio::time::sleep(Duration::from_secs(1)).await;

    // 4b. Видео из локального файла
    println!("4b. Sending message with video attachment...");
    let builder = SendMessageParamsBuilder::new()
        .text("Video attachment:")
        .chat_id(chat_id)
        .attachment(Attachment::video_local("examples/files/boom.mp4"));
    let ids = client.send_message_builder(builder).await?;
    println!("   Sent, message ID: {:?}", ids.first().unwrap());
    tokio::time::sleep(Duration::from_secs(2)).await;

    // 4c. Видео по веб-ссылке
    let builder = SendMessageParamsBuilder::new()
        .text("ВИА «Верасы» — Любовь, Комсомол и весна")
        .chat_id(chat_id)
        .attachment(Attachment::video_url("https://gitflic.ru/project/perdumonocle/public-files/blob/raw?file=%D0%92%D0%98%D0%90%20%C2%AB%D0%92%D0%B5%D1%80%D0%B0%D1%81%D1%8B%C2%BB%20%E2%80%94%20%D0%9B%D1%8E%D0%B1%D0%BE%D0%B2%D1%8C%2C%20%D0%9A%D0%BE%D0%BC%D1%81%D0%BE%D0%BC%D0%BE%D0%BB%20%D0%B8%20%D0%B2%D0%B5%D1%81%D0%BD%D0%B0.mp4&inline=false&commit=b4d8f376ab49070c2c165a48f350a83aa610309e", "ВИА «Верасы» — Любовь, Комсомол и весна.mp4"));
    let ids = client.send_message_builder(builder).await?;
    println!("   Sent, message ID: {:?}", ids.first().unwrap());
    tokio::time::sleep(Duration::from_secs(2)).await;

    // 4d. Аудио
    println!("4c. Sending message with audio attachment...");
    let builder = SendMessageParamsBuilder::new()
        .text("Audio attachment:")
        .chat_id(chat_id)
        .attachment(Attachment::audio_local("examples/files/Детский хор Зарянка — Солдатушки браво ребятушки.mp3"));
    let ids = client.send_message_builder(builder).await?;
    println!("   Sent, message ID: {:?}", ids.first().unwrap());
    tokio::time::sleep(Duration::from_secs(1)).await;

    // 4e. Произвольный файл
    println!("4d. Sending message with file attachment...");
    let builder = SendMessageParamsBuilder::new()
        .text("File attachment:")
        .chat_id(chat_id)
        .attachment(Attachment::file_local("examples/files/terror.pdf"));
    let ids = client.send_message_builder(builder).await?;
    println!("   Sent, message ID: {:?}", ids.first().unwrap());
    tokio::time::sleep(Duration::from_secs(1)).await;

    // 4f. Комбинированное вложение (изображение + видео)
    println!("4e. Sending message with combined attachments (image + video)...");
    let builder = SendMessageParamsBuilder::new()
        .text("Combined image and video:")
        .chat_id(chat_id)
        .attachments(vec![
            Attachment::image_local("examples/files/hello.png"),
            Attachment::video_local("examples/files/boom.mp4"),
        ]);
    match client.send_message_builder(builder).await {
        Ok(ids) => println!("   Sent, message ID: {:?}", ids.first().unwrap()),
        Err(e) => eprintln!("   Note: API may not support image+video combination, error: {}", e),
    }
    tokio::time::sleep(Duration::from_secs(2)).await;

    // -----------------------------------------------------------------
    // 5. Пересылка сообщения
    // -----------------------------------------------------------------
    // Сначала отправим сообщение, которое потом перешлём
    println!("5a. Sending a message to be forwarded...");
    let builder = SendMessageParamsBuilder::new()
        .text("This message will be forwarded.")
        .chat_id(chat_id);
    let ids = client.send_message_builder(builder).await?;
    let source_mid = ids.first().unwrap().clone();
    println!("   Source message ID: {}", source_mid);
    tokio::time::sleep(Duration::from_secs(1)).await;

    println!("5b. Forwarding the message...");
    let new_mid = client
        .forward_message(Some(chat_id), None, &source_mid, Some(true), None)
        .await?;
    println!("   Forwarded, new message ID: {}", new_mid);
    tokio::time::sleep(Duration::from_secs(1)).await;

    // -----------------------------------------------------------------
    // 6. Ответ (reply) на сообщение
    // -----------------------------------------------------------------
    println!("6. Replying to the original message...");
    let builder = SendMessageParamsBuilder::new()
        .text("This is a reply to the message above.")
        .chat_id(chat_id)
        .reply_to(&source_mid);
    let ids = client.send_message_builder(builder).await?;
    println!("   Reply sent, message ID: {:?}", ids.first().unwrap());

    println!("\nAll demonstrations completed successfully!");
    Ok(())
}