Files
character-roleplay-backend/models/base.py
T

65 lines
1.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import hashlib
from sqlalchemy import Column, String
from sqlalchemy.orm import declarative_base, declared_attr
import ulid
Base = declarative_base()
# Base62 字符集
ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
def encode_base62(num: int) -> str:
"""将一个整数编码为 Base62 字符串"""
if num == 0:
return ALPHABET[0]
arr = []
base = len(ALPHABET)
while num:
num, rem = divmod(num, base)
arr.append(ALPHABET[rem])
return "".join(reversed(arr))
def encode_tablename_to_prefix(tablename: str, length: int = 3) -> str:
"""
将表名 encode 成固定长度的前缀,使用 MD5 拿到表名的唯一哈希值,转为整数后用 Base62 截取前 N 位
"""
# 计算表名的 MD5 哈希
hasher = hashlib.md5(tablename.encode("utf-8"))
hex_digest = hasher.hexdigest()
# 将十六进制哈希转为大整数
num = int(hex_digest, 16)
# 转为 Base62 字符串
b62_str = encode_base62(num)
# 截取固定长度(例如 3 位)作为该表的专属代码
return b62_str[:length]
def gen_convex_payload() -> str:
"""生成 128位 ULID 转 Base62 的趋势递增 Payload"""
u = ulid.new()
return encode_base62(u.int)
class AutoID:
"""
全自动 Convex 风格 ID 注入器
不再需要手动定义任何 prefix,全自动根据 __tablename__ 编码生成
"""
@declared_attr
def id(cls):
# 运行时动态获取子类的 __tablename__
tablename = cls.__tablename__
# 将表名编码为固定前缀(例如 "users" -> "7X1"
table_prefix = encode_tablename_to_prefix(tablename, length=3)
# 核心工厂函数:拼接【编码后的表前缀】和【递增Payload】
def id_factory():
return f"{table_prefix}_{gen_convex_payload()}"
return Column(String(32), primary_key=True, default=id_factory)