mirror of
https://github.com/Lilac-Rose/Lacie.git
synced 2026-10-01 12:46:39 -05:00
Ported sparkles over from Nova, updated normal sparkle emoji to not be a star
This commit is contained in:
51
bot.py
51
bot.py
@@ -5,7 +5,10 @@ from discord.ext import commands
|
||||
import asyncio
|
||||
import glob
|
||||
import traceback
|
||||
from xp.database import get_db
|
||||
from xp.database import get_db as get_xp_db
|
||||
|
||||
# Import sparkle DB to ensure it exists
|
||||
from sparkle.database import get_db as get_sparkle_db
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -15,15 +18,16 @@ ADMIN_ROLE_ID = int(os.getenv("ADMIN_ROLE_ID"))
|
||||
bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())
|
||||
|
||||
async def load_cogs(folder: str):
|
||||
# List of files that are NOT cogs (utility files)
|
||||
non_cog_files = {"add_xp.py", "database.py", "utils.py", "__init__.py","import_old_data.py", "repair_db.py", "reset_db.py"}
|
||||
|
||||
"""Load all cogs in the folder except utility files"""
|
||||
non_cog_files = {"add_xp.py", "database.py", "utils.py", "__init__.py",
|
||||
"import_old_data.py", "repair_db.py", "reset_db.py"}
|
||||
|
||||
for file in glob.glob(f"{folder}/*.py"):
|
||||
filename = os.path.basename(file)
|
||||
if filename in non_cog_files:
|
||||
print(f"Skipping {filename} (utility file)")
|
||||
continue
|
||||
|
||||
|
||||
module_name = f"{folder}.{os.path.splitext(filename)[0]}"
|
||||
try:
|
||||
await bot.load_extension(module_name)
|
||||
@@ -36,26 +40,34 @@ async def load_cogs(folder: str):
|
||||
async def on_ready():
|
||||
print(f"Logged in as {bot.user}!")
|
||||
|
||||
# Test database connections
|
||||
# Ensure XP database connection works
|
||||
for lifetime in (True, False):
|
||||
try:
|
||||
conn, cur = get_db(lifetime)
|
||||
conn, cur = get_xp_db(lifetime)
|
||||
conn.close()
|
||||
print(f"Database connection successful (lifetime={lifetime})")
|
||||
print(f"XP database connection successful (lifetime={lifetime})")
|
||||
except Exception as e:
|
||||
print(f"Database connection failed (lifetime={lifetime}): {e}")
|
||||
|
||||
# Load cogs FIRST
|
||||
print(f"XP database connection failed (lifetime={lifetime}): {e}")
|
||||
|
||||
# Ensure Sparkle DB exists
|
||||
try:
|
||||
conn = get_sparkle_db()
|
||||
conn.close()
|
||||
print("Sparkle database initialized successfully.")
|
||||
except Exception as e:
|
||||
print(f"Failed to initialize sparkle database: {e}")
|
||||
|
||||
# Load all cogs
|
||||
await load_cogs("commands")
|
||||
await load_cogs("wordbomb")
|
||||
await load_cogs("moderation")
|
||||
await load_cogs("xp")
|
||||
|
||||
# Sync slash commands AFTER cogs are loaded
|
||||
await load_cogs("sparkle") # <-- Load sparkle cogs
|
||||
|
||||
# Sync slash commands after loading cogs
|
||||
try:
|
||||
synced = await bot.tree.sync()
|
||||
print(f"Synced {len(synced)} slash commands")
|
||||
# Print the names of synced commands for debugging
|
||||
for cmd in synced:
|
||||
print(f" - {cmd.name}")
|
||||
except Exception as e:
|
||||
@@ -72,20 +84,21 @@ async def on_command_error(ctx, error):
|
||||
@bot.command(name="reload")
|
||||
@commands.has_role(ADMIN_ROLE_ID)
|
||||
async def reload(ctx):
|
||||
# Reload cogs
|
||||
"""Reload commands cogs and sync slash commands"""
|
||||
await load_cogs("commands")
|
||||
await load_cogs("moderation")
|
||||
await load_cogs("xp")
|
||||
|
||||
# Re-sync slash commands after reload
|
||||
await load_cogs("sparkle") # Reload sparkle cogs
|
||||
|
||||
try:
|
||||
synced = await bot.tree.sync()
|
||||
await ctx.send(f"Cogs reloaded successfully! Synced {len(synced)} slash commands.")
|
||||
except Exception as e:
|
||||
await ctx.send(f"Cogs reloaded but failed to sync slash commands: {e}")
|
||||
|
||||
# hook XP into messages
|
||||
# Hook XP into messages
|
||||
from xp.add_xp import add_xp
|
||||
|
||||
@bot.event
|
||||
async def on_message(message):
|
||||
if message.author.bot:
|
||||
@@ -106,4 +119,4 @@ async def main():
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
asyncio.run(main())
|
||||
|
||||
20
sparkle/database.py
Normal file
20
sparkle/database.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import sqlite3
|
||||
import os
|
||||
|
||||
DB_PATH = os.path.join(os.path.dirname(__file__), "sparkle.db")
|
||||
|
||||
def get_db():
|
||||
"""Return a SQLite3 connection."""
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS sparkles (
|
||||
server_id TEXT,
|
||||
user_id TEXT,
|
||||
epic INTEGER DEFAULT 0,
|
||||
rare INTEGER DEFAULT 0,
|
||||
regular INTEGER DEFAULT 0,
|
||||
PRIMARY KEY (server_id, user_id)
|
||||
)
|
||||
""")
|
||||
conn.commit()
|
||||
return conn
|
||||
73
sparkle/leaderboard.py
Normal file
73
sparkle/leaderboard.py
Normal file
@@ -0,0 +1,73 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from discord import app_commands
|
||||
from discord.utils import escape_markdown
|
||||
from .database import get_db
|
||||
import asyncio
|
||||
|
||||
class SparkleLeaderboard(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.sparkle_emojis = {
|
||||
"epic": "✨",
|
||||
"rare": "🌟",
|
||||
"regular": "💫"
|
||||
}
|
||||
|
||||
|
||||
@commands.hybrid_command(name="sparkleleaderboard", aliases=["sparklelb"], description="Show server Sparkle leaderboard")
|
||||
@app_commands.describe(limit="Number of users to show (max 20)")
|
||||
async def sparkle_leaderboard(self, ctx: commands.Context, limit: int = 10):
|
||||
limit = max(1, min(20, limit))
|
||||
guild_member_ids = {str(member.id) for member in ctx.guild.members}
|
||||
|
||||
if not guild_member_ids:
|
||||
await ctx.send("This server has no members to display.", ephemeral=True)
|
||||
return
|
||||
|
||||
def db_task():
|
||||
conn = get_db()
|
||||
placeholders = ",".join(["?"] * len(guild_member_ids))
|
||||
query = f"""
|
||||
SELECT user_id, epic, rare, regular,
|
||||
(epic + rare + regular) as total
|
||||
FROM sparkles
|
||||
WHERE server_id = ? AND user_id IN ({placeholders})
|
||||
ORDER BY total DESC
|
||||
LIMIT ?
|
||||
"""
|
||||
params = [str(ctx.guild.id), *guild_member_ids, limit]
|
||||
cursor = conn.execute(query, params)
|
||||
results = cursor.fetchall()
|
||||
conn.close()
|
||||
return results
|
||||
|
||||
results = await asyncio.to_thread(db_task)
|
||||
|
||||
if not results:
|
||||
await ctx.send("No sparkle data available for members of this server.", ephemeral=True)
|
||||
return
|
||||
|
||||
embed = discord.Embed(
|
||||
title=f"{escape_markdown(ctx.guild.name)} Sparkle Leaderboard",
|
||||
color=discord.Color.gold()
|
||||
)
|
||||
|
||||
for rank, (user_id, epic, rare, regular, total) in enumerate(results, 1):
|
||||
user = ctx.guild.get_member(int(user_id))
|
||||
display_name = escape_markdown(user.display_name) if user else f"Unknown User ({user_id})"
|
||||
sparkles = (
|
||||
f"{self.sparkle_emojis['epic']} {epic} (Epic) | "
|
||||
f"{self.sparkle_emojis['rare']} {rare} (Rare) | "
|
||||
f"{self.sparkle_emojis['regular']} {regular} (Regular) | "
|
||||
f"**Total:** {total}"
|
||||
)
|
||||
embed.add_field(name=f"{rank}. {display_name}", value=sparkles, inline=False)
|
||||
if rank == 1 and user:
|
||||
embed.set_thumbnail(url=user.display_avatar.url)
|
||||
|
||||
embed.set_footer(text="✨ Epic | 🌟 Rare | 💫 Regular")
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(SparkleLeaderboard(bot))
|
||||
51
sparkle/sparkle.py
Normal file
51
sparkle/sparkle.py
Normal file
@@ -0,0 +1,51 @@
|
||||
import random
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
from .database import get_db
|
||||
import asyncio
|
||||
|
||||
class Sparkle(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.chances = {
|
||||
"epic": (1, "✨", "an **epic sparkle**"),
|
||||
"rare": (10, "🌟", "a **rare sparkle**"),
|
||||
"regular": (1000, "💫", "a **sparkle**")
|
||||
}
|
||||
|
||||
async def _add_sparkle(self, message, sparkle_type):
|
||||
emoji, description = self.chances[sparkle_type][1:]
|
||||
await message.add_reaction(emoji)
|
||||
await message.reply(
|
||||
f"**{message.author.name}** got {description}! {emoji}",
|
||||
mention_author=False
|
||||
)
|
||||
|
||||
def db_task():
|
||||
conn = get_db()
|
||||
conn.execute(
|
||||
f"""INSERT INTO sparkles (server_id, user_id, {sparkle_type})
|
||||
VALUES (?, ?, 1)
|
||||
ON CONFLICT(server_id, user_id) DO UPDATE SET
|
||||
{sparkle_type} = {sparkle_type} + 1""",
|
||||
(str(message.guild.id), str(message.author.id))
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
await asyncio.to_thread(db_task)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message):
|
||||
if message.author.bot or not message.guild:
|
||||
return
|
||||
chance = random.randint(1, 1000000)
|
||||
if chance == 1:
|
||||
await self._add_sparkle(message, "epic")
|
||||
elif chance <= 10:
|
||||
await self._add_sparkle(message, "rare")
|
||||
elif chance <= 1000:
|
||||
await self._add_sparkle(message, "regular")
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(Sparkle(bot))
|
||||
Reference in New Issue
Block a user