import hashlib from enum import Enum from pydantic import Field from pydantic import BaseModel, validator from settings import settings from ipaddress import IPv4Address FIELD_MAP = { 'user_id': 'x01', 'account_id': 'x02', 'distinct_id': 'x03', 'event_name': 'x04', 'server_time':'x05', 'ip': 'a01', 'country': 'a02', 'country_code': 'a03', 'province': 'a04', 'city': 'a05', 'os_version': 'a06', 'manufacturer': 'a07', 'os': 'a08', 'device_id': 'a09', 'screen_height': 'a10', 'screen_width': 'a11', 'device_model': 'a12', 'app_version': 'a13', 'bundle_id': 'a14', 'lib': 'a15', 'lib_version': 'a16', 'network_type': 'a17', 'carrier': 'a18', 'browser': 'a19', 'browser_version': 'a20', 'duration': 'a21', 'url': 'a22', 'url_path': 'a23', 'referrer': 'a24', 'referrer_host': 'a25', 'title': 'a26', 'screen_name': 'a27', 'element_id': 'a28', 'element_type': 'a29', 'resume_from_background': 'a30', 'element_selector': 'a31', 'element_position': 'a32', 'element_content': 'a33', 'scene': 'a34', 'mp_platform': 'a35', 'app_crashed_reason': 'a36', 'zone_offset': 'a37', 'app_id':'b01', 'event_time':'b06' } def to_alias(k: str) -> str: return FIELD_MAP.get(k) or k class IP4(str): @classmethod def __get_validators__(cls): yield cls.validate @classmethod def validate(cls, v): IPv4Address(v) return str(v) class ActEnum(str, Enum): track = 'track' user_set = 'user_set' user_setOnce = 'user_setOnce' user_add = 'user_add' user_unset = 'user_unset' user_append = 'user_append' user_del = 'user_del' class Base(BaseModel): # sign = md5(game+act+ts+salt) game: str = Field(..., title='游戏代号') act: ActEnum = Field(..., title='操作', description='同ta一致') preset: BaseModel properties: dict = Field(..., title='自定义属性') ts: int = Field(..., title='时间戳') sign: str = Field(..., title='签名') @validator('sign') def sign_validator(cls, v: str, values: dict): s = f'{values.get("game", "")}{values.get("act", "")}{values.get("ts", "")}{settings.SALT}' if hashlib.md5(s.encode()).hexdigest() == v: return v raise ValueError(f'sign {hashlib.md5(s.encode()).hexdigest()}') def dict(self, **kwargs): kwargs.setdefault('exclude', {'preset', 'account_id', 'distinct_id', 'event_name'}) self.properties.update(self.preset.dict(**kwargs)) return super().dict(**kwargs)