文本消息示例
本指南演示如何使用 BotRS 处理和发送文本消息。文本消息是 QQ 频道机器人中最常见的交互类型,支持从简单回复到复杂命令系统的各种场景。
基础文本处理
简单回声机器人
最基本的文本消息处理涉及将用户输入回显给他们。
rust
use botrs::{Client, Context, EventHandler, Intents, Message, Ready, Token};
struct EchoHandler;
#[async_trait::async_trait]
impl EventHandler for EchoHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("机器人 {} 已准备就绪!", ready.user.username);
}
async fn message_create(&self, ctx: Context, message: Message) {
// 忽略机器人消息以防止循环
if message.is_from_bot() {
return;
}
// 检查消息是否有内容
if let Some(content) = &message.content {
// 简单回声 - 用相同内容回复
if let Err(e) = message.reply(&ctx.api, &ctx.token, content).await {
eprintln!("发送回复失败: {}", e);
}
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let token = Token::new("your_app_id", "your_secret");
let intents = Intents::default().with_public_guild_messages();
let handler = EchoHandler;
let mut client = Client::new(token, intents, handler, true)?;
client.start().await?;
Ok(())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@ 提及回复
专门回复提及机器人的消息。
rust
use botrs::{Client, Context, EventHandler, Intents, Message, Ready, Token};
struct MentionHandler;
#[async_trait::async_trait]
impl EventHandler for MentionHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("机器人 {} 已准备好接收提及!", ready.user.username);
}
async fn message_create(&self, ctx: Context, message: Message) {
if message.is_from_bot() {
return;
}
if let Some(content) = &message.content {
// 获取机器人名称以提供个性化响应
let bot_name = ctx
.bot_info
.as_ref()
.map(|info| info.username.as_str())
.unwrap_or("机器人");
let reply_content = format!(
"你好!机器人 {} 收到了你的提及:{}",
bot_name, content
);
if let Err(e) = message.reply(&ctx.api, &ctx.token, &reply_content).await {
eprintln!("回复提及失败: {}", e);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
命令系统
简单命令处理器
构建一个响应带前缀消息的基本命令系统。
rust
use botrs::{Client, Context, EventHandler, Intents, Message, Ready, Token};
use std::collections::HashMap;
type CommandHandler = fn(&str) -> String;
struct CommandBot {
commands: HashMap<String, CommandHandler>,
}
impl CommandBot {
fn new() -> Self {
let mut commands = HashMap::new();
// 注册命令
commands.insert("ping".to_string(), ping_command as CommandHandler);
commands.insert("hello".to_string(), hello_command as CommandHandler);
commands.insert("echo".to_string(), echo_command as CommandHandler);
commands.insert("help".to_string(), help_command as CommandHandler);
Self { commands }
}
fn handle_command(&self, content: &str) -> Option<String> {
// 命令以 ! 开头
if !content.starts_with('!') {
return None;
}
let content = &content[1..]; // 移除 !
let parts: Vec<&str> = content.splitn(2, ' ').collect();
let command = parts[0];
let args = parts.get(1).unwrap_or(&"");
self.commands.get(command).map(|handler| handler(args))
}
}
// 命令实现
fn ping_command(_args: &str) -> String {
"Pong!".to_string()
}
fn hello_command(args: &str) -> String {
if args.is_empty() {
"你好!".to_string()
} else {
format!("你好,{}!", args)
}
}
fn echo_command(args: &str) -> String {
if args.is_empty() {
"没有内容可回显!".to_string()
} else {
format!("回显:{}", args)
}
}
fn help_command(_args: &str) -> String {
"可用命令:\n!ping - 回复 Pong!\n!hello [名字] - 向你问好\n!echo <文本> - 回显你的文本\n!help - 显示此帮助".to_string()
}
#[async_trait::async_trait]
impl EventHandler for CommandBot {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("命令机器人 {} 已准备就绪!", ready.user.username);
}
async fn message_create(&self, ctx: Context, message: Message) {
if message.is_from_bot() {
return;
}
if let Some(content) = &message.content {
if let Some(response) = self.handle_command(content) {
if let Err(e) = message.reply(&ctx.api, &ctx.token, &response).await {
eprintln!("发送命令响应失败: {}", e);
}
}
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let token = Token::new("your_app_id", "your_secret");
let intents = Intents::default().with_public_guild_messages();
let handler = CommandBot::new();
let mut client = Client::new(token, intents, handler, true)?;
client.start().await?;
Ok(())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
带别名的高级命令系统
更复杂的命令处理,支持命令别名和参数解析。
rust
use botrs::{Client, Context, EventHandler, Intents, Message, Ready, Token};
struct CommandRegistry {
commands: Vec<(Vec<String>, fn(&str) -> Option<String>)>,
}
impl CommandRegistry {
fn new() -> Self {
let mut registry = Self {
commands: Vec::new(),
};
// 注册带别名的命令
registry.register(vec!["hello", "hi", "hey", "你好"], hello_handler);
registry.register(vec!["goodbye", "bye", "cya", "再见"], goodbye_handler);
registry.register(vec!["time", "clock", "时间"], time_handler);
registry.register(vec!["random", "rand", "随机"], random_handler);
registry
}
fn register(&mut self, aliases: Vec<&str>, handler: fn(&str) -> Option<String>) {
let aliases: Vec<String> = aliases.iter().map(|s| s.to_string()).collect();
self.commands.push((aliases, handler));
}
fn execute(&self, content: &str) -> Option<String> {
let trimmed = content.trim();
for (aliases, handler) in &self.commands {
for alias in aliases {
if trimmed.starts_with(alias) {
let params = if trimmed.len() > alias.len() {
trimmed[alias.len()..].trim()
} else {
""
};
return handler(params);
}
}
}
None
}
}
// 命令处理器
fn hello_handler(params: &str) -> Option<String> {
Some(if params.is_empty() {
"你好!今天过得怎么样?".to_string()
} else {
format!("你好,{}!很高兴认识你!", params)
})
}
fn goodbye_handler(params: &str) -> Option<String> {
Some(if params.is_empty() {
"再见!祝你有美好的一天!".to_string()
} else {
format!("再见,{}!回头见!", params)
})
}
fn time_handler(_params: &str) -> Option<String> {
use chrono::Utc;
let now = Utc::now();
Some(format!("当前 UTC 时间:{}", now.format("%Y-%m-%d %H:%M:%S")))
}
fn random_handler(params: &str) -> Option<String> {
use rand::Rng;
if params.is_empty() {
let num = rand::thread_rng().gen_range(1..=100);
Some(format!("随机数字:{}", num))
} else if let Ok(max) = params.parse::<u32>() {
let num = rand::thread_rng().gen_range(1..=max);
Some(format!("随机数字 (1-{}):{}", max, num))
} else {
Some("无效的数字格式。用法:random [最大数字]".to_string())
}
}
struct AdvancedCommandHandler {
registry: CommandRegistry,
}
impl AdvancedCommandHandler {
fn new() -> Self {
Self {
registry: CommandRegistry::new(),
}
}
}
#[async_trait::async_trait]
impl EventHandler for AdvancedCommandHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("高级命令机器人 {} 已准备就绪!", ready.user.username);
}
async fn message_create(&self, ctx: Context, message: Message) {
if message.is_from_bot() {
return;
}
if let Some(content) = &message.content {
if let Some(response) = self.registry.execute(content) {
if let Err(e) = message.reply(&ctx.api, &ctx.token, &response).await {
eprintln!("发送响应失败: {}", e);
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
不同消息类型
群消息
处理 QQ 群中的文本消息。
rust
use botrs::{Client, Context, EventHandler, GroupMessage, Intents, Ready, Token};
struct GroupTextHandler;
#[async_trait::async_trait]
impl EventHandler for GroupTextHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("群机器人 {} 已准备就绪!", ready.user.username);
}
async fn group_message_create(&self, ctx: Context, message: GroupMessage) {
if let Some(content) = &message.content {
println!("收到群消息: {}", content);
// 处理特定的群命令
let response = if content.contains("你好") || content.contains("hello") {
Some("大家好!")
} else if content.contains("帮助") || content.contains("help") {
Some("群命令:你好、帮助、信息")
} else if content.contains("信息") || content.contains("info") {
Some("这是一个使用 BotRS 构建的 QQ 群机器人")
} else {
None
};
if let Some(reply_text) = response {
// 使用便捷的回复方法
if let Err(e) = message.reply(&ctx.api, &ctx.token, reply_text).await {
eprintln!("回复群消息失败: {}", e);
}
}
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let token = Token::new("your_app_id", "your_secret");
let intents = Intents::default().with_public_messages();
let handler = GroupTextHandler;
let mut client = Client::new(token, intents, handler, true)?;
client.start().await?;
Ok(())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
C2C 消息
处理客户端到客户端的文本消息。
rust
use botrs::{C2CMessage, Client, Context, EventHandler, Intents, Ready, Token};
struct C2CTextHandler;
#[async_trait::async_trait]
impl EventHandler for C2CTextHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("C2C 机器人 {} 已准备就绪!", ready.user.username);
}
async fn c2c_message_create(&self, ctx: Context, message: C2CMessage) {
if let Some(content) = &message.content {
println!("收到 C2C 消息: {}", content);
// 创建个性化响应
let reply_content = format!("我收到了你的私人消息:{}", content);
// 回复 C2C 消息
if let Err(e) = message.reply(&ctx.api, &ctx.token, &reply_content).await {
eprintln!("回复 C2C 消息失败: {}", e);
}
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let token = Token::new("your_app_id", "your_secret");
let intents = Intents::default().with_public_messages();
let handler = C2CTextHandler;
let mut client = Client::new(token, intents, handler, true)?;
client.start().await?;
Ok(())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
私信
处理频道环境中的私信。
rust
use botrs::{Client, Context, DirectMessage, EventHandler, Intents, Ready, Token};
struct DirectMessageHandler;
#[async_trait::async_trait]
impl EventHandler for DirectMessageHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("私信机器人 {} 已准备就绪!", ready.user.username);
}
async fn direct_message_create(&self, ctx: Context, message: DirectMessage) {
if let Some(content) = &message.content {
println!("收到私信: {}", content);
// 处理私信特定命令
let response = match content.to_lowercase().as_str() {
"帮助" | "help" => "私信命令:帮助、状态、信息",
"状态" | "status" => "机器人运行正常",
"信息" | "info" => "这是与机器人的私人对话",
_ => "感谢你的消息!输入'帮助'查看可用命令。",
};
if let Err(e) = message.reply(&ctx.api, &ctx.token, response).await {
eprintln!("回复私信失败: {}", e);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
高级文本处理
文本分析和响应
分析消息内容以提供智能响应。
rust
use botrs::{Client, Context, EventHandler, Intents, Message, Ready, Token};
struct AnalysisHandler;
impl AnalysisHandler {
fn analyze_sentiment(&self, text: &str) -> &'static str {
let positive_words = ["好", "棒", "太棒了", "喜欢", "开心", "优秀", "不错"];
let negative_words = ["坏", "糟糕", "讨厌", "难过", "可怕", "恐怖"];
let positive_count = positive_words.iter()
.map(|word| text.matches(word).count())
.sum::<usize>();
let negative_count = negative_words.iter()
.map(|word| text.matches(word).count())
.sum::<usize>();
if positive_count > negative_count {
"积极"
} else if negative_count > positive_count {
"消极"
} else {
"中性"
}
}
fn generate_response(&self, content: &str) -> String {
let sentiment = self.analyze_sentiment(content);
let word_count = content.chars().count();
match sentiment {
"积极" => format!("很高兴听到积极的话!你的消息({} 个字符)听起来很棒!", word_count),
"消极" => format!("希望一切都会好起来!感谢你与我分享这 {} 个字符。", word_count),
_ => format!("感谢你的消息!我收到了你的 {} 个字符。", word_count),
}
}
}
#[async_trait::async_trait]
impl EventHandler for AnalysisHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("分析机器人 {} 已准备就绪!", ready.user.username);
}
async fn message_create(&self, ctx: Context, message: Message) {
if message.is_from_bot() {
return;
}
if let Some(content) = &message.content {
// 跳过短消息
if content.len() < 10 {
return;
}
let response = self.generate_response(content);
if let Err(e) = message.reply(&ctx.api, &ctx.token, &response).await {
eprintln!("发送分析响应失败: {}", e);
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
频率限制和垃圾邮件保护
为文本响应实现基本的频率限制。
rust
use botrs::{Client, Context, EventHandler, Intents, Message, Ready, Token};
use std::collections::HashMap;
use std::time::{Duration, Instant};
struct RateLimitedHandler {
last_response: HashMap<String, Instant>,
cooldown: Duration,
}
impl RateLimitedHandler {
fn new(cooldown_seconds: u64) -> Self {
Self {
last_response: HashMap::new(),
cooldown: Duration::from_secs(cooldown_seconds),
}
}
fn can_respond(&mut self, user_id: &str) -> bool {
let now = Instant::now();
if let Some(&last_time) = self.last_response.get(user_id) {
if now.duration_since(last_time) < self.cooldown {
return false;
}
}
self.last_response.insert(user_id.to_string(), now);
true
}
}
#[async_trait::async_trait]
impl EventHandler for RateLimitedHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("频率限制机器人 {} 已准备就绪!", ready.user.username);
}
async fn message_create(&mut self, ctx: Context, message: Message) {
if message.is_from_bot() {
return;
}
if let (Some(content), Some(author)) = (&message.content, &message.author) {
// 检查频率限制
if !self.can_respond(&author.id) {
return; // 如果用户被频率限制,则静默忽略
}
// 带频率限制的简单回声
let response = format!("回显(频率限制):{}", content);
if let Err(e) = message.reply(&ctx.api, &ctx.token, &response).await {
eprintln!("发送频率限制响应失败: {}", e);
}
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let token = Token::new("your_app_id", "your_secret");
let intents = Intents::default().with_public_guild_messages();
let handler = RateLimitedHandler::new(5); // 5 秒冷却时间
let mut client = Client::new(token, intents, handler, true)?;
client.start().await?;
Ok(())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
错误处理
健壮的错误处理
为文本消息操作实现全面的错误处理。
rust
use botrs::{BotError, Client, Context, EventHandler, Intents, Message, Ready, Token};
struct RobustHandler;
impl RobustHandler {
async fn safe_reply(&self, ctx: &Context, message: &Message, content: &str) -> Result<(), BotError> {
match message.reply(&ctx.api, &ctx.token, content).await {
Ok(_) => {
println!("成功发送回复");
Ok(())
}
Err(BotError::Http(status)) => {
eprintln!("HTTP 错误 {}:发送消息失败", status);
Err(BotError::Http(status))
}
Err(BotError::RateLimit(retry_after)) => {
eprintln!("频率限制,{}秒后重试", retry_after);
// 可以在这里实现重试逻辑
Err(BotError::RateLimit(retry_after))
}
Err(e) => {
eprintln!("其他错误: {}", e);
Err(e)
}
}
}
}
#[async_trait::async_trait]
impl EventHandler for RobustHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("健壮机器人 {} 已准备就绪!", ready.user.username);
}
async fn message_create(&self, ctx: Context, message: Message) {
if message.is_from_bot() {
return;
}
if let Some(content) = &message.content {
// 验证消息内容
if content.len() > 2000 {
let _ = self.safe_reply(&ctx, &message, "消息太长!请保持在2000个字符以内。").await;
return;
}
if content.trim().is_empty() {
return; // 忽略空消息
}
// 处理消息
let response = format!("已处理:{}", content);
let _ = self.safe_reply(&ctx, &message, &response).await;
}
}
async fn error(&self, error: BotError) {
eprintln!("处理器错误: {}", error);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
最佳实践
性能考虑
rust
use botrs::{Client, Context, EventHandler, Intents, Message, Ready, Token};
use tokio::sync::Semaphore;
use std::sync::Arc;
struct PerformantHandler {
// 限制并发消息处理
semaphore: Arc<Semaphore>,
}
impl PerformantHandler {
fn new(max_concurrent: usize) -> Self {
Self {
semaphore: Arc::new(Semaphore::new(max_concurrent)),
}
}
async fn process_message(&self, ctx: Context, message: Message) {
// 获取处理许可
let _permit = self.semaphore.acquire().await.unwrap();
if let Some(content) = &message.content {
// 模拟处理时间
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
let response = format!("已处理:{}", content);
if let Err(e) = message.reply(&ctx.api, &ctx.token, &response).await {
eprintln!("回复失败: {}", e);
}
}
}
}
#[async_trait::async_trait]
impl EventHandler for PerformantHandler {
async fn ready(&self, _ctx: Context, ready: Ready) {
println!("高性能机器人 {} 已准备就绪!", ready.user.username);
}
async fn message_create(&self, ctx: Context, message: Message) {
if message.is_from_bot() {
return;
}
// 为并发处理生成任务
let handler = Arc::new(self.clone());
tokio::spawn(async move {
handler.process_message(ctx, message).await;
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
这份全面的指南涵盖了在 BotRS 中处理文本消息的基本模式,从基本的回声机器人到具有错误处理和性能优化的复杂命令系统。