add server metadata sync

This commit is contained in:
rambros 2026-02-20 12:14:38 +05:30
parent 198612d5f0
commit ee391701a7
4 changed files with 102 additions and 5 deletions

View file

@ -56,6 +56,46 @@ class MigrationEngine:
await self.discord_reader.close() await self.discord_reader.close()
await self.fluxer_writer.close() await self.fluxer_writer.close()
async def sync_server_metadata(self, progress_callback: Callable[[str, str], Awaitable[None]]):
"""Syncs the server name, logo and banner."""
metadata = await self.discord_reader.get_server_metadata()
name = metadata.get("name")
# 1. Sync Name
try:
await self.fluxer_writer.update_guild_metadata(name=name)
await progress_callback("Server Name", "DONE")
except Exception:
await progress_callback("Server Name", "ERROR")
# 2. Sync Icon
try:
icon_bytes = None
if self.discord_reader.guild and self.discord_reader.guild.icon:
icon_bytes = await self.discord_reader.download_asset(self.discord_reader.guild.icon)
if icon_bytes:
await self.fluxer_writer.update_guild_metadata(icon=icon_bytes)
await progress_callback("Server Icon", "DONE")
else:
await progress_callback("Server Icon", "SKIP")
except Exception:
await progress_callback("Server Icon", "ERROR")
# 3. Sync Banner
try:
banner_bytes = None
if self.discord_reader.guild and self.discord_reader.guild.banner:
banner_bytes = await self.discord_reader.download_asset(self.discord_reader.guild.banner)
if banner_bytes:
await self.fluxer_writer.update_guild_metadata(banner=banner_bytes)
await progress_callback("Server Banner", "DONE")
else:
await progress_callback("Server Banner", "SKIP")
except Exception:
await progress_callback("Server Banner", "ERROR")
async def migrate_channels(self, progress_callback: Callable[[str, int, int], Awaitable[None]] | None = None): async def migrate_channels(self, progress_callback: Callable[[str, int, int], Awaitable[None]] | None = None):
"""Clones categories and text channels.""" """Clones categories and text channels."""
categories = await self.discord_reader.get_categories() categories = await self.discord_reader.get_categories()

View file

@ -49,9 +49,14 @@ class DiscordReader:
return { return {
"name": self.guild.name, "name": self.guild.name,
"id": str(self.guild.id), "id": str(self.guild.id),
"icon_url": self.guild.icon.url if self.guild.icon else None "icon_url": self.guild.icon.url if self.guild.icon else None,
"banner_url": self.guild.banner.url if self.guild.banner else None
} }
async def download_asset(self, asset: discord.Asset) -> bytes:
"""Downloads an asset (icon, banner) into memory."""
return await asset.read()
async def get_categories(self): async def get_categories(self):
if not self.guild: if not self.guild:
return [] return []

View file

@ -115,6 +115,36 @@ class FluxerWriter:
print(f"Failed to copy emoji {name}: {e}") print(f"Failed to copy emoji {name}: {e}")
return "" return ""
async def update_guild_metadata(self, name: Optional[str] = None, icon: Optional[bytes] = None, banner: Optional[bytes] = None) -> None:
"""
Updates the Fluxer community name, icon, and banner.
"""
assert self.client is not None
kwargs = {}
if banner:
import base64
image_data = base64.b64encode(banner).decode("ascii")
if banner.startswith(b"\x89PNG"):
mime_type = "image/png"
elif banner.startswith(b"\xff\xd8\xff"):
mime_type = "image/jpeg"
elif banner.startswith(b"GIF89a") or banner.startswith(b"GIF87a"):
mime_type = "image/gif"
else:
mime_type = "image/png"
kwargs["banner"] = f"data:{mime_type};base64,{image_data}"
try:
await self.client.modify_guild(
guild_id=self.community_id,
name=name,
icon=icon,
**kwargs
)
except Exception as e:
print(f"Failed to update community metadata: {e}")
async def close(self): async def close(self):
"""Cleanly close connection.""" """Cleanly close connection."""
if self.client: if self.client:

View file

@ -37,14 +37,15 @@ class MigrationCLI:
console.print("(1) Clone Server Template (Channels & Categories)") console.print("(1) Clone Server Template (Channels & Categories)")
console.print("(2) Copy Roles & Permissions") console.print("(2) Copy Roles & Permissions")
console.print("(3) Copy Emojis & Stickers") console.print("(3) Copy Emojis & Stickers")
console.print("(4) Migrate message history") console.print("(4) Sync Server Name, Logo and Banner")
console.print("(5) Migrate message history")
val_status = "[bold green][VALID][/bold green]" if self.tokens_valid else "[bold red][INVALID][/bold red]" val_status = "[bold green][VALID][/bold green]" if self.tokens_valid else "[bold red][INVALID][/bold red]"
console.print(f"(5) Configuration {val_status}") console.print(f"(6) Configuration {val_status}")
console.print("(Q) Exit") console.print("(Q) Exit")
choice = Prompt.ask("Select an option", choices=["1", "2", "3", "4", "5", "Q", "q"], default="1").upper() choice = Prompt.ask("Select an option", choices=["1", "2", "3", "4", "5", "6", "Q", "q"], default="1").upper()
if choice == "1": if choice == "1":
await self.clone_server_template() await self.clone_server_template()
@ -53,8 +54,10 @@ class MigrationCLI:
elif choice == "3": elif choice == "3":
await self.copy_emojis() await self.copy_emojis()
elif choice == "4": elif choice == "4":
await self.migrate_message_history() await self.sync_server_metadata()
elif choice == "5": elif choice == "5":
await self.migrate_message_history()
elif choice == "6":
await self.edit_configuration() await self.edit_configuration()
elif choice == "Q": elif choice == "Q":
console.print("[yellow]Exiting tool...[/yellow]") console.print("[yellow]Exiting tool...[/yellow]")
@ -257,6 +260,25 @@ class MigrationCLI:
await self.engine.close_connections() await self.engine.close_connections()
self.engine.is_running = False self.engine.is_running = False
async def sync_server_metadata(self):
if not Confirm.ask("Are you sure you want to sync server name, logo and banner?"):
return
console.print("\n[bold green]Syncing Server Metadata...[/bold green]")
async def progress_callback(item: str, status: str):
color = "green" if status == "DONE" else "red" if status == "ERROR" else "yellow"
console.print(f"{item} [[bold {color}]{status}[/bold {color}]]")
try:
await self.engine.start_connections()
await self.engine.sync_server_metadata(progress_callback)
console.print("[bold green]Server metadata sync finished![/bold green]")
except Exception as e:
console.print(f"[bold red]Error during metadata sync: {str(e)}[/bold red]")
finally:
await self.engine.close_connections()
async def migrate_message_history(self): async def migrate_message_history(self):
if not Confirm.ask("Are you sure you want to migrate message history?"): if not Confirm.ask("Are you sure you want to migrate message history?"):
return return