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,
|
target_channel_id: str,
|
||||||
after_message_id: int | None = None,
|
after_message_id: int | None = None,
|
||||||
progress_callback: Callable[[Dict[str, Any]], Awaitable[None]] | 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]:
|
) -> Dict[str, Any]:
|
||||||
"""Migrate messages for a specific channel and returns detailed statistics."""
|
"""Migrate messages for a specific channel and returns detailed statistics."""
|
||||||
stats = {
|
stats = {
|
||||||
|
|
@ -128,11 +130,7 @@ async def migrate_messages(
|
||||||
|
|
||||||
|
|
||||||
# Skip system messages like "pinned a message", etc.
|
# Skip system messages like "pinned a message", etc.
|
||||||
# We treat thread_starter_message (type 21) as our thread marker.
|
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 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 we are skipping the parent, we STILL need to check for a thread!
|
# If we are skipping the parent, we STILL need to check for a thread!
|
||||||
if hasattr(msg, 'thread') and msg.thread:
|
if hasattr(msg, 'thread') and msg.thread:
|
||||||
thread = msg.thread
|
thread = msg.thread
|
||||||
|
|
@ -146,7 +144,9 @@ async def migrate_messages(
|
||||||
context=context,
|
context=context,
|
||||||
source_channel_id=thread.id,
|
source_channel_id=thread.id,
|
||||||
target_channel_id=target_channel_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["messages"] += thread_stats["messages"]
|
||||||
stats["attachments"] += thread_stats["attachments"]
|
stats["attachments"] += thread_stats["attachments"]
|
||||||
|
|
@ -211,6 +211,14 @@ async def migrate_messages(
|
||||||
else:
|
else:
|
||||||
logger.debug(f"Reply target Discord ID {msg.reference.message_id} not found in current session map.")
|
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
|
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"):
|
if avatar_url and not avatar_url.startswith("http"):
|
||||||
avatar_url = None
|
avatar_url = None
|
||||||
|
|
@ -262,7 +270,9 @@ async def migrate_messages(
|
||||||
context=context,
|
context=context,
|
||||||
source_channel_id=thread.id,
|
source_channel_id=thread.id,
|
||||||
target_channel_id=target_channel_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["messages"] += thread_stats["messages"]
|
||||||
stats["attachments"] += thread_stats["attachments"]
|
stats["attachments"] += thread_stats["attachments"]
|
||||||
|
|
|
||||||
|
|
@ -299,7 +299,7 @@ class FluxerWriter:
|
||||||
print(err_msg)
|
print(err_msg)
|
||||||
return None
|
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.
|
Sends a simple marker message (e.g., thread start/end) using the bot directly.
|
||||||
"""
|
"""
|
||||||
|
|
@ -309,11 +309,16 @@ class FluxerWriter:
|
||||||
if files:
|
if files:
|
||||||
fluxer_files = [File(io.BytesIO(f["data"]), filename=f["filename"]) for f in 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:
|
try:
|
||||||
msg_data = await self.client.send_message(
|
msg_data = await self.client.send_message(
|
||||||
channel_id=channel_id,
|
channel_id=channel_id,
|
||||||
content=content,
|
content=content,
|
||||||
files=fluxer_files
|
files=fluxer_files,
|
||||||
|
message_reference=message_reference
|
||||||
)
|
)
|
||||||
return str(msg_data["id"]) if msg_data else None
|
return str(msg_data["id"]) if msg_data else None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,9 @@ async def migrate_messages(
|
||||||
target_channel_id: str,
|
target_channel_id: str,
|
||||||
after_message_id: int | None = None,
|
after_message_id: int | None = None,
|
||||||
progress_callback: Callable[[Dict[str, Any]], Awaitable[None]] | 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]:
|
) -> Dict[str, Any]:
|
||||||
"""Migrate messages for a specific channel using Stoat masquerade for author impersonation."""
|
"""Migrate messages for a specific channel using Stoat masquerade for author impersonation."""
|
||||||
stats = {
|
stats = {
|
||||||
|
|
@ -133,14 +135,8 @@ async def migrate_messages(
|
||||||
|
|
||||||
|
|
||||||
# Skip system messages like "pinned a message", etc.
|
# Skip system messages like "pinned a message", etc.
|
||||||
# We treat thread_starter_message (type 21) as our thread marker.
|
|
||||||
content = "" # Initialize content
|
content = "" # Initialize content
|
||||||
if msg.type == context.discord_reader.MESSAGE_TYPE_THREAD_STARTER:
|
if msg.type not in [context.discord_reader.MESSAGE_TYPE_DEFAULT, context.discord_reader.MESSAGE_TYPE_REPLY, 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 we are skipping the parent, we STILL need to check for a thread!
|
# If we are skipping the parent, we STILL need to check for a thread!
|
||||||
if hasattr(msg, 'thread') and msg.thread:
|
if hasattr(msg, 'thread') and msg.thread:
|
||||||
thread = msg.thread
|
thread = msg.thread
|
||||||
|
|
@ -149,12 +145,16 @@ async def migrate_messages(
|
||||||
# Track thread entry
|
# Track thread entry
|
||||||
stats["threads"] += 1
|
stats["threads"] += 1
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
# Migrate thread messages recursively
|
# Migrate thread messages recursively
|
||||||
thread_stats = await migrate_messages(
|
thread_stats = await migrate_messages(
|
||||||
context=context,
|
context=context,
|
||||||
source_channel_id=thread.id,
|
source_channel_id=thread.id,
|
||||||
target_channel_id=target_channel_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["messages"] += thread_stats["messages"]
|
||||||
stats["attachments"] += thread_stats["attachments"]
|
stats["attachments"] += thread_stats["attachments"]
|
||||||
|
|
@ -214,6 +214,14 @@ async def migrate_messages(
|
||||||
else:
|
else:
|
||||||
logger.debug(f"Reply target Discord ID {msg.reference.message_id} not found in current session map.")
|
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
|
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"):
|
if avatar_url and not avatar_url.startswith("http"):
|
||||||
avatar_url = None
|
avatar_url = None
|
||||||
|
|
@ -260,12 +268,16 @@ async def migrate_messages(
|
||||||
# Track thread entry
|
# Track thread entry
|
||||||
stats["threads"] += 1
|
stats["threads"] += 1
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
# Migrate thread messages recursively
|
# Migrate thread messages recursively
|
||||||
thread_stats = await migrate_messages(
|
thread_stats = await migrate_messages(
|
||||||
context=context,
|
context=context,
|
||||||
source_channel_id=thread.id,
|
source_channel_id=thread.id,
|
||||||
target_channel_id=target_channel_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["messages"] += thread_stats["messages"]
|
||||||
stats["attachments"] += thread_stats["attachments"]
|
stats["attachments"] += thread_stats["attachments"]
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,7 @@ class StoatWriter:
|
||||||
logger.error(f"Failed to send Stoat message to {channel_id}: {e}")
|
logger.error(f"Failed to send Stoat message to {channel_id}: {e}")
|
||||||
raise # Let caller handle (migration loop will stop for permission errors)
|
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:
|
try:
|
||||||
channel = await self.client.fetch_channel(channel_id)
|
channel = await self.client.fetch_channel(channel_id)
|
||||||
attachments = None
|
attachments = None
|
||||||
|
|
@ -287,7 +287,16 @@ class StoatWriter:
|
||||||
attachments = []
|
attachments = []
|
||||||
for f in files:
|
for f in files:
|
||||||
attachments.append((f["filename"], f["data"]))
|
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)
|
return str(msg.id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to send Stoat marker to {channel_id}: {e}")
|
logger.error(f"Failed to send Stoat marker to {channel_id}: {e}")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue