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