208 lines
8.1 KiB
Python
208 lines
8.1 KiB
Python
# ╔══════════════════════════════════════════════════════════════════╗
|
|
# ║ ║
|
|
# ║ +-+-+-+-+-+-+-+-+ ║
|
|
# ║ |H|e|x|a|H|o|s|t| ║
|
|
# ║ +-+-+-+-+-+-+-+-+ ║
|
|
# ║ ║
|
|
# ║ © 2026 HexaHost — All Rights Reserved ║
|
|
# ║ ║
|
|
# ║ discord ── https://discord.gg/hexahost ║
|
|
# ║ github ── https://github.com/theoneandonlymace ║
|
|
# ║ ║
|
|
# ╚══════════════════════════════════════════════════════════════════╝
|
|
|
|
import discord
|
|
from utils.db_paths import db_path
|
|
from utils.emoji import ARROWRED, CROSS, NEXT_ALT1, REDRULESBOOK, RED_BUTTON, RED_PIN, STAR, TICK, ZBACK, ZPAUSE, ZPLAY, ZWARNING
|
|
from discord.ext import commands
|
|
import json
|
|
import os
|
|
import asyncio
|
|
from discord.ui import LayoutView, TextDisplay, Separator, Container
|
|
from utils.cv2 import CV2, build_container
|
|
|
|
|
|
|
|
# Emoji Variables
|
|
CROSS = CROSS
|
|
TICK = TICK
|
|
WARNING = ZWARNING
|
|
WARNING = ZWARNING
|
|
BOOK = REDRULESBOOK
|
|
PLAY = ZPLAY
|
|
PAUSE = ZPAUSE
|
|
STOP = RED_BUTTON
|
|
NEXT = NEXT_ALT1
|
|
BACK = ZBACK
|
|
ARROW = ARROWRED
|
|
PIN = RED_PIN
|
|
STAR = STAR
|
|
|
|
class Counting(commands.Cog):
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
self.data_file = db_path("counting.json")
|
|
if not os.path.exists(self.data_file):
|
|
with open(self.data_file, 'w') as f:
|
|
json.dump({}, f)
|
|
with open(self.data_file, 'r') as f:
|
|
self.counting_data = json.load(f)
|
|
|
|
def save_data(self):
|
|
with open(self.data_file, 'w') as f:
|
|
json.dump(self.counting_data, f, indent=4)
|
|
|
|
def is_enabled(self, guild_id):
|
|
guild_id = str(guild_id)
|
|
return self.counting_data.get(guild_id, {}).get("enabled", False)
|
|
|
|
async def not_enabled_embed(self, ctx):
|
|
await ctx.send(view=CV2(
|
|
f"{BOOK} Counting Settings For {ctx.guild.name}",
|
|
f"**Current Status:** {CROSS} Disabled",
|
|
"**How to Enable:** Use `counting enable` to enable counting."
|
|
))
|
|
|
|
async def send_help_embed(self, ctx):
|
|
await ctx.send(view=CV2(
|
|
f"{BOOK} Counting Commands",
|
|
"Manage and control the counting game settings.\n\n"
|
|
"**counting enable/disable** — Enable or Disable counting in server\n"
|
|
"**counting channel #channel** — Set counting channel\n"
|
|
"**counting config reset/continue** — Set reset mode on mistake\n"
|
|
"**counting reset** — Reset counting back to 0\n"
|
|
"**counting stats** — View current counting stats"
|
|
))
|
|
|
|
@commands.group(name="counting", invoke_without_command=True)
|
|
async def counting(self, ctx):
|
|
if not self.is_enabled(ctx.guild.id):
|
|
await self.not_enabled_embed(ctx)
|
|
else:
|
|
await self.send_help_embed(ctx)
|
|
|
|
@counting.command(name="enable")
|
|
@commands.has_permissions(manage_channels=True)
|
|
async def enable(self, ctx):
|
|
guild_id = str(ctx.guild.id)
|
|
if guild_id not in self.counting_data:
|
|
self.counting_data[guild_id] = {"enabled": True, "channel": None, "count": 0, "reset_on_fail": False}
|
|
else:
|
|
self.counting_data[guild_id]["enabled"] = True
|
|
self.save_data()
|
|
await ctx.send(view=CV2("Counting", f"{TICK} Counting has been Enabled!"))
|
|
|
|
@counting.command(name="disable")
|
|
@commands.has_permissions(manage_channels=True)
|
|
async def disable(self, ctx):
|
|
guild_id = str(ctx.guild.id)
|
|
if guild_id not in self.counting_data:
|
|
await self.not_enabled_embed(ctx)
|
|
return
|
|
self.counting_data[guild_id]["enabled"] = False
|
|
self.save_data()
|
|
await ctx.send(view=CV2("Counting", f"{STOP} Counting has been Disabled!"))
|
|
|
|
@counting.command(name="channel")
|
|
@commands.has_permissions(manage_channels=True)
|
|
async def channel(self, ctx, channel: discord.TextChannel):
|
|
guild_id = str(ctx.guild.id)
|
|
if not self.is_enabled(guild_id):
|
|
await self.not_enabled_embed(ctx)
|
|
return
|
|
self.counting_data[guild_id]["channel"] = channel.id
|
|
self.save_data()
|
|
await ctx.send(view=CV2("Counting", f"{PIN} Counting channel set to {channel.mention}"))
|
|
|
|
@counting.command(name="config")
|
|
@commands.has_permissions(manage_channels=True)
|
|
async def config(self, ctx, mode: str):
|
|
guild_id = str(ctx.guild.id)
|
|
if not self.is_enabled(guild_id):
|
|
await self.not_enabled_embed(ctx)
|
|
return
|
|
if mode.lower() in ["reset", "true", "on"]:
|
|
self.counting_data[guild_id]["reset_on_fail"] = True
|
|
msg = f"{TICK} Counting will now reset on mistakes."
|
|
elif mode.lower() in ["continue", "false", "off"]:
|
|
self.counting_data[guild_id]["reset_on_fail"] = False
|
|
msg = f"{TICK} Counting will now continue on mistakes."
|
|
else:
|
|
await ctx.send(f"{CROSS} Invalid mode! Use `reset` or `continue`.")
|
|
return
|
|
self.save_data()
|
|
await ctx.send(view=CV2("Counting", msg))
|
|
|
|
@counting.command(name="reset")
|
|
@commands.has_permissions(manage_channels=True)
|
|
async def reset(self, ctx):
|
|
guild_id = str(ctx.guild.id)
|
|
if not self.is_enabled(guild_id):
|
|
await self.not_enabled_embed(ctx)
|
|
return
|
|
self.counting_data[guild_id]["count"] = 0
|
|
self.save_data()
|
|
await ctx.send(view=CV2("Counting", f"{NEXT} Counting has been reset to 0!"))
|
|
|
|
@counting.command(name="stats")
|
|
async def stats(self, ctx):
|
|
guild_id = str(ctx.guild.id)
|
|
if not self.is_enabled(guild_id):
|
|
await self.not_enabled_embed(ctx)
|
|
return
|
|
data = self.counting_data[guild_id]
|
|
channel = ctx.guild.get_channel(data["channel"]) if data["channel"] else None
|
|
channel_str = channel.mention if channel else "Not Set"
|
|
reset_str = f"{TICK} Yes" if data["reset_on_fail"] else f"{CROSS} No"
|
|
await ctx.send(view=CV2(
|
|
f"{BOOK} Counting Stats",
|
|
f"**Current Count:** {data['count']}\n"
|
|
f"**Channel:** {channel_str}\n"
|
|
f"**Reset on Mistake:** {reset_str}"
|
|
))
|
|
|
|
@commands.Cog.listener()
|
|
async def on_message(self, message):
|
|
if message.author.bot:
|
|
return
|
|
|
|
guild_id = str(message.guild.id)
|
|
if guild_id not in self.counting_data:
|
|
return
|
|
|
|
data = self.counting_data[guild_id]
|
|
if not data.get("enabled", False):
|
|
return
|
|
|
|
if message.channel.id != data.get("channel"):
|
|
return
|
|
|
|
content = message.content.strip()
|
|
|
|
if not content.isdigit():
|
|
msg = await message.channel.send(f"{WARNING} Alphabet not allowed!")
|
|
await asyncio.sleep(3)
|
|
await msg.delete()
|
|
await message.delete()
|
|
return
|
|
|
|
number = int(content)
|
|
expected_number = data.get("count", 0) + 1
|
|
|
|
if number != expected_number:
|
|
msg = await message.channel.send(f"{CROSS} Wrong number entered! Expected number is **{expected_number}**")
|
|
await asyncio.sleep(3)
|
|
await msg.delete()
|
|
await message.delete()
|
|
if data.get("reset_on_fail", False):
|
|
self.counting_data[guild_id]["count"] = 0
|
|
self.save_data()
|
|
return
|
|
|
|
# Correct number
|
|
self.counting_data[guild_id]["count"] = number
|
|
self.save_data()
|
|
await message.add_reaction(TICK)
|
|
|
|
def setup(bot):
|
|
bot.add_cog(Counting(bot)) |