diff --git a/.gitignore b/.gitignore index 87f8719..01ae978 100644 --- a/.gitignore +++ b/.gitignore @@ -27,9 +27,11 @@ venv/ ENV/ # Configuration and Secrets -config.test.yaml -config.yaml -!config.example.yaml +configs/ +!fluxer.config.example.yaml +!stoat.config.example.yaml +fluxer.config.yaml +stoat.config.yaml # Logs and State *.log diff --git a/config.example.yaml b/config.example.yaml deleted file mode 100644 index f8c2094..0000000 --- a/config.example.yaml +++ /dev/null @@ -1,8 +0,0 @@ -discord_bot_token: DISCORD_BOT_TOKEN -fluxer_bot_token: FLUXER_BOT_TOKEN -discord_server_id: 'DISCORD_SERVER_ID' -fluxer_community_id: 'FLUXER_COMMUNITY_ID' -migration: - batch_size: 50 - rate_limit_delay_seconds: 2 - log_level: INFO diff --git a/dist1/fluxer-reaper b/dist1/fluxer-reaper deleted file mode 100755 index dba7766..0000000 Binary files a/dist1/fluxer-reaper and /dev/null differ diff --git a/fluxer-reaper.py b/fluxer-reaper.py index 84b65ba..3ec7c90 100644 --- a/fluxer-reaper.py +++ b/fluxer-reaper.py @@ -12,7 +12,7 @@ def setup_logging(): except Exception: level = logging.INFO - handlers = [logging.FileHandler('migration.log', mode='a')] + handlers = [logging.FileHandler('fluxer.migration.log', mode='a')] if level == logging.DEBUG: handlers.append(logging.StreamHandler(sys.stdout)) diff --git a/fluxer.config.example.yaml b/fluxer.config.example.yaml new file mode 100644 index 0000000..00b0a49 --- /dev/null +++ b/fluxer.config.example.yaml @@ -0,0 +1,9 @@ +discord_bot_token: DISCORD_BOT_TOKEN # Token used to connect the Discord Bot +discord_server_id: 'DISCORD_SERVER_ID' # ID of the source Discord Server +fluxer_bot_token: FLUXER_BOT_TOKEN # Token used to connect the Fluxer Bot +fluxer_community_id: 'FLUXER_COMMUNITY_ID' # ID of the target Fluxer Community +fluxer_api_url: 'default' # URL of the Fluxer API (default is https://api.fluxer.app) +migration: + batch_size: 50 + rate_limit_delay_seconds: 2 + log_level: INFO diff --git a/src/core/clone_server.py b/src/core/clone_server.py index 3ddcd21..6b599bb 100644 --- a/src/core/clone_server.py +++ b/src/core/clone_server.py @@ -8,8 +8,8 @@ logger = logging.getLogger(__name__) async def sync_channel_state(context: MigrationContext): """ - Scans Fluxer for channels matching Discord names and updates state.json mappings. - This prevents duplicate creation when the state.json is empty but channels exist in Fluxer. + Scans Fluxer for channels matching Discord names and updates fluxer.state.json mappings. + This prevents duplicate creation when the fluxer.state.json is empty but channels exist in Fluxer. """ categories = await context.discord_reader.get_categories() channels = await context.discord_reader.get_channels() diff --git a/src/core/configuration.py b/src/core/configuration.py index 23fe761..97f6392 100644 --- a/src/core/configuration.py +++ b/src/core/configuration.py @@ -12,9 +12,10 @@ class AppConfig(BaseModel): fluxer_bot_token: str discord_server_id: str fluxer_community_id: str + fluxer_api_url: str = Field(default="default") migration: MigrationSettings = Field(default_factory=MigrationSettings) -def load_config(config_path: str | Path = "config.yaml") -> AppConfig: +def load_config(config_path: str | Path = "fluxer.config.yaml") -> AppConfig: path = Path(config_path) if not path.exists(): # Create dummy config if missing @@ -22,7 +23,8 @@ def load_config(config_path: str | Path = "config.yaml") -> AppConfig: discord_bot_token="YOUR_DISCORD_TOKEN", fluxer_bot_token="YOUR_FLUXER_TOKEN", discord_server_id="000000000000000000", - fluxer_community_id="000000000000000000" + fluxer_community_id="000000000000000000", + fluxer_api_url="default" ) save_config(config, path) print(f"Created default configuration: {config_path}") @@ -36,7 +38,7 @@ def load_config(config_path: str | Path = "config.yaml") -> AppConfig: return AppConfig(**data) -def save_config(config: AppConfig, config_path: str | Path = "config.yaml"): +def save_config(config: AppConfig, config_path: str | Path = "fluxer.config.yaml"): path = Path(config_path) # Dump model to dictionary data = config.model_dump() diff --git a/src/core/emoji_stickers.py b/src/core/emoji_stickers.py index c6b0728..6be9a44 100644 --- a/src/core/emoji_stickers.py +++ b/src/core/emoji_stickers.py @@ -8,7 +8,7 @@ logger = logging.getLogger(__name__) async def sync_assets_state(context: MigrationContext): """ - Scans Fluxer for emojis and stickers matching Discord names and updates state.json mappings. + Scans Fluxer for emojis and stickers matching Discord names and updates fluxer.state.json mappings. """ discord_emojis = await context.discord_reader.get_emojis() discord_stickers = await context.discord_reader.get_stickers() diff --git a/src/core/roles_permissions.py b/src/core/roles_permissions.py index fa3eaf4..99c8a9c 100644 --- a/src/core/roles_permissions.py +++ b/src/core/roles_permissions.py @@ -8,7 +8,7 @@ logger = logging.getLogger(__name__) async def sync_roles_state(context: MigrationContext): """ - Scans Fluxer for roles matching Discord names and updates state.json mappings. + Scans Fluxer for roles matching Discord names and updates fluxer.state.json mappings. """ discord_roles = await context.discord_reader.get_roles() fluxer_roles = await context.fluxer_writer.client.get_guild_roles(context.config.fluxer_community_id) diff --git a/src/core/state.py b/src/core/state.py index 36356a2..b745303 100644 --- a/src/core/state.py +++ b/src/core/state.py @@ -5,7 +5,7 @@ from typing import Dict, Any class MigrationState: """Manages persistence of the migration state to allow resumability.""" - def __init__(self, state_file: str | Path = "state.json", messages_file: str | Path = "messages.json"): + def __init__(self, state_file: str | Path = "fluxer.state.json", messages_file: str | Path = "fluxer.messages.json"): self.state_file = Path(state_file) self.messages_file = Path(messages_file) @@ -30,7 +30,7 @@ class MigrationState: migrated_state = False migrated_messages = False - # 1. Load primary state.json + # 1. Load primary fluxer.state.json if self.state_file.exists(): with open(self.state_file, "r", encoding="utf-8") as f: data = json.load(f) @@ -41,12 +41,12 @@ class MigrationState: self.sticker_map = data.get("stickers", {}) self.audit_log_channel = data.get("audit_log_channel") - # Check for legacy messages in state.json + # Check for legacy messages in fluxer.state.json 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.json later + migrated_messages = True # We found legacy data, we should write it out to fluxer.messages.json later # Legacy Migration: Move role_, emoji_, sticker_ from channel_map to dedicated maps legacy_keys = list(self.channel_map.keys()) @@ -64,7 +64,7 @@ class MigrationState: self.sticker_map[discord_id] = self.channel_map.pop(k) migrated_state = True - # 2. Load separate messages.json (overrides legacy state.json) + # 2. Load separate fluxer.messages.json (overrides legacy fluxer.state.json) if self.messages_file.exists(): with open(self.messages_file, "r", encoding="utf-8") as f: msg_data = json.load(f) diff --git a/src/ui/app.py b/src/ui/app.py index e847e98..5fbc6b1 100644 --- a/src/ui/app.py +++ b/src/ui/app.py @@ -268,7 +268,17 @@ class MigrationCLI: console.print(f"Discord Server ID {get_status_str(self.validation_results.get('discord_server', False), self.validation_results.get('discord_server_name'))}") console.print(f"Fluxer Community ID {get_status_str(self.validation_results.get('fluxer_community', False), self.validation_results.get('fluxer_community_name'))}") - if not Confirm.ask("\nEdit now?"): + console.print("\n(1) Edit tokens") + console.print("(2) Edit API url (for self hosted instances)") + console.print("(B) Back") + + menu_choice = Prompt.ask("\nSelect an option [1/2/B]", choices=["1", "2", "B", "b"], default="B", show_choices=False).upper() + + if menu_choice == "B": + return + + if menu_choice == "2": + console.print("[yellow]Not implemented yet.[/yellow]") return console.print("\n[bold]Configuration Editor[/bold] (leave blank to keep current)") @@ -302,7 +312,7 @@ class MigrationCLI: console.print(f"Discord Server ID {get_status_str(self.validation_results.get('discord_server', False))}") console.print(f"Fluxer Community ID {get_status_str(self.validation_results.get('fluxer_community', False))}") - console.print("[bold green]Configuration updated and saved to config.yaml![/bold green]") + console.print("[bold green]Configuration updated and saved to fluxer.config.yaml![/bold green]") else: console.print("[yellow]No changes made.[/yellow]") @@ -375,7 +385,7 @@ class MigrationCLI: force = False if cached_count > 0: - console.print(f"[yellow]\u26a0 {cached_count}/{all_ids_len} item(s) already in state.json cache.[/yellow]") + console.print(f"[yellow]\u26a0 {cached_count}/{all_ids_len} item(s) already in fluxer.state.json cache.[/yellow]") # End of table consolidated section, back to standard flow logic. console.print("[bold green](Y) Continue with only missing items[/bold green]")