use anyhow::Result;
use async_trait::async_trait;
use sea_orm::DatabaseConnection;
use tracing::{info, warn};
use robson_core::plugin::{Gateway, MessageEvent, MessageEventKind};
use crate::entities::subscriber::Model as Subscriber;
pub struct WebhookGateway {
db: DatabaseConnection,
}
impl WebhookGateway {
pub fn new(db: DatabaseConnection) -> Self {
Self { db }
}
pub async fn connect_and_migrate(db_path: &str) -> Result<Self> {
let db = crate::db::connect_and_migrate(db_path).await?;
Ok(Self { db })
}
}
#[async_trait]
impl Gateway for WebhookGateway {
fn name(&self) -> &'static str {
"webhook"
}
async fn send(&self, msg: MessageEvent) -> Result<()> {
if !matches!(msg.kind, MessageEventKind::Delivered) {
return Ok(());
}
if !msg.channel_id.is_empty() {
let client = reqwest::Client::new();
let payload = serde_json::json!({ "content": msg.content });
match client.post(&msg.channel_id).json(&payload).send().await {
Ok(resp) => {
info!(url = %msg.channel_id, status = %resp.status(), "webhook callback sent")
}
Err(e) => warn!(url = %msg.channel_id, error = %e, "webhook callback failed"),
}
return Ok(());
}
let subscribers = Subscriber::find_all(&self.db).await?;
if subscribers.is_empty() {
return Ok(());
}
let client = reqwest::Client::new();
let payload = serde_json::json!({ "content": msg.content });
for sub in subscribers {
match client.post(&sub.callback_url).json(&payload).send().await {
Ok(resp) => {
info!(url = %sub.callback_url, status = %resp.status(), "webhook callback sent")
}
Err(e) => warn!(url = %sub.callback_url, error = %e, "webhook callback failed"),
}
}
Ok(())
}
async fn start(&self, _db: DatabaseConnection) -> Result<()> {
Ok(())
}
}