improve role mapping and permission syncing
This commit is contained in:
parent
c5abc6d0e5
commit
ab31f889a4
4 changed files with 107 additions and 11 deletions
|
|
@ -158,6 +158,36 @@ class MigrationEngine:
|
||||||
if updates > 0 or removals > 0:
|
if updates > 0 or removals > 0:
|
||||||
logger.info(f"Channel sync: {updates} mapped, {removals} stale mappings removed")
|
logger.info(f"Channel sync: {updates} mapped, {removals} stale mappings removed")
|
||||||
|
|
||||||
|
async def sync_roles_state(self):
|
||||||
|
"""
|
||||||
|
Scans Fluxer for roles matching Discord names and updates state.json mappings.
|
||||||
|
"""
|
||||||
|
discord_roles = await self.discord_reader.get_roles()
|
||||||
|
fluxer_roles = await self.fluxer_writer.client.get_guild_roles(self.config.fluxer_community_id)
|
||||||
|
|
||||||
|
# Build name -> id maps and ID sets for Fluxer for fast lookup
|
||||||
|
fluxer_role_map = {r.get("name"): str(r.get("id")) for r in fluxer_roles if r.get("name")}
|
||||||
|
fluxer_role_ids = {str(r.get("id")) for r in fluxer_roles}
|
||||||
|
|
||||||
|
updates = 0
|
||||||
|
removals = 0
|
||||||
|
|
||||||
|
# Verify and Sync Roles
|
||||||
|
for role in discord_roles:
|
||||||
|
discord_id = str(role.id)
|
||||||
|
fluxer_id = self.state.get_fluxer_role_id(discord_id)
|
||||||
|
|
||||||
|
if fluxer_id:
|
||||||
|
if fluxer_id not in fluxer_role_ids:
|
||||||
|
self.state.remove_role_mapping(discord_id)
|
||||||
|
removals += 1
|
||||||
|
elif role.name in fluxer_role_map:
|
||||||
|
self.state.set_role_mapping(discord_id, fluxer_role_map[role.name])
|
||||||
|
updates += 1
|
||||||
|
|
||||||
|
if updates > 0 or removals > 0:
|
||||||
|
logger.info(f"Role sync: {updates} mapped, {removals} stale mappings removed")
|
||||||
|
|
||||||
async def sync_assets_state(self):
|
async def sync_assets_state(self):
|
||||||
"""
|
"""
|
||||||
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 state.json mappings.
|
||||||
|
|
@ -310,12 +340,38 @@ class MigrationEngine:
|
||||||
if total == 0:
|
if total == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
async def _sync_overwrites(discord_item, fluxer_id):
|
||||||
|
"""Helper to sync role overwrites for a given channel or category."""
|
||||||
|
for target, overwrite in discord_item.overwrites.items():
|
||||||
|
if type(target).__name__ == "Role":
|
||||||
|
discord_role_id = str(target.id)
|
||||||
|
# Handle @everyone role special case
|
||||||
|
if discord_role_id == self.config.discord_server_id:
|
||||||
|
fluxer_role_id = self.config.fluxer_community_id
|
||||||
|
else:
|
||||||
|
fluxer_role_id = self.state.get_fluxer_role_id(discord_role_id)
|
||||||
|
|
||||||
|
if not fluxer_role_id:
|
||||||
|
continue
|
||||||
|
|
||||||
|
allow_val, deny_val = overwrite.pair()
|
||||||
|
await self.fluxer_writer.set_channel_permission(
|
||||||
|
channel_id=fluxer_id,
|
||||||
|
overwrite_id=fluxer_role_id,
|
||||||
|
allow=allow_val.value,
|
||||||
|
deny=deny_val.value,
|
||||||
|
is_role=True
|
||||||
|
)
|
||||||
|
|
||||||
# Sync Category Permissions (Role Overwrites)
|
# Sync Category Permissions (Role Overwrites)
|
||||||
for cat in categories:
|
for cat in categories:
|
||||||
if not self.is_running: break
|
if not self.is_running: break
|
||||||
fluxer_id = self.state.get_fluxer_channel_id(str(cat.id))
|
fluxer_id = self.state.get_fluxer_category_id(str(cat.id))
|
||||||
# In a real implementation, we would diff discord perms
|
if fluxer_id:
|
||||||
# and apply them to fluxer_id using client methods.
|
try:
|
||||||
|
await _sync_overwrites(cat, fluxer_id)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed syncing permissions for category {cat.name}: {e}")
|
||||||
|
|
||||||
current_idx += 1
|
current_idx += 1
|
||||||
if progress_callback: await progress_callback(f"Cat: {cat.name}", current_idx, total)
|
if progress_callback: await progress_callback(f"Cat: {cat.name}", current_idx, total)
|
||||||
|
|
@ -324,7 +380,11 @@ class MigrationEngine:
|
||||||
for channel in channels:
|
for channel in channels:
|
||||||
if not self.is_running: break
|
if not self.is_running: break
|
||||||
fluxer_id = self.state.get_fluxer_channel_id(str(channel.id))
|
fluxer_id = self.state.get_fluxer_channel_id(str(channel.id))
|
||||||
# apply perms
|
if fluxer_id:
|
||||||
|
try:
|
||||||
|
await _sync_overwrites(channel, fluxer_id)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed syncing permissions for channel {channel.name}: {e}")
|
||||||
|
|
||||||
current_idx += 1
|
current_idx += 1
|
||||||
if progress_callback: await progress_callback(channel.name, current_idx, total)
|
if progress_callback: await progress_callback(channel.name, current_idx, total)
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,10 @@ class MigrationState:
|
||||||
def get_fluxer_role_id(self, discord_id: str) -> str | None:
|
def get_fluxer_role_id(self, discord_id: str) -> str | None:
|
||||||
return self.role_map.get(str(discord_id))
|
return self.role_map.get(str(discord_id))
|
||||||
|
|
||||||
|
def remove_role_mapping(self, discord_id: str):
|
||||||
|
self.role_map.pop(str(discord_id), None)
|
||||||
|
self.save()
|
||||||
|
|
||||||
def set_emoji_mapping(self, discord_id: str, fluxer_id: str):
|
def set_emoji_mapping(self, discord_id: str, fluxer_id: str):
|
||||||
self.emoji_map[str(discord_id)] = str(fluxer_id)
|
self.emoji_map[str(discord_id)] = str(fluxer_id)
|
||||||
self.save()
|
self.save()
|
||||||
|
|
|
||||||
|
|
@ -436,9 +436,16 @@ class FluxerWriter:
|
||||||
overwrites = ch.get("permission_overwrites", [])
|
overwrites = ch.get("permission_overwrites", [])
|
||||||
for ow in overwrites:
|
for ow in overwrites:
|
||||||
try:
|
try:
|
||||||
await self.client.delete_channel_permission(ch["id"], ow["id"])
|
await self.client.request(
|
||||||
except Exception:
|
self.client._route(
|
||||||
pass
|
"DELETE",
|
||||||
|
"/channels/{channel_id}/permissions/{overwrite_id}",
|
||||||
|
channel_id=ch["id"],
|
||||||
|
overwrite_id=ow["id"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to delete overwrite {ow['id']} for channel {ch['id']}: {e}")
|
||||||
processed += 1
|
processed += 1
|
||||||
if progress_callback:
|
if progress_callback:
|
||||||
await progress_callback(ch.get("name", "Unknown"), processed, total)
|
await progress_callback(ch.get("name", "Unknown"), processed, total)
|
||||||
|
|
@ -446,6 +453,21 @@ class FluxerWriter:
|
||||||
print(f"Failed to reset permissions for channel {ch.get('name')}: {e}")
|
print(f"Failed to reset permissions for channel {ch.get('name')}: {e}")
|
||||||
return processed
|
return processed
|
||||||
|
|
||||||
|
async def set_channel_permission(self, channel_id: str, overwrite_id: str, allow: int, deny: int, is_role: bool = True):
|
||||||
|
"""Sets a permission overwrite for a channel or category."""
|
||||||
|
assert self.client is not None
|
||||||
|
try:
|
||||||
|
await self.client.edit_channel_permissions(
|
||||||
|
channel_id=int(channel_id),
|
||||||
|
overwrite_id=int(overwrite_id),
|
||||||
|
allow=allow,
|
||||||
|
deny=deny,
|
||||||
|
type=0 if is_role else 1
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to set permission on channel {channel_id} for overwrite {overwrite_id}: {e}")
|
||||||
|
|
||||||
|
|
||||||
async def delete_all_roles(self, progress_callback=None) -> int:
|
async def delete_all_roles(self, progress_callback=None) -> int:
|
||||||
"""
|
"""
|
||||||
Deletes all non-managed, non-default roles in the Fluxer community,
|
Deletes all non-managed, non-default roles in the Fluxer community,
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,8 @@ class MigrationCLI:
|
||||||
"discord_intents": {}, "discord_permissions": {},
|
"discord_intents": {}, "discord_permissions": {},
|
||||||
"fluxer_token": False, "fluxer_bot_name": None,
|
"fluxer_token": False, "fluxer_bot_name": None,
|
||||||
"fluxer_community": False, "fluxer_community_name": None,
|
"fluxer_community": False, "fluxer_community_name": None,
|
||||||
"fluxer_permissions": {}
|
"fluxer_permissions": {},
|
||||||
|
"discord_timeout": False, "fluxer_timeout": False
|
||||||
}
|
}
|
||||||
self.tokens_valid = False
|
self.tokens_valid = False
|
||||||
|
|
||||||
|
|
@ -108,6 +109,7 @@ class MigrationCLI:
|
||||||
console.print(f"[bold red]Discord validation failed with error: {e}[/bold red]")
|
console.print(f"[bold red]Discord validation failed with error: {e}[/bold red]")
|
||||||
else:
|
else:
|
||||||
console.print("[bold red]Discord bot token validation timed out after 10 seconds.[/bold red]")
|
console.print("[bold red]Discord bot token validation timed out after 10 seconds.[/bold red]")
|
||||||
|
self.validation_results["discord_timeout"] = True
|
||||||
discord_task.cancel()
|
discord_task.cancel()
|
||||||
|
|
||||||
# Process Fluxer Result
|
# Process Fluxer Result
|
||||||
|
|
@ -130,6 +132,7 @@ class MigrationCLI:
|
||||||
console.print(f"[bold red]Fluxer validation failed with error: {e}[/bold red]")
|
console.print(f"[bold red]Fluxer validation failed with error: {e}[/bold red]")
|
||||||
else:
|
else:
|
||||||
console.print("[bold red]Fluxer bot token validation timed out after 10 seconds.[/bold red]")
|
console.print("[bold red]Fluxer bot token validation timed out after 10 seconds.[/bold red]")
|
||||||
|
self.validation_results["fluxer_timeout"] = True
|
||||||
fluxer_task.cancel()
|
fluxer_task.cancel()
|
||||||
|
|
||||||
# Only tokens and server/community existence are strictly required for 'tokens_valid'
|
# Only tokens and server/community existence are strictly required for 'tokens_valid'
|
||||||
|
|
@ -168,10 +171,10 @@ class MigrationCLI:
|
||||||
console.print("")
|
console.print("")
|
||||||
console.print(Panel.fit("Fluxer Reaper", style="bold blue"))
|
console.print(Panel.fit("Fluxer Reaper", style="bold blue"))
|
||||||
d_name = self.validation_results.get("discord_server_name")
|
d_name = self.validation_results.get("discord_server_name")
|
||||||
d_display = f"[bold green]\"{d_name}\"[/bold green]" if d_name else "[bold red]NOT SET UP[/bold red]"
|
d_display = f"[bold green]\"{d_name}\"[/bold green]" if d_name else ("[bold yellow]TIMEOUT ERROR[/bold yellow]" if self.validation_results.get("discord_timeout") else "[bold red]NOT SET UP[/bold red]")
|
||||||
|
|
||||||
f_name = self.validation_results.get("fluxer_community_name")
|
f_name = self.validation_results.get("fluxer_community_name")
|
||||||
f_display = f"[bold green]\"{f_name}\"[/bold green]" if f_name else "[bold red]NOT SET UP[/bold red]"
|
f_display = f"[bold green]\"{f_name}\"[/bold green]" if f_name else ("[bold yellow]TIMEOUT ERROR[/bold yellow]" if self.validation_results.get("fluxer_timeout") else "[bold red]NOT SET UP[/bold red]")
|
||||||
|
|
||||||
console.print(f"[bold cyan]Discord Server:[/bold cyan] {d_display}")
|
console.print(f"[bold cyan]Discord Server:[/bold cyan] {d_display}")
|
||||||
console.print(f"[bold #4641D9]Fluxer Community:[/bold #4641D9] {f_display}")
|
console.print(f"[bold #4641D9]Fluxer Community:[/bold #4641D9] {f_display}")
|
||||||
|
|
@ -190,7 +193,7 @@ class MigrationCLI:
|
||||||
val_status = "[bold green][VALID][/bold green]"
|
val_status = "[bold green][VALID][/bold green]"
|
||||||
|
|
||||||
console.print(f"(6) Configuration {val_status}")
|
console.print(f"(6) Configuration {val_status}")
|
||||||
console.print("(7) [bold red]⚠ Danger Zone[/bold red]")
|
console.print("(7) [red]Danger Zone ⚠[/red]")
|
||||||
|
|
||||||
console.print("(Q) Exit")
|
console.print("(Q) Exit")
|
||||||
|
|
||||||
|
|
@ -466,6 +469,13 @@ class MigrationCLI:
|
||||||
return
|
return
|
||||||
elif sub_choice == "F":
|
elif sub_choice == "F":
|
||||||
force = True
|
force = True
|
||||||
|
else:
|
||||||
|
if not Confirm.ask("Clone roles?", default=True):
|
||||||
|
await self.engine.close_connections()
|
||||||
|
return
|
||||||
|
if not Confirm.ask("Are you sure?", default=True):
|
||||||
|
await self.engine.close_connections()
|
||||||
|
return
|
||||||
|
|
||||||
console.print("\n[bold green]Starting Role Migration...[/bold green]")
|
console.print("\n[bold green]Starting Role Migration...[/bold green]")
|
||||||
with Progress(
|
with Progress(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue