Skip to content

Commit 31d7815

Browse files
feat: Category Creation
1 parent 5fee705 commit 31d7815

File tree

1 file changed

+307
-0
lines changed

1 file changed

+307
-0
lines changed

gitcord/cogs/general.py

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,154 @@ async def slashping(self, interaction: discord.Interaction) -> None:
193193
)
194194
await interaction.response.send_message(embed=embed)
195195

196+
@app_commands.command(name="createcategory", description="Create a category and its channels from YAML configuration")
197+
@app_commands.describe(yaml_path="Path to the category YAML file (optional)")
198+
async def createcategory_slash(self, interaction: discord.Interaction, yaml_path: str = None) -> None:
199+
"""Slash command to create a category and its channels based on YAML configuration."""
200+
await interaction.response.defer()
201+
202+
# Use default path if none provided
203+
if yaml_path is None:
204+
yaml_path = "/home/user/Projects/gitcord-template/community/category.yaml"
205+
206+
try:
207+
# Check if the user has permission to manage channels
208+
if not interaction.user.guild_permissions.manage_channels:
209+
embed = create_embed(
210+
title="❌ Permission Denied",
211+
description="You need the 'Manage Channels' permission to use this command.",
212+
color=discord.Color.red()
213+
)
214+
await interaction.followup.send(embed=embed)
215+
return
216+
217+
# Parse category configuration
218+
try:
219+
with open(yaml_path, 'r', encoding='utf-8') as file:
220+
category_config = yaml.safe_load(file)
221+
except FileNotFoundError:
222+
embed = create_embed(
223+
title="❌ File Not Found",
224+
description=f"Category YAML file not found at: {yaml_path}",
225+
color=discord.Color.red()
226+
)
227+
await interaction.followup.send(embed=embed)
228+
return
229+
except yaml.YAMLError as e:
230+
embed = create_embed(
231+
title="❌ Invalid YAML",
232+
description=f"Failed to parse YAML file: {str(e)}",
233+
color=discord.Color.red()
234+
)
235+
await interaction.followup.send(embed=embed)
236+
return
237+
238+
# Validate required fields
239+
required_fields = ['name', 'type', 'channels']
240+
for field in required_fields:
241+
if field not in category_config:
242+
embed = create_embed(
243+
title="❌ Invalid Configuration",
244+
description=f"Missing required field: {field}",
245+
color=discord.Color.red()
246+
)
247+
await interaction.followup.send(embed=embed)
248+
return
249+
250+
# Create the category
251+
category_kwargs = {
252+
'name': category_config['name'],
253+
'position': category_config.get('position', 0)
254+
}
255+
256+
new_category = await interaction.guild.create_category(**category_kwargs)
257+
created_channels = []
258+
259+
# Create channels within the category
260+
for channel_name in category_config['channels']:
261+
try:
262+
# Construct path to individual channel YAML file
263+
channel_yaml_path = f"/home/user/Projects/gitcord-template/community/{channel_name}.yaml"
264+
265+
# Parse individual channel configuration
266+
channel_config = parse_channel_config(channel_yaml_path)
267+
268+
# Prepare channel creation parameters
269+
channel_kwargs = {
270+
'name': channel_config['name'],
271+
'category': new_category,
272+
'topic': channel_config.get('topic', ''),
273+
'nsfw': channel_config.get('nsfw', False)
274+
}
275+
276+
# Set position if specified
277+
if 'position' in channel_config:
278+
channel_kwargs['position'] = channel_config['position']
279+
280+
# Create the channel based on type
281+
if channel_config['type'].lower() == 'text':
282+
new_channel = await interaction.guild.create_text_channel(**channel_kwargs)
283+
elif channel_config['type'].lower() == 'voice':
284+
new_channel = await interaction.guild.create_voice_channel(**channel_kwargs)
285+
else:
286+
logger.warning("Skipping channel '%s': Invalid type '%s'",
287+
channel_name, channel_config['type'])
288+
continue
289+
290+
created_channels.append(new_channel)
291+
logger.info("Channel '%s' created successfully in category '%s'",
292+
channel_config['name'], category_config['name'])
293+
294+
except Exception as e:
295+
logger.error("Failed to create channel '%s': %s", channel_name, e)
296+
continue
297+
298+
# Create success embed
299+
embed = create_embed(
300+
title="✅ Category Created",
301+
description=f"Successfully created category: **{new_category.name}**",
302+
color=discord.Color.green()
303+
)
304+
305+
# Add fields
306+
embed.add_field(name="Category Name", value=new_category.name, inline=True)
307+
embed.add_field(name="Category Type", value=category_config['type'], inline=True)
308+
embed.add_field(name="Position", value=category_config.get('position', 0), inline=True)
309+
embed.add_field(name="Channels Created", value=f"{len(created_channels)}/{len(category_config['channels'])}", inline=False)
310+
311+
if created_channels:
312+
channel_list = "\n".join([f"• {channel.mention}" for channel in created_channels])
313+
embed.add_field(name="Created Channels", value=channel_list, inline=False)
314+
315+
await interaction.followup.send(embed=embed)
316+
logger.info("Category '%s' with %d channels created successfully by %s",
317+
category_config['name'], len(created_channels), interaction.user)
318+
319+
except discord.Forbidden:
320+
embed = create_embed(
321+
title="❌ Permission Error",
322+
description="I don't have permission to create categories or channels in this server.",
323+
color=discord.Color.red()
324+
)
325+
await interaction.followup.send(embed=embed)
326+
logger.error("Permission error in createcategory slash command")
327+
except discord.HTTPException as e:
328+
embed = create_embed(
329+
title="❌ Discord Error",
330+
description=f"Discord API error: {str(e)}",
331+
color=discord.Color.red()
332+
)
333+
await interaction.followup.send(embed=embed)
334+
logger.error("Discord HTTP error in createcategory slash command: %s", e)
335+
except Exception as e: # pylint: disable=broad-except
336+
embed = create_embed(
337+
title="❌ Unexpected Error",
338+
description=f"An unexpected error occurred: {str(e)}",
339+
color=discord.Color.red()
340+
)
341+
await interaction.followup.send(embed=embed)
342+
logger.error("Unexpected error in createcategory slash command: %s", e)
343+
196344
@commands.command(name='hello')
197345
async def hello(self, ctx: commands.Context) -> None:
198346
"""Simple hello world command."""
@@ -335,6 +483,165 @@ async def createchannel_error(self, ctx: commands.Context,
335483
logger.error("Error in createchannel command: %s", error)
336484
await ctx.send(f"An error occurred: {error}")
337485

486+
@commands.command(name='createcategory')
487+
@commands.has_permissions(manage_channels=True)
488+
async def createcategory(self, ctx: commands.Context) -> None:
489+
"""Create a category and its channels based on properties defined in a YAML file."""
490+
yaml_path = "/home/user/Projects/gitcord-template/community/category.yaml"
491+
492+
try:
493+
# Check if the user has permission to manage channels
494+
if not ctx.author.guild_permissions.manage_channels:
495+
embed = create_embed(
496+
title="❌ Permission Denied",
497+
description="You need the 'Manage Channels' permission to use this command.",
498+
color=discord.Color.red()
499+
)
500+
await ctx.send(embed=embed)
501+
return
502+
503+
# Parse category configuration
504+
try:
505+
with open(yaml_path, 'r', encoding='utf-8') as file:
506+
category_config = yaml.safe_load(file)
507+
except FileNotFoundError:
508+
embed = create_embed(
509+
title="❌ File Not Found",
510+
description=f"Category YAML file not found at: {yaml_path}",
511+
color=discord.Color.red()
512+
)
513+
await ctx.send(embed=embed)
514+
return
515+
except yaml.YAMLError as e:
516+
embed = create_embed(
517+
title="❌ Invalid YAML",
518+
description=f"Failed to parse YAML file: {str(e)}",
519+
color=discord.Color.red()
520+
)
521+
await ctx.send(embed=embed)
522+
return
523+
524+
# Validate required fields
525+
required_fields = ['name', 'type', 'channels']
526+
for field in required_fields:
527+
if field not in category_config:
528+
embed = create_embed(
529+
title="❌ Invalid Configuration",
530+
description=f"Missing required field: {field}",
531+
color=discord.Color.red()
532+
)
533+
await ctx.send(embed=embed)
534+
return
535+
536+
# Create the category
537+
category_kwargs = {
538+
'name': category_config['name'],
539+
'position': category_config.get('position', 0)
540+
}
541+
542+
new_category = await ctx.guild.create_category(**category_kwargs)
543+
created_channels = []
544+
545+
# Create channels within the category
546+
for channel_name in category_config['channels']:
547+
try:
548+
# Construct path to individual channel YAML file
549+
channel_yaml_path = f"/home/user/Projects/gitcord-template/community/{channel_name}.yaml"
550+
551+
# Parse individual channel configuration
552+
channel_config = parse_channel_config(channel_yaml_path)
553+
554+
# Prepare channel creation parameters
555+
channel_kwargs = {
556+
'name': channel_config['name'],
557+
'category': new_category,
558+
'topic': channel_config.get('topic', ''),
559+
'nsfw': channel_config.get('nsfw', False)
560+
}
561+
562+
# Set position if specified
563+
if 'position' in channel_config:
564+
channel_kwargs['position'] = channel_config['position']
565+
566+
# Create the channel based on type
567+
if channel_config['type'].lower() == 'text':
568+
new_channel = await ctx.guild.create_text_channel(**channel_kwargs)
569+
elif channel_config['type'].lower() == 'voice':
570+
new_channel = await ctx.guild.create_voice_channel(**channel_kwargs)
571+
else:
572+
logger.warning("Skipping channel '%s': Invalid type '%s'",
573+
channel_name, channel_config['type'])
574+
continue
575+
576+
created_channels.append(new_channel)
577+
logger.info("Channel '%s' created successfully in category '%s'",
578+
channel_config['name'], category_config['name'])
579+
580+
except Exception as e:
581+
logger.error("Failed to create channel '%s': %s", channel_name, e)
582+
continue
583+
584+
# Create success embed
585+
embed = create_embed(
586+
title="✅ Category Created",
587+
description=f"Successfully created category: **{new_category.name}**",
588+
color=discord.Color.green()
589+
)
590+
591+
# Add fields
592+
embed.add_field(name="Category Name", value=new_category.name, inline=True)
593+
embed.add_field(name="Category Type", value=category_config['type'], inline=True)
594+
embed.add_field(name="Position", value=category_config.get('position', 0), inline=True)
595+
embed.add_field(name="Channels Created", value=f"{len(created_channels)}/{len(category_config['channels'])}", inline=False)
596+
597+
if created_channels:
598+
channel_list = "\n".join([f"• {channel.mention}" for channel in created_channels])
599+
embed.add_field(name="Created Channels", value=channel_list, inline=False)
600+
601+
await ctx.send(embed=embed)
602+
logger.info("Category '%s' with %d channels created successfully by %s",
603+
category_config['name'], len(created_channels), ctx.author)
604+
605+
except discord.Forbidden:
606+
embed = create_embed(
607+
title="❌ Permission Error",
608+
description="I don't have permission to create categories or channels in this server.",
609+
color=discord.Color.red()
610+
)
611+
await ctx.send(embed=embed)
612+
logger.error("Permission error in createcategory command")
613+
except discord.HTTPException as e:
614+
embed = create_embed(
615+
title="❌ Discord Error",
616+
description=f"Discord API error: {str(e)}",
617+
color=discord.Color.red()
618+
)
619+
await ctx.send(embed=embed)
620+
logger.error("Discord HTTP error in createcategory command: %s", e)
621+
except Exception as e: # pylint: disable=broad-except
622+
embed = create_embed(
623+
title="❌ Unexpected Error",
624+
description=f"An unexpected error occurred: {str(e)}",
625+
color=discord.Color.red()
626+
)
627+
await ctx.send(embed=embed)
628+
logger.error("Unexpected error in createcategory command: %s", e)
629+
630+
@createcategory.error
631+
async def createcategory_error(self, ctx: commands.Context,
632+
error: commands.CommandError) -> None:
633+
"""Handle errors for the createcategory command."""
634+
if isinstance(error, commands.MissingPermissions):
635+
embed = create_embed(
636+
title="❌ Permission Denied",
637+
description="You need the 'Manage Channels' permission to use this command.",
638+
color=discord.Color.red()
639+
)
640+
await ctx.send(embed=embed)
641+
else:
642+
logger.error("Error in createcategory command: %s", error)
643+
await ctx.send(f"An error occurred: {error}")
644+
338645
@commands.Cog.listener()
339646
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError) -> None:
340647
"""Handle command errors."""

0 commit comments

Comments
 (0)