# Source: https://github.com/smallfawn/QLScriptPublic/blob/main/daily/erke.py
# Raw: https://raw.githubusercontent.com/smallfawn/QLScriptPublic/main/daily/erke.py
# Repo: smallfawn/QLScriptPublic
# Path: daily/erke.py
# UploadedAt: 2026-04-01T12:37:39Z
# SHA256: c82ab68bd69e9577d92fa8366558ae24b3be8793d62bef0381e1914cc805750d
# Category: 微信小程序/抓包版
# Evidence: appid/openid/session_key/encryptedData等小程序字段

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
new Env('鸿星尔克签到');
cron: 1 10 * * *
"""
# =================================================================
# 使用说明：
# 1. 环境变量名称：ERKE_CONF
# 2. 环境变量格式：member_id#enterprise_id#unionid#openid#wx_openid#备注
# 3. 多账号支持：多个账号请换行，或者使用 & 符号连接
# 示例：
# 12345#67890#unionid123#openid123#wx_openid123#我的账号
# 54321#09876#unionid456#openid456#wx_openid456#大号
# =================================================================
# 配置日志
import os
import requests
import hashlib
import random
import logging
from typing import Dict
from datetime import datetime, timedelta, timezone


logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger("ErkeCheckIn")

def get_gmt8_time() -> str:
    """获取北京时间字符串"""
    tz = timezone(timedelta(hours=8))
    return datetime.now(tz).strftime('%Y-%m-%d %H:%M:%S')

def calculate_sign(appid: str, member_id: str, timestamp: str = None) -> dict:
    """计算请求签名逻辑"""
    if timestamp is None:
        timestamp = get_gmt8_time()

    random_num = random.randint(0, 9999999)
    trans_id = appid + timestamp

    # 按照JS逻辑拼接字符串
    sign_str = f"timestamp={timestamp}transId={trans_id}secret=damogic8888random={random_num}memberId={member_id}"
    sign = hashlib.md5(sign_str.encode()).hexdigest()

    return {
        'sign': sign,
        'timestamp': timestamp,
        'transId': trans_id,
        'random': random_num,
        'appid': appid,
        'memberId': member_id
    }

class ErkeAPI:
    def __init__(self, member_id, enterprise_id, unionid, openid, wx_openid, account_name):
        self.member_id = member_id
        self.enterprise_id = enterprise_id
        self.unionid = unionid
        self.openid = openid
        self.wx_openid = wx_openid
        self.account_name = account_name
        self.appid = "wxa1f1fa3785a47c7d"
        self.base_url = 'https://hope.demogic.com/gic-wx-app'
        self.ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF'

    def get_headers(self, sign_val: str) -> Dict[str, str]:
        return {
            'User-Agent': self.ua,
            'Content-Type': 'application/x-www-form-urlencoded',
            'sign': sign_val, # 注意：原逻辑此处传入的是enterprise_id
            'channelEntrance': 'wx_app',
            'Referer': 'https://servicewechat.com/wxa1f1fa3785a47c7d/85/page-frame.html',
        }

    def get_integral(self):
        """查询积分明细"""
        sign_data = calculate_sign(self.appid, self.member_id)
        data = {
            'currentPage': 1,
            'pageSize': 20,
            'memberId': self.member_id,
            'cliqueId': '-1',
            'enterpriseId': self.enterprise_id,
            'unionid': self.unionid,
            'openid': self.openid,
            'wxOpenid': self.wx_openid,
            'random': sign_data['random'],
            'appid': self.appid,
            'transId': sign_data['transId'],
            'sign': sign_data['sign'],
            'timestamp': sign_data['timestamp'],
            'gicWxaVersion': '3.9.56'
        }
        
        try:
            res = requests.post(f"{self.base_url}/integral_record.json", 
                                headers=self.get_headers(self.enterprise_id), 
                                data=data, timeout=10).json()
            response_obj = res.get('response', {})
            accumulate = response_obj.get('accumulatPoints', 0)
            logger.info(f"[{self.account_name}] 当前累计积分: {accumulate}")
            return accumulate
        except Exception as e:
            logger.error(f"[{self.account_name}] 积分查询异常: {e}")
            return "未知"

    def sign_in(self):
        """执行签到"""
        sign_data = calculate_sign(self.appid, self.member_id)
        payload = {
            'source': 'wxapp',
            'memberId': self.member_id,
            'cliqueId': '-1',
            'enterpriseId': self.enterprise_id,
            'unionid': self.unionid,
            'openid': self.openid,
            'wxOpenid': self.wx_openid,
            'sign': sign_data['sign'],
            'random': sign_data['random'],
            'appid': self.appid,
            'transId': sign_data['transId'],
            'timestamp': sign_data['timestamp'],
            'gicWxaVersion': '3.9.56'
        }
        
        headers = self.get_headers(self.enterprise_id)
        headers['Content-Type'] = 'application/json;charset=UTF-8'

        try:
            res = requests.post(f"{self.base_url}/sign/member_sign.json", 
                                headers=headers, json=payload, timeout=10).json()
            msg = res.get('message', '无返回信息')
            code = res.get('code')
            if code in ['0000', '1001', 0]:
                logger.info(f"[{self.account_name}] 签到结果: {msg}")
                return True, msg
            else:
                logger.warning(f"[{self.account_name}] 签到失败: {msg}")
                return False, msg
        except Exception as e:
            logger.error(f"[{self.account_name}] 签到请求异常: {e}")
            return False, str(e)

def main():
    # 尝试从环境变量读取配置
    conf_str = os.getenv("ERKE_CONF", "")
    if not conf_str:
        logger.error("未找到环境变量 ERKE_CONF，请检查配置！")
        return
    # 处理多账号，支持换行或 & 分隔
    accounts_raw = conf_str.replace("&", "\n").splitlines()
    summary = []

    for line in accounts_raw:
        if not line.strip(): continue
        
        params = line.strip().split("#")
        if len(params) < 5:
            logger.error(f"账号配置格式错误 (需5个#分隔): {line}")
            continue
        
        # 提取参数
        m_id, e_id, uid, oid, wx_oid = params[:5]
        name = params[5] if len(params) > 5 else f"账号_{m_id[-4:]}"
        
        api = ErkeAPI(m_id, e_id, uid, oid, wx_oid, name)
        
        # 执行流程
        points_before = api.get_integral()
        success, msg = api.sign_in()
        points_after = api.get_integral()
        
        status_emoji = "✅" if success else "❌"
        summary.append(f"{status_emoji} 【{name}】: {msg} (积分: {points_before} -> {points_after})")

    # 打印最终统计
    print("\n" + "="*30)
    print("      鸿星尔克任务简报")
    print("="*30)
    print("\n".join(summary))
    
    # 如果有通知推送逻辑，可以在此处调用
    # send_notification("鸿星尔克签到", "\n".join(summary))

if __name__ == "__main__":
    main()