235 lines
9.0 KiB
Python
235 lines
9.0 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)
|
|
chat_id = fields.BigIntField(default=0)
|
|
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)
|
|
chat_id = fields.BigIntField(default=0)
|
|
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 Whitelist(TimestampMixin, Model):
|
|
"""白名单用户:命中垃圾规则时只删除消息,不封禁账号。"""
|
|
id = fields.BigIntField(pk=True, generated=True)
|
|
chat_id = fields.BigIntField(default=0)
|
|
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)
|
|
operator_id = fields.BigIntField(null=True)
|
|
enabled = fields.BooleanField(default=True)
|
|
|
|
class Meta:
|
|
table = "whitelists"
|
|
indexes = (("chat_id", "user_id"), ("user_id", "enabled"))
|
|
unique_together = (("chat_id", "user_id"),)
|
|
|
|
|
|
class VerifyQueue(TimestampMixin, Model):
|
|
"""入群验证队列"""
|
|
id = fields.BigIntField(pk=True, generated=True)
|
|
chat_id = fields.BigIntField(default=0)
|
|
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)
|
|
chat_id = fields.BigIntField(default=0)
|
|
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)
|
|
chat_id = fields.BigIntField(default=0)
|
|
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 = (("chat_id", "user_id", "game_type"),)
|
|
indexes = (("chat_id", "game_type", "score"), ("chat_id", "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 ShopItem(TimestampMixin, Model):
|
|
"""群组积分商城商品"""
|
|
id = fields.BigIntField(pk=True, generated=True)
|
|
chat_id = fields.BigIntField(default=0)
|
|
item_key = fields.CharField(max_length=50)
|
|
name = fields.CharField(max_length=255)
|
|
cost = fields.IntField(default=0)
|
|
stock = fields.IntField(default=-1) # -1 表示不限库存
|
|
desc = fields.CharField(max_length=500, null=True)
|
|
enabled = fields.BooleanField(default=True)
|
|
|
|
class Meta:
|
|
table = "shop_items"
|
|
unique_together = (("chat_id", "item_key"),)
|
|
indexes = (("chat_id", "enabled"),)
|
|
|
|
|
|
class ShopTransaction(TimestampMixin, Model):
|
|
"""积分商城交易记录"""
|
|
id = fields.BigIntField(pk=True, generated=True)
|
|
chat_id = fields.BigIntField(default=0)
|
|
user_id = fields.BigIntField()
|
|
username = fields.CharField(max_length=255, null=True)
|
|
item_key = fields.CharField(max_length=50)
|
|
item_name = fields.CharField(max_length=255)
|
|
cost = fields.IntField(default=0)
|
|
status = fields.CharField(max_length=30, default="success")
|
|
note = fields.CharField(max_length=500, null=True)
|
|
|
|
class Meta:
|
|
table = "shop_transactions"
|
|
indexes = (("chat_id", "created_at"), ("chat_id", "user_id"), ("item_key", "created_at"),)
|
|
|
|
|
|
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)
|
|
title = fields.CharField(max_length=255, null=True)
|
|
description = fields.TextField(null=True)
|
|
draw_type = fields.CharField(max_length=50, default="people") # instant/people/time/manual
|
|
draw_at = fields.DatetimeField(null=True)
|
|
max_participants = fields.IntField(default=0)
|
|
prize = fields.CharField(max_length=500)
|
|
prize_count = fields.IntField(default=1)
|
|
remaining_count = fields.IntField(default=1)
|
|
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)
|
|
is_winner = fields.BooleanField(default=False)
|
|
|
|
class Meta:
|
|
table = "lottery_participants"
|
|
indexes = (("event_id", "user_id"),)
|
|
unique_together = (("event_id", "user_id"),)
|