use botrs::{Client, Context, EventHandler, Intents, Message, Ready, Token};
use tracing::{info, warn};
struct SimpleHandler;
#[async_trait::async_trait]
impl EventHandler for SimpleHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
info!("Bot is ready! Logged in as: {}", ready.user.username);
info!("Session ID: {}", ready.session_id);
}
async fn message_create(&self, ctx: Context, message: Message) {
if message.is_from_bot() {
return;
}
let content = match &message.content {
Some(content) => content,
None => return,
};
info!(
"Received message from {}: {}",
message
.author
.as_ref()
.map(|a| a.username.as_deref().unwrap_or("Unknown"))
.unwrap_or("Unknown"),
content
);
let response = match content.trim().to_lowercase().as_str() {
"!ping" => Some("Pong! π".to_string()),
"!hello" => Some("Hello there! π".to_string()),
"!help" => Some(
"Available commands:\nβ’ !ping - Test bot responsiveness\nβ’ !hello - Get a greeting\nβ’ !info - Get bot information"
.to_string(),
),
"!info" => Some(
"I'm a simple QQ Guild bot built with BotRS! π€\nWritten in Rust for performance and safety."
.to_string(),
),
_ => {
if content.contains("bot") || content.contains("ζΊε¨δΊΊ") {
Some(format!("You mentioned me! You said: {content}"))
} else {
None
}
}
};
if let Some(response_text) = response {
match message.reply(&ctx.api, &ctx.token, &response_text).await {
Ok(_) => info!("Successfully sent reply"),
Err(e) => warn!("Failed to send reply: {}", e),
}
}
}
async fn group_message_create(&self, ctx: Context, message: botrs::GroupMessage) {
let content = match &message.content {
Some(content) => content,
None => return,
};
info!(
"Received group message from {}: {}",
message
.author
.as_ref()
.and_then(|a| a.member_openid.as_deref())
.unwrap_or("Unknown"),
content
);
let response = match content.trim().to_lowercase().as_str() {
"!ping" => Some("Pong! π".to_string()),
"!hello" => Some("Hello there! π".to_string()),
"!help" => Some(
"Available commands:\nβ’ !ping - Test bot responsiveness\nβ’ !hello - Get a greeting\nβ’ !info - Get bot information"
.to_string(),
),
"!info" => Some(
"I'm a simple QQ Guild bot built with BotRS! π€\nWritten in Rust for performance and safety."
.to_string(),
),
_ => {
if content.contains("bot") || content.contains("ζΊε¨δΊΊ") {
Some(format!("You mentioned me! You said: {content}"))
} else {
None
}
}
};
if let Some(response_text) = response {
match message.reply(&ctx.api, &ctx.token, &response_text).await {
Ok(_) => info!("Successfully sent group message reply"),
Err(e) => warn!("Failed to send group message reply: {}", e),
}
}
}
async fn error(&self, error: botrs::BotError) {
warn!("Event handler error: {}", error);
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_env_filter("botrs=debug,simple_bot=info")
.init();
info!("Starting simple bot example...");
let app_id = std::env::var("QQ_BOT_APP_ID")
.or_else(|_| std::env::args().nth(1).ok_or("Missing app_id"))
.expect("Please provide QQ_BOT_APP_ID environment variable or as first argument");
let secret = std::env::var("QQ_BOT_SECRET")
.or_else(|_| std::env::args().nth(2).ok_or("Missing secret"))
.expect("Please provide QQ_BOT_SECRET environment variable or as second argument");
let token = Token::new(app_id, secret);
if let Err(e) = token.validate() {
panic!("Invalid token: {e}");
}
info!("Token validated successfully");
let intents = Intents::default()
.with_public_guild_messages()
.with_direct_message()
.with_guilds();
info!("Configured intents: {}", intents);
let handler = SimpleHandler;
let mut client = Client::new(token, intents, handler, true)?;
info!("Client created, starting bot...");
client.start().await?;
info!("Bot stopped");
Ok(())
}