fix voice channel
This commit is contained in:
parent
939e063d46
commit
93c54c4d0f
4 changed files with 101 additions and 47 deletions
|
|
@ -998,7 +998,8 @@ class BackupReader:
|
||||||
Forbidden = BackupForbidden
|
Forbidden = BackupForbidden
|
||||||
|
|
||||||
CHANNEL_TYPE_TEXT = ChannelType.text
|
CHANNEL_TYPE_TEXT = ChannelType.text
|
||||||
CHANNEL_TYPE_NEWS = ChannelType.voice # simplified
|
CHANNEL_TYPE_VOICE = ChannelType.voice
|
||||||
|
CHANNEL_TYPE_NEWS = ChannelType.news
|
||||||
CHANNEL_TYPE_FORUM = ChannelType.forum
|
CHANNEL_TYPE_FORUM = ChannelType.forum
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,17 @@ async def migrate_channels(context: MigrationContext, progress_callback: Callabl
|
||||||
"""
|
"""
|
||||||
# Sort by position to respect Discord arrangement
|
# Sort by position to respect Discord arrangement
|
||||||
categories = sorted(await context.discord_reader.get_categories(), key=lambda c: getattr(c, 'position', 0))
|
categories = sorted(await context.discord_reader.get_categories(), key=lambda c: getattr(c, 'position', 0))
|
||||||
channels = sorted(await context.discord_reader.get_channels(), key=lambda c: getattr(c, 'position', 0))
|
all_channels = sorted(await context.discord_reader.get_channels(), key=lambda c: getattr(c, 'position', 0))
|
||||||
|
|
||||||
|
# Only migrate text-like and voice channels. Forum channels are not yet supported in Fluxer.
|
||||||
|
reader = context.discord_reader
|
||||||
|
channels = [
|
||||||
|
ch for ch in all_channels
|
||||||
|
if ch.type != reader.CHANNEL_TYPE_FORUM
|
||||||
|
]
|
||||||
|
skipped = [ch.name for ch in all_channels if ch not in channels]
|
||||||
|
if skipped:
|
||||||
|
logger.info(f"Skipping {len(skipped)} forum channel(s): {', '.join(skipped)}")
|
||||||
|
|
||||||
cloned_info = {
|
cloned_info = {
|
||||||
"categories_created": [],
|
"categories_created": [],
|
||||||
|
|
@ -130,13 +140,27 @@ async def migrate_channels(context: MigrationContext, progress_callback: Callabl
|
||||||
parent_id = context.state.get_fluxer_category_id(str(channel.category_id)) if channel.category_id else None
|
parent_id = context.state.get_fluxer_category_id(str(channel.category_id)) if channel.category_id else None
|
||||||
pos = getattr(channel, 'position', None)
|
pos = getattr(channel, 'position', None)
|
||||||
|
|
||||||
|
# Map Discord-specific types to target-supported types
|
||||||
|
# 5 (News) -> 0 (Text), and fallback any unknown non-voice types to text
|
||||||
|
raw_type = channel.type.value if hasattr(channel.type, 'value') else 0
|
||||||
|
if raw_type == context.discord_reader.CHANNEL_TYPE_VOICE.value:
|
||||||
|
ch_type = 2
|
||||||
|
is_voice = True
|
||||||
|
elif raw_type in [context.discord_reader.CHANNEL_TYPE_TEXT.value, context.discord_reader.CHANNEL_TYPE_NEWS.value]:
|
||||||
|
ch_type = 0
|
||||||
|
is_voice = False
|
||||||
|
else:
|
||||||
|
# Fallback for Stage channels (13) etc. to Text for safety
|
||||||
|
ch_type = 0
|
||||||
|
is_voice = False
|
||||||
|
|
||||||
fluxer_id = await context.fluxer_writer.create_channel(
|
fluxer_id = await context.fluxer_writer.create_channel(
|
||||||
name=channel.name,
|
name=channel.name,
|
||||||
topic=topic,
|
topic=topic if not is_voice else "",
|
||||||
type=0,
|
type=ch_type,
|
||||||
parent_id=parent_id,
|
parent_id=parent_id,
|
||||||
nsfw=nsfw,
|
nsfw=nsfw if not is_voice else False,
|
||||||
slowmode_delay=slowmode,
|
slowmode_delay=slowmode if not is_voice else 0,
|
||||||
position=pos
|
position=pos
|
||||||
)
|
)
|
||||||
context.state.set_channel_mapping(state_key, fluxer_id)
|
context.state.set_channel_mapping(state_key, fluxer_id)
|
||||||
|
|
@ -147,7 +171,8 @@ async def migrate_channels(context: MigrationContext, progress_callback: Callabl
|
||||||
cloned_info["structure"][parent_name] = []
|
cloned_info["structure"][parent_name] = []
|
||||||
cloned_info["structure"][parent_name].append(channel.name)
|
cloned_info["structure"][parent_name].append(channel.name)
|
||||||
|
|
||||||
# Sync again immediately because some properties (like slowmode) are ignored on creation
|
# Sync again immediately (only for non-voice channels)
|
||||||
|
if not is_voice:
|
||||||
await context.fluxer_writer.modify_channel(
|
await context.fluxer_writer.modify_channel(
|
||||||
channel_id=fluxer_id,
|
channel_id=fluxer_id,
|
||||||
parent_id=parent_id,
|
parent_id=parent_id,
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,21 @@ async def migrate_channels(context: MigrationContext, progress_callback: Callabl
|
||||||
force: If True, re-create channels even if they exist in state.
|
force: If True, re-create channels even if they exist in state.
|
||||||
"""
|
"""
|
||||||
categories = await context.discord_reader.get_categories()
|
categories = await context.discord_reader.get_categories()
|
||||||
channels = await context.discord_reader.get_channels()
|
all_channels = await context.discord_reader.get_channels()
|
||||||
|
|
||||||
# Sort categories and channels by position to preserve order
|
# Sort categories and channels by position to preserve order
|
||||||
categories = sorted(categories, key=lambda c: getattr(c, 'position', 0))
|
categories = sorted(categories, key=lambda c: getattr(c, 'position', 0))
|
||||||
channels = sorted(channels, key=lambda c: getattr(c, 'position', 0))
|
all_channels = sorted(all_channels, key=lambda c: getattr(c, 'position', 0))
|
||||||
|
|
||||||
|
# Only migrate text-like and voice channels. Forum channels are not yet supported in Stoat.
|
||||||
|
reader = context.discord_reader
|
||||||
|
channels = [
|
||||||
|
ch for ch in all_channels
|
||||||
|
if ch.type != reader.CHANNEL_TYPE_FORUM
|
||||||
|
]
|
||||||
|
skipped = [ch.name for ch in all_channels if ch not in channels]
|
||||||
|
if skipped:
|
||||||
|
logger.info(f"Skipping {len(skipped)} forum channel(s): {', '.join(skipped)}")
|
||||||
|
|
||||||
cloned_info = {
|
cloned_info = {
|
||||||
"categories_created": [],
|
"categories_created": [],
|
||||||
|
|
@ -97,22 +107,7 @@ async def migrate_channels(context: MigrationContext, progress_callback: Callabl
|
||||||
if total == 0:
|
if total == 0:
|
||||||
return cloned_info
|
return cloned_info
|
||||||
|
|
||||||
# 1. Migrate Categories
|
# 1. Create missing channels (unparented for now)
|
||||||
for cat in missing_categories:
|
|
||||||
if not context.is_running: break
|
|
||||||
|
|
||||||
state_key = str(cat.id)
|
|
||||||
target_id = await context.writer.create_channel(cat.name, type=4)
|
|
||||||
if target_id:
|
|
||||||
context.state.set_target_category_mapping(state_key, target_id)
|
|
||||||
cloned_info["categories_created"].append(cat.name)
|
|
||||||
if cat.name not in cloned_info["structure"]:
|
|
||||||
cloned_info["structure"][cat.name] = []
|
|
||||||
|
|
||||||
current_idx += 1
|
|
||||||
if progress_callback: await progress_callback(f"Cat: {cat.name}", "Copying", current_idx, total)
|
|
||||||
|
|
||||||
# 2. Create missing channels (unparented for now)
|
|
||||||
for channel in channels_to_create:
|
for channel in channels_to_create:
|
||||||
if not context.is_running: break
|
if not context.is_running: break
|
||||||
|
|
||||||
|
|
@ -123,13 +118,27 @@ async def migrate_channels(context: MigrationContext, progress_callback: Callabl
|
||||||
|
|
||||||
logger.debug(f"Creating channel {channel.name}: topic={topic}, nsfw={nsfw}, slowmode={slowmode}")
|
logger.debug(f"Creating channel {channel.name}: topic={topic}, nsfw={nsfw}, slowmode={slowmode}")
|
||||||
|
|
||||||
|
# Map Discord-specific types to target-supported types
|
||||||
|
# 5 (News) -> 0 (Text), and fallback any unknown non-voice types to text
|
||||||
|
raw_type = channel.type.value if hasattr(channel.type, 'value') else 0
|
||||||
|
if raw_type == context.discord_reader.CHANNEL_TYPE_VOICE.value:
|
||||||
|
ch_type = 2
|
||||||
|
is_voice = True
|
||||||
|
elif raw_type in [context.discord_reader.CHANNEL_TYPE_TEXT.value, context.discord_reader.CHANNEL_TYPE_NEWS.value]:
|
||||||
|
ch_type = 0
|
||||||
|
is_voice = False
|
||||||
|
else:
|
||||||
|
# Fallback for Stage channels (13) etc. to Text for safety
|
||||||
|
ch_type = 0
|
||||||
|
is_voice = False
|
||||||
|
|
||||||
target_id = await context.writer.create_channel(
|
target_id = await context.writer.create_channel(
|
||||||
name=channel.name,
|
name=channel.name,
|
||||||
topic=topic,
|
topic=topic if not is_voice else "",
|
||||||
type=0,
|
type=ch_type,
|
||||||
parent_id=None,
|
parent_id=None,
|
||||||
nsfw=nsfw,
|
nsfw=nsfw if not is_voice else False,
|
||||||
slowmode_delay=slowmode
|
slowmode_delay=slowmode if not is_voice else 0
|
||||||
)
|
)
|
||||||
if target_id:
|
if target_id:
|
||||||
context.state.set_target_channel_mapping(state_key, target_id)
|
context.state.set_target_channel_mapping(state_key, target_id)
|
||||||
|
|
@ -140,7 +149,8 @@ async def migrate_channels(context: MigrationContext, progress_callback: Callabl
|
||||||
cloned_info["structure"][parent_name] = []
|
cloned_info["structure"][parent_name] = []
|
||||||
cloned_info["structure"][parent_name].append(channel.name)
|
cloned_info["structure"][parent_name].append(channel.name)
|
||||||
|
|
||||||
# Sync properties immediately
|
# Sync properties immediately (only for non-voice channels)
|
||||||
|
if not is_voice:
|
||||||
await context.writer.modify_channel(
|
await context.writer.modify_channel(
|
||||||
channel_id=target_id,
|
channel_id=target_id,
|
||||||
name=channel.name,
|
name=channel.name,
|
||||||
|
|
@ -175,6 +185,21 @@ async def migrate_channels(context: MigrationContext, progress_callback: Callabl
|
||||||
current_idx += 1
|
current_idx += 1
|
||||||
if progress_callback: await progress_callback(channel.name, "Syncing", current_idx, total)
|
if progress_callback: await progress_callback(channel.name, "Syncing", current_idx, total)
|
||||||
|
|
||||||
|
# 3. Create missing categories
|
||||||
|
for cat in missing_categories:
|
||||||
|
if not context.is_running: break
|
||||||
|
|
||||||
|
state_key = str(cat.id)
|
||||||
|
target_id = await context.writer.create_channel(cat.name, type=4)
|
||||||
|
if target_id:
|
||||||
|
context.state.set_target_category_mapping(state_key, target_id)
|
||||||
|
cloned_info["categories_created"].append(cat.name)
|
||||||
|
if cat.name not in cloned_info["structure"]:
|
||||||
|
cloned_info["structure"][cat.name] = []
|
||||||
|
|
||||||
|
current_idx += 1
|
||||||
|
if progress_callback: await progress_callback(f"Cat: {cat.name}", "Copying", current_idx, total)
|
||||||
|
|
||||||
# 4. Final step: Parent the channels into categories via mass server.edit()
|
# 4. Final step: Parent the channels into categories via mass server.edit()
|
||||||
logger.info("Parenting all channels into their respective categories...")
|
logger.info("Parenting all channels into their respective categories...")
|
||||||
# Force refresh server to get latest categories created during migration
|
# Force refresh server to get latest categories created during migration
|
||||||
|
|
|
||||||
|
|
@ -263,9 +263,12 @@ class StoatWriter:
|
||||||
await server.edit(categories=categories)
|
await server.edit(categories=categories)
|
||||||
self._server = None # Clear cache after structural change
|
self._server = None # Clear cache after structural change
|
||||||
return new_id
|
return new_id
|
||||||
|
elif type == 2: # Voice Channel
|
||||||
|
ch = await server.create_voice_channel(name=name)
|
||||||
|
self._server = None # Clear cache
|
||||||
|
return str(ch.id)
|
||||||
else: # Text Channel
|
else: # Text Channel
|
||||||
ch = await server.create_text_channel(name=name, description=topic)
|
ch = await server.create_text_channel(name=name, description=topic)
|
||||||
# We no longer parent here, clone_server.py will do it in bulk
|
|
||||||
self._server = None # Clear cache
|
self._server = None # Clear cache
|
||||||
return str(ch.id)
|
return str(ch.id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue