# Source: https://github.com/smallfawn/QLScriptPublic/blob/main/backup/sysxc.py
# Raw: https://raw.githubusercontent.com/smallfawn/QLScriptPublic/main/backup/sysxc.py
# Repo: smallfawn/QLScriptPublic
# Path: backup/sysxc.py
# UploadedAt: 2026-05-14T17:47:57+08:00
# SHA256: b9f66359e357df42cb7ba689f5ae6ae61a49e64a850dba95a577e66b9226cff3
# Category: web版/抓包
# Evidence: web/H5关键词 + cookie/token/header

"""
new Env("书亦烧仙草python版")
1. 书亦烧仙草签到 抓包scrm-prod.shuyi.org.cn域名请求头里的auth
   脚本仅供学习交流使用, 请在下载后24h内删除
2. cron 以防ocr识别出错每天运行两次左右
3. ddddocr搭建方法https://github.com/sml2h3/ocr_api_server #如果脚本里的失效请自行搭建
"""
import json,logging,os,sys,time,base64,requests
from os import environ, system, path

logger = logging.getLogger(name=None)
logging.Formatter("%(message)s")
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())

def load_send():
    global send, mg
    cur_path = path.abspath(path.dirname(__file__))
    if path.exists(cur_path + "/notify.py"):
        try:
            from notify import send
            print("加载通知服务成功！")
        except:
            send = False
            print("加载通知服务失败~")
    else:
        send = False
        print("加载通知服务失败~")

load_send()

try:
    from Crypto.Cipher import AES
except:
    logger.info(
        "\n未检测到pycryptodome\n需要Python依赖里安装pycryptodome\n安装失败先linux依赖里安装gcc、python3-dev、libc-dev\n如果还是失败,重启容器,或者重启docker就能解决")
    exit(0)

def setHeaders(i):
    headers = {
        "auth": cookies[i],
        "hostname": "scrm-prod.shuyi.org.cn",
        "content-type": "application/json",
        "host": "scrm-prod.shuyi.org.cn",
        "User-Agent": "Mozilla/5.0 (Linux; Android 10; V2203A Build/SP1A.210812.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/107.0.5304.141 Mobile Safari/537.36 XWEB/5023 MMWEBSDK/20221012 MMWEBID/1571 MicroMessenger/8.0.30.2260(0x28001E55) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android"
    }
    return headers

cookies = []
try:
    cookies = os.environ["sysxc_auth"].split("&")
    if len(os.environ["sysxc_auth"]) > 0:
        logger.info("已获取并使用Env环境Cookie\n声明：本脚本为学习python，请勿用于非法用途\n")
            

except:
    logger.info(
        "【提示】请先添加sysxc_auth")
    exit(3)

def getVCode(headers):
    """获取滑块图片"""
    data = {
        "captchaType": "blockPuzzle",
        "clientUid": "slider-6292e85b-e871-4abd-89df-4d97709c6e0c",
        "ts": int(time.time() * 1000)
    }
    url = 'https://scrm-prod.shuyi.org.cn/saas-gateway/api/agg-trade/v1/signIn/getVCode'
    response = requests.post(url, json=data, headers=headers)
    return response.json()



def ocr(tg,bg):
    """使用自有ocr识别滑块坐标"""
    url = 'http://103.45.185.224:9898/slide/match/b64/json'
    jsonstr = json.dumps({'target_img': tg, 'bg_img': bg})
    response = requests.post(url, data=base64.b64encode(jsonstr.encode()).decode())
    return response.json()


'''
采用AES对称加密算法
'''

BLOCK_SIZE = 16  # Bytes
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * \
                chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]


def aesEncrypt(key, data):
    '''
    AES的ECB模式加密方法
    :param key: 密钥
    :param data:被加密字符串（明文）
    :return:密文
    '''
    key = key.encode('utf8')
    # 字符串补位
    data = pad(data)
    cipher = AES.new(key, AES.MODE_ECB)
    # 加密后得到的是bytes类型的数据，使用Base64进行编码,返回byte字符串
    result = cipher.encrypt(data.encode())
    encodestrs = base64.b64encode(result)
    enctext = encodestrs.decode('utf8')
    return enctext


def aesDecrypt(key, data):
    '''
    :param key: 密钥
    :param data: 加密后的数据（密文）
    :return:明文
    '''
    key = key.encode('utf8')
    data = base64.b64decode(data)
    cipher = AES.new(key, AES.MODE_ECB)

    # 去补位
    text_decrypted = unpad(cipher.decrypt(data))
    text_decrypted = text_decrypted.decode('utf8')
    return text_decrypted


def checkVCode(pointJson, token):
    """验证"""
    try:
        data = {
            "captchaType": "blockPuzzle",
            "pointJson": pointJson,
            "token": token
        }
        
        url = 'https://scrm-prod.shuyi.org.cn/saas-gateway/api/agg-trade/v1/signIn/checkVCode'
        response = requests.post(url, json=data, headers=headers)
        result = response.json()
        resultCode = result['resultCode']
        resultMsg = result['resultMsg']
        if resultCode == '0000':
            logger.info(f"校验结果：成功")
        else:
            logger.info(f"校验结果： {resultMsg}")
            time.sleep(3)
            main()
    except Exception as err:
        print(err)


def check_sign(pointJson):
    """签到"""
    try:
        data = {
            "captchaVerification": pointJson
        }
        url = 'https://scrm-prod.shuyi.org.cn/saas-gateway/api/agg-trade/v1/signIn/insertSignInV3'
        response = requests.post(url, json=data, headers=headers)
        result = response.json()
        resultCode = result['resultCode']
        
        resultMsg = result['resultMsg']
        if resultCode == '0':
            logger.info(f"签到结果：{result}")
            send('书亦烧仙草签到通知', result)
        else:
            logger.info(f"签到结果： {resultMsg}")
            send('书亦烧仙草签到通知', resultMsg)
    except Exception as err:
        print(err)
        sys.exit(0)

def main():
    logger.info("--------------------任务开始--------------------")
    result = getVCode(headers)
    bg = result['data']['originalImageBase64']
    tg = result['data']['jigsawImageBase64']
    key = result['data']['secretKey']
    token = result['data']['token']
    logger.info(f"本次口令为： {token}")
    logger.info(f"本次密钥为： {key}")
    time.sleep(1.5)
    logger.info("--------------------识别滑块--------------------")
    result = ocr(tg,bg)
    res = result['result']['target']
    d = (res[0])
    logger.info(f"滑动距离为： {d}")
    logger.info("--------------------执行算法--------------------")
    aes_str = json.dumps({"x": d, "y": 5})
    data = aes_str.replace(' ', '')
    logger.info(f"加密前： {data}")
    time.sleep(1.5)
    ecdata = aesEncrypt(key, data)
    aesDecrypt(key, ecdata)
    pointJson = aesEncrypt(key, data)
    logger.info(f"加密后： {pointJson}")
    logger.info("--------------------校验滑块--------------------")
    checkVCode(pointJson, token)
    logger.info("--------------------开始签到--------------------")
    str = (token + '---' + aes_str)
    data = str.replace(' ', '')
    ecdata = aesEncrypt(key, data)
    aesDecrypt(key, ecdata)
    pointJson = aesEncrypt(key, data)
    time.sleep(0.5)
    check_sign(pointJson)

if __name__ == '__main__':
    for i in range(len(cookies)):
        logger.info(f"\n开始第{i + 1}个账号")
        
        headers = setHeaders(i)
        main()
    logger.info("所有账号执行完成\n")
    sys.exit(0)

