agentmux_srv/messaging/discord/
rest.rs1use crate::messaging::{EmbedField, MsgEmbed, OutboundMsg};
11
12use super::types::{DiscordEmbed, DiscordEmbedField, DiscordEmbedFooter, SendMessageBody};
13
14const DISCORD_API: &str = "https://discord.com/api/v10";
15
16pub async fn send_message(
18 http: &reqwest::Client,
19 token: &str,
20 channel_id: &str,
21 msg: &OutboundMsg,
22) -> Result<(), String> {
23 let embeds = msg.embed.as_ref().map(to_discord_embed).into_iter().collect();
24
25 let body = SendMessageBody {
26 content: msg.text.clone(),
27 embeds,
28 };
29
30 let url = format!("{}/channels/{}/messages", DISCORD_API, channel_id);
31 let resp = http
32 .post(&url)
33 .header("Authorization", format!("Bot {}", token))
34 .json(&body)
35 .send()
36 .await
37 .map_err(|e| format!("discord rest: http error: {e}"))?;
38
39 let status = resp.status();
40 if status == reqwest::StatusCode::TOO_MANY_REQUESTS {
41 let body = resp.text().await.unwrap_or_default();
42 return Err(format!("discord rest: rate limited: {body}"));
43 }
44 if !status.is_success() {
45 let body = resp.text().await.unwrap_or_default();
46 return Err(format!("discord rest: {status}: {body}"));
47 }
48
49 Ok(())
50}
51
52fn to_discord_embed(embed: &MsgEmbed) -> DiscordEmbed {
53 DiscordEmbed {
54 title: embed.title.clone(),
55 description: embed.description.clone(),
56 color: embed.color,
57 fields: embed.fields.iter().map(to_discord_field).collect(),
58 footer: embed
59 .footer
60 .as_ref()
61 .map(|t| DiscordEmbedFooter { text: t.clone() }),
62 }
63}
64
65fn to_discord_field(f: &EmbedField) -> DiscordEmbedField {
66 DiscordEmbedField {
67 name: f.name.clone(),
68 value: f.value.clone(),
69 inline: f.inline,
70 }
71}