frc/src/botdriver.rs

126 lines
3.8 KiB
Rust

use std::pin::Pin;
use futures::Future;
use telexide::{
api::types::SendMessage,
client::{self, ClientBuilder},
model::{self, MessageContent, MessageEntity, UpdateContent},
};
use typemap::Key;
use crate::browser::BrowserHandle;
pub struct BotDriver {
client: client::Client,
listen_user: String,
}
struct BotConfig {
handle: BrowserHandle,
listen_user: String,
}
struct BotConfigKey {}
impl Key for BotConfigKey {
type Value = BotConfig;
}
fn telegram_handler(
ctx: client::Context,
upd: model::Update,
) -> Pin<Box<dyn Future<Output = ()> + Send>> {
let config = if let Some(cfg) = ctx.data.read().get::<BotConfigKey>() {
BotConfig {
handle: cfg.handle.clone(),
listen_user: cfg.listen_user.clone(),
}
} else {
panic!("no config");
};
if let UpdateContent::Message(msg) = upd.content {
if let Some(user) = msg.from {
if let Some(name) = user.username {
if name.to_lowercase() == config.listen_user.to_lowercase() {
if let MessageContent::Text { content, entities } = msg.content {
if let Some(url_text) = get_url(content, entities) {
return Box::pin(async move {
match config.handle.go_to(url_text.as_str()).await {
Err(err) => {
println!("failed opening url [{}]: {}", url_text, err)
}
_ => {}
};
});
}
}
} else {
return Box::pin(async move {
match ctx
.api
.send_message(SendMessage::new(
msg.chat.get_id(),
"we don't listen to you",
))
.await
{
Err(err) => println!("failed writing not listening: {}", err),
_ => {}
};
});
}
}
}
}
Box::pin(async {})
}
impl BotDriver {
pub fn new(token: String, listen_user: String) -> Self {
Self {
client: ClientBuilder::new()
.set_token(&token)
.add_handler_func(telegram_handler)
.build(),
listen_user: listen_user,
}
}
pub async fn listen_and_paste(&mut self, handle: BrowserHandle) -> Result<(), anyhow::Error> {
let listen_to = self.listen_user.clone();
let config = BotConfig {
handle: handle,
listen_user: listen_to,
};
// Scope it so it instantly drops. Might instantly drop anyway cause I don't use the result. Ah well.
{
self.client.data.write().insert::<BotConfigKey>(config);
}
self.client.start().await?;
println!("telegram bot finished early");
Ok(())
}
}
fn get_url(text: String, entities: Vec<MessageEntity>) -> Option<String> {
match entities
.into_iter()
.filter(|ent| match ent {
MessageEntity::Url(_) => true,
_ => false,
})
.take(1)
.collect::<Vec<MessageEntity>>()
.first()
{
Some(def) => match def {
MessageEntity::Url(url_def) => Some(
text.chars()
.skip(url_def.offset as usize)
.take(url_def.length as usize)
.collect(),
),
_ => None,
},
_ => None,
}
}