1+ #![ forbid( clippy:: expect_used, clippy:: unwrap_used) ]
2+
13use base64:: { Engine , prelude:: BASE64_STANDARD } ;
24use dashmap:: DashMap ;
35use reqwest:: header:: CONTENT_TYPE ;
@@ -22,6 +24,8 @@ use serenity::{
2224 } ,
2325} ;
2426
27+ use crate :: Error ;
28+
2529pub struct DmSupportStatus {
2630 webhook_cache : DashMap < ChannelId , Webhook > ,
2731}
@@ -50,16 +54,22 @@ impl DmSupportStatus {
5054 return ;
5155 }
5256
53- if message. guild_id . is_none ( ) {
54- self . handle_dm_message ( ctx, message) . await ;
57+ let msg_id = message. id ;
58+
59+ let res = if message. guild_id . is_none ( ) {
60+ self . handle_dm_message ( ctx, message) . await
5561 } else {
56- self . handle_guild_message ( ctx, message) . await ;
62+ self . handle_guild_message ( ctx, message) . await
63+ } ;
64+
65+ if let Err ( e) = res {
66+ error ! ( %msg_id, "got error while handing DM support: {}" , e) ;
5767 }
5868 }
5969
60- async fn handle_dm_message ( & self , ctx : Context , message : Message ) {
61- let channel = self . get_or_create_channel ( & ctx, & message. author ) . await ;
62- let hook = self . get_webhook ( & ctx, & channel. id ) . await ;
70+ async fn handle_dm_message ( & self , ctx : Context , message : Message ) -> Result < ( ) , Error > {
71+ let channel = self . get_or_create_channel ( & ctx, & message. author ) . await ? ;
72+ let hook = self . get_webhook ( & ctx, & channel. id ) . await ? ;
6373
6474 let mut webhook_execute = ExecuteWebhook :: default ( )
6575 . avatar_url ( message. author . face ( ) )
@@ -81,8 +91,7 @@ impl DmSupportStatus {
8191 attachment. url . as_str ( ) ,
8292 attachment. filename . to_string ( ) ,
8393 )
84- . await
85- . expect ( "failed to handle message attachments" ) ,
94+ . await ?,
8695 ) ;
8796 }
8897 webhook_execute = webhook_execute. files ( attachments) ;
@@ -100,34 +109,35 @@ impl DmSupportStatus {
100109
101110 if let Err ( e) = resp {
102111 warn ! ( "failed to send message to webhook: {:?}" , e) ;
103- let _ = message
112+ message
104113 . reply ( & ctx. http , format ! ( "failed to send message: {}" , e) )
105- . await ;
114+ . await ? ;
106115 }
116+
117+ Ok ( ( ) )
107118 }
108119
109- async fn handle_guild_message ( & self , ctx : Context , message : Message ) {
120+ async fn handle_guild_message ( & self , ctx : Context , message : Message ) -> Result < ( ) , Error > {
110121 let config = scripty_config:: get_config ( ) ;
111122 if message. guild_id != Some ( GuildId :: new ( config. dm_support . guild_id ) ) {
112- return ;
123+ return Ok ( ( ) ) ;
113124 }
114125 let message_channel = message
115126 . channel ( & ctx)
116- . await
117- . expect ( "failed to get message channel" )
127+ . await ?
118128 . guild ( )
119- . expect ( "should be in guild" ) ;
129+ . ok_or_else ( Error :: expected_guild ) ? ;
120130
121- let category = get_forwarding_category ( & ctx) . await ;
131+ let category = get_forwarding_category ( & ctx) . await ? ;
122132 if message_channel. parent_id != Some ( category. id ) {
123- return ;
133+ return Ok ( ( ) ) ;
124134 }
125135
126136 let user_id = match message_channel. base . name . parse :: < u64 > ( ) {
127137 Ok ( id) => id,
128138 Err ( e) => {
129139 warn ! ( "failed to parse user id from channel name: {:?}" , e) ;
130- return ;
140+ return Ok ( ( ) ) ;
131141 }
132142 } ;
133143
@@ -163,27 +173,33 @@ impl DmSupportStatus {
163173 )
164174 . await ;
165175 }
176+
177+ Ok ( ( ) )
166178 }
167179
168- async fn get_or_create_channel ( & self , ctx : & Context , user : & User ) -> GuildChannel {
180+ async fn get_or_create_channel (
181+ & self ,
182+ ctx : & Context ,
183+ user : & User ,
184+ ) -> Result < GuildChannel , Error > {
169185 let config = scripty_config:: get_config ( ) ;
170- let category = get_forwarding_category ( ctx) . await ;
186+ let category = get_forwarding_category ( ctx) . await ? ;
171187 let guild_id = GuildId :: new ( config. dm_support . guild_id ) ;
172188
173189 let user_id_str = user. id . to_string ( ) ;
174190
175191 let channel = {
176192 ctx. cache
177193 . guild ( guild_id)
178- . expect ( "failed to get guild" )
194+ . ok_or_else ( Error :: expected_guild ) ?
179195 . channels
180196 . iter ( )
181197 . find ( |c| c. parent_id == Some ( category. id ) && c. base . name == user_id_str)
182198 . cloned ( )
183199 } ;
184200
185201 if let Some ( channel) = channel {
186- return channel;
202+ return Ok ( channel) ;
187203 }
188204
189205 let channel = guild_id
@@ -193,35 +209,26 @@ impl DmSupportStatus {
193209 . category ( category. id )
194210 . kind ( ChannelType :: Text ) ,
195211 )
196- . await
197- . expect ( "failed to create channel" ) ;
212+ . await ?;
198213
199214 let user_face_url = user. face ( ) ;
200- let resp = reqwest:: get ( user_face_url)
201- . await
202- . expect ( "failed to fetch url" ) ;
215+ let resp = reqwest:: get ( user_face_url) . await ?;
203216 let content_type = resp
204217 . headers ( )
205218 . get ( CONTENT_TYPE )
206- . expect ( "expected Content-Type header" )
207- . to_str ( )
208- . expect ( "not ASCII string" ) ;
219+ . ok_or_else ( || Error :: custom ( "expected Content-Type header" . to_string ( ) ) ) ?
220+ . to_str ( ) ?;
209221
210222 let hook = channel
211223 . create_webhook (
212224 & ctx. http ,
213- CreateWebhook :: new ( user. tag ( ) ) . avatar (
214- ImageData :: from_base64 ( format ! (
215- "data:{};base64,{}" ,
216- content_type. to_ascii_lowercase( ) ,
217- BASE64_STANDARD
218- . encode( resp. bytes( ) . await . expect( "failed to download image bytes" ) )
219- ) )
220- . expect ( "should always be valid image data" ) ,
221- ) ,
225+ CreateWebhook :: new ( user. tag ( ) ) . avatar ( ImageData :: from_base64 ( format ! (
226+ "data:{};base64,{}" ,
227+ content_type. to_ascii_lowercase( ) ,
228+ BASE64_STANDARD . encode( resp. bytes( ) . await ?)
229+ ) ) ?) ,
222230 )
223- . await
224- . expect ( "failed to create webhook" ) ;
231+ . await ?;
225232 self . webhook_cache . insert ( channel. id , hook) ;
226233
227234 if let Err ( e) = self . handle_opening ( ctx, user. id ) . await {
@@ -231,11 +238,10 @@ impl DmSupportStatus {
231238 & ctx. http ,
232239 CreateMessage :: default ( ) . content ( format ! ( "failed to handle opening: {}" , e) ) ,
233240 )
234- . await
235- . expect ( "failed to send message" ) ;
241+ . await ?;
236242 }
237243
238- channel
244+ Ok ( channel)
239245 }
240246
241247 async fn handle_opening ( & self , ctx : & Context , user : UserId ) -> serenity:: Result < ( ) > {
@@ -254,45 +260,39 @@ impl DmSupportStatus {
254260 . map ( |_| ( ) )
255261 }
256262
257- async fn get_webhook ( & self , ctx : & Context , channel : & ChannelId ) -> Webhook {
263+ async fn get_webhook ( & self , ctx : & Context , channel : & ChannelId ) -> Result < Webhook , Error > {
258264 let hook = self . webhook_cache . get ( channel) . map ( |x| x. clone ( ) ) ;
259265 if let Some ( hook) = hook {
260- return hook;
266+ return Ok ( hook) ;
261267 }
262268
263- if let Some ( hook) = channel
264- . webhooks ( & ctx. http )
265- . await
266- . expect ( "error fetching hooks" )
267- . pop ( )
268- {
269- return hook;
269+ if let Some ( hook) = channel. webhooks ( & ctx. http ) . await ?. pop ( ) {
270+ return Ok ( hook) ;
270271 }
271272
272273 let hook = channel
273274 . create_webhook ( & ctx. http , CreateWebhook :: new ( "Scripty" ) )
274- . await
275- . expect ( "failed to create webhook" ) ;
275+ . await ?;
276276 self . webhook_cache . insert ( * channel, hook. clone ( ) ) ;
277- hook
277+ Ok ( hook)
278278 }
279279
280- pub async fn close_ticket ( & self , ctx : & Context , channel : GuildChannel ) {
280+ pub async fn close_ticket ( & self , ctx : & Context , channel : GuildChannel ) -> Result < ( ) , Error > {
281281 let config = scripty_config:: get_config ( ) ;
282282 if channel. base . guild_id != GuildId :: new ( config. dm_support . guild_id ) {
283- return ;
283+ return Ok ( ( ) ) ;
284284 }
285285
286- let category = get_forwarding_category ( ctx) . await ;
286+ let category = get_forwarding_category ( ctx) . await ? ;
287287 if channel. parent_id != Some ( category. id ) {
288- return ;
288+ return Ok ( ( ) ) ;
289289 }
290290
291291 let user_id = match channel. base . name . parse :: < u64 > ( ) {
292292 Ok ( id) => UserId :: new ( id) ,
293293 Err ( e) => {
294294 warn ! ( "failed to parse user id from channel name: {:?}" , e) ;
295- return ;
295+ return Ok ( ( ) ) ;
296296 }
297297 } ;
298298
@@ -313,15 +313,17 @@ impl DmSupportStatus {
313313
314314 self . webhook_cache . remove ( & channel. id ) ;
315315
316- let _ = channel
316+ channel
317317 . delete ( & ctx. http , Some ( "DM support ticket closed" ) )
318- . await ;
318+ . await ?;
319+
320+ Ok ( ( ) )
319321 }
320322}
321323
322- async fn get_forwarding_category ( ctx : & Context ) -> GuildChannel {
324+ async fn get_forwarding_category ( ctx : & Context ) -> Result < GuildChannel , Error > {
323325 ChannelId :: new ( scripty_config:: get_config ( ) . dm_support . forwarding_category )
324326 . to_guild_channel ( & ctx, None )
325327 . await
326- . expect ( "failed to get forwarding category" )
328+ . map_err ( Error :: from )
327329}
0 commit comments