CCCPaste

28a9b74589f04

import discord
from discord.ext import commands
from discord import app_commands
import aiosqlite
from datetime import datetime, date
import pytz  # fallback for zoneinfo because im sped

# Configuration
TOKEN = "YOUR_TOKEN_HERE"  # replace with your bot token
ADMIN_LOG_CHANNEL_ID = None  # Optional if you want

# Timezone fallback (US Central)
central_tz = pytz.timezone("America/Chicago")

# Intents setup
intents = discord.Intents.default()
intents.members = True
intents.guilds = True
intents.message_content = True
intents.guild_messages = True
intents.guild_reactions = True

bot = commands.Bot(command_prefix="!", intents=intents)

def current_central_date():
    return datetime.now(central_tz).date().isoformat()

@bot.event
async def on_ready():
    if not hasattr(bot, 'db'):
        bot.db = await aiosqlite.connect('thanks.db')
        await bot.db.execute(
            """
            CREATE TABLE IF NOT EXISTS thread_thanks (
                guild_id INTEGER, thread_id INTEGER, from_id INTEGER, to_id INTEGER, timestamp TEXT,
                PRIMARY KEY (guild_id, thread_id, from_id, to_id)
            )
            """
        )
        await bot.db.execute(
            """
            CREATE TABLE IF NOT EXISTS daily_thanks (
                guild_id INTEGER, from_id INTEGER, to_id INTEGER, date TEXT, timestamp TEXT,
                PRIMARY KEY (guild_id, from_id, to_id, date)
            )
            """
        )
        await bot.db.execute(
            """
            CREATE TABLE IF NOT EXISTS totals (
                guild_id INTEGER, user_id INTEGER, count INTEGER,
                PRIMARY KEY (guild_id, user_id)
            )
            """
        )
        await bot.db.commit()
        print("Database initialized.")
    if not hasattr(bot, 'synced'):
        await bot.tree.sync()
        bot.synced = True
        print("Slash commands synced.")
    print(f"Logged in as {bot.user} (ID: {bot.user.id})")

# Helpers
async def log_action(content):
    if ADMIN_LOG_CHANNEL_ID:
        channel = bot.get_channel(ADMIN_LOG_CHANNEL_ID)
        if channel:
            await channel.send(content)

async def has_thanked_in_thread(guild_id, thread_id, from_id, to_id):
    cursor = await bot.db.execute(
        "SELECT 1 FROM thread_thanks WHERE guild_id = ? AND thread_id = ? AND from_id = ? AND to_id = ?",
        (guild_id, thread_id, from_id, to_id)
    )
    exists = await cursor.fetchone()
    await cursor.close()
    return exists is not None

async def has_thanked_today(guild_id, from_id, to_id, date_str):
    cursor = await bot.db.execute(
        "SELECT 1 FROM daily_thanks WHERE guild_id = ? AND from_id = ? AND to_id = ? AND date = ?",
        (guild_id, from_id, to_id, date_str)
    )
    exists = await cursor.fetchone()
    await cursor.close()
    return exists is not None

async def user_participated(thread, user_id):
    async for message in thread.history(limit=100):
        if message.author.id == user_id:
            return True
    return False

async def record_thank(guild_id, from_id, to_id, context_id, is_thread):
    timestamp = datetime.utcnow().isoformat()
    if is_thread:
        await bot.db.execute(
            "INSERT OR IGNORE INTO thread_thanks VALUES (?, ?, ?, ?, ?)",
            (guild_id, context_id, from_id, to_id, timestamp)
        )
    else:
        today = current_central_date()
        await bot.db.execute(
            "INSERT OR IGNORE INTO daily_thanks VALUES (?, ?, ?, ?, ?)",
            (guild_id, from_id, to_id, today, timestamp)
        )
    await bot.db.execute(
        "INSERT INTO totals(guild_id, user_id, count) VALUES (?, ?, 1)"
        " ON CONFLICT(guild_id, user_id) DO UPDATE SET count = count + 1",
        (guild_id, to_id)
    )
    await bot.db.commit()

# Slash Command: Thank
@bot.tree.command(name="thank", description="Thank another user")
async def thank(interaction: discord.Interaction, user: discord.Member):
    from_user = interaction.user
    to_user = user
    channel = interaction.channel
    guild = interaction.guild

    if guild is None:
        await interaction.response.send_message("❌ Must be used in a server.", ephemeral=True)
        return
    if to_user.bot or to_user.id == from_user.id:
        await interaction.response.send_message("❌ Cannot thank bots or yourself.", ephemeral=True)
        return

    is_thread = isinstance(channel, discord.Thread)
    if is_thread:
        if not await user_participated(channel, to_user.id):
            await interaction.response.send_message(f"❌ {to_user.display_name} has not participated in this thread.", ephemeral=True)
            return
        if await has_thanked_in_thread(guild.id, channel.id, from_user.id, to_user.id):
            await interaction.response.send_message("❌ Already thanked this user in this thread.", ephemeral=True)
            return
    else:
        today = current_central_date()
        if await has_thanked_today(guild.id, from_user.id, to_user.id, today):
            await interaction.response.send_message("❌ Already thanked this user today.", ephemeral=True)
            return

    await record_thank(guild.id, from_user.id, to_user.id, channel.id if is_thread else None, is_thread)
    await interaction.response.send_message(f"✅ You thanked {to_user.mention}!", ephemeral=True)
    await log_action(f"{from_user} thanked {to_user} via /thank in {channel.mention}")

# Slash Command: Top
@bot.tree.command(name="topthanks", description="Show top 10 thanked users")
async def topthanks(interaction: discord.Interaction):
    guild_id = interaction.guild.id
    cursor = await bot.db.execute(
        "SELECT user_id, count FROM totals WHERE guild_id = ? ORDER BY count DESC LIMIT 10", (guild_id,)
    )
    results = await cursor.fetchall()
    await cursor.close()

    lines = []
    for i, (uid, count) in enumerate(results, 1):
        member = interaction.guild.get_member(uid)
        name = member.display_name if member else f"User ID {uid}"
        lines.append(f"{i}. {name} — {count} thanks")

    if lines:
        await interaction.response.send_message("🏆 **Top 10 Thanked Users:**\n" + "\n".join(lines), ephemeral=True)
    else:
        await interaction.response.send_message("No data yet.", ephemeral=True)

# Slash Command: My Thanks
@bot.tree.command(name="mythanks", description="Show how many thanks you've received")
async def mythanks(interaction: discord.Interaction):
    guild_id = interaction.guild.id
    user_id = interaction.user.id
    cursor = await bot.db.execute(
        "SELECT count FROM totals WHERE guild_id = ? AND user_id = ?",
        (guild_id, user_id)
    )
    result = await cursor.fetchone()
    await cursor.close()

    total = result[0] if result else 0
    await interaction.response.send_message(f"You have been thanked **{total}** times.", ephemeral=True)

# Reaction Handler
@bot.event
async def on_reaction_add(reaction, user):
    if str(reaction.emoji) != '✅' or user.bot:
        return
    msg = reaction.message
    guild = msg.guild
    if not guild or not msg.author:
        return
    to_user = msg.author
    from_user = user
    if to_user.bot or from_user.id == to_user.id:
        try: await from_user.send("❌ You cannot thank bots or yourself.")
        except: pass
        return

    channel = msg.channel
    is_thread = isinstance(channel, discord.Thread)

    if is_thread:
        if not await user_participated(channel, to_user.id):
            try: await from_user.send(f"❌ {to_user.display_name} has not posted in this thread.")
            except: pass
            await msg.remove_reaction(reaction.emoji, from_user)
            return
        if await has_thanked_in_thread(guild.id, channel.id, from_user.id, to_user.id):
            try: await from_user.send(f"❌ Already thanked {to_user.display_name} in this thread.")
            except: pass
            await msg.remove_reaction(reaction.emoji, from_user)
            return
    else:
        today = current_central_date()
        if await has_thanked_today(guild.id, from_user.id, to_user.id, today):
            try: await from_user.send(f"❌ Already thanked {to_user.display_name} today.")
            except: pass
            await msg.remove_reaction(reaction.emoji, from_user)
            return

    await record_thank(guild.id, from_user.id, to_user.id, channel.id if is_thread else None, is_thread)
    await log_action(f"{from_user} thanked {to_user} via ✅ in {channel.mention}\n[Jump]({msg.jump_url})")

bot.run(TOKEN)