42个版本
新版本 0.0.46 | 2024年8月16日 |
---|---|
0.0.44 | 2024年7月14日 |
0.0.36 | 2024年1月6日 |
0.0.35 | 2023年12月30日 |
0.0.3 | 2022年11月8日 |
#205 在 Web编程 中
每月219 次下载
5.5MB
128K SLoC
botapi-rs
自动生成的Telegram机器人API封装器。生成基于serde的全异步Telegram机器人API封装器。
这个库旨在超越仅仅生成HTTP封装器,更干净地将Telegram类型和方法映射到Rust设计模式,同时保持低开销并避免不必要的克隆或分配。
方法尽可能利用泛型参数、切片和原始类型,并且所有API类型都提供易于使用的构建器模式接口。
特性
- 自动与最新版本的Telegram API保持同步
- 最小化冗余和样板代码
- 全异步支持,与tokio兼容
- 支持长轮询和Webhooks
- 支持大文件上传和本地API服务器
- 自动生成文档
- 自动处理Telegram的速率限制
将botapi添加到您的项目中
您可以通过cargo-edit添加
cargo add botapi
或编辑您的Cargo.toml文件以包含
[dependencies]
botapi = { version = "0.0.40", features = [] }
有一个可用的功能: rhai
,该功能为所有Telegram类型启用rhai脚本支持(更多信息请参见下文)。普通用户不需要此功能。
选择示例
一些您可以使用此库执行的操作示例,这不是完整的文档,只是作为介绍。
创建新的客户端
机器人API客户端允许低成本的Clone,以便移动到其他作用域。客户端支持可选的"auto-wait"功能,允许在处理带有retry_after参数的速率限制错误时进行延迟自动重试。如果您有自己的429错误处理方法,可以禁用此功能。
let client = BotBuilder::new("12345:mytoken")
.unwrap()
.auto_wait(true) // Automatically retry after 429 errors
.build();
let handle = client.clone();
async move {
// async context, cloned client is moved
let me = handle.get_me().await.unwrap();
}
简单回复机器人
回复所有消息为 不要哭!!
// Setup long polling with default updates
let longpoller = LongPoller::new(&client, None);
let mut upd = longpoller.get_updates().await;
while let Some(update) = upd.next().await {
if let UpdateExt::Message(message) = update {
client.build_send_message(message.chat.id, "Not cry!")
.reply_parameters(
&ReplyParametersBuilder::new(message.message_id).build(),
)
.build()
.await?;
}
}
反高级机器人
对聊天成员加入和禁止高级用户做出反应
let updates = vec![
"update_id",
"message",
"edited_message",
"channel_post",
"edited_channel_post",
"inline_query",
"chosen_inline_result",
"callback_query",
"shipping_query",
"pre_checkout_query",
"poll",
"poll_answer",
"my_chat_member",
"chat_member",
"chat_join_request",
]
.into_iter()
.map(|v| v.to_owned())
.collect();
// Setup long polling with all updates including joins
let longpoller = LongPoller::new(&client, Some(updates));
let mut upd = longpoller.get_updates().await;
while let Some(update) = upd.next().await {
if let UpdateExt::ChatMember(member) = update {
TG.client()
.build_ban_chat_member(member.chat.id, member.from.id)
.build()
.await?;
client.build_send_message(member.chat.id, "Begone, blue star!")
.build()
.await?;
}
}
设置Webhooks
注意: 这需要支持TLS的反向代理。此库不支持TLS。
Webhook::new(
&client,
BotUrl::Host("https://bothook.tsinghua.edu.cn"),
false,
([0, 0, 0, 0], 8080).into(),
None,
)
.get_updates()
.await?
.for_each_concurrent(
None,
|update| async move { log::info!("update {:?}", update); },
)
.await
BoxWrapper<Unbox<T>>是什么意思?
警告:以下是一些技术内容。TL;DR:在大多数情况下,包括所有botapi函数,您可以像处理BoxWrapper<Box<T>>和BoxWrapper<Unbox<T>>一样处理T。如果您需要从BoxWrapper获取T,请使用.into()或传递引用。这不是错误,这是必需的。请相信我!
技术解释
由于Rust不允许递归类型(包含自身实例的类型),除非有像Rc
由于这个库是自动生成的,我们需要使用Box
目前存在的一些针对此问题的近似算法,其运行时间在多项式时间内,但会导致类型在添加新的Telegram类型时被Box化,这会导致每次Telegram版本发布时API更改被破坏。我提出的解决方案是将任何JSON类型(即可能导致循环的类型)泛化到Box
关于.noskip()方法的处理是什么情况?
API类型T上的T.noskip()方法从T构建了一个NoSkipT类型。这个类型与其原始类型serde兼容(这意味着你可以序列化一个T,然后将其反序列化为NoSkipT),但它不使用任何字段的#[serde)]["Option::is_none""
属性。
你需要这样做是因为如果你使用像rmp_serde这样的序列化器,它将结构体序列化为数组。当serde使用数组时跳过字段会导致反序列化时出错。这是一个边缘情况,但有其用处。
Rhai绑定
Rhai是一种简单的嵌入式脚本语言,旨在允许与Rust类型进行一些互操作性。由于rhai需要编写一些样板代码才能与某些Rust类型(如枚举)交互,因此这个库也可以选择性地自动生成所有Telegram类型的rhai样板代码。是的,这需要与botapi库本身集成,因为需要自动生成。
由于这会增加相当大的二进制大小,因此默认情况下是禁用的,受rhai
功能的控制。启用rhai支持不会以任何方式影响性能,除了二进制大小。
启用rhai功能
在Cargo.toml
中启用
[dependencies]
botapi = { version = "0.0.40", features = [ "rhai" ] }
初始化rhai引擎
为了在rhai环境中与botapi类型交互,必须将每个所需类型注册到rhai引擎中。这可以一次处理所有类型,也可以一次处理一个类型。
let mut engine = Engine::new();
// Register all types
botapi::gen_types::rhai_helpers::setup_all_rhai(&mut engine);
// Register just one type (recursively registers all fields)
Message::setup_rhai(&mut engine);
rhai绑定的示例用法
botapi类型中的大多数字段都可以直接供rhai脚本访问。主要的例外是枚举,它们通过类似以下API公开
从botapi::gen_types::Message
类型检查枚举字段示例中,匿名函数的m
参数假定是botapi::gen_types::Message
|m| if m.from.value.is_premium.value {
"no premium users allowed"
} else {
"nice"
}
检查botapi::gen_types::Message
是否具有文本的示例
// check if value is a unit
|m| m.text.value == ()
// check if enum_type is None
|m m.text.enum_type == "None"
构建文档
文档将与库本身自动生成。文档可在 https://docs.rs/botapi 上实时查看,或者您可以通过运行以下命令在离线状态下查看文档:
cargo build
cargo doc --open
其他链接
https://github.com/fmeef/dijkstra_bot:一个使用此库的模块化Telegram机器人框架。
https://github.com/PaulSonOfLars/telegram-bot-api-spec:本项目的灵感来源和API规范的来源。(感谢Paul!)
依赖项
~11-24MB
~365K SLoC