Use a webhook for Discord if one is available
This commit is contained in:
parent
48c3eb1830
commit
6b07721ffa
4 changed files with 103 additions and 9 deletions
|
@ -6,6 +6,7 @@ pub struct ChatAuthor {
|
|||
pub reference: ChatReference,
|
||||
pub display_name: String,
|
||||
pub display_color: Option<[u8; 3]>,
|
||||
pub avatar_url: String,
|
||||
}
|
||||
|
||||
mod content;
|
||||
|
|
|
@ -10,3 +10,4 @@ sqlx = { version = "0.5", features = ["runtime-tokio-native-tls", "sqlite"] }
|
|||
tracing = "0.1"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
discord_message_format = { git = "https://git.lavender.software/charlotte/discord-message-format.git" }
|
||||
serde_json = "1.0.79"
|
||||
|
|
|
@ -32,6 +32,10 @@ impl DiscordHandler {
|
|||
reference: discord_reference(message.author.id),
|
||||
display_name,
|
||||
display_color,
|
||||
avatar_url: message
|
||||
.author
|
||||
.static_avatar_url()
|
||||
.unwrap_or_else(|| message.author.default_avatar_url()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,82 @@
|
|||
use phoebe::{
|
||||
mid_chat::{ChatMessage, ChatMessageReference, ChatReference},
|
||||
prelude::{future, Result},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use serenity::{model::prelude::*, prelude::*};
|
||||
|
||||
use crate::{chat_conv, discord_reference, DiscordService};
|
||||
|
||||
async fn get_or_create_webhook_for_channel(
|
||||
discord: &mut DiscordService,
|
||||
channel: &ChannelId,
|
||||
) -> Option<Webhook> {
|
||||
if let Ok(webhooks) = channel.webhooks(&discord.ctx).await {
|
||||
for webhook in webhooks {
|
||||
if matches!(webhook.name.as_deref(), Some("Phoebe")) {
|
||||
return Some(webhook);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(webhook) = channel.create_webhook(&discord.ctx, "Phoebe").await {
|
||||
return Some(webhook);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
async fn create_webhook_reply_embeds(
|
||||
discord_ctx: &Context,
|
||||
channel_id: ChannelId,
|
||||
message_id: MessageId,
|
||||
) -> Vec<serde_json::Value> {
|
||||
if let Ok(replied_message) = channel_id.message(discord_ctx, message_id).await {
|
||||
let replied_author_name = format!(
|
||||
"{} ↩️",
|
||||
replied_message
|
||||
.author_nick(discord_ctx)
|
||||
.await
|
||||
.as_ref()
|
||||
.unwrap_or(&replied_message.author.name)
|
||||
);
|
||||
|
||||
let reply_description = format!(
|
||||
"**[Reply to:]({})**\n{}",
|
||||
replied_message.id.link(
|
||||
channel_id,
|
||||
discord_ctx
|
||||
.cache
|
||||
.guild_channel(channel_id)
|
||||
.await
|
||||
.map(|gc| gc.guild_id)
|
||||
),
|
||||
&replied_message.content
|
||||
);
|
||||
|
||||
return vec![Embed::fake(|e| {
|
||||
e.author(|a| {
|
||||
a.icon_url(
|
||||
&replied_message
|
||||
.author
|
||||
.static_avatar_url()
|
||||
.unwrap_or_else(|| replied_message.author.default_avatar_url()),
|
||||
)
|
||||
.name(replied_author_name)
|
||||
})
|
||||
.description(reply_description)
|
||||
})];
|
||||
}
|
||||
|
||||
vec![]
|
||||
}
|
||||
|
||||
pub async fn send_discord_message(
|
||||
discord: &mut DiscordService,
|
||||
source: &ChatMessage,
|
||||
destination_channel: ChatReference,
|
||||
) -> Result<ChatMessageReference> {
|
||||
// TODO: If we have a webhook we should use the webhook
|
||||
|
||||
let channel_id = destination_channel.id.parse::<ChannelId>()?;
|
||||
let formatted_message = chat_conv::format(&source.content);
|
||||
let content = format!(
|
||||
"{} ({}): {}",
|
||||
source.author.display_name, source.author.reference.service, formatted_message
|
||||
);
|
||||
|
||||
let discord_reply = if let Some(reply) = &source.replying {
|
||||
if let Some(reply_ref) = discord
|
||||
|
@ -37,6 +94,38 @@ pub async fn send_discord_message(
|
|||
None
|
||||
};
|
||||
|
||||
if let Some(webhook) = get_or_create_webhook_for_channel(&mut *discord, &channel_id).await {
|
||||
let reply_embeds = if let Some((channel, message)) = discord_reply {
|
||||
create_webhook_reply_embeds(&discord.ctx, channel, message).await
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
if let Some(sent_message) = webhook
|
||||
.execute(&discord.ctx, true, |w| {
|
||||
w.content(chat_conv::format(&source.content))
|
||||
.username(format!(
|
||||
"{} ({})",
|
||||
&source.author.display_name, &source.author.reference.service
|
||||
))
|
||||
.avatar_url(&source.author.avatar_url)
|
||||
.embeds(reply_embeds)
|
||||
})
|
||||
.await?
|
||||
{
|
||||
return Ok(ChatMessageReference::new(
|
||||
discord_reference(sent_message.channel_id),
|
||||
sent_message.id,
|
||||
));
|
||||
}
|
||||
}
|
||||
let content = format!(
|
||||
"{} ({}): {}",
|
||||
source.author.display_name,
|
||||
source.author.reference.service,
|
||||
chat_conv::format(&source.content)
|
||||
);
|
||||
|
||||
let sent_message = channel_id
|
||||
.send_message(&discord.ctx, move |m| {
|
||||
let m = m.content(content);
|
||||
|
@ -47,7 +136,6 @@ pub async fn send_discord_message(
|
|||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(ChatMessageReference::new(
|
||||
discord_reference(sent_message.channel_id),
|
||||
sent_message.id,
|
||||
|
|
Loading…
Reference in a new issue