Refactor command definitions across multiple cogs to replace hybrid commands with regular commands for consistency. This change enhances clarity and standardizes command handling throughout the bot.
This commit is contained in:
@@ -51,10 +51,24 @@ TICKET_LIMIT_PER_USER = 3
|
||||
# --- Database Class ---
|
||||
class TicketDatabase:
|
||||
def __init__(self, path):
|
||||
self.conn = sqlite3.connect(path, check_same_thread=False)
|
||||
self.path = path
|
||||
self.conn = None
|
||||
self._connect()
|
||||
|
||||
def _connect(self):
|
||||
self.conn = sqlite3.connect(self.path, check_same_thread=False)
|
||||
self.conn.row_factory = sqlite3.Row
|
||||
self._create_tables()
|
||||
|
||||
def _ensure_open(self):
|
||||
if self.conn is None:
|
||||
self._connect()
|
||||
return
|
||||
try:
|
||||
self.conn.execute("SELECT 1")
|
||||
except (sqlite3.ProgrammingError, sqlite3.OperationalError):
|
||||
self._connect()
|
||||
|
||||
def _create_tables(self):
|
||||
with self.conn:
|
||||
self.conn.execute("CREATE TABLE IF NOT EXISTS guild_configs (guild_id INTEGER PRIMARY KEY, panel_channel_id INTEGER, logging_channel_id INTEGER, panel_message_id INTEGER, panel_type TEXT, embed_title TEXT, embed_description TEXT, embed_color INTEGER, embed_image_url TEXT, embed_thumbnail_url TEXT, closed_category_id INTEGER)")
|
||||
@@ -63,13 +77,29 @@ class TicketDatabase:
|
||||
self.conn.execute("CREATE TABLE IF NOT EXISTS user_ticket_counts (guild_id INTEGER, user_id INTEGER, ticket_count INTEGER DEFAULT 0, PRIMARY KEY (guild_id, user_id))")
|
||||
|
||||
def execute(self, q, p=()):
|
||||
with self.conn: return self.conn.execute(q, p)
|
||||
self._ensure_open()
|
||||
with self.conn:
|
||||
return self.conn.execute(q, p)
|
||||
|
||||
def fetchone(self, q, p=()):
|
||||
cur = self.conn.cursor(); cur.execute(q, p); return cur.fetchone()
|
||||
self._ensure_open()
|
||||
cur = self.conn.cursor()
|
||||
cur.execute(q, p)
|
||||
return cur.fetchone()
|
||||
|
||||
def fetchall(self, q, p=()):
|
||||
cur = self.conn.cursor(); cur.execute(q, p); return cur.fetchall()
|
||||
self._ensure_open()
|
||||
cur = self.conn.cursor()
|
||||
cur.execute(q, p)
|
||||
return cur.fetchall()
|
||||
|
||||
def close(self):
|
||||
if self.conn: self.conn.close()
|
||||
if self.conn is not None:
|
||||
try:
|
||||
self.conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
self.conn = None
|
||||
|
||||
# --- Utility Functions ---
|
||||
async def get_or_create_log_channel(db, guild):
|
||||
@@ -270,13 +300,30 @@ class CategoryConfigView(discord.ui.View):
|
||||
|
||||
class TicketCog(commands.Cog, name="Ticket System"):
|
||||
def __init__(self, bot):
|
||||
self.bot, self.db = bot, TicketDatabase(DB_PATH)
|
||||
self.bot.loop.create_task(self.load_persistent_views())
|
||||
self.bot = bot
|
||||
self.db = TicketDatabase(DB_PATH)
|
||||
self._views_task: asyncio.Task | None = None
|
||||
|
||||
async def cog_load(self):
|
||||
# Start after inject succeeds — avoids closed-DB race when add_cog fails/unloads
|
||||
self._views_task = asyncio.create_task(self.load_persistent_views())
|
||||
|
||||
async def load_persistent_views(self):
|
||||
await self.bot.wait_until_ready()
|
||||
for config in self.db.fetchall("SELECT guild_id, panel_message_id FROM guild_configs WHERE panel_message_id IS NOT NULL"):
|
||||
if view := self.create_panel_view(config['guild_id']): self.bot.add_view(view, message_id=config['panel_message_id'])
|
||||
try:
|
||||
await self.bot.wait_until_ready()
|
||||
configs = self.db.fetchall(
|
||||
"SELECT guild_id, panel_message_id FROM guild_configs WHERE panel_message_id IS NOT NULL"
|
||||
)
|
||||
for config in configs:
|
||||
if view := self.create_panel_view(config["guild_id"]):
|
||||
self.bot.add_view(view, message_id=config["panel_message_id"])
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
except sqlite3.ProgrammingError:
|
||||
# Cog unloaded / DB closed before ready — ignore
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Ticket persistent views load failed: {e}")
|
||||
|
||||
def create_panel_view(self, guild_id):
|
||||
config = self.db.fetchone("SELECT panel_type FROM guild_configs WHERE guild_id=?", (guild_id,))
|
||||
@@ -290,7 +337,10 @@ class TicketCog(commands.Cog, name="Ticket System"):
|
||||
for c in categories: view.add_item(discord.ui.Button(label=c['name'], style=discord.ButtonStyle(c['button_style']), emoji=c['emoji'], custom_id=f"create_ticket_{c['category_id']}"))
|
||||
return view
|
||||
|
||||
def cog_unload(self): self.db.close()
|
||||
def cog_unload(self):
|
||||
if self._views_task and not self._views_task.done():
|
||||
self._views_task.cancel()
|
||||
self.db.close()
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_interaction(self, inter):
|
||||
|
||||
Reference in New Issue
Block a user