improve thread start & end markers
This commit is contained in:
parent
0e67e721d9
commit
1835cbcc17
4 changed files with 59 additions and 23 deletions
|
|
@ -102,7 +102,9 @@ async def migrate_messages(
|
|||
target_channel_id: str,
|
||||
after_message_id: int | None = None,
|
||||
progress_callback: Callable[[Dict[str, Any]], Awaitable[None]] | None = None,
|
||||
thread_id: str | None = None
|
||||
thread_id: str | None = None,
|
||||
parent_target_id: str | None = None,
|
||||
thread_name: str | None = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Migrate messages for a specific channel and returns detailed statistics."""
|
||||
stats = {
|
||||
|
|
@ -128,11 +130,7 @@ async def migrate_messages(
|
|||
|
||||
|
||||
# Skip system messages like "pinned a message", etc.
|
||||
# We treat thread_starter_message (type 21) as our thread marker.
|
||||
if msg.type == context.discord_reader.MESSAGE_TYPE_THREAD_STARTER:
|
||||
channel_name = msg.channel.name if msg.channel else "Unknown Thread"
|
||||
content = f"> <<< THREAD: **{channel_name}** >>>"
|
||||
elif msg.type not in [context.discord_reader.MESSAGE_TYPE_DEFAULT, context.discord_reader.MESSAGE_TYPE_REPLY]:
|
||||
if msg.type not in [context.discord_reader.MESSAGE_TYPE_DEFAULT, context.discord_reader.MESSAGE_TYPE_REPLY, context.discord_reader.MESSAGE_TYPE_THREAD_STARTER]:
|
||||
# If we are skipping the parent, we STILL need to check for a thread!
|
||||
if hasattr(msg, 'thread') and msg.thread:
|
||||
thread = msg.thread
|
||||
|
|
@ -146,7 +144,9 @@ async def migrate_messages(
|
|||
context=context,
|
||||
source_channel_id=thread.id,
|
||||
target_channel_id=target_channel_id,
|
||||
thread_id=str(thread.id)
|
||||
thread_id=str(thread.id),
|
||||
parent_target_id=None,
|
||||
thread_name=thread.name
|
||||
)
|
||||
stats["messages"] += thread_stats["messages"]
|
||||
stats["attachments"] += thread_stats["attachments"]
|
||||
|
|
@ -211,6 +211,14 @@ async def migrate_messages(
|
|||
else:
|
||||
logger.debug(f"Reply target Discord ID {msg.reference.message_id} not found in current session map.")
|
||||
|
||||
# If this is the FIRST thread message and we have a parent_target_id, force it as reply to the starter
|
||||
if not reply_to_fluxer_id and parent_target_id and stats["messages"] == 0:
|
||||
reply_to_fluxer_id = parent_target_id
|
||||
|
||||
# Prepend thread marker to the first message of the thread
|
||||
if thread_name and stats["messages"] == 0:
|
||||
content = f"> <<< THREAD: **{thread_name}** >>>\n{content}"
|
||||
|
||||
avatar_url = str(msg.author.display_avatar.url) if msg.author.display_avatar.url else None
|
||||
if avatar_url and not avatar_url.startswith("http"):
|
||||
avatar_url = None
|
||||
|
|
@ -262,7 +270,9 @@ async def migrate_messages(
|
|||
context=context,
|
||||
source_channel_id=thread.id,
|
||||
target_channel_id=target_channel_id,
|
||||
thread_id=str(thread.id)
|
||||
thread_id=str(thread.id),
|
||||
parent_target_id=fluxer_msg_id,
|
||||
thread_name=thread.name
|
||||
)
|
||||
stats["messages"] += thread_stats["messages"]
|
||||
stats["attachments"] += thread_stats["attachments"]
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ class FluxerWriter:
|
|||
print(err_msg)
|
||||
return None
|
||||
|
||||
async def send_marker(self, channel_id: str, content: str, files: list[dict] | None = None) -> Optional[str]:
|
||||
async def send_marker(self, channel_id: str, content: str, files: list[dict] | None = None, reply_to_message_id: Optional[str] = None) -> Optional[str]:
|
||||
"""
|
||||
Sends a simple marker message (e.g., thread start/end) using the bot directly.
|
||||
"""
|
||||
|
|
@ -308,12 +308,17 @@ class FluxerWriter:
|
|||
fluxer_files = None
|
||||
if files:
|
||||
fluxer_files = [File(io.BytesIO(f["data"]), filename=f["filename"]) for f in files]
|
||||
|
||||
|
||||
message_reference = None
|
||||
if reply_to_message_id:
|
||||
message_reference = {"message_id": str(reply_to_message_id), "channel_id": str(channel_id)}
|
||||
|
||||
try:
|
||||
msg_data = await self.client.send_message(
|
||||
channel_id=channel_id,
|
||||
content=content,
|
||||
files=fluxer_files
|
||||
files=fluxer_files,
|
||||
message_reference=message_reference
|
||||
)
|
||||
return str(msg_data["id"]) if msg_data else None
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -107,7 +107,9 @@ async def migrate_messages(
|
|||
target_channel_id: str,
|
||||
after_message_id: int | None = None,
|
||||
progress_callback: Callable[[Dict[str, Any]], Awaitable[None]] | None = None,
|
||||
thread_id: str | None = None
|
||||
thread_id: str | None = None,
|
||||
parent_target_id: str | None = None,
|
||||
thread_name: str | None = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Migrate messages for a specific channel using Stoat masquerade for author impersonation."""
|
||||
stats = {
|
||||
|
|
@ -133,14 +135,8 @@ async def migrate_messages(
|
|||
|
||||
|
||||
# Skip system messages like "pinned a message", etc.
|
||||
# We treat thread_starter_message (type 21) as our thread marker.
|
||||
content = "" # Initialize content
|
||||
if msg.type == context.discord_reader.MESSAGE_TYPE_THREAD_STARTER:
|
||||
channel_name = msg.channel.name if msg.channel else "Unknown Thread"
|
||||
content = f"> <<< THREAD: **{channel_name}** >>>"
|
||||
# If it's a thread starter and we already processed the thread at the top,
|
||||
# we might be double-posting. But we want it as a marker.
|
||||
elif msg.type not in [context.discord_reader.MESSAGE_TYPE_DEFAULT, context.discord_reader.MESSAGE_TYPE_REPLY]:
|
||||
if msg.type not in [context.discord_reader.MESSAGE_TYPE_DEFAULT, context.discord_reader.MESSAGE_TYPE_REPLY, context.discord_reader.MESSAGE_TYPE_THREAD_STARTER]:
|
||||
# If we are skipping the parent, we STILL need to check for a thread!
|
||||
if hasattr(msg, 'thread') and msg.thread:
|
||||
thread = msg.thread
|
||||
|
|
@ -149,12 +145,16 @@ async def migrate_messages(
|
|||
# Track thread entry
|
||||
stats["threads"] += 1
|
||||
|
||||
pass
|
||||
|
||||
# Migrate thread messages recursively
|
||||
thread_stats = await migrate_messages(
|
||||
context=context,
|
||||
source_channel_id=thread.id,
|
||||
target_channel_id=target_channel_id,
|
||||
thread_id=str(thread.id)
|
||||
thread_id=str(thread.id),
|
||||
parent_target_id=None,
|
||||
thread_name=thread.name
|
||||
)
|
||||
stats["messages"] += thread_stats["messages"]
|
||||
stats["attachments"] += thread_stats["attachments"]
|
||||
|
|
@ -213,6 +213,14 @@ async def migrate_messages(
|
|||
logger.debug(f"Detected reply to Discord ID {msg.reference.message_id} -> Stoat ID {reply_to_stoat_id}")
|
||||
else:
|
||||
logger.debug(f"Reply target Discord ID {msg.reference.message_id} not found in current session map.")
|
||||
|
||||
# If this is the FIRST thread message and we have a parent_target_id, force it as reply to the starter
|
||||
if not reply_to_stoat_id and parent_target_id and stats["messages"] == 0:
|
||||
reply_to_stoat_id = parent_target_id
|
||||
|
||||
# Prepend thread marker to the first message of the thread
|
||||
if thread_name and stats["messages"] == 0:
|
||||
content = f"> <<< THREAD: **{thread_name}** >>>\n{content}"
|
||||
|
||||
avatar_url = str(msg.author.display_avatar.url) if msg.author.display_avatar.url else None
|
||||
if avatar_url and not avatar_url.startswith("http"):
|
||||
|
|
@ -260,12 +268,16 @@ async def migrate_messages(
|
|||
# Track thread entry
|
||||
stats["threads"] += 1
|
||||
|
||||
pass
|
||||
|
||||
# Migrate thread messages recursively
|
||||
thread_stats = await migrate_messages(
|
||||
context=context,
|
||||
source_channel_id=thread.id,
|
||||
target_channel_id=target_channel_id,
|
||||
thread_id=str(thread.id)
|
||||
thread_id=str(thread.id),
|
||||
parent_target_id=stoat_msg_id,
|
||||
thread_name=thread.name
|
||||
)
|
||||
stats["messages"] += thread_stats["messages"]
|
||||
stats["attachments"] += thread_stats["attachments"]
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ class StoatWriter:
|
|||
logger.error(f"Failed to send Stoat message to {channel_id}: {e}")
|
||||
raise # Let caller handle (migration loop will stop for permission errors)
|
||||
|
||||
async def send_marker(self, channel_id: str, content: str, files: Optional[List[Dict[str, Any]]] = None) -> Optional[str]:
|
||||
async def send_marker(self, channel_id: str, content: str, files: Optional[List[Dict[str, Any]]] = None, reply_to_message_id: Optional[str] = None) -> Optional[str]:
|
||||
try:
|
||||
channel = await self.client.fetch_channel(channel_id)
|
||||
attachments = None
|
||||
|
|
@ -287,7 +287,16 @@ class StoatWriter:
|
|||
attachments = []
|
||||
for f in files:
|
||||
attachments.append((f["filename"], f["data"]))
|
||||
msg = await channel.send(content=content, attachments=attachments)
|
||||
|
||||
replies = None
|
||||
if reply_to_message_id:
|
||||
replies = [stoat.Reply(id=reply_to_message_id, mention=False)]
|
||||
|
||||
msg = await channel.send(
|
||||
content=content,
|
||||
attachments=attachments,
|
||||
replies=replies
|
||||
)
|
||||
return str(msg.id)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to send Stoat marker to {channel_id}: {e}")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue