Files
tg-spam-guard/db/models.py
T
2026-07-07 12:27:13 +08:00

170 lines
6.3 KiB
Python

"""数据库模型定义"""
from tortoise import fields
from tortoise.models import Model
class TimestampMixin:
"""通用时间戳字段。所有业务表统一包含 created_at / updated_at。"""
created_at = fields.DatetimeField(auto_now_add=True, description="创建时间")
updated_at = fields.DatetimeField(auto_now=True, description="更新时间")
class Message(TimestampMixin, Model):
"""消息记录"""
id = fields.BigIntField(pk=True, generated=True)
msg_id = fields.BigIntField(null=True)
chat_id = fields.BigIntField()
user_id = fields.BigIntField()
username = fields.CharField(max_length=255, null=True)
first_name = fields.CharField(max_length=255, null=True)
text = fields.TextField(null=True)
is_spam = fields.BooleanField(default=False)
spam_reason = fields.CharField(max_length=255, null=True)
manually_deleted = fields.BooleanField(default=False)
deleted_at = fields.DatetimeField(null=True)
delete_reason = fields.CharField(max_length=255, null=True)
class Meta:
table = "messages"
indexes = (("chat_id", "msg_id"), ("user_id", "created_at"), ("is_spam", "created_at"))
class Ban(TimestampMixin, Model):
"""封禁记录"""
id = fields.BigIntField(pk=True, generated=True)
user_id = fields.BigIntField()
username = fields.CharField(max_length=255, null=True)
first_name = fields.CharField(max_length=255, null=True)
reason = fields.CharField(max_length=500, null=True)
method = fields.CharField(max_length=50, default="auto") # auto/command/verify_fail
duration_minutes = fields.IntField(default=2)
auto_unban = fields.BooleanField(default=True)
unban_at = fields.DatetimeField(null=True)
class Meta:
table = "bans"
indexes = (("user_id", "created_at"), ("auto_unban", "unban_at"))
class Action(TimestampMixin, Model):
"""操作日志(入群/退群/删除/解封/警告等)"""
id = fields.BigIntField(pk=True, generated=True)
action = fields.CharField(max_length=50)
user_id = fields.BigIntField(null=True)
username = fields.CharField(max_length=255, null=True)
operator_id = fields.BigIntField(null=True)
details = fields.JSONField(null=True)
class Meta:
table = "actions"
indexes = (("action", "created_at"), ("user_id", "created_at"), ("operator_id", "created_at"))
class VerifyQueue(TimestampMixin, Model):
"""入群验证队列"""
id = fields.BigIntField(pk=True, generated=True)
user_id = fields.BigIntField()
username = fields.CharField(max_length=255, null=True)
question = fields.CharField(max_length=500, null=True)
answer = fields.CharField(max_length=500, null=True)
attempts = fields.IntField(default=0)
status = fields.CharField(max_length=20, default="pending")
verified_at = fields.DatetimeField(null=True)
class Meta:
table = "verify_queue"
indexes = (("user_id", "status"), ("status", "created_at"))
class UserBinding(TimestampMixin, Model):
"""TG ↔ Harvest 账号绑定"""
id = fields.BigIntField(pk=True, generated=True)
tg_user_id = fields.BigIntField(unique=True)
tg_username = fields.CharField(max_length=255, null=True)
harvest_uid = fields.CharField(max_length=255, null=True)
harvest_token = fields.CharField(max_length=500, null=True)
auth_email = fields.CharField(max_length=255, null=True)
time_expire = fields.CharField(max_length=100, null=True)
# 兼容旧代码/展示语义:绑定时间;created_at 仍作为统一审计字段
bound_at = fields.DatetimeField(auto_now_add=True)
class Meta:
table = "user_bindings"
indexes = (("tg_user_id",), ("harvest_uid",))
class Warning(TimestampMixin, Model):
"""警告记录"""
id = fields.BigIntField(pk=True, generated=True)
user_id = fields.BigIntField()
username = fields.CharField(max_length=255, null=True)
reason = fields.CharField(max_length=500, null=True)
operator_id = fields.BigIntField(null=True)
active = fields.BooleanField(default=True)
class Meta:
table = "warnings"
indexes = (("user_id", "active"), ("operator_id", "created_at"))
class GameScore(TimestampMixin, Model):
"""游戏积分"""
id = fields.BigIntField(pk=True, generated=True)
user_id = fields.BigIntField()
username = fields.CharField(max_length=255, null=True)
game_type = fields.CharField(max_length=50)
score = fields.IntField(default=0)
wins = fields.IntField(default=0)
total = fields.IntField(default=0)
streak = fields.IntField(default=0)
last_played = fields.DatetimeField(null=True)
class Meta:
table = "game_scores"
unique_together = (("user_id", "game_type"),)
indexes = (("game_type", "score"), ("user_id", "game_type"))
class GroupConfig(TimestampMixin, Model):
"""群组配置"""
key = fields.CharField(max_length=100, pk=True)
value = fields.JSONField(null=True)
class Meta:
table = "group_config"
class LotteryEvent(TimestampMixin, Model):
"""群内抽奖活动"""
id = fields.BigIntField(pk=True, generated=True)
chat_id = fields.BigIntField()
message_id = fields.BigIntField(null=True)
creator_id = fields.BigIntField()
creator_name = fields.CharField(max_length=255, null=True)
prize = fields.CharField(max_length=500)
condition_type = fields.CharField(max_length=50, default="all") # all/checkin/min_points
condition_value = fields.IntField(default=0)
end_type = fields.CharField(max_length=50, default="people") # people/minutes/manual
end_value = fields.IntField(default=0)
status = fields.CharField(max_length=20, default="active")
winner_id = fields.BigIntField(null=True)
winner_name = fields.CharField(max_length=255, null=True)
ended_at = fields.DatetimeField(null=True)
class Meta:
table = "lottery_events"
indexes = (("chat_id", "status"), ("creator_id", "created_at"))
class LotteryParticipant(TimestampMixin, Model):
"""抽奖参与者"""
id = fields.BigIntField(pk=True, generated=True)
event_id = fields.BigIntField()
user_id = fields.BigIntField()
username = fields.CharField(max_length=255, null=True)
first_name = fields.CharField(max_length=255, null=True)
class Meta:
table = "lottery_participants"
indexes = (("event_id", "user_id"),)