@@ -319,96 +319,109 @@ async def restore_from_snooze(self):
319319 f"[UNSNOOZE] Tried to restore thread { self .id } but snooze_data is None or not a dict."
320320 )
321321 return False
322- # Now safe to access self.snooze_data
322+
323+ # Cache some fields we need later (before we potentially clear snooze_data)
323324 snoozed_by = self .snooze_data .get ("snoozed_by" )
324325 snooze_command = self .snooze_data .get ("snooze_command" )
326+
325327 guild = self .bot .modmail_guild
326328 behavior = (self .bot .config .get ("snooze_behavior" ) or "delete" ).lower ()
329+
327330 # Determine original category; fall back to main_category_id if original missing
328331 orig_category = (
329- guild .get_channel (self .snooze_data [ "category_id" ] )
332+ guild .get_channel (self .snooze_data . get ( "category_id" ) )
330333 if self .snooze_data .get ("category_id" )
331334 else None
332335 )
333336 if not isinstance (orig_category , discord .CategoryChannel ):
334337 main_cat_id = self .bot .config .get ("main_category_id" )
335338 orig_category = guild .get_channel (int (main_cat_id )) if main_cat_id else None
336339
340+ # Default: assume we'll need to recreate
341+ channel : typing .Optional [discord .TextChannel ] = None
342+
343+ # If move-behavior and channel still exists, move it back and restore overwrites
337344 if behavior == "move" and isinstance (self .channel , discord .TextChannel ):
338- # Channel exists but is snoozed in another category; move back
339345 try :
340346 await self .channel .edit (
341347 category = orig_category ,
342348 position = self .snooze_data .get ("position" , self .channel .position ),
343349 reason = "Thread unsnoozed/restored" ,
344350 )
345- # After moving back, restore original overwrites captured at snooze time
351+ # Restore original overwrites captured at snooze time
346352 try :
347- overwrites = {}
353+ ow_map : dict = {}
348354 for role_id , perm_values in self .snooze_data .get ("overwrites" , []):
349355 target = guild .get_role (role_id ) or guild .get_member (role_id )
350- if target :
351- overwrites [target ] = discord .PermissionOverwrite (** perm_values )
352- if overwrites :
353- await self .channel .edit (overwrites = overwrites , reason = "Restore original overwrites" )
356+ if target is None :
357+ continue
358+ ow_map [target ] = discord .PermissionOverwrite (** perm_values )
359+ if ow_map :
360+ await self .channel .edit (overwrites = ow_map , reason = "Restore original overwrites" )
354361 except Exception as e :
355362 logger .warning ("Failed to restore original overwrites on unsnooze: %s" , e )
356363
357364 channel = self .channel
358365 except Exception as e :
359366 logger .warning ("Failed to move snoozed channel back, recreating: %s" , e )
360367 channel = None
361- else :
362- channel = None
363368
369+ # If we couldn't move back (or behavior=delete), recreate the channel
364370 if channel is None :
365- # Recreate channel and replay messages (delete behavior or move fallback)
366- overwrites = {}
367- for role_id , perm_values in self .snooze_data ["overwrites" ]:
368- role = guild .get_role (role_id ) or guild .get_member (role_id )
369- if role :
370- overwrites [role ] = discord .PermissionOverwrite (** perm_values )
371- channel = await guild .create_text_channel (
372- name = self .snooze_data ["name" ],
373- category = orig_category ,
374- topic = self .snooze_data ["topic" ],
375- slowmode_delay = self .snooze_data ["slowmode_delay" ],
376- overwrites = overwrites ,
377- nsfw = self .snooze_data ["nsfw" ],
378- position = self .snooze_data ["position" ],
379- reason = "Thread unsnoozed/restored" ,
380- )
381- self ._channel = channel
382- else :
383- self ._channel = channel
371+ try :
372+ ow_map : dict = {}
373+ for role_id , perm_values in self .snooze_data .get ("overwrites" , []):
374+ target = guild .get_role (role_id ) or guild .get_member (role_id )
375+ if target is None :
376+ continue
377+ ow_map [target ] = discord .PermissionOverwrite (** perm_values )
378+
379+ channel = await guild .create_text_channel (
380+ name = self .snooze_data .get ("name" ) or f"thread-{ self .id } " ,
381+ category = orig_category ,
382+ overwrites = ow_map or None ,
383+ position = self .snooze_data .get ("position" ),
384+ topic = self .snooze_data .get ("topic" ),
385+ slowmode_delay = self .snooze_data .get ("slowmode_delay" ) or 0 ,
386+ nsfw = bool (self .snooze_data .get ("nsfw" )),
387+ reason = "Thread unsnoozed/restored (recreated)" ,
388+ )
389+ self ._channel = channel
390+ except Exception :
391+ logger .error ("Failed to recreate thread channel during unsnooze." , exc_info = True )
392+ return False
384393 # Strictly restore the log_key from snooze_data (never create a new one)
385394 self .log_key = self .snooze_data .get ("log_key" )
395+
386396 # Replay messages only if we re-created the channel (delete behavior or move fallback)
387397 if behavior != "move" or (behavior == "move" and not self .snooze_data .get ("moved" , False )):
388- for msg in self .snooze_data [ "messages" ] :
398+ for msg in self .snooze_data . get ( "messages" , []) :
389399 try :
390400 author = self .bot .get_user (msg ["author_id" ]) or await self .bot .get_or_fetch_user (
391401 msg ["author_id" ]
392402 )
393403 except discord .NotFound :
394404 author = None
395- content = msg ["content" ]
405+
406+ content = msg .get ("content" )
396407 embeds = [discord .Embed .from_dict (e ) for e in msg .get ("embeds" , []) if e ]
397408 attachments = msg .get ("attachments" , [])
398- msg_type = msg . get ( "type" )
399- # Only send if there is content, embeds, or attachments
409+
410+ # Only send if there is something to send
400411 if not content and not embeds and not attachments :
401- continue # Skip empty messages
412+ continue
413+
402414 author_is_mod = msg ["author_id" ] not in [r .id for r in self .recipients ]
403415 if author_is_mod :
404- # Prioritize stored author_name from snooze data over fetched user
416+ # Prefer stored author_name/avatar
405417 username = (
406418 msg .get ("author_name" )
407419 or (getattr (author , "name" , None ) if author else None )
408420 or "Unknown"
409421 )
410422 user_id = msg .get ("author_id" )
411423 if embeds :
424+ # Ensure embeds show author details
412425 embeds [0 ].set_author (
413426 name = f"{ username } ({ user_id } )" ,
414427 icon_url = msg .get ("author_avatar" )
@@ -418,21 +431,22 @@ async def restore_from_snooze(self):
418431 else None
419432 ),
420433 )
421- await channel .send (
422- embeds = embeds , allowed_mentions = discord .AllowedMentions .none ()
423- )
434+ await channel .send (embeds = embeds , allowed_mentions = discord .AllowedMentions .none ())
424435 else :
425- formatted = (
426- f"**{ username } ({ user_id } )**: { content } "
427- if content
428- else f"**{ username } ({ user_id } )**"
429- )
430- await channel .send (
431- formatted , allowed_mentions = discord .AllowedMentions .none ()
432- )
436+ # Build a non-empty message; include attachment URLs if no content
437+ header = f"**{ username } ({ user_id } )**"
438+ if content :
439+ formatted = f"{ header } : { content } "
440+ elif attachments :
441+ formatted = header + "\n " + "\n " .join (attachments )
442+ else :
443+ formatted = header
444+ await channel .send (formatted , allowed_mentions = discord .AllowedMentions .none ())
433445 else :
446+ # Recipient message: include attachment URLs if content is empty
447+ content_to_send = content if content else ("\n " .join (attachments ) if attachments else None )
434448 await channel .send (
435- content = content or None ,
449+ content = content_to_send ,
436450 embeds = embeds or None ,
437451 allowed_mentions = discord .AllowedMentions .none (),
438452 )
0 commit comments