move state and message json files

This commit is contained in:
rambros 2026-02-27 16:28:42 +05:30
parent ea87aa1f1f
commit dddaaf7de9
3 changed files with 66 additions and 37 deletions

View file

@ -29,9 +29,25 @@ class MigrationContext:
]: ]:
server_id = "unconfigured" server_id = "unconfigured"
# Try to find an existing folder for this server_id
import os
from pathlib import Path
state_file: str | Path = ""
messages_file: str | Path = ""
if server_id and server_id not in ["000000000000000000", "DISCORD_SERVER_ID", "FLUXER_COMMUNITY_ID", "STOAT_SERVER_ID", "unconfigured", ""]:
# If a folder doesn't exist yet, we stick with the generic server_id names,
# but they won't be saved until set_folder is called.
for d in Path(".").iterdir():
if d.is_dir() and d.name.endswith(f"-{server_id}"):
state_file = d / "state-migration.json"
messages_file = d / "message-tracker.json"
break
self.state = MigrationState( self.state = MigrationState(
state_file=f"{server_id}.state.json", state_file=state_file,
messages_file=f"{server_id}.messages.json" messages_file=messages_file
) )
self.discord_reader = DiscordReader( self.discord_reader = DiscordReader(

View file

@ -1,13 +1,16 @@
import json import json
import logging
from pathlib import Path from pathlib import Path
from typing import Dict, Any from typing import Dict, Any
logger = logging.getLogger(__name__)
class MigrationState: class MigrationState:
"""Manages persistence of the migration state to allow resumability.""" """Manages persistence of the migration state to allow resumability."""
def __init__(self, state_file: str | Path = "default.state.json", messages_file: str | Path = "default.messages.json"): def __init__(self, state_file: str | Path = "", messages_file: str | Path = ""):
self.state_file = Path(state_file) self.state_file: Path | None = Path(state_file) if state_file else None
self.messages_file = Path(messages_file) self.messages_file: Path | None = Path(messages_file) if messages_file else None
# mappings: discord_id -> fluxer_id # mappings: discord_id -> fluxer_id
self.channel_map: Dict[str, str] = {} self.channel_map: Dict[str, str] = {}
@ -31,7 +34,7 @@ class MigrationState:
migrated_messages = False migrated_messages = False
# 1. Load primary state file # 1. Load primary state file
if self.state_file.exists(): if self.state_file and self.state_file.exists():
with open(self.state_file, "r", encoding="utf-8") as f: with open(self.state_file, "r", encoding="utf-8") as f:
data = json.load(f) data = json.load(f)
self.channel_map = data.get("channels", {}) self.channel_map = data.get("channels", {})
@ -40,47 +43,21 @@ class MigrationState:
self.emoji_map = data.get("emojis", {}) self.emoji_map = data.get("emojis", {})
self.sticker_map = data.get("stickers", {}) self.sticker_map = data.get("stickers", {})
self.audit_log_channel = data.get("audit_log_channel") self.audit_log_channel = data.get("audit_log_channel")
# Check for legacy messages in state file
if "messages" in data or "last_message_timestamps" in data:
self.message_map = data.get("messages", {})
self.last_message_ids = data.get("last_message_ids", {})
self.last_message_timestamps = data.get("last_message_timestamps", {})
migrated_messages = True # We found legacy data, we should write it out to messages file later
# Legacy Migration: Move role_, emoji_, sticker_ from channel_map to dedicated maps # 2. Load separate messages file
legacy_keys = list(self.channel_map.keys()) if self.messages_file and self.messages_file.exists():
for k in legacy_keys:
if k.startswith("role_"):
discord_id = k.replace("role_", "")
self.role_map[discord_id] = self.channel_map.pop(k)
migrated_state = True
elif k.startswith("emoji_"):
discord_id = k.replace("emoji_", "")
self.emoji_map[discord_id] = self.channel_map.pop(k)
migrated_state = True
elif k.startswith("sticker_"):
discord_id = k.replace("sticker_", "")
self.sticker_map[discord_id] = self.channel_map.pop(k)
migrated_state = True
# 2. Load separate messages file (overrides legacy state file messages)
if self.messages_file.exists():
with open(self.messages_file, "r", encoding="utf-8") as f: with open(self.messages_file, "r", encoding="utf-8") as f:
msg_data = json.load(f) msg_data = json.load(f)
self.message_map = msg_data.get("messages", {}) self.message_map = msg_data.get("messages", {})
self.last_message_ids = msg_data.get("last_message_ids", {}) self.last_message_ids = msg_data.get("last_message_ids", {})
self.last_message_timestamps = msg_data.get("last_message_timestamps", {}) self.last_message_timestamps = msg_data.get("last_message_timestamps", {})
migrated_messages = False # No need to force a migrating save since it already exists
# 3. Save if we migrated any legacy data to separate maps/files
if migrated_state or migrated_messages:
self.save_state()
if migrated_messages:
self.save_messages()
def save_state(self): def save_state(self):
"""Saves only the core server configuration (channels, roles, emojis).""" """Saves only the core server configuration (channels, roles, emojis)."""
if not self.state_file:
return
data = { data = {
"channels": self.channel_map, "channels": self.channel_map,
"categories": self.category_map, "categories": self.category_map,
@ -94,6 +71,8 @@ class MigrationState:
def save_messages(self): def save_messages(self):
"""Saves only the message tracking data.""" """Saves only the message tracking data."""
if not self.messages_file:
return
data = { data = {
"last_message_ids": self.last_message_ids, "last_message_ids": self.last_message_ids,
"last_message_timestamps": self.last_message_timestamps, "last_message_timestamps": self.last_message_timestamps,
@ -242,3 +221,23 @@ class MigrationState:
self.last_message_ids.clear() self.last_message_ids.clear()
self.last_message_timestamps.clear() self.last_message_timestamps.clear()
self.save_messages() self.save_messages()
def set_folder(self, server_id: str, clean_name: str):
new_folder = Path(f"{clean_name}-{server_id}")
# If we have an existing folder that is different, rename it
if self.state_file and self.state_file.parent.exists() and self.state_file.parent != new_folder:
# Check if it's actually in a server-specific folder (not roots)
if self.state_file.parent.name.endswith(f"-{server_id}"):
try:
self.state_file.parent.rename(new_folder)
except Exception as e:
logger.debug(f"Could not rename {self.state_file.parent} to {new_folder}: {e}")
new_folder.mkdir(exist_ok=True)
self.state_file = new_folder / "state-migration.json"
self.messages_file = new_folder / "message-tracker.json"
self.save_state()
self.save_messages()

View file

@ -230,6 +230,20 @@ class MigrationCLI:
self.tokens_valid = discord_valid and target_valid self.tokens_valid = discord_valid and target_valid
if self.tokens_valid:
if self.target_platform == "fluxer":
srv_id = self.config.fluxer_community_id
srv_name = self.validation_results.get("fluxer_community_name", "unknown")
else:
srv_id = self.config.stoat_server_id
srv_name = self.validation_results.get("stoat_server_name", "unknown")
if srv_id and srv_name and srv_id not in ["000000000000000000", "DISCORD_SERVER_ID", "FLUXER_COMMUNITY_ID", "STOAT_SERVER_ID", "unconfigured", ""]:
import re
safe_name = re.sub(r'[^a-zA-Z0-9_\-\.]', '_', srv_name)
self.engine.state.set_folder(str(srv_id), safe_name)
# Check if all permissions are actually granted # Check if all permissions are actually granted
self.permissions_complete = True self.permissions_complete = True
if self.tokens_valid: if self.tokens_valid: