Skip to main content

chat_system/messengers/
webhook.rs

1//! Generic webhook messenger — HTTP POST implementation.
2
3use crate::{Message, Messenger};
4use anyhow::Result;
5use async_trait::async_trait;
6use reqwest::Client;
7use serde_json::json;
8
9pub struct WebhookMessenger {
10    name: String,
11    url: String,
12    client: Client,
13    connected: bool,
14}
15
16impl WebhookMessenger {
17    pub fn new(name: impl Into<String>, url: impl Into<String>) -> Self {
18        Self {
19            name: name.into(),
20            url: url.into(),
21            client: Client::new(),
22            connected: false,
23        }
24    }
25}
26
27#[async_trait]
28impl Messenger for WebhookMessenger {
29    fn name(&self) -> &str {
30        &self.name
31    }
32
33    fn messenger_type(&self) -> &str {
34        "webhook"
35    }
36
37    async fn initialize(&mut self) -> Result<()> {
38        self.connected = true;
39        Ok(())
40    }
41
42    async fn send_message(&self, recipient: &str, content: &str) -> Result<String> {
43        let body = json!({
44            "recipient": recipient,
45            "content": content,
46            "timestamp": chrono::Utc::now().timestamp(),
47        });
48
49        let resp = self.client.post(&self.url).json(&body).send().await?;
50
51        if resp.status().is_success() {
52            Ok(format!("webhook:{}", chrono::Utc::now().timestamp_millis()))
53        } else {
54            let status = resp.status();
55            let text = resp.text().await.unwrap_or_default();
56            anyhow::bail!("Webhook POST failed {}: {}", status, text);
57        }
58    }
59
60    async fn receive_messages(&self) -> Result<Vec<Message>> {
61        Ok(Vec::new())
62    }
63
64    fn is_connected(&self) -> bool {
65        self.connected
66    }
67
68    async fn disconnect(&mut self) -> Result<()> {
69        self.connected = false;
70        Ok(())
71    }
72}