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 reference: ChatReference, | ||||||
|     pub display_name: String, |     pub display_name: String, | ||||||
|     pub display_color: Option<[u8; 3]>, |     pub display_color: Option<[u8; 3]>, | ||||||
|  |     pub avatar_url: String, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| mod content; | mod content; | ||||||
|  |  | ||||||
|  | @ -10,3 +10,4 @@ sqlx = { version = "0.5", features = ["runtime-tokio-native-tls", "sqlite"] } | ||||||
| tracing = "0.1" | tracing = "0.1" | ||||||
| tokio = { version = "1", features = ["full"] } | tokio = { version = "1", features = ["full"] } | ||||||
| discord_message_format = { git = "https://git.lavender.software/charlotte/discord-message-format.git" }  | 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), |             reference: discord_reference(message.author.id), | ||||||
|             display_name, |             display_name, | ||||||
|             display_color, |             display_color, | ||||||
|  |             avatar_url: message | ||||||
|  |                 .author | ||||||
|  |                 .static_avatar_url() | ||||||
|  |                 .unwrap_or_else(|| message.author.default_avatar_url()), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,25 +1,82 @@ | ||||||
| use phoebe::{ | use phoebe::{ | ||||||
|     mid_chat::{ChatMessage, ChatMessageReference, ChatReference}, |     mid_chat::{ChatMessage, ChatMessageReference, ChatReference}, | ||||||
|     prelude::{future, Result}, |     prelude::*, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use serenity::{model::prelude::*, prelude::*}; | use serenity::{model::prelude::*, prelude::*}; | ||||||
| 
 | 
 | ||||||
| use crate::{chat_conv, discord_reference, DiscordService}; | 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( | pub async fn send_discord_message( | ||||||
|     discord: &mut DiscordService, |     discord: &mut DiscordService, | ||||||
|     source: &ChatMessage, |     source: &ChatMessage, | ||||||
|     destination_channel: ChatReference, |     destination_channel: ChatReference, | ||||||
| ) -> Result<ChatMessageReference> { | ) -> Result<ChatMessageReference> { | ||||||
|     // TODO: If we have a webhook we should use the webhook
 |  | ||||||
| 
 |  | ||||||
|     let channel_id = destination_channel.id.parse::<ChannelId>()?; |     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 { |     let discord_reply = if let Some(reply) = &source.replying { | ||||||
|         if let Some(reply_ref) = discord |         if let Some(reply_ref) = discord | ||||||
|  | @ -37,6 +94,38 @@ pub async fn send_discord_message( | ||||||
|         None |         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 |     let sent_message = channel_id | ||||||
|         .send_message(&discord.ctx, move |m| { |         .send_message(&discord.ctx, move |m| { | ||||||
|             let m = m.content(content); |             let m = m.content(content); | ||||||
|  | @ -47,7 +136,6 @@ pub async fn send_discord_message( | ||||||
|             } |             } | ||||||
|         }) |         }) | ||||||
|         .await?; |         .await?; | ||||||
| 
 |  | ||||||
|     Ok(ChatMessageReference::new( |     Ok(ChatMessageReference::new( | ||||||
|         discord_reference(sent_message.channel_id), |         discord_reference(sent_message.channel_id), | ||||||
|         sent_message.id, |         sent_message.id, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue