feat: Tái cấu trúc bot sang kiến trúc cog, thêm hỗ trợ đa máy chủ, giới thiệu tính năng đăng ký bóng đá, giao diện web và quản lý cấu hình.

This commit is contained in:
2026-01-16 17:26:42 +07:00
parent 8c38357c28
commit b24365927a
39 changed files with 3864 additions and 997 deletions
+3 -1
View File
@@ -1,9 +1,11 @@
from models.home_debt import HomeDebt
from models.score import Score
from models.noi_tu import DiscordNoiTu
from models.football import FootballSubscription
__all__ = [
'HomeDebt',
'Score',
'DiscordNoiTu'
'DiscordNoiTu',
'FootballSubscription'
]
+20
View File
@@ -0,0 +1,20 @@
from sqlalchemy import Column, String, Text, BigInteger, PrimaryKeyConstraint
from infra.db.base import Base, TimestampMixin
class BotConfig(Base, TimestampMixin):
__tablename__ = "bot_configs"
guild_id = Column(BigInteger, nullable=False, default=0) # 0 for Global/Template, real ID for specific
key = Column(String(255), nullable=False)
value = Column(Text, nullable=True)
description = Column(Text, nullable=True)
__table_args__ = (
PrimaryKeyConstraint('guild_id', 'key'),
)
def __str__(self):
return f"Key: {self.key}, Value: {self.value}"
def __repr__(self):
return self.__str__()
+19
View File
@@ -0,0 +1,19 @@
from sqlalchemy import Column, String, BigInteger, Boolean, ForeignKey, PrimaryKeyConstraint
from infra.db.base import Base, TimestampMixin
class FeatureToggle(Base, TimestampMixin):
__tablename__ = "feature_toggles"
guild_id = Column(BigInteger, ForeignKey("guilds.id"), nullable=False)
feature_name = Column(String(50), nullable=False)
is_enabled = Column(Boolean, default=False)
__table_args__ = (
PrimaryKeyConstraint('guild_id', 'feature_name'),
)
def __str__(self):
return f"Guild: {self.guild_id}, Feature: {self.feature_name}, Enabled: {self.is_enabled}"
def __repr__(self):
return self.__str__()
+20
View File
@@ -0,0 +1,20 @@
from sqlalchemy import Column, Integer, String, BigInteger, DateTime, UniqueConstraint
from datetime import datetime
from infra.db.postgres import Base
class FootballSubscription(Base):
__tablename__ = "football_subscriptions"
id = Column(Integer, primary_key=True, index=True)
guild_id = Column(BigInteger, nullable=False, index=True)
channel_id = Column(BigInteger, nullable=False)
team_name = Column(String, nullable=False) # Storing name for easier user interaction/display, or mapped ID later
team_id = Column(Integer, nullable=True) # Optional: Store API ID for reliability
created_at = Column(DateTime, default=datetime.now)
__table_args__ = (
UniqueConstraint('guild_id', 'team_name', name='uix_guild_team'),
)
def __repr__(self):
return f"<FootballSubscription(guild_id={self.guild_id}, team={self.team_name})>"
+15
View File
@@ -0,0 +1,15 @@
from sqlalchemy import Column, String, BigInteger, Boolean
from infra.db.base import Base, TimestampMixin
class Guild(Base, TimestampMixin):
__tablename__ = "guilds"
id = Column(BigInteger, primary_key=True) # Discord Guild ID
name = Column(String(255), nullable=True)
is_active = Column(Boolean, default=True)
def __str__(self):
return f"Guild ID: {self.id}, Name: {self.name}"
def __repr__(self):
return self.__str__()
+7 -2
View File
@@ -1,13 +1,18 @@
from sqlalchemy import Column, Integer, BigInteger
from sqlalchemy import Column, Integer, BigInteger, UniqueConstraint
from infra.db.base import Base, TimestampMixin
class HomeDebt(Base, TimestampMixin):
__tablename__ = "home_debt"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(BigInteger, nullable=False, unique=True)
guild_id = Column(BigInteger, nullable=False, default=0)
user_id = Column(BigInteger, nullable=False)
value = Column(Integer, nullable=False, default=0)
__table_args__ = (
UniqueConstraint('guild_id', 'user_id', name='uq_home_debt_guild_user'),
)
def __str__(self):
return f"ID: {self.id}, User ID: {self.user_id}, Value: {self.value}, Created At: {self.created_at}, Updated At: {self.updated_at}"
+9 -4
View File
@@ -1,14 +1,19 @@
from sqlalchemy import Column, Integer, BigInteger, String
from infra.db.base import Base
from sqlalchemy import Column, Integer, BigInteger, String, UniqueConstraint
from infra.db.base import Base, TimestampMixin
class Score(Base):
class Score(Base, TimestampMixin):
__tablename__ = "score"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(BigInteger, nullable=False, unique=True)
guild_id = Column(BigInteger, nullable=False, default=0)
user_id = Column(BigInteger, nullable=False)
user_name = Column(String(255), nullable=True)
point = Column(Integer, nullable=False, default=0)
__table_args__ = (
UniqueConstraint('guild_id', 'user_id', name='uq_score_guild_user'),
)
def __str__(self):
return f"ID: {self.id}, User ID: {self.user_id}, User Name: {self.user_name}, point: {self.point}"