-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add beep beep bot for custom webhooks (#25)
- Loading branch information
Showing
8 changed files
with
260 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
use notifine::get_webhook_url_or_create; | ||
use std::env; | ||
use teloxide::dispatching::dialogue; | ||
use teloxide::dispatching::dialogue::InMemStorage; | ||
use teloxide::dptree::case; | ||
use teloxide::filter_command; | ||
use teloxide::prelude::*; | ||
use teloxide::types::{ChatMemberKind, ParseMode}; | ||
use teloxide::utils::command::BotCommands; | ||
|
||
type MyDialogue = Dialogue<State, InMemStorage<State>>; | ||
|
||
pub async fn run_beep_bot() { | ||
log::info!("Starting bot..."); | ||
|
||
let bot = create_new_bot(); | ||
|
||
let command_handler = | ||
filter_command::<Command, _>().branch(case![Command::Start].endpoint(handle_start_command)); | ||
|
||
let message_handler = dptree::entry() | ||
.branch( | ||
Update::filter_message() | ||
.branch(command_handler) | ||
.branch(case![State::ReceiveBotReview].endpoint(handle_bot_review)) | ||
.branch(dptree::endpoint(handle_new_message)), | ||
) | ||
.branch(Update::filter_my_chat_member().endpoint(handle_my_chat_member_update)); | ||
|
||
let handler = | ||
dialogue::enter::<Update, InMemStorage<State>, State, _>().branch(message_handler); | ||
|
||
Dispatcher::builder(bot, handler) | ||
.dependencies(dptree::deps![InMemStorage::<State>::new()]) | ||
.enable_ctrlc_handler() | ||
.build() | ||
.dispatch() | ||
.await; | ||
|
||
log::info!("Closing bot... Goodbye!"); | ||
} | ||
|
||
#[derive(Clone, Default)] | ||
pub enum State { | ||
#[default] | ||
Start, | ||
ReceiveBotReview, | ||
} | ||
|
||
#[derive(BotCommands, Clone)] | ||
#[command( | ||
rename_rule = "lowercase", | ||
description = "These commands are supported:" | ||
)] | ||
enum Command { | ||
#[command(description = "starts!")] | ||
Start, | ||
} | ||
|
||
// async fn handle_start_command(bot: Bot, dialogue: MyDialogue, msg: Message) -> ResponseResult<()> { | ||
// log::info!("Start command received"); | ||
// bot.send_message(msg.chat.id, "What do you think about our bot?") | ||
// .await?; | ||
// dialogue.update(State::ReceiveBotReview).await.unwrap(); | ||
// Ok(()) | ||
// } | ||
|
||
async fn handle_start_command(msg: Message) -> ResponseResult<()> { | ||
log::info!("Start command received"); | ||
handle_new_chat_and_start_command( | ||
msg.chat | ||
.id | ||
.to_string() | ||
.parse::<i64>() | ||
.expect("Error parsing chat id"), | ||
) | ||
.await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn handle_bot_review(bot: Bot, dialogue: MyDialogue, msg: Message) -> ResponseResult<()> { | ||
log::info!("Bot review received"); | ||
let chat_id = msg.chat.id; | ||
// let message = msg.text().unwrap(); | ||
bot.send_message(chat_id, "Thanks.").await?; | ||
dialogue.exit().await.unwrap(); | ||
|
||
Ok(()) | ||
} | ||
|
||
async fn handle_new_message(message: Message) -> ResponseResult<()> { | ||
let chat_id = message.chat.id.0; | ||
|
||
if let Some(text) = message.text() { | ||
log::info!("Received message from {}: {}", chat_id, text); | ||
} | ||
|
||
log::warn!("{:#?}", message.via_bot); | ||
Ok(()) | ||
} | ||
|
||
async fn handle_my_chat_member_update(update: ChatMemberUpdated) -> ResponseResult<()> { | ||
let chat_id = update.chat.id.0; | ||
|
||
log::info!( | ||
"Received chat member update from {}: {:#?} {:#?}", | ||
chat_id, | ||
update.old_chat_member, | ||
update.new_chat_member | ||
); | ||
|
||
// bot joining a group or a new private chat | ||
if update.old_chat_member.kind == ChatMemberKind::Left | ||
&& update.new_chat_member.kind == ChatMemberKind::Member | ||
{ | ||
handle_new_chat_and_start_command(chat_id).await? | ||
} | ||
|
||
log::info!( | ||
"Received a chat member update from {}: {:?}", | ||
chat_id, | ||
update.new_chat_member | ||
); | ||
Ok(()) | ||
} | ||
|
||
pub async fn send_message_beep(chat_id: i64, message: String) -> ResponseResult<()> { | ||
log::info!("Sending message to {}: {}", chat_id, message); | ||
let bot = create_new_bot(); | ||
|
||
let chat_id = ChatId(chat_id); | ||
|
||
bot.send_message(chat_id, message) | ||
.disable_web_page_preview(true) | ||
.parse_mode(ParseMode::Html) | ||
.send() | ||
.await?; | ||
Ok(()) | ||
} | ||
|
||
async fn handle_new_chat_and_start_command(telegram_chat_id: i64) -> ResponseResult<()> { | ||
let webhook_url = get_webhook_url_or_create(telegram_chat_id); | ||
|
||
let message = if webhook_url.0.is_empty() { | ||
log::error!("Error creating or getting webhook: {:?}", webhook_url); | ||
"Hi there!\ | ||
Our bot is curently has some problems \ | ||
Please create a github issue here: \ | ||
https://github.com/mhkafadar/notifine/issues/new" | ||
.to_string() | ||
} else { | ||
format!( | ||
"Hi there! \ | ||
To setup notifications for \ | ||
this chat your custom app, \ | ||
add this \ | ||
URL: {}/beep/{}", | ||
env::var("WEBHOOK_BASE_URL").expect("WEBHOOK_BASE_URL must be set"), | ||
webhook_url.0 | ||
) | ||
}; | ||
|
||
send_message_beep(telegram_chat_id, message).await?; | ||
|
||
if webhook_url.1 { | ||
// send message to admin on telegram and inform new install | ||
send_message_beep( | ||
env::var("TELEGRAM_ADMIN_CHAT_ID") | ||
.expect("TELEGRAM_ADMIN_CHAT_ID must be set") | ||
.parse::<i64>() | ||
.expect("Error parsing TELEGRAM_ADMIN_CHAT_ID"), | ||
format!("New beep webhook added: {telegram_chat_id}"), | ||
) | ||
.await?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
fn create_new_bot() -> Bot { | ||
Bot::new(env::var("BEEP_TELOXIDE_TOKEN").expect("BEEP_TELOXIDE_TOKEN must be set")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod beep_bot; | ||
pub mod github_bot; | ||
pub mod gitlab_bot; | ||
pub mod trello_bot; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use crate::bots::beep_bot::send_message_beep; | ||
use actix_web::{post, web, HttpRequest, HttpResponse, Responder}; | ||
use notifine::{find_chat_by_id, find_webhook_by_webhook_url}; | ||
use std::env; | ||
|
||
#[post("/beep/{webhook_url}")] | ||
pub async fn handle_beep_webhook( | ||
webhook_url: web::Path<String>, | ||
req: HttpRequest, | ||
body: web::Bytes, | ||
) -> impl Responder { | ||
let event_name = "beep"; | ||
log::info!("Event name: {:?}", event_name); | ||
// create a message from request body. json stringified | ||
let message = String::from_utf8(body.to_vec()).unwrap(); | ||
log::info!("Message: {}", message); | ||
// if message is empty, then we don't need to send it to telegram | ||
if message.is_empty() { | ||
return HttpResponse::Ok(); | ||
} | ||
|
||
let webhook_url = &webhook_url; | ||
log::info!("webhook_url: {}", webhook_url); | ||
let webhook = find_webhook_by_webhook_url(webhook_url); | ||
|
||
if webhook.is_none() { | ||
log::error!("Webhook not found"); | ||
return HttpResponse::NotFound(); | ||
} | ||
let webhook = webhook.unwrap(); | ||
|
||
// log chat_id | ||
log::info!("Webhook: {}", webhook.webhook_url); | ||
let chat_id = webhook.chat_id.expect("Chat id must be set"); | ||
log::info!("Chat id: {}", chat_id); | ||
|
||
let chat = find_chat_by_id(webhook.chat_id.expect("Chat id must be set")); | ||
|
||
if chat.is_none() { | ||
log::error!("Chat not found"); | ||
return HttpResponse::NotFound(); | ||
} | ||
let chat = chat.unwrap(); | ||
|
||
send_message_beep( | ||
chat.telegram_id | ||
.parse::<i64>() | ||
.expect("CHAT_ID must be an integer"), | ||
message, | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
// send message to telegram admin | ||
send_message_beep( | ||
env::var("TELEGRAM_ADMIN_CHAT_ID") | ||
.expect("TELEGRAM_ADMIN_CHAT_ID must be set") | ||
.parse::<i64>() | ||
.expect("Error parsing TELEGRAM_ADMIN_CHAT_ID"), | ||
format!("Event: {event_name:?}, Chat id: {chat_id}"), | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
log::info!("bot sent message"); | ||
HttpResponse::Ok() // | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod http_server; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod gitlab; | ||
pub mod beep; | ||
pub mod github; | ||
pub mod gitlab; | ||
pub mod trello; |