improve startup behaviour
This commit is contained in:
parent
478fa85b32
commit
7267253f8b
3 changed files with 128 additions and 28 deletions
|
|
@ -1,18 +1,71 @@
|
||||||
import sys
|
import sys
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
from src.ui.app import run_cli
|
from src.ui.app import run_cli
|
||||||
from src.core.configuration import load_config
|
from src.core.configuration import load_config
|
||||||
|
|
||||||
def setup_logging():
|
def select_config():
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.prompt import Prompt
|
||||||
|
from rich.panel import Panel
|
||||||
|
|
||||||
|
console = Console()
|
||||||
|
|
||||||
|
fluxer_exists = Path("fluxer.config.yaml").exists()
|
||||||
|
stoat_exists = Path("stoat.config.yaml").exists()
|
||||||
|
|
||||||
|
if fluxer_exists and not stoat_exists:
|
||||||
|
return "fluxer.config.yaml"
|
||||||
|
elif stoat_exists and not fluxer_exists:
|
||||||
|
return "stoat.config.yaml"
|
||||||
|
elif fluxer_exists and stoat_exists:
|
||||||
|
console.print(Panel.fit(
|
||||||
|
"[bold]Both Fluxer and Stoat configurations found.[/bold]\n"
|
||||||
|
"Which one do you want to use?",
|
||||||
|
title="[bold cyan]Configuration Selection[/bold cyan]"
|
||||||
|
))
|
||||||
|
console.print("(1) [bold blue]Fluxer[/bold blue]")
|
||||||
|
console.print("(2) [bold red]Stoat[/bold red]")
|
||||||
|
console.print("(Q) [bold dim]Quit[/bold dim]")
|
||||||
|
console.print("")
|
||||||
|
|
||||||
|
choice = Prompt.ask("Select an option [[bold cyan]1/2/Q[/bold cyan]]", choices=["1", "2", "Q", "q"], show_choices=False).upper()
|
||||||
|
if choice == "1":
|
||||||
|
return "fluxer.config.yaml"
|
||||||
|
elif choice == "2":
|
||||||
|
return "stoat.config.yaml"
|
||||||
|
else:
|
||||||
|
sys.exit(0)
|
||||||
|
else:
|
||||||
|
console.print(Panel.fit(
|
||||||
|
"[bold]First setup, Tool configuration[/bold]\n"
|
||||||
|
"Which platform do you want to migrate to?",
|
||||||
|
title="[bold cyan]Initial Setup[/bold cyan]"
|
||||||
|
))
|
||||||
|
console.print("(1) [bold blue]Fluxer[/bold blue]")
|
||||||
|
console.print("(2) [bold red]Stoat[/bold red]")
|
||||||
|
console.print("(Q) [bold dim]Quit[/bold dim]")
|
||||||
|
console.print("")
|
||||||
|
|
||||||
|
choice = Prompt.ask("Select an option [[bold cyan]1/2/Q[/bold cyan]]", choices=["1", "2", "Q", "q"], show_choices=False).upper()
|
||||||
|
if choice == "1":
|
||||||
|
return "fluxer.config.yaml"
|
||||||
|
elif choice == "2":
|
||||||
|
return "stoat.config.yaml"
|
||||||
|
else:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def setup_logging(config_path):
|
||||||
try:
|
try:
|
||||||
config = load_config()
|
config = load_config(config_path)
|
||||||
log_level_str = config.migration.log_level.upper()
|
log_level_str = config.migration.log_level.upper()
|
||||||
level = getattr(logging, log_level_str, logging.INFO)
|
level = getattr(logging, log_level_str, logging.INFO)
|
||||||
except Exception:
|
except Exception:
|
||||||
level = logging.INFO
|
level = logging.INFO
|
||||||
|
|
||||||
handlers = [logging.FileHandler('fluxer.migration.log', mode='a')]
|
platform = config_path.split('.')[0]
|
||||||
|
handlers = [logging.FileHandler(f'{platform}.migration.log', mode='a')]
|
||||||
if level == logging.DEBUG:
|
if level == logging.DEBUG:
|
||||||
handlers.append(logging.StreamHandler(sys.stdout))
|
handlers.append(logging.StreamHandler(sys.stdout))
|
||||||
|
|
||||||
|
|
@ -87,9 +140,10 @@ def relaunch_in_terminal():
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
relaunch_in_terminal()
|
relaunch_in_terminal()
|
||||||
setup_logging()
|
config_path = select_config()
|
||||||
|
setup_logging(config_path)
|
||||||
try:
|
try:
|
||||||
asyncio.run(run_cli())
|
asyncio.run(run_cli(config_path))
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\nOperation terminated by user.")
|
print("\nOperation terminated by user.")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
|
||||||
|
|
@ -55,9 +55,10 @@ console = Console()
|
||||||
class MigrationCLI:
|
class MigrationCLI:
|
||||||
"""Standard CLI app to manage the Discord to Fluxer migration."""
|
"""Standard CLI app to manage the Discord to Fluxer migration."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, config_path="fluxer.config.yaml"):
|
||||||
|
self.config_path = config_path
|
||||||
try:
|
try:
|
||||||
self.config = load_config()
|
self.config = load_config(self.config_path)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
console.print(f"[bold red]Failed to load config: {e}[/bold red]")
|
console.print(f"[bold red]Failed to load config: {e}[/bold red]")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
@ -83,20 +84,38 @@ class MigrationCLI:
|
||||||
}
|
}
|
||||||
self.tokens_valid = False
|
self.tokens_valid = False
|
||||||
|
|
||||||
discord_task = asyncio.create_task(self.engine.discord_reader.validate())
|
d_token = self.config.discord_bot_token
|
||||||
fluxer_task = asyncio.create_task(self.engine.fluxer_writer.validate())
|
f_token = self.config.fluxer_bot_token
|
||||||
|
|
||||||
|
discord_dummy = d_token in ["YOUR_DISCORD_TOKEN", "DISCORD_BOT_TOKEN", ""]
|
||||||
|
fluxer_dummy = f_token in ["YOUR_FLUXER_TOKEN", "FLUXER_BOT_TOKEN", "YOUR_STOAT_TOKEN", "STOAT_BOT_TOKEN", ""]
|
||||||
|
|
||||||
|
discord_task = None
|
||||||
|
if not discord_dummy:
|
||||||
|
discord_task = asyncio.create_task(self.engine.discord_reader.validate())
|
||||||
|
|
||||||
|
fluxer_task = None
|
||||||
|
if not fluxer_dummy:
|
||||||
|
fluxer_task = asyncio.create_task(self.engine.fluxer_writer.validate())
|
||||||
|
|
||||||
|
tasks_to_wait = [t for t in [discord_task, fluxer_task] if t is not None]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with console.status("[yellow]Validating tokens...[/yellow]"):
|
with console.status("[yellow]Validating tokens...[/yellow]"):
|
||||||
start_time = asyncio.get_event_loop().time()
|
start_time = asyncio.get_event_loop().time()
|
||||||
done, pending = await asyncio.wait(
|
done = set()
|
||||||
[discord_task, fluxer_task],
|
pending = set()
|
||||||
timeout=10.0,
|
if tasks_to_wait:
|
||||||
return_when=asyncio.ALL_COMPLETED
|
done, pending = await asyncio.wait(
|
||||||
)
|
tasks_to_wait,
|
||||||
|
timeout=10.0,
|
||||||
|
return_when=asyncio.ALL_COMPLETED
|
||||||
|
)
|
||||||
|
|
||||||
# Process Discord Result
|
# Process Discord Result
|
||||||
if discord_task in done:
|
if discord_dummy:
|
||||||
|
console.print("[bold yellow]Discord setup incomplete (Using default token).[/bold yellow]")
|
||||||
|
elif discord_task in done:
|
||||||
try:
|
try:
|
||||||
res = discord_task.result()
|
res = discord_task.result()
|
||||||
self.validation_results["discord_token"] = res.get("token", False)
|
self.validation_results["discord_token"] = res.get("token", False)
|
||||||
|
|
@ -120,7 +139,9 @@ class MigrationCLI:
|
||||||
discord_task.cancel()
|
discord_task.cancel()
|
||||||
|
|
||||||
# Process Fluxer Result
|
# Process Fluxer Result
|
||||||
if fluxer_task in done:
|
if fluxer_dummy:
|
||||||
|
console.print("[bold yellow]Target Platform setup incomplete (Using default token).[/bold yellow]")
|
||||||
|
elif fluxer_task in done:
|
||||||
try:
|
try:
|
||||||
res = fluxer_task.result()
|
res = fluxer_task.result()
|
||||||
self.validation_results["fluxer_token"] = res.get("token", False)
|
self.validation_results["fluxer_token"] = res.get("token", False)
|
||||||
|
|
@ -169,10 +190,25 @@ class MigrationCLI:
|
||||||
finally:
|
finally:
|
||||||
# Ensure tasks are cleaned up
|
# Ensure tasks are cleaned up
|
||||||
for t in [discord_task, fluxer_task]:
|
for t in [discord_task, fluxer_task]:
|
||||||
if not t.done(): t.cancel()
|
if t is not None and not t.done(): t.cancel()
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
await self.validate_config()
|
if self.config.discord_bot_token == "YOUR_DISCORD_TOKEN":
|
||||||
|
console.print("\n[bold yellow]First time setup detected. Redirecting to configuration...[/bold yellow]")
|
||||||
|
self.validation_results = {
|
||||||
|
"discord_token": False, "discord_bot_name": None,
|
||||||
|
"discord_server": False, "discord_server_name": None,
|
||||||
|
"discord_intents": {}, "discord_permissions": {},
|
||||||
|
"fluxer_token": False, "fluxer_bot_name": None,
|
||||||
|
"fluxer_community": False, "fluxer_community_name": None,
|
||||||
|
"fluxer_permissions": {},
|
||||||
|
"discord_timeout": False, "fluxer_timeout": False
|
||||||
|
}
|
||||||
|
self.tokens_valid = False
|
||||||
|
self.permissions_complete = False
|
||||||
|
await self.edit_configuration(skip_validation=True)
|
||||||
|
else:
|
||||||
|
await self.validate_config()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
console.print("")
|
console.print("")
|
||||||
|
|
@ -225,8 +261,9 @@ class MigrationCLI:
|
||||||
await self.engine.close_connections()
|
await self.engine.close_connections()
|
||||||
break
|
break
|
||||||
|
|
||||||
async def edit_configuration(self):
|
async def edit_configuration(self, skip_validation=False):
|
||||||
await self.validate_config()
|
if not skip_validation:
|
||||||
|
await self.validate_config()
|
||||||
|
|
||||||
# Display Required Permissions FIRST
|
# Display Required Permissions FIRST
|
||||||
def fmt(name, val):
|
def fmt(name, val):
|
||||||
|
|
@ -264,8 +301,8 @@ class MigrationCLI:
|
||||||
return status
|
return status
|
||||||
|
|
||||||
console.print(f"Discord Bot Token {get_status_str(self.validation_results.get('discord_token', False), self.validation_results.get('discord_bot_name'))}")
|
console.print(f"Discord Bot Token {get_status_str(self.validation_results.get('discord_token', False), self.validation_results.get('discord_bot_name'))}")
|
||||||
console.print(f"Fluxer Bot Token {get_status_str(self.validation_results.get('fluxer_token', False), self.validation_results.get('fluxer_bot_name'))}")
|
|
||||||
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"Discord Server ID {get_status_str(self.validation_results.get('discord_server', False), self.validation_results.get('discord_server_name'))}")
|
||||||
|
console.print(f"Fluxer Bot Token {get_status_str(self.validation_results.get('fluxer_token', False), self.validation_results.get('fluxer_bot_name'))}")
|
||||||
console.print(f"Fluxer Community ID {get_status_str(self.validation_results.get('fluxer_community', False), self.validation_results.get('fluxer_community_name'))}")
|
console.print(f"Fluxer Community ID {get_status_str(self.validation_results.get('fluxer_community', False), self.validation_results.get('fluxer_community_name'))}")
|
||||||
|
|
||||||
console.print("\n(1) Edit tokens")
|
console.print("\n(1) Edit tokens")
|
||||||
|
|
@ -284,8 +321,8 @@ class MigrationCLI:
|
||||||
console.print("\n[bold]Configuration Editor[/bold] (leave blank to keep current)")
|
console.print("\n[bold]Configuration Editor[/bold] (leave blank to keep current)")
|
||||||
|
|
||||||
d_token = Prompt.ask("Discord Bot Token", default=self.config.discord_bot_token)
|
d_token = Prompt.ask("Discord Bot Token", default=self.config.discord_bot_token)
|
||||||
f_token = Prompt.ask("Fluxer Bot Token", default=self.config.fluxer_bot_token)
|
|
||||||
d_server = Prompt.ask("Discord Server ID", default=self.config.discord_server_id)
|
d_server = Prompt.ask("Discord Server ID", default=self.config.discord_server_id)
|
||||||
|
f_token = Prompt.ask("Fluxer Bot Token", default=self.config.fluxer_bot_token)
|
||||||
f_comm = Prompt.ask("Fluxer Community ID", default=self.config.fluxer_community_id)
|
f_comm = Prompt.ask("Fluxer Community ID", default=self.config.fluxer_community_id)
|
||||||
|
|
||||||
# Only rewrite if changed
|
# Only rewrite if changed
|
||||||
|
|
@ -299,7 +336,7 @@ class MigrationCLI:
|
||||||
self.config.discord_server_id = d_server
|
self.config.discord_server_id = d_server
|
||||||
self.config.fluxer_community_id = f_comm
|
self.config.fluxer_community_id = f_comm
|
||||||
|
|
||||||
save_config(self.config)
|
save_config(self.config, self.config_path)
|
||||||
# Recreate engine with new config
|
# Recreate engine with new config
|
||||||
self.engine = MigrationContext(self.config)
|
self.engine = MigrationContext(self.config)
|
||||||
|
|
||||||
|
|
@ -308,11 +345,11 @@ class MigrationCLI:
|
||||||
await self.update_validation_status()
|
await self.update_validation_status()
|
||||||
|
|
||||||
console.print(f"\nDiscord Bot Token {get_status_str(self.validation_results.get('discord_token', False))}")
|
console.print(f"\nDiscord Bot Token {get_status_str(self.validation_results.get('discord_token', False))}")
|
||||||
console.print(f"Fluxer Bot Token {get_status_str(self.validation_results.get('fluxer_token', False))}")
|
|
||||||
console.print(f"Discord Server ID {get_status_str(self.validation_results.get('discord_server', False))}")
|
console.print(f"Discord Server ID {get_status_str(self.validation_results.get('discord_server', False))}")
|
||||||
|
console.print(f"Fluxer Bot Token {get_status_str(self.validation_results.get('fluxer_token', False))}")
|
||||||
console.print(f"Fluxer Community ID {get_status_str(self.validation_results.get('fluxer_community', 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 fluxer.config.yaml![/bold green]")
|
console.print(f"[bold green]Configuration updated and saved to {self.config_path}![/bold green]")
|
||||||
else:
|
else:
|
||||||
console.print("[yellow]No changes made.[/yellow]")
|
console.print("[yellow]No changes made.[/yellow]")
|
||||||
|
|
||||||
|
|
@ -1290,6 +1327,6 @@ class MigrationCLI:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async def run_cli():
|
async def run_cli(config_path="fluxer.config.yaml"):
|
||||||
cli = MigrationCLI()
|
cli = MigrationCLI(config_path)
|
||||||
await cli.run()
|
await cli.run()
|
||||||
|
|
|
||||||
9
stoat.config.example.yaml
Normal file
9
stoat.config.example.yaml
Normal file
|
|
@ -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
|
||||||
|
stoat_bot_token: STOAT_BOT_TOKEN # Token used to connect the Stoat Bot
|
||||||
|
stoat_server_id: 'STOAT_SERVER_ID' # ID of the target Stoat Server
|
||||||
|
stoat_api_url: 'default' # URL of the Stoat API (default is https://api.stoat.chat)
|
||||||
|
migration:
|
||||||
|
batch_size: 50
|
||||||
|
rate_limit_delay_seconds: 2
|
||||||
|
log_level: INFO
|
||||||
Loading…
Add table
Reference in a new issue