Files
Mace-AIO-Discord-Bot---With…/bot/cogs/commands/Birthday.py
2026-07-12 15:16:07 +05:30

179 lines
7.3 KiB
Python

import discord
from discord.ext import commands, tasks
import json
import datetime
import asyncio
import os
from discord.ui import LayoutView, TextDisplay, Separator, Container
from utils.cv2 import CV2, build_container
class CV2(LayoutView):
def __init__(self, title, *sections):
super().__init__(timeout=None)
items = [TextDisplay(f"**{title}**")]
for s in sections:
if s:
items.append(Separator(visible=True))
items.append(TextDisplay(str(s)))
self.add_item(build_container(*items))
def read_db(filename):
"""Read the JSON database file."""
if os.path.exists(filename):
with open(filename, 'r') as f:
return json.load(f)
return {}
def write_db(filename, data):
"""Write data to the JSON database file."""
with open(filename, 'w') as f:
json.dump(data, f, indent=4)
class Birthdays(commands.Cog):
"""Handle birthday notifications and setup."""
def __init__(self, client: commands.Bot):
self.client = client
self.check_birthdays.start()
@commands.command(
name="birthdaysetup",
help="Set up the birthday log channel and role.")
@commands.has_permissions(administrator=True)
@commands.guild_only()
async def birthday_setup(self, ctx: commands.Context, channel: discord.TextChannel, role: discord.Role):
db = read_db('jsondb/birthday_logs.json')
guild_id = str(ctx.guild.id)
if guild_id not in db:
db[guild_id] = {"birthday_channel_id": channel.id, "birthday_role_id": role.id}
else:
db[guild_id]["birthday_channel_id"] = channel.id
db[guild_id]["birthday_role_id"] = role.id
write_db('jsondb/birthday_logs.json', db)
await ctx.send(view=CV2("Birthday Setup", f"Birthday log channel set to {channel.mention} and birthday role set to {role.mention}."))
@commands.command(
name="setbirthday",
help="Set your birthday.")
@commands.guild_only()
async def set_birthday(self, ctx: commands.Context):
def check(msg):
return msg.author.id == ctx.author.id and msg.channel.id == ctx.channel.id
await ctx.send(view=CV2("Birthday Setup", "Please enter your birth day (DD):"))
try:
msg = await self.client.wait_for('message', timeout=60.0, check=check)
day = msg.content.strip().zfill(2)
if not day.isdigit() or int(day) not in range(1, 32):
await ctx.send(view=CV2("Error", "Invalid day entered. Please enter a number between 01 and 31."))
return
await ctx.send(view=CV2("Birthday Setup", "Please enter your birth month (MM):"))
msg = await self.client.wait_for('message', timeout=60.0, check=check)
month = msg.content.strip().zfill(2)
if not month.isdigit() or int(month) not in range(1, 13):
await ctx.send(view=CV2("Error", "Invalid month entered. Please enter a number between 01 and 12."))
return
await ctx.send(view=CV2("Birthday Setup", "Please enter your birth year (YYYY):"))
msg = await self.client.wait_for('message', timeout=60.0, check=check)
year = msg.content.strip()
if not year.isdigit() or len(year) != 4:
await ctx.send(view=CV2("Error", "Invalid year entered. Please enter a valid year in YYYY format."))
return
date = f"{month}-{day}-{year}"
db = read_db('jsondb/birthdays.json')
db[str(ctx.author.id)] = date
write_db('jsondb/birthdays.json', db)
await ctx.send(view=CV2("Success", f"Your birthday has been set to {date}."))
except asyncio.TimeoutError:
await ctx.send(view=CV2("Error", "You took too long to respond. Please try again."))
@commands.command(
name="removebirthday",
help="Remove your birthday.")
@commands.guild_only()
async def remove_birthday(self, ctx: commands.Context):
db = read_db('jsondb/birthdays.json')
if str(ctx.author.id) in db:
del db[str(ctx.author.id)]
write_db('jsondb/birthdays.json', db)
await ctx.send(view=CV2("Success", "Your birthday has been removed."))
else:
await ctx.send(view=CV2("Error", "You have no birthday set."))
@commands.command(
name="listbirthdays",
help="List all members who have their birthday today.")
@commands.guild_only()
async def list_birthdays(self, ctx: commands.Context):
now = datetime.datetime.now()
today_date = now.strftime("%m-%d")
db = read_db('jsondb/birthdays.json')
members_with_birthday = [ctx.guild.get_member(int(user_id)) for user_id, date in db.items() if date.startswith(today_date)]
if members_with_birthday:
mentions = ', '.join(member.mention for member in members_with_birthday if member)
await ctx.send(view=CV2("Birthdays Today", f"Members with birthdays today: {mentions}"))
else:
await ctx.send(view=CV2("Birthdays", "No birthdays today."))
@commands.command(
name="birthday",
help="Check your birthday.")
@commands.guild_only()
async def check_birthday(self, ctx: commands.Context):
db = read_db('jsondb/birthdays.json')
if str(ctx.author.id) in db:
date = db[str(ctx.author.id)]
await ctx.send(view=CV2("Your Birthday", f"Your birthday is set to {date}."))
else:
await ctx.send(view=CV2("Your Birthday", "You haven't set your birthday."))
@tasks.loop(hours=24)
async def check_birthdays(self):
now = datetime.datetime.now()
today_date = now.strftime("%m-%d")
db = read_db('jsondb/birthdays.json')
guild_settings = read_db('jsondb/birthday_logs.json')
for user_id, birthday in db.items():
if birthday.startswith(today_date):
user = self.client.get_user(int(user_id))
if user:
for guild_id, settings in guild_settings.items():
channel_id = settings.get("birthday_channel_id")
role_id = settings.get("birthday_role_id")
if channel_id:
channel = self.client.get_channel(channel_id)
if channel:
await channel.send(view=CV2("Happy Birthday! 🎉", f"Wishing {user.mention} a fantastic birthday!"))
role = discord.utils.get(channel.guild.roles, id=role_id)
if role:
await user.add_roles(role)
break
@check_birthdays.before_loop
async def before_check_birthdays(self):
await self.client.wait_until_ready()
now = datetime.datetime.now()
first_run = datetime.datetime.combine(now.date(), datetime.time(hour=0, minute=0))
if now > first_run:
first_run += datetime.timedelta(days=1)
await asyncio.sleep((first_run - now).total_seconds())
async def setup(client: commands.Bot):
await client.add_cog(Birthdays(client))