char/phoebe
git clone https://git.t4t.associates/char/phoebe
602a042
main
1use phoebe::{ 2 attachments:: attachment_to_url, 3 mid_chat::{ ChatAttachment , ChatMessage , ChatMessageEdit , ChatMessageReference , ChatReference }, 4 prelude:: * , 5}; 6 7use serenity::{ http:: AttachmentType , model:: prelude:: * , prelude:: * }; 8 9use crate ::{ chat_conv, discord_reference, DiscordService }; 10 11async fn get_or_create_webhook_for_channel ( 12discord : & mut DiscordService , 13channel : & ChannelId , 14) ->Option < Webhook > { 15if let Ok ( webhooks) = channel. webhooks ( & discord. ctx ). await { 16for webhookin webhooks{ 17if matches! ( webhook. name . as_deref (), Some ( "Phoebe" )) { 18return Some ( webhook); 19} 20} 21} 22 23if let Ok ( webhook) = channel. create_webhook ( & discord. ctx , "Phoebe" ). await { 24return Some ( webhook); 25} 26 27None 28} 29 30async fn create_webhook_reply_embeds ( 31discord_ctx : & Context , 32channel_id : ChannelId , 33message_id : MessageId , 34) ->Vec < serde_json:: Value > { 35if let Ok ( replied_message) = channel_id. message ( discord_ctx, message_id). await { 36let replied_author_name =format! ( 37"{} ↩️" , 38 replied_message 39. author_nick ( discord_ctx) 40. await 41. as_ref () 42. unwrap_or ( & replied_message. author . name ) 43); 44 45let reply_description =format! ( 46"**[Reply to:]({})**\n{}" , 47 replied_message. id . link ( 48 channel_id, 49 discord_ctx 50. cache 51. guild_channel ( channel_id) 52. await 53. map ( |gc| gc. guild_id ) 54), 55& replied_message. content 56); 57 58return vec! [ Embed :: fake ( |e|{ 59 e. author ( |a|{ 60 a. icon_url ( 61& replied_message 62. author 63. static_avatar_url () 64. unwrap_or_else ( || replied_message. author . default_avatar_url ()), 65) 66. name ( replied_author_name) 67}) 68. description ( reply_description) 69})]; 70} 71 72vec! [] 73} 74 75async fn create_discord_attachments ( source : &' _ ChatMessage ) ->Vec < AttachmentType < ' _ >> { 76 source 77. attachments 78. iter () 79. map ( |a|match a{ 80ChatAttachment :: Online { 81 url, 82media_type : Some ( media_type), 83} =>{ 84if media_type. starts_with ( "image/" ) { 85AttachmentType :: Image ( url) 86} else { 87todo! ( "Handle non-image online attachment" ) 88} 89} 90ChatAttachment :: Online { ..} =>{ 91todo! ( "Handle online attachment with no media_type" ) 92} 93ChatAttachment :: InMemory { 94 file_name, data, .. 95} =>AttachmentType :: Bytes { 96filename : file_name. clone (), 97data : data. into (), 98}, 99}) 100. collect () 101} 102 103pub async fn send_discord_message ( 104discord : & mut DiscordService , 105source : & ChatMessage , 106destination_channel : ChatReference , 107) ->Result < ChatMessageReference > { 108let channel_id = destination_channel. id . parse ::< ChannelId >() ?; 109 110let discord_reply =if let Some ( reply) =& source. replying { 111if let Some ( reply_ref) = discord 112. lookup_message ( reply, |r| future:: ready ( r. channel == destination_channel)) 113. await 114{ 115assert_eq! ( reply_ref. channel . service , "discord" ); 116let channel_id: ChannelId = reply_ref. channel . id . parse (). unwrap (); 117let message_id: MessageId = reply_ref. message_id . parse ::< u64 >(). unwrap (). into (); 118Some (( channel_id, message_id)) 119} else { 120None 121} 122} else { 123None 124}; 125 126let files =create_discord_attachments ( source). await ; 127 128if let Some ( webhook) =get_or_create_webhook_for_channel ( & mut * discord, & channel_id). await { 129let reply_embeds =if let Some (( channel, message)) = discord_reply{ 130create_webhook_reply_embeds ( & discord. ctx , channel, message). await 131} else { 132vec! [] 133}; 134 135let avatar_url =attachment_to_url ( & source. author . avatar ). await ; 136 137if let Some ( sent_message) = webhook 138. execute ( & discord. ctx , true , |w|{ 139 w. content ( chat_conv:: format ( & source. content )) 140. username ( format! ( 141"{} ({})" , 142& source. author . display_name , & source. author . reference . service 143)) 144. avatar_url ( & avatar_url) 145. embeds ( reply_embeds) 146. add_files ( files. clone ()) 147}) 148. await ? 149{ 150return Ok ( ChatMessageReference :: new ( 151discord_reference ( sent_message. channel_id ), 152 sent_message. id , 153)); 154} 155} 156 157let content =format! ( 158"{} ({}): {}" , 159 source. author . display_name , 160 source. author . reference . service , 161 chat_conv:: format ( & source. content ) 162); 163 164let sent_message = channel_id 165. send_message ( & discord. ctx , move |m|{ 166let m = m. content ( content); 167let m = m. add_files ( files); 168if let Some ( reply) = discord_reply{ 169 m. reference_message ( reply) 170} else { 171 m 172} 173}) 174. await ?; 175 176Ok ( ChatMessageReference :: new ( 177discord_reference ( sent_message. channel_id ), 178 sent_message. id , 179)) 180} 181 182pub async fn delete_discord_message ( 183discord : & mut DiscordService , 184message : & ChatMessageReference , 185) ->Result <()> { 186let channel_id = message. channel . id . parse ::< ChannelId >() ?; 187let message_id: MessageId = message. message_id . parse ::< u64 >() ?. into (); 188 189if let Some ( webhook) =get_or_create_webhook_for_channel ( & mut * discord, & channel_id). await { 190if webhook 191. delete_message ( & discord. ctx , message_id) 192. await 193. is_ok () 194{ 195return Ok (()); 196} 197} 198 199 channel_id. delete_message ( & discord. ctx , message_id). await ?; 200Ok (()) 201} 202 203pub async fn edit_discord_message ( 204discord : & mut DiscordService , 205prev_origin : & ChatMessageReference , 206edit : & ChatMessageEdit , 207) ->Result <()> { 208let channel_id = prev_origin. channel . id . parse ::< ChannelId >() ?; 209let message_id: MessageId = prev_origin. message_id . parse ::< u64 >() ?. into (); 210 211if let Some ( webhook) =get_or_create_webhook_for_channel ( & mut * discord, & channel_id). await { 212if webhook 213. edit_message ( & discord. ctx , message_id, |w|{ 214 w. content ( chat_conv:: format ( & edit. new_content )) 215}) 216. await 217. is_ok () 218{ 219return Ok (()); 220} 221} 222 223let content =format! ( 224"{} ({}): {}" , 225 edit. author . display_name , 226 edit. author . reference . service , 227 chat_conv:: format ( & edit. new_content ) 228); 229 230 channel_id 231. edit_message ( & discord. ctx , message_id, |m| m. content ( content)) 232. await ?; 233 234Ok (()) 235}