cortexfs_channels/platform/
discord.rs1use serde_json::json;
2
3use super::{ChannelCodec, OutboundRequest, object, participant, scalar, text};
4use crate::{
5 ChannelError, ChannelId, ConversationId, InboundMessage, MessageTarget, OutboundMessage,
6};
7
8#[derive(Clone, Copy, Debug, Default)]
10pub struct DiscordCodec;
11
12impl ChannelCodec for DiscordCodec {
13 fn channel(&self) -> ChannelId {
14 ChannelId::from_static("discord")
15 }
16
17 fn decode(&self, payload: &str) -> Result<Option<InboundMessage>, ChannelError> {
18 let root = object(payload)?;
19 if root
20 .get("author")
21 .and_then(|author| author.get("bot"))
22 .and_then(serde_json::Value::as_bool)
23 == Some(true)
24 {
25 return Ok(None);
26 }
27 let id = scalar(root.get("id"), "id")?;
28 let conversation = ConversationId::new(scalar(root.get("channel_id"), "channel_id")?)?;
29 Ok(Some(InboundMessage {
30 id,
31 target: MessageTarget {
32 channel: self.channel(),
33 conversation,
34 thread: root
35 .get("thread_id")
36 .map(|value| scalar(Some(value), "thread_id"))
37 .transpose()?,
38 reply_to: root
39 .get("message_reference")
40 .and_then(|reference| reference.get("message_id"))
41 .map(|value| scalar(Some(value), "message_reference.message_id"))
42 .transpose()?,
43 },
44 sender: participant(
45 root.get("author"),
46 scalar(
47 root.get("author").and_then(|value| value.get("id")),
48 "author.id",
49 )?,
50 ),
51 body: text(root.get("content"))?,
52 timestamp_ms: None,
53 metadata: std::collections::BTreeMap::new(),
54 }))
55 }
56
57 fn encode(&self, message: &OutboundMessage) -> Result<OutboundRequest, ChannelError> {
58 message.body.validate()?;
59 if !message.body.attachments.is_empty() {
60 return Err(ChannelError::Unsupported(
61 "discord media attachments".to_owned(),
62 ));
63 }
64 let mut fields = serde_json::Map::new();
65 fields.insert("content".to_owned(), json!(message.body.text));
66 fields.insert("allowed_mentions".to_owned(), json!({ "parse": [] }));
67 if let Some(thread) = message.target.thread.as_deref() {
68 fields.insert("thread_id".to_owned(), json!(thread));
69 }
70 Ok(OutboundRequest {
71 method: "POST".to_owned(),
72 path: "webhook".to_owned(),
73 content_type: "application/json".to_owned(),
74 body: serde_json::Value::Object(fields).to_string(),
75 headers: std::collections::BTreeMap::new(),
76 })
77 }
78}