use maxbot::{MaxClient, SendMessageParamsBuilder, Attachment};
use std::env;
use std::time::Duration;
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);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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(())
}