feat: Add level-up notification settings and toggle command for users

This commit is contained in:
Slipstream 2025-05-29 10:35:45 -06:00
parent 02f2117acc
commit 7bbd21af1d
Signed by: slipstream
GPG Key ID: 13E498CE010AC6FD

View File

@ -35,7 +35,8 @@ class LevelingCog(commands.Cog):
"xp_per_reaction": DEFAULT_XP_PER_REACTION,
"message_cooldown": DEFAULT_XP_COOLDOWN,
"reaction_cooldown": DEFAULT_REACTION_COOLDOWN,
"reaction_xp_enabled": True
"reaction_xp_enabled": True,
"default_level_notifs_enabled": False # New setting: level notifications disabled by default
}
# Load existing data
@ -51,7 +52,13 @@ class LevelingCog(commands.Cog):
with open(LEVELS_FILE, "r", encoding="utf-8") as f:
# Convert string keys (from JSON) back to integers
data = json.load(f)
self.user_data = {int(k): v for k, v in data.items()}
self.user_data = {}
for k, v in data.items():
user_id = int(k)
# Ensure 'level_notifs_enabled' is present with default if missing
if "level_notifs_enabled" not in v:
v["level_notifs_enabled"] = self.config["default_level_notifs_enabled"]
self.user_data[user_id] = v
print(f"Loaded level data for {len(self.user_data)} users")
except Exception as e:
print(f"Error loading level data: {e}")
@ -177,7 +184,12 @@ class LevelingCog(commands.Cog):
def get_user_data(self, user_id: int) -> Dict:
"""Get user data with defaults if not set"""
if user_id not in self.user_data:
self.user_data[user_id] = {"xp": 0, "level": 0, "last_message_time": 0}
self.user_data[user_id] = {
"xp": 0,
"level": 0,
"last_message_time": 0,
"level_notifs_enabled": self.config["default_level_notifs_enabled"]
}
return self.user_data[user_id]
async def add_xp(self, user_id: int, guild_id: int, xp_amount: int = DEFAULT_XP_PER_MESSAGE) -> Optional[int]:
@ -322,18 +334,26 @@ class LevelingCog(commands.Cog):
xp_amount = random.randint(max(1, base_xp - 5), base_xp + 5)
new_level = await self.add_xp(user_id, message.guild.id, xp_amount)
# If user leveled up, send a message
# If user leveled up, send a message if notifications are enabled for them
if new_level:
try:
await message.channel.send(
f"🎉 Congratulations {message.author.mention}! You've reached level **{new_level}**!",
delete_after=10 # Delete after 10 seconds
)
except discord.Forbidden:
pass # Ignore if we can't send messages
user_data = self.get_user_data(user_id)
if user_data.get("level_notifs_enabled", self.config["default_level_notifs_enabled"]):
try:
await message.channel.send(
f"🎉 Congratulations {message.author.mention}! You've reached level **{new_level}**!",
delete_after=10 # Delete after 10 seconds
)
except discord.Forbidden:
pass # Ignore if we can't send messages
@commands.hybrid_command(name="level", description="Check your current level and XP")
async def level_command(self, ctx: commands.Context, member: discord.Member = None):
@commands.hybrid_group(name="level", description="Leveling system commands")
async def level(self, ctx: commands.Context):
"""Leveling system commands"""
if ctx.invoked_subcommand is None:
await ctx.send_help(ctx.command)
@level.hybrid_command(name="check", description="Check your current level and XP")
async def level_check(self, ctx: commands.Context, member: discord.Member = None):
"""Check your current level and XP or another member's"""
target = member or ctx.author
user_data = self.get_user_data(target.id)
@ -362,7 +382,7 @@ class LevelingCog(commands.Cog):
await ctx.send(embed=embed)
@commands.hybrid_command(name="leaderboard", description="Show the server's level leaderboard")
@level.hybrid_command(name="leaderboard", description="Show the server's level leaderboard")
async def leaderboard_command(self, ctx: commands.Context):
"""Show the server's level leaderboard"""
if not ctx.guild:
@ -398,7 +418,7 @@ class LevelingCog(commands.Cog):
await ctx.send(embed=embed)
@commands.hybrid_command(name="register_level_role", description="Register a role for a specific level")
@level.hybrid_command(name="register_role", description="Register a role for a specific level")
@commands.has_permissions(manage_roles=True)
async def register_level_role(self, ctx: commands.Context, level: int, role: discord.Role):
"""Register a role to be assigned at a specific level"""
@ -420,7 +440,7 @@ class LevelingCog(commands.Cog):
await ctx.send(f"✅ Role {role.mention} will now be assigned at level {level}.")
@commands.hybrid_command(name="remove_level_role", description="Remove a level role registration")
@level.hybrid_command(name="remove_role", description="Remove a level role registration")
@commands.has_permissions(manage_roles=True)
async def remove_level_role(self, ctx: commands.Context, level: int):
"""Remove a level role registration"""
@ -438,7 +458,7 @@ class LevelingCog(commands.Cog):
await ctx.send(f"✅ Level {level} role registration has been removed.")
@commands.hybrid_command(name="list_level_roles", description="List all registered level roles")
@level.hybrid_command(name="list_roles", description="List all registered level roles")
async def list_level_roles(self, ctx: commands.Context):
"""List all registered level roles for this server"""
if not ctx.guild:
@ -468,7 +488,7 @@ class LevelingCog(commands.Cog):
await ctx.send(embed=embed)
@commands.hybrid_command(name="restrict_channel", description="Restrict a channel from giving XP")
@level.hybrid_command(name="restrict_channel", description="Restrict a channel from giving XP")
@commands.has_permissions(manage_channels=True)
async def restrict_channel(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""Restrict a channel from giving XP"""
@ -482,7 +502,7 @@ class LevelingCog(commands.Cog):
self.save_restricted_channels()
await ctx.send(f"{target_channel.mention} will no longer give XP for messages.")
@commands.hybrid_command(name="unrestrict_channel", description="Allow a channel to give XP again")
@level.hybrid_command(name="unrestrict_channel", description="Allow a channel to give XP again")
@commands.has_permissions(manage_channels=True)
async def unrestrict_channel(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""Allow a channel to give XP again"""
@ -496,7 +516,7 @@ class LevelingCog(commands.Cog):
self.save_restricted_channels()
await ctx.send(f"{target_channel.mention} will now give XP for messages.")
@commands.hybrid_command(name="process_existing_messages", description="Process existing messages to award XP")
@level.hybrid_command(name="process_messages", description="Process existing messages to award XP")
@commands.is_owner()
async def process_existing_messages(self, ctx: commands.Context, limit: int = 10000):
"""Process existing messages to award XP (Owner only)"""
@ -612,7 +632,7 @@ class LevelingCog(commands.Cog):
self.save_config()
print(f'{self.__class__.__name__} cog has been unloaded and data saved.')
@commands.hybrid_command(name="xp_config", description="Configure XP settings")
@level.hybrid_command(name="config", description="Configure XP settings")
@commands.has_permissions(administrator=True)
async def xp_config(self, ctx: commands.Context, setting: str = None, value: str = None):
"""Configure XP settings for the leveling system"""
@ -702,7 +722,19 @@ class LevelingCog(commands.Cog):
# Save the updated configuration
self.save_config()
@commands.hybrid_command(name="setup_medieval_roles", description="Set up medieval-themed level roles")
@level.hybrid_command(name="toggle_notifs", description="Toggle level-up notifications for yourself")
async def toggle_level_notifs(self, ctx: commands.Context):
"""Toggle level-up notifications for yourself"""
user_data = self.get_user_data(ctx.author.id)
current_status = user_data.get("level_notifs_enabled", self.config["default_level_notifs_enabled"])
new_status = not current_status
user_data["level_notifs_enabled"] = new_status
self.save_user_data()
status_text = "enabled" if new_status else "disabled"
await ctx.send(f"✅ Level-up notifications have been **{status_text}** for you.")
@level.hybrid_command(name="setup_medieval_roles", description="Set up medieval-themed level roles")
@commands.has_permissions(manage_roles=True)
async def setup_medieval_roles(self, ctx: commands.Context):
"""Automatically set up medieval-themed level roles with gender customization"""