feat: telegram bot for moderation (allow/deny commands)

This commit is contained in:
Lewis Wynne 2026-04-09 12:39:45 +01:00
parent 660c02d63f
commit 37d2a2b99e
2 changed files with 87 additions and 1 deletions

68
src/telegram.rs Normal file
View file

@ -0,0 +1,68 @@
use std::path::PathBuf;
use teloxide::prelude::*;
use tokio::sync::mpsc::Receiver;
use crate::entries::{self, Entry, Status};
/// Send a notification to Telegram about a new entry.
async fn notify(bot: &Bot, chat_id: ChatId, entry: &Entry) {
let short_id = entry.id.split('-').last().unwrap_or(&entry.id);
let text = format!(
"New guestbook entry:\n\nName: {}\nWebsite: {}\n\n{}\n\n/allow_{}\n/deny_{}",
entry.meta.name, entry.meta.website, entry.body, short_id, short_id
);
if let Err(e) = bot.send_message(chat_id, &text).await {
tracing::error!("failed to send telegram message: {e}");
}
}
/// Listen for new entries on the channel and send Telegram notifications.
pub async fn notification_task(bot: Bot, chat_id: ChatId, mut rx: Receiver<Entry>) {
while let Some(entry) = rx.recv().await {
notify(&bot, chat_id, &entry).await;
}
}
/// Run the Telegram bot that listens for /allow_ and /deny_ commands.
pub async fn bot_task(bot: Bot, chat_id: ChatId, entries_dir: PathBuf) {
let handler = Update::filter_message().endpoint(
|bot: Bot, msg: Message, entries_dir: PathBuf, chat_id: ChatId| async move {
let text = msg.text().unwrap_or("");
// Only respond to the configured chat
if msg.chat.id != chat_id {
return respond(());
}
if let Some(id) = text.strip_prefix("/allow_") {
match entries::set_status(&entries_dir, id, Status::Approved) {
Ok(name) => {
bot.send_message(msg.chat.id, format!("Approved ({name})."))
.await?;
}
Err(e) => {
bot.send_message(msg.chat.id, e).await?;
}
}
} else if let Some(id) = text.strip_prefix("/deny_") {
match entries::set_status(&entries_dir, id, Status::Denied) {
Ok(name) => {
bot.send_message(msg.chat.id, format!("Denied ({name})."))
.await?;
}
Err(e) => {
bot.send_message(msg.chat.id, e).await?;
}
}
}
Ok(())
},
);
Dispatcher::builder(bot, handler)
.dependencies(dptree::deps![entries_dir, chat_id])
.build()
.dispatch()
.await;
}