3个版本
0.1.2 | 2023年1月30日 |
---|---|
0.1.1 | 2022年10月26日 |
0.1.0 | 2022年10月17日 |
#8 in #mt-proto
21KB
581 行
Teleser
基于grammers的Telegram MTProto 机器人框架,支持使用手机号码和机器人令牌登录
创建机器人
首先
从https://core.telegram.org/api/obtaining_api_id 获取api id
将teleser添加到依赖项
如果在中国大陆网络,添加代理功能是个好主意
teleser = { version = "0", features = ["proxy"] }
并且查看机器人模板源代码
主要
- 设置记录器
- 使用
tokio
异步运行时运行异步main
fn main() -> Result<()> {
init_tracing_subscriber();
return runtime::Builder::new_multi_thread()
.enable_all()
.max_blocking_threads(30)
.worker_threads(50)
.build()
.unwrap()
.block_on(async_main());
}
记录器
tracing_subscriber
来设置日志级别,您需要将"teleser_template"
修改为您自己的crate名称。
fn init_tracing_subscriber() {
tracing_subscriber::registry()
.with(
tracing_subscriber::fmt::layer()
.with_target(true)
.without_time(),
)
.with(
tracing_subscriber::filter::Targets::new()
.with_target("teleser", Level::DEBUG)
.with_target("teleser_template", Level::DEBUG),
)
.init();
}
异步_main
async fn async_main() -> Result<()> {
// Using `ClientBuilder` build a bot client
let client = Arc::new(
teleser::ClientBuilder::new()
// read api id from env (on build)
.with_api_id(env!("API_ID").parse()?)
// read api hash from env (on build)
.with_api_hash(env!("API_HASH").to_string())
// auth
.with_auth(Auth::AuthWithPhoneAndCode(Box::new(Input {}))
// load session file on startup
// save session to file teleser.session if login
.with_session_store(Box::new(FileSessionStore{
path: "teleser.session".to_string(),
}))
// modules
.with_modules(vec![raw_plugin::module(), proc_plugin::module()])
// connect to server via proxy url, like socks5://127.0.0.1:1080 (runtime)
// please delete this code if you not add feature named proxy
.with_init_params(match std::env::var("TELESER_PROXY") {
Ok(url) => {
let mut ip = InitParams::default();
ip.proxy_url = Some(url);
Some(ip)
}
Err(_) => Some(InitParams::default()),
})
.build()?,
);
//////////////////////////////////////
// can start some timer task like this
let copy_client = client.clone();
tokio::spawn(async move {
let lock = copy_client.inner_client.lock().await;
let ic = lock.clone();
drop(lock);
if let Some(_ic) = ic {
// _ic.send_message();
}
});
//////////////////////////////////////
// run client
teleser::run_client_and_reconnect(client).await?;
/////////////////////////////////////
Ok(())
}
输入
仅从控制台读取一行
pub struct Input {}
#[async_trait]
impl AuthWithPhoneAndCode for Input {
async fn input_phone(&self) -> Result<String> {
input("Input your phone number ( like +112345678 )")
}
async fn input_code(&self) -> Result<String> {
input("Input your device or sms code ( like 12345 )")
}
async fn input_password(&self) -> Result<String> {
input("Input your password")
}
}
fn input(tips: &str) -> Result<String> {
let mut s = String::new();
print!("{tips}: ");
let _ = stdout().flush();
stdin().read_line(&mut s)?;
if let Some('\n') = s.chars().next_back() {
s.pop();
}
if let Some('\r') = s.chars().next_back() {
s.pop();
}
Ok(s)
}
处理程序
此示例具有处理程序grammers Update::OnNewMessage
。您可以使用这些处理程序
new_message
/ message_edited
/ message_deleted
/ callback_query
/ inline_query
/ raw
但我无法在grammers上获取message_edited事件,只能获取原始数据。
use crate::Result;
use teleser::re_exports::grammers_client::types::Message;
use teleser::{new_message, Handler, InnerClient};
#[new_message]
async fn proc_new_message(_: &mut InnerClient, message: &Message) -> Result<bool> {
println!("PROC : A NEW MESSAGE : {}", message.text());
Ok(false)
}
pub(crate) fn module() -> Module {
Module {
id: "proc_new_message".to_owned(),
name: "proc_new_message".to_owned(),
handlers: vec![Handler {
id: "proc_new_message".to_owned(),
process: proc_new_message {}.into(),
}],
}
}
解析为处理程序
pub(crate) fn module() -> Module {
Module {
id: "proc_new_message".to_owned(),
name: "proc_new_message".to_owned(),
handlers: vec![proc_new_message {}.into()],
}
}
解析为处理程序
pub(crate) fn module() -> Module {
Module {
id: "proc_new_message".to_owned(),
name: "proc_new_message".to_owned(),
handlers: proc_new_message {}.into(),
}
}
解析为模块
pub(crate) fn module() -> Module {
proc_new_message {}.into()
}
手动编写处理程序
use teleser::re_exports::async_trait::async_trait;
use teleser::re_exports::grammers_client::types::Message;
use teleser::{Handler, InnerClient, NewMessageProcess, Process};
pub(crate) struct RawPlugin {}
#[async_trait]
impl NewMessageProcess for RawPlugin {
async fn handle(&self, _: &mut InnerClient, event: &Message) -> crate::Result<bool> {
println!("RAW : A NEW MESSAGE : {}", event.text());
Ok(false)
}
}
pub(crate) fn module() -> Module {
Module {
id: "RawPlugin".to_owned(),
name: "RawPlugin".to_owned(),
handlers: vec![Handler {
id: "RawPlugin".to_owned(),
process: Process::NewMessageProcess(Box::new(RawPlugin {})),
}],
}
}
依赖项
~9–23MB
~281K SLoC