use dotenvy::dotenv;
use open_lark::{
client::LarkClient,
core::{constants::AppType, trait_system::ExecutableBuilder},
service::im::v1::message::{CreateMessageRequestBody, MessageText, SendMessageTrait},
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv().ok();
env_logger::init();
let client = LarkClient::builder(
&std::env::var("APP_ID").expect("APP_ID is required"),
&std::env::var("APP_SECRET").expect("APP_SECRET is required"),
)
.with_app_type(AppType::SelfBuild)
.build();
println!("=== 飞书IM服务现代Builder模式示例 ===\n");
println!("📋 方式一: 传统API调用方式");
println!("适用于: 现有代码迁移、简单消息发送\n");
let text_message = MessageText::new("Hello from traditional API!")
.add_text(" 这是一条测试消息")
.at_user("all")
.build();
let message_body = CreateMessageRequestBody::builder()
.receive_id("test_chat_id") .msg_type(text_message.msg_type())
.content(text_message.content())
.uuid("demo-uuid-traditional")
.build();
let traditional_request = open_lark::service::im::v1::message::CreateMessageRequest::builder()
.receive_id_type("chat_id")
.request_body(message_body)
.build();
match client.im.v1.message.create(traditional_request, None).await {
Ok(message) => {
println!("✅ 传统方式消息发送成功");
println!(" 消息ID: {}", message.message_id);
println!(" 消息类型: {}", message.msg_type);
}
Err(e) => {
println!("❌ 传统方式发送失败: {e}");
println!(" 这可能是因为权限问题或测试环境限制");
}
}
println!();
println!("🏗️ 方式二: 现代Builder模式 (推荐)");
println!("适用于: 新代码开发、复杂消息构建、链式调用\n");
let rich_text = MessageText::new("📢 现代Builder模式消息:")
.text_line("✨ 支持链式调用")
.text_line("🔄 统一错误处理")
.text_line("⚡ 类型安全保证")
.at_user("all")
.build();
let modern_body = CreateMessageRequestBody::builder()
.receive_id("test_chat_id") .msg_type(rich_text.msg_type())
.content(rich_text.content())
.uuid("demo-uuid-modern")
.build();
let builder_result = open_lark::service::im::v1::message::CreateMessageRequest::builder()
.receive_id_type("chat_id")
.request_body(modern_body)
.execute(&client.im.v1.message)
.await;
match builder_result {
Ok(message) => {
println!("✅ Builder模式消息发送成功");
println!(" 消息ID: {}", message.message_id);
println!(" 消息类型: {}", message.msg_type);
println!(" 创建时间: {}", message.create_time);
println!("\n📜 尝试查询消息历史...");
let list_result = open_lark::service::im::v1::message::ListMessageRequest::builder()
.container_id_type("chat")
.container_id("test_chat_id") .page_size(10)
.sort_type("ByCreateTimeDesc")
.execute(&client.im.v1.message)
.await;
match list_result {
Ok(list_data) => {
println!("✅ 消息历史查询成功");
println!(" 消息数量: {}", list_data.items.len());
println!(" 是否有更多: {}", list_data.has_more);
for (i, msg) in list_data.items.iter().take(3).enumerate() {
println!(" 消息 {}: {} ({})", i + 1, msg.message_id, msg.msg_type);
}
}
Err(e) => {
println!("❌ 消息历史查询失败: {e}");
}
}
}
Err(e) => {
println!("❌ Builder模式发送失败: {e}");
println!(" 这可能是因为权限问题或测试环境限制");
}
}
println!();
println!("⚡ 方式三: Builder模式高级用法");
println!("展示: 条件构建、消息类型多样性、批量操作\n");
let message_types = [
("text", "这是文本消息"),
("text", "这是另一条文本消息 📝"),
("text", "最后一条测试消息 🎉"),
];
for (i, (_msg_type, content)) in message_types.iter().enumerate() {
let text_msg = MessageText::new(content)
.add_text(&format!(" [批量消息 {}]", i + 1))
.build();
let body = CreateMessageRequestBody::builder()
.receive_id("test_chat_id")
.msg_type(text_msg.msg_type())
.content(text_msg.content())
.uuid(format!("demo-batch-{i}"))
.build();
let message_builder = open_lark::service::im::v1::message::CreateMessageRequest::builder()
.receive_id_type("chat_id")
.request_body(body);
if i == 2 {
println!("📌 为最后一条消息添加特殊标识");
}
match message_builder.execute(&client.im.v1.message).await {
Ok(message) => {
println!("✅ 批量消息 {} 发送成功: {}", i + 1, message.message_id);
}
Err(e) => {
println!("❌ 批量消息 {} 发送失败: {}", i + 1, e);
}
}
}
println!();
println!("🛡️ 错误处理最佳实践");
println!("展示: 统一错误处理、详细错误信息、重试策略\n");
let invalid_body = CreateMessageRequestBody::builder()
.receive_id("") .msg_type("text")
.content("{\"text\":\"测试错误处理\"}")
.uuid("demo-error-test")
.build();
let error_demo_result = open_lark::service::im::v1::message::CreateMessageRequest::builder()
.receive_id_type("chat_id")
.request_body(invalid_body)
.execute(&client.im.v1.message)
.await;
match error_demo_result {
Ok(message) => {
println!("✅ 意外成功: {}", message.message_id);
}
Err(e) => {
println!("❌ 预期错误示例:");
println!(" 错误信息: {e}");
use open_lark::core::error::LarkAPIError;
match &e {
LarkAPIError::APIError { code, msg, .. } => {
println!(" 错误码: {code}");
println!(" 错误消息: {msg}");
match *code {
9499 => {
println!(" 💡 建议: 应用没有权限操作指定资源");
}
1061002 => {
println!(" 💡 建议: 参数错误,检查receive_id和消息格式");
}
400 => {
println!(" 💡 建议: 请求参数错误,检查消息体格式");
}
_ => {
println!(" 💡 建议: 检查网络连接和API配置");
}
}
}
LarkAPIError::DataError(msg) => {
println!(" 数据错误: {msg}");
println!(" 💡 建议: 检查消息内容和格式");
}
_ => {
println!(" 其他错误类型");
println!(" 💡 建议: 查看详细日志获取更多信息");
}
}
}
}
println!();
println!("📚 IM服务现代Builder模式最佳实践:");
println!("1. 🔄 消息发送推荐使用Builder模式,支持链式调用");
println!("2. 🔧 条件性构建适用于不同消息类型和接收者");
println!("3. 🛡️ 统一错误处理提供详细的消息发送错误诊断");
println!("4. ⚡ 类型安全保证确保消息格式正确");
println!("5. 🎯 批量消息发送时建议使用Builder模式提高代码复用性");
println!("6. 🔍 使用.execute()方法获得一致的异步执行体验");
println!("7. 📝 实际使用时记得使用真实的chat_id和receive_id");
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use open_lark::service::im::v1::message::{
CreateMessageRequestBody, MessageText, SendMessageTrait,
};
#[test]
fn test_im_builder_pattern_creation() {
let client = LarkClient::builder("test_app_id", "test_app_secret")
.with_app_type(AppType::SelfBuild)
.build();
let text_message = MessageText::new("Hello World!")
.add_text(" 测试消息")
.at_user("test_user")
.build();
assert_eq!(text_message.msg_type(), "text");
assert!(text_message.content().contains("Hello World!"));
let message_body = CreateMessageRequestBody::builder()
.receive_id("test_chat_id")
.msg_type(text_message.msg_type())
.content(text_message.content())
.uuid("test-uuid")
.build();
assert_eq!(message_body.receive_id, "test_chat_id");
assert_eq!(message_body.msg_type, "text");
assert_eq!(message_body.uuid, Some("test-uuid".to_string()));
let request_builder = open_lark::service::im::v1::message::CreateMessageRequest::builder()
.receive_id_type("chat_id")
.request_body(message_body);
let request = request_builder.build();
assert!(!request.api_req.body.is_empty());
}
#[test]
fn test_message_types() {
let text_msg = MessageText::new("Simple text").build();
assert_eq!(text_msg.msg_type(), "text");
let rich_text = MessageText::new("Rich text")
.text_line("with line break")
.at_user("user123")
.build();
assert_eq!(rich_text.msg_type(), "text");
assert!(rich_text.content().contains("\\n"));
assert!(rich_text.content().contains("user123"));
}
#[test]
fn test_list_message_builder() {
let list_request = open_lark::service::im::v1::message::ListMessageRequest::builder()
.container_id_type("chat")
.container_id("test_chat_id")
.page_size(20)
.sort_type("ByCreateTimeDesc")
.build();
assert!(list_request
.api_req
.query_params
.contains_key("container_id_type"));
assert!(list_request
.api_req
.query_params
.contains_key("container_id"));
assert!(list_request.api_req.query_params.contains_key("page_size"));
assert!(list_request.api_req.query_params.contains_key("sort_type"));
}
}