from sqlalchemy import Column, Integer, String, Boolean, DateTime, Text, ForeignKey, Enum from sqlalchemy.orm import relationship from sqlalchemy.sql import func from app.database import Base import enum class MembershipType(str, enum.Enum): FREE = "free" PRO = "pro" class AccountStatus(str, enum.Enum): ACTIVE = "active" # 可用 IN_USE = "in_use" # 使用中 DISABLED = "disabled" # 禁用 EXPIRED = "expired" # 过期 class KeyStatus(str, enum.Enum): UNUSED = "unused" # 未使用 ACTIVE = "active" # 已激活(主密钥) MERGED = "merged" # 已合并到主密钥 REVOKED = "revoked" # 已撤销 DISABLED = "disabled" # 禁用 EXPIRED = "expired" # 过期 class CursorAccount(Base): """Cursor 账号池""" __tablename__ = "cursor_accounts" id = Column(Integer, primary_key=True, autoincrement=True) email = Column(String(255), unique=True, nullable=False, comment="邮箱") access_token = Column(Text, nullable=False, comment="访问令牌") refresh_token = Column(Text, nullable=True, comment="刷新令牌") workos_session_token = Column(Text, nullable=True, comment="WorkOS会话令牌") membership_type = Column(Enum(MembershipType), default=MembershipType.PRO, comment="会员类型") status = Column(Enum(AccountStatus), default=AccountStatus.ACTIVE, comment="状态") # 使用统计 usage_count = Column(Integer, default=0, comment="使用次数") last_used_at = Column(DateTime, nullable=True, comment="最后使用时间") current_key_id = Column(Integer, ForeignKey("activation_keys.id"), nullable=True, comment="当前使用的激活码") # 备注 remark = Column(String(500), nullable=True, comment="备注") created_at = Column(DateTime, server_default=func.now()) updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now()) class ActivationKey(Base): """激活码""" __tablename__ = "activation_keys" id = Column(Integer, primary_key=True, autoincrement=True) key = Column(String(64), unique=True, nullable=False, index=True, comment="激活码") status = Column(Enum(KeyStatus), default=KeyStatus.UNUSED, comment="状态") # 套餐类型 membership_type = Column(Enum(MembershipType), default=MembershipType.PRO, comment="套餐类型: free=Auto池, pro=Pro池") # 密钥合并关系 master_key_id = Column(Integer, ForeignKey("activation_keys.id"), nullable=True, comment="主密钥ID(如果已合并)") device_id = Column(String(255), nullable=True, index=True, comment="绑定的设备ID") # 该密钥贡献的资源 (创建时设置,不变) duration_days = Column(Integer, default=30, comment="Auto: 该密钥贡献的天数") quota_contribution = Column(Integer, default=500, comment="Pro: 该密钥贡献的积分") # 额度系统 (仅主密钥使用,累计值) quota = Column(Integer, default=500, comment="Pro主密钥: 总额度(累加)") quota_used = Column(Integer, default=0, comment="Pro主密钥: 已用额度") # 有效期 (仅主密钥使用) expire_at = Column(DateTime, nullable=True, comment="Auto主密钥: 到期时间(累加)") # 激活信息 first_activated_at = Column(DateTime, nullable=True, comment="首次激活时间") merged_at = Column(DateTime, nullable=True, comment="合并时间") # 设备限制 (可换设备,此字段保留但不强制) max_devices = Column(Integer, default=3, comment="最大设备数(可换设备)") # 当前绑定的账号 (仅主密钥使用) current_account_id = Column(Integer, ForeignKey("cursor_accounts.id"), nullable=True) current_account = relationship("CursorAccount", foreign_keys=[current_account_id]) # 统计 (仅主密钥使用) switch_count = Column(Integer, default=0, comment="总换号次数") last_switch_at = Column(DateTime, nullable=True, comment="最后换号时间") merged_count = Column(Integer, default=0, comment="已合并的密钥数量") # 备注 remark = Column(String(500), nullable=True, comment="备注") created_at = Column(DateTime, server_default=func.now()) updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now()) # 关系 master_key = relationship("ActivationKey", remote_side=[id], foreign_keys=[master_key_id]) @property def valid_days(self): """兼容旧API: duration_days的别名""" return self.duration_days or 0 class KeyDevice(Base): """激活码绑定的设备""" __tablename__ = "key_devices" id = Column(Integer, primary_key=True, autoincrement=True) key_id = Column(Integer, ForeignKey("activation_keys.id"), nullable=False) device_id = Column(String(255), nullable=False, comment="设备标识") device_name = Column(String(255), nullable=True, comment="设备名称") last_active_at = Column(DateTime, nullable=True, comment="最后活跃时间") created_at = Column(DateTime, server_default=func.now()) key = relationship("ActivationKey") class GlobalSettings(Base): """全局设置""" __tablename__ = "global_settings" id = Column(Integer, primary_key=True, autoincrement=True) key = Column(String(100), unique=True, nullable=False, comment="设置键") value = Column(String(500), nullable=False, comment="设置值") description = Column(String(500), nullable=True, comment="描述") updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now()) class UsageLog(Base): """使用日志""" __tablename__ = "usage_logs" id = Column(Integer, primary_key=True, autoincrement=True) key_id = Column(Integer, ForeignKey("activation_keys.id"), nullable=False) account_id = Column(Integer, ForeignKey("cursor_accounts.id"), nullable=True) action = Column(String(50), nullable=False, comment="操作类型: verify/switch/seamless") ip_address = Column(String(50), nullable=True) user_agent = Column(String(500), nullable=True) success = Column(Boolean, default=True) message = Column(String(500), nullable=True) created_at = Column(DateTime, server_default=func.now()) key = relationship("ActivationKey") account = relationship("CursorAccount")