Skip to content

Commit 1d611aa

Browse files
committed
feat: migrate thread create to async factory method
resolves #13 where log keys were not set upon a Thread object being created for an existing thread
1 parent 45bb880 commit 1d611aa

2 files changed

Lines changed: 54 additions & 32 deletions

File tree

cogs/modmail.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2682,7 +2682,6 @@ async def cog_load(self):
26822682

26832683
@tasks.loop(seconds=10)
26842684
async def snooze_auto_unsnooze(self):
2685-
logger.debug("snooze_auto_unsnooze")
26862685
now = datetime.now(timezone.utc)
26872686
snoozed = await self.bot.api.logs.find(
26882687
{"snoozed": True, "open": True, "snooze_until": {"$lte": now}}

core/thread.py

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,31 @@
4141

4242
class Thread:
4343
"""Represents a discord Modmail thread"""
44+
class _SnoozeMessageData(typing.TypedDict, total=False):
45+
author_id: int
46+
content: str
47+
attachments: list[str]
48+
embeds: list[dict[str, typing.Any]]
49+
created_at: str
50+
type: typing.Optional[str]
51+
author_name: typing.Optional[str]
52+
author_avatar: typing.Optional[str]
53+
54+
class _SnoozeData(typing.TypedDict, total=False):
55+
category_id: typing.Optional[int]
56+
position: int
57+
name: str
58+
topic: typing.Optional[str]
59+
slowmode_delay: int
60+
nsfw: bool
61+
overwrites: list[tuple[int, dict[str, typing.Any]]]
62+
messages: list["Thread._SnoozeMessageData"]
63+
snoozed_by: typing.Optional[int]
64+
snooze_command: typing.Optional[str]
65+
log_key: typing.Optional[str]
66+
snooze_start: datetime
67+
snooze_for: typing.Any
68+
moved: bool
4469

4570
def __init__(
4671
self,
@@ -74,37 +99,35 @@ def __init__(
7499
# --- SNOOZE STATE ---
75100
self.snoozed: bool = False # True if thread is snoozed
76101
self.log_key: str | None = None # Ensure log_key always exists
77-
class _SnoozeMessageData(typing.TypedDict, total=False):
78-
author_id: int
79-
content: str
80-
attachments: list[str]
81-
embeds: list[dict[str, typing.Any]]
82-
created_at: str
83-
type: typing.Optional[str]
84-
author_name: typing.Optional[str]
85-
author_avatar: typing.Optional[str]
86-
87-
class _SnoozeData(typing.TypedDict, total=False):
88-
category_id: typing.Optional[int]
89-
position: int
90-
name: str
91-
topic: typing.Optional[str]
92-
slowmode_delay: int
93-
nsfw: bool
94-
overwrites: list[tuple[int, dict[str, typing.Any]]]
95-
messages: list[_SnoozeMessageData]
96-
snoozed_by: typing.Optional[int]
97-
snooze_command: typing.Optional[str]
98-
log_key: typing.Optional[str]
99-
snooze_start: datetime
100-
snooze_for: typing.Any
101-
moved: bool
102-
103-
self.snooze_data: typing.Optional[_SnoozeData] = None # Dict with channel/category/position/messages for restoration
102+
103+
104+
self.snooze_data: typing.Optional[self._SnoozeData] = None # Dict with channel/category/position/messages for restoration
104105
# --- UNSNOOZE COMMAND QUEUE ---
105106
self._unsnoozing = False # True while restore_from_snooze is running
106107
self._command_queue = [] # Queue of (ctx, command) tuples; close commands always last
107108

109+
110+
@classmethod
111+
async def create(cls,
112+
manager: "ThreadManager",
113+
recipient: typing.Union[discord.Member, discord.User, int],
114+
channel: discord.DMChannel | discord.TextChannel | None = None,
115+
other_recipients: typing.List[typing.Union[discord.Member, discord.User]] | None = None,
116+
):
117+
"""Async factory method to create and initialize a Thread instance."""
118+
self = cls(manager, recipient, channel, other_recipients)
119+
# Perform any async initialization here if needed
120+
if channel is not None:
121+
log = await manager.bot.api.get_log(str(channel.id))
122+
logger.debug(log)
123+
if log and "key" in log:
124+
self._key = log["key"]
125+
self.log_key = log["key"]
126+
logger.debug(f"set key to {log['key']}")
127+
return self
128+
129+
130+
108131
def __repr__(self):
109132
return f'Thread(recipient="{self.recipient or self.id}", channel={self.channel.id}, other_recipients={len(self._other_recipients)})'
110133

@@ -2603,9 +2626,9 @@ async def _find_from_channel(self, channel):
26032626
other_recipients.append(other_recipient)
26042627

26052628
if recipient is None:
2606-
thread = Thread(self, user_id, channel, other_recipients)
2629+
thread = await Thread.create(self, user_id, channel, other_recipients)
26072630
else:
2608-
self.cache[user_id] = thread = Thread(self, recipient, channel, other_recipients)
2631+
self.cache[user_id] = thread = await Thread.create(self, recipient, channel, other_recipients)
26092632
thread.ready = True
26102633

26112634
return thread
@@ -2644,7 +2667,7 @@ async def create(
26442667
)
26452668
)
26462669
await message.channel.send(embed=embed)
2647-
thread = Thread(self, recipient)
2670+
thread = await Thread.create(self, recipient)
26482671
thread.cancelled = True
26492672
return thread
26502673

@@ -2673,7 +2696,7 @@ async def create(
26732696
thread.close(closer=self.bot.user, silent=True, delete_channel=False)
26742697
)
26752698

2676-
thread = Thread(self, recipient)
2699+
thread = await Thread.create(self, recipient)
26772700

26782701
self.cache[recipient.id] = thread
26792702

0 commit comments

Comments
 (0)