add re-parenting logic for new categories

This commit is contained in:
rambros 2026-02-21 23:41:02 +05:30
parent 27ace55242
commit af0c9914ab
4 changed files with 63 additions and 16 deletions

View file

@ -213,23 +213,47 @@ class MigrationEngine:
categories = await self.discord_reader.get_categories()
channels = await self.discord_reader.get_channels()
# Filter items if not forcing
if not force:
categories = [cat for cat in categories if not self.state.get_fluxer_category_id(str(cat.id))]
channels = [ch for ch in channels if not self.state.get_fluxer_channel_id(str(ch.id))]
# 1. Identify categories to create
missing_categories = [cat for cat in categories if force or not self.state.get_fluxer_category_id(str(cat.id))]
missing_category_ids = {str(cat.id) for cat in missing_categories}
total = len(categories) + len(channels)
# 2. Identify channels to create or move
# Fetch current Fluxer state to check parent_ids
fluxer_channels = await self.fluxer_writer.get_channels()
fluxer_parent_map = {str(c["id"]): (str(c.get("parent_id")) if c.get("parent_id") else None) for c in fluxer_channels}
channels_to_create = []
channels_to_move = []
for ch in channels:
discord_id = str(ch.id)
fluxer_id = self.state.get_fluxer_channel_id(discord_id)
discord_parent_id = str(ch.category_id) if ch.category_id else None
if force or not fluxer_id:
# We'll resolve the parent_id in the loop after categories are created
channels_to_create.append(ch)
else:
current_fluxer_parent = fluxer_parent_map.get(fluxer_id)
# Case A: Its category is being created right now
# Case B: It has a category that exists but is not set in Fluxer correctly
will_create_parent = discord_parent_id in missing_category_ids
expected_parent_fluxer_id = self.state.get_fluxer_category_id(discord_parent_id) if discord_parent_id else None
if will_create_parent or current_fluxer_parent != expected_parent_fluxer_id:
channels_to_move.append((ch, fluxer_id))
total = len(missing_categories) + len(channels_to_create) + len(channels_to_move)
current_idx = 0
if total == 0:
return
# Migrate Categories first
for cat in categories:
for cat in missing_categories:
if not self.is_running: break
state_key = str(cat.id)
# 4 corresponds to Category type in Discord/Fluxer typically
fluxer_id = await self.fluxer_writer.create_channel(cat.name, type=4)
self.state.set_category_mapping(state_key, fluxer_id)
@ -237,8 +261,8 @@ class MigrationEngine:
if progress_callback: await progress_callback(f"Cat: {cat.name}", "Copying", current_idx, total)
await asyncio.sleep(self.config.migration.rate_limit_delay_seconds)
# Migrate Text Channels
for channel in channels:
# Create missing channels
for channel in channels_to_create:
if not self.is_running: break
state_key = str(channel.id)
@ -257,6 +281,17 @@ class MigrationEngine:
if progress_callback: await progress_callback(channel.name, "Copying", current_idx, total)
await asyncio.sleep(self.config.migration.rate_limit_delay_seconds)
# Move existing channels if needed
for channel, fluxer_id in channels_to_move:
if not self.is_running: break
parent_id = self.state.get_fluxer_category_id(str(channel.category_id)) if channel.category_id else None
await self.fluxer_writer.move_channel(fluxer_id, parent_id)
current_idx += 1
if progress_callback: await progress_callback(channel.name, "Moving", current_idx, total)
await asyncio.sleep(self.config.migration.rate_limit_delay_seconds)
async def sync_permissions(self, progress_callback: Callable[[str, int, int], Awaitable[None]] | None = None):
"""Syncs category and channel role overrides/permissions."""
categories = await self.discord_reader.get_categories()

View file

@ -138,4 +138,5 @@ class DiscordReader:
return await attachment.read()
async def close(self):
await self.client.close()
if self.client:
await self.client.close()

View file

@ -119,6 +119,17 @@ class FluxerWriter:
)
return str(guild_channel["id"])
async def move_channel(self, channel_id: str, parent_id: Optional[str]) -> bool:
"""
Updates the parent category of an existing channel.
"""
assert self.client is not None
await self.client.modify_channel(
channel_id=channel_id,
parent_id=parent_id
)
return True
async def get_channels(self) -> List[Dict[str, Any]]:
"""Returns all channels in the community."""
assert self.client is not None

View file

@ -143,7 +143,7 @@ class MigrationCLI:
f_display = f"[bold green]\"{f_name}\"[/bold green]" if f_name else "[bold red]NOT SET UP[/bold red]"
console.print(f"[bold cyan]Discord Server:[/bold cyan] {d_display}")
console.print(f"[bold magenta]Fluxer Community:[/bold magenta] {f_display}")
console.print(f"[bold #4641D9]Fluxer Community:[/bold #4641D9] {f_display}")
console.print("[bold]Main Menu[/bold]")
console.print("(1) Clone Server Template (Channels & Categories)")
console.print("(2) Copy Roles & Permissions")
@ -249,7 +249,7 @@ class MigrationCLI:
await self.engine.close_connections()
return
table = Table(show_header=True, header_style="bold magenta")
table = Table(show_header=True, header_style="bold #4641D9")
table.add_column("Type", width=12)
table.add_column("Discord Name")
table.add_column("Status", justify="right")
@ -370,7 +370,7 @@ class MigrationCLI:
roles = await self.engine.discord_reader.get_roles()
table = Table(show_header=True, header_style="bold magenta")
table = Table(show_header=True, header_style="bold #4641D9")
table.add_column("Discord Role")
table.add_column("Status", justify="center")
table.add_column("Fluxer ID", justify="right")
@ -484,7 +484,7 @@ class MigrationCLI:
emojis = await self.engine.discord_reader.get_emojis()
stickers = await self.engine.discord_reader.get_stickers()
table = Table(show_header=True, header_style="bold magenta")
table = Table(show_header=True, header_style="bold #4641D9")
table.add_column("Type", width=10)
table.add_column("Name")
table.add_column("Status", justify="right")
@ -804,7 +804,7 @@ class MigrationCLI:
finally:
self.engine.is_running = False
table = Table(show_header=True, header_style="bold magenta", title="Migration Summary & Estimates")
table = Table(show_header=True, header_style="bold #4641D9", title="Migration Summary & Estimates")
table.add_column("Item", width=15)
table.add_column("Count", justify="right", width=10)
table.add_column("Overhead/Details")
@ -829,7 +829,7 @@ class MigrationCLI:
console.print("")
console.print(table)
if not Confirm.ask(f"\nMigrate messages from Discord [cyan]#{source_channel.name}[/cyan] to Fluxer [magenta]#{target_channel.get('name')}[/magenta]?"):
if not Confirm.ask(f"\nMigrate messages from Discord [cyan]#{source_channel.name}[/cyan] to Fluxer [#4641D9]#{target_channel.get('name')}[/#4641D9]?"):
return
# 5. Migration Execution