Initial Qinglong script classification corpus

This commit is contained in:
Hermes Agent
2026-05-23 18:48:48 +00:00
commit 5b4854515c
32 changed files with 15496 additions and 0 deletions

View File

@@ -0,0 +1,487 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/cloud189.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/cloud189.py
# Repo: lksky8/sign-ql
# Path: cloud189.py
# UploadedAt: 2025-09-06T12:51:46Z
# SHA256: 7c90c2eb0032873254db7819a42440cd062ae32af3fa537efc7c295c0e1da804
# Category: 微信小程序/抓包版
# Evidence: appid/openid/session_key/encryptedData等小程序字段
"""
天翼云盘签到
作者https://github.com/lksky8/sign-ql
最后更新日期2025-9-6
如脚本无法运行先在青龙依赖管理的Python里面安装pycryptodome这个包
食用方法打开天翼云盘app抓请求url=api.cloud.189.cn/guns/getPageBanners.action里面accessToken(一般在请求头里)填到变量cloud189_token里面即可
支持多用户运行
多用户用&或者@隔开
例如账号110086 账号2 1008611
则变量为
export cloud189_token="10086&1008611"
cron: 50 1,18 * * *
"""
import requests
import time
import hmac
import hashlib
import base64
import os
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Crypto.Cipher import PKCS1_v1_5
import re
from urllib.parse import unquote
from datetime import datetime, timedelta
if 'cloud189_token' in os.environ:
cloud189_token = re.split("@|&",os.environ.get("cloud189_token"))
print(f'查找到{len(cloud189_token)}个账号')
else:
cloud189_token =['']
print('无cloud189_token变量')
aes_iv = "Zx8dG46ax3Mc8Mj2".encode() # 16 字节
aes_key = "bf8395f745c04f23".encode() # 16 字节
# RSA_PUBLIC_KEY_PEM = """-----BEGIN PUBLIC KEY-----
# MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaoVRMEdxN2LZj7f0UL/0OMJJj
# GuD1OgDRF4WTY1ZCupektwYvS5nU2FelBJ9bV5dv5MVYAp6r9rOkRwE+PEvgwaVP
# ghwfNg1ljCkQ2QFNAmwKHF/sjgHsHu94IbYL7MokSETU6Y4d5k+Vm/3qvqxZs8Yf
# 1HGx3ojEU6Atxqp/QwIDAQAB
# -----END PUBLIC KEY-----"""
RSA_PUBLIC_KEY_PEM = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC72L803mNmrQgyvaU
t115S5gSHuDcS+nGdqBakHYqFShEwrEaqKsr2Z/7DQt9AobB0ne2vIS
UW0tXjhgf5vfl00kT7K+J4j+t3WLkQ6Zwc9KtZHkSW6/fkFSC1EnShP
YLsG6rHYa5+wfefOY2P7yEFRsd5DGCqHNWkzOZclsXawIDAQAB
-----END PUBLIC KEY-----"""
# AES CBC 加密函数
def aes_cbc_encrypt(plaintext, key, iv):
cipher = AES.new(key, AES.MODE_CBC, iv)
padded_plaintext = pad(plaintext.encode('utf-8'), AES.block_size)
ciphertext = cipher.encrypt(padded_plaintext)
return base64.b64encode(ciphertext).decode('utf-8')
# AES CBC 解密函数
def aes_cbc_decrypt(ciphertext, key, iv):
ciphertext = base64.b64decode(ciphertext)
cipher = AES.new(key, AES.MODE_CBC, iv)
padded_plaintext = cipher.decrypt(ciphertext)
plaintext = unpad(padded_plaintext, AES.block_size)
return plaintext.decode('utf-8')
def encrypt_aes_key(key):
aes_session_key = key.encode('utf-8')
rsa_public_key = RSA.import_key(RSA_PUBLIC_KEY_PEM)
rsa_cipher = PKCS1_v1_5.new(rsa_public_key)
encrypted_aes_key = rsa_cipher.encrypt(aes_session_key)
return base64.b64encode(encrypted_aes_key).decode('utf-8')
def md5_encrypt(plaintext):
md5_hash = hashlib.md5()
md5_hash.update(plaintext.encode('utf-8'))
return md5_hash.hexdigest()
def hmac_sha1_hex(key, message):
key_bytes = key.encode('utf-8')
message_bytes = message.encode('utf-8')
hmac_hash = hmac.new(key_bytes, message_bytes, hashlib.sha1)
return hmac_hash.digest().hex()
def get_task_info(data):
task_info = []
for task in data["data"]:
if not task["status"]: # 只返回未完成的任务
task_info.append({
"taskId": task["taskId"],
"taskName": task["taskName"],
})
return task_info
send_msg = ''
one_msg = ''
def log(cont=''):
global send_msg, one_msg
if cont:
one_msg += f'{cont}\n'
send_msg += f'{cont}\n'
# 发送通知消息
def send_notification_message(title):
try:
from notify import send
print("加载通知服务成功!")
send(title, send_msg)
except Exception as e:
if e:
print('发送通知消息失败!')
def generateRsakey():
headers = {
'Host': 'api.cloud.189.cn',
'accept': 'application/json;charset=UTF-8',
'accept-language': 'zh-cn',
'x-request-id': '26E11B6CBEB94F77A2E5615C20C06113',
'date': 'Sun, 22 Jun 2025 14:33:08 GMT',
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari/604.1',
}
params = {
'clientType': 'TELEIPHONE',
'version': '10.3.3',
'model': 'iPhone',
'osFamily': 'iOS',
'osVersion': '15.8.3',
'clientSn': '02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8',
'returnType': 'JSON',
}
response = requests.get('https://api.cloud.189.cn/security/generateRsaKey.action', params=params, headers=headers).json()
return response['pkId']
def get_AccessToken(sessionKey):
timestamp_1 = str(int(time.time()))
signature = md5_encrypt(f'AppKey=600100422&Timestamp={timestamp_1}&sessionKey={sessionKey}')
headers = {
'Host': 'api.cloud.189.cn',
'accept': 'application/json;charset=UTF-8',
'sign-type': '1',
'timestamp': timestamp_1,
'sec-fetch-site': 'same-site',
'accept-language': 'zh-CN,zh-Hans;q=0.9',
'signature': signature,
'sec-fetch-mode': 'cors',
'origin': 'https://m.cloud.189.cn',
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Ecloud/10.3.3 iOS/16.6.1 clientId/027A8AB808-F7A5-431E-8B37-6BD9559D22D7 clientModel/iPhone proVersion/1.0.5',
'appkey': '600100422',
'referer': 'https://m.cloud.189.cn/',
'sec-fetch-dest': 'empty',
}
params = {
'sessionKey': sessionKey,
}
response = requests.get('https://api.cloud.189.cn/open/oauth2/getAccessTokenBySsKey.action', params=params,headers=headers).json()
return response['accessToken']
def login4MergedClient(token):
timestamp = str(int(time.time()))
appsignature = hmac_sha1_hex('fe5734c74c2f96a38157f420b32dc995',f'AppKey=600100885&Operate=POST&RequestURI=/login4MergedClient.action&Timestamp={timestamp}')
param = f'isCache=1&jgOpenId=1114a89792bbaa8d350&deviceModel=iPhone%206s%20Plus&exRetryTimes=1&accessToken={token}&networkAccessMode=WIFI&telecomsOperator=&idfa=00000000-0000-0000-0000-000000000000&clientType=TELEIPHONE&version=10.3.3&model=iPhone&osFamily=iOS&osVersion=15.8.3&clientSn=02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8'
encrypted_param = aes_cbc_encrypt(param, aes_key, aes_iv)
epkey = encrypt_aes_key("bf8395f745c04f23")
pkId = generateRsakey()
headers = {
'Host': 'api.cloud.189.cn',
'content-type': 'application/x-www-form-urlencoded',
'epver': '2',
'accept': '*/*',
'epway': '3',
'timestamp': timestamp,
'appsignature': appsignature,
'accept-language': 'zh-CN,zh-Hans;q=0.9',
'x-request-id': '26E11B6CBEB94F77A2E5615C20C06113',
'epkey': epkey,
'appkey': '600100885',
'user-agent': 'Cloud189/8 CFNetwork/1410.0.3 Darwin/22.6.0',
}
data = {
'pkId': pkId,
'param': encrypted_param,
}
try:
response = requests.post('https://api.cloud.189.cn/login4MergedClient.action', headers=headers, data=data).text
ciphertext = re.search(r'<ciphertext>(.*?)</ciphertext>', response, re.DOTALL).group(1)
user_data = unquote(aes_cbc_decrypt(ciphertext, aes_key, aes_iv))
# print(user_data)
login_Name = re.search(r'<loginName>(.*?)</loginName>', user_data, re.DOTALL).group(1)
session_Key = re.search(r'<sessionKey>(.*?)</sessionKey>', user_data, re.DOTALL).group(1)
sessionSecret = re.search(r'<sessionSecret>(.*?)</sessionSecret>', user_data, re.DOTALL).group(1)
familySessionKey = re.search(r'<familySessionKey>(.*?)</familySessionKey>', user_data, re.DOTALL).group(1)
return login_Name, session_Key,sessionSecret,familySessionKey
except Exception as e:
print(e)
return False
def day_sign(sS,session_key):
gmt_time = datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
signature = hmac_sha1_hex(sS,f'SessionKey={session_key}&Operate=GET&RequestURI=/mkt/userSign.action&Date={gmt_time}')
headers = {
'Host': 'api.cloud.189.cn',
'x-request-id': '26E11B6CBEB94F77A2E5615C20C06113',
'signature': signature,
'date': gmt_time,
'accept-language': 'zh-cn',
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Ecloud/10.3.3 (iPhone; 02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8; appStore) iOS/15.8.3',
'sessionkey': session_key,
'accept': '*/*',
}
params = {
'clientType': 'TELEIPHONE',
'version': '10.3.3',
'model': 'iPhone',
'osFamily': 'iOS',
'osVersion': '15.8.3',
'clientSn': '02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8',
}
response = requests.get('https://api.cloud.189.cn/mkt/userSign.action', params=params, headers=headers).text
if 'userSignResult' in response:
print('【天翼云盘】签到成功:' + re.search(r'<resultTip>(.*?)</resultTip>', response, re.DOTALL).group(1))
log('【天翼云盘】签到成功:' + re.search(r'<resultTip>(.*?)</resultTip>', response, re.DOTALL).group(1))
else:
print('【天翼云盘】签到失败:' + response)
log('【天翼云盘】签到失败:' + response)
def vip_sign(session_key):
headers = {
'Host': 'm.cloud.189.cn',
'accept': 'application/json, text/plain, */*',
'sec-fetch-site': 'same-origin',
'sec-fetch-dest': 'empty',
'accept-language': 'zh-CN,zh-Hans;q=0.9',
'sec-fetch-mode': 'cors',
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Ecloud/10.3.11 iOS/16.6.1 clientId/027A8AB808-F7A5-431E-8B37-6BD9559D22D7 clientModel/iPhone proVersion/1.0.5',
'referer': 'https://m.cloud.189.cn/zt/2025/cloud-space-receive/index.html',
}
params = {
'noCache': str(int(time.time() *1000)),
'activityId': 'ACT2025VIP2T',
'sessionKey': session_key,
'prizeId': '2T_2025VIP',
}
response = requests.get('https://m.cloud.189.cn/market/drawTargetSpace.action', params=params, headers=headers).json()
if response['code'] == '0' and response['message'] == '成功':
print('【天翼云盘】2T空间月月领:领取成功')
log('【天翼云盘】2T空间月月领:领取成功')
else:
print('【天翼云盘】2T空间月月领:' + response['message'])
log('【天翼云盘】2T空间月月领:' + response['message'])
def ssoLoginMerge(sk,skF,token):
print("" * 35 )
session = requests.Session()
timestamp = str(int(time.time()))
api_headers = {
'Host': 'm.cloud.189.cn',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Ecloud/10.3.3 iOS/15.8.3 clientId/02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8 clientModel/iPhone proVersion/1.0.5',
'accept-language': 'zh-CN,zh-Hans;q=0.9',
'referer': 'https://m.cloud.189.cn/zt/2024/green-task-system/index.html?uxChannel=10021132000'
}
session.headers.update(api_headers)
params = {
'sessionKey': sk,
'sessionKeyFm': skF,
'eAccessToken': token,
'redirectUrl': 'https://m.cloud.189.cn/zt/2024/green-task-system/index.html?uxChannel=10021132000',
'rand': f'6947_{timestamp}',
}
# 获取cookie数据
session.get('https://m.cloud.189.cn/ssoLoginMerge.action', params=params)
# 签到
params = {
'sessionKey': sk,
'activityId': 'ACT2024cztx',
}
response = session.get('https://m.cloud.189.cn/market/signInNew.action', params=params)
if response.json().get('result'):
print('【绿色能量活动】签到成功')
log('【绿色能量活动】签到成功')
params = {
'sessionKey': sk,
'activityId': 'ACT2024cztx',
}
response = session.get('https://m.cloud.189.cn/market/signInNewInfo.action', params=params)
print('【绿色能量活动】已签到,今天是本周第' + str(response.json().get('data')) + '天签到')
else:
print('【绿色能量活动】签到失败:' + response.text)
log('【绿色能量活动】签到失败:' + response.text)
print("\n" + "-" * 50)
print('【绿色能量活动】获取新人专属任务')
params = {
'sessionKey': sk,
'activityId': 'ACT2024cztx',
'random': '0.48929593893531875',
'taskType': '1',
}
response = session.get('https://m.cloud.189.cn/market/getGreenTaskList.action', params=params).json()
new_task = get_task_info(response)
if len(new_task) > 0:
print('【绿色能量活动】获取到' + str(len(new_task)) + '个未完成新人专属任务')
for task in new_task:
task_id = task["taskId"]
task_name = task["taskName"]
data = {
'activityId': 'ACT2024cztx',
'sessionKey': sk,
'taskId': task_id,
}
response = session.post('https://m.cloud.189.cn/market/doGreenTask.action', data=data)
if response.json().get('data'):
print(f'【绿色能量活动--->新人专属任务】✅ 任务完成: {task_name}')
else:
print(f'【绿色能量活动--->新人专属任务】⏩ 任务已跳过: {task_name}')
time.sleep(1)
else:
print('【绿色能量活动】新人专属任务已完成,跳过操作')
print("-" * 50 + "\n")
print("-" * 50)
print('【绿色能量活动】获取AI任务')
params = {
'sessionKey': sk,
'activityId': 'ACT2024cztx',
'random': '0.3382804414050936',
'taskType': '2',
}
response = session.get('https://m.cloud.189.cn/market/getGreenTaskList.action', params=params).json()
AI_task = get_task_info(response)
if len(AI_task) > 0:
print('【绿色能量活动】获取到' + str(len(AI_task)) + '个未完成日常AI任务')
for task in AI_task:
task_id = task["taskId"]
task_name = task["taskName"]
data = {
'activityId': 'ACT2024cztx',
'sessionKey': sk,
'taskId': task_id,
}
response = session.post('https://m.cloud.189.cn/market/doGreenTask.action', data=data)
if response.json().get('data'):
print(f'【绿色能量活动--->日常AI任务】✅ 任务完成: {task_name} ')
else:
print(f'【绿色能量活动--->日常AI任务】⏩ 任务已跳过: {task_name} ')
time.sleep(1)
else:
print('【绿色能量活动】日常AI任务已完成跳过操作')
print("-" * 50 + "\n")
print("-" * 50)
print('【绿色能量活动】获取绿动任务')
params = {
'sessionKey': sk,
'activityId': 'ACT2024cztx',
'random': '0.3382804414050936',
'taskType': '3',
}
response = session.get('https://m.cloud.189.cn/market/getGreenTaskList.action', params=params).json()
AI_task = get_task_info(response)
if len(AI_task) > 0:
print('【绿色能量活动】获取到' + str(len(AI_task)) + '个未完成绿动任务')
for task in AI_task:
task_id = task["taskId"]
task_name = task["taskName"]
data = {
'activityId': 'ACT2024cztx',
'sessionKey': sk,
'taskId': task_id,
}
response = session.post('https://m.cloud.189.cn/market/doGreenTask.action', data=data)
if response.json().get('data'):
print(f'【绿色能量活动--->绿动任务】✅ 任务完成: {task_name} ')
else:
print(f'【绿色能量活动--->绿动任务】⏩ 任务已跳过: {task_name} ')
time.sleep(1)
else:
print('【绿色能量活动】绿动任务已完成,跳过操作')
print("-" * 50 + "\n")
# 获取绿色能量数据
params = {
'sessionKey': sk,
'activityId': 'ACT2024cztx',
}
response = requests.get('https://m.cloud.189.cn/market/getGreenLevelList.action', params=params).json()
print('【绿色能量活动】目前能量:' + str(response['data']['userScore']) + 'g')
log('【绿色能量活动】目前能量:' + str(response['data']['userScore']) + 'g'+ "\n")
print("" * 35 + "\n")
def main():
z = 1
for ck in cloud189_token:
try:
print('=' * 60 + '\n')
print(f'登录第{z}个账号')
print('=' * 60 + '\n')
login_result = login4MergedClient(ck)
print('\n开始签到操作>>>>>>>>>>')
if isinstance(login_result, tuple):
sessionKey = login_result[1]
sessionSecret = login_result[2]
login_name = login_result[0]
print(f'{login_name}】登录成功')
log(f'{login_name}】登录成功')
print('获取到的临时Session_key:' + sessionKey)
day_sign(sessionSecret, sessionKey)
vip_sign(sessionKey)
print("" * 35 + "\n")
ssoLoginMerge(sessionKey, login_result[3], ck)
else:
print(f'{z}个账号获取sessionKey失败请检查accessToken是否正确')
log(f'{z}个账号获取sessionKey失败请检查accessToken是否正确')
z = z + 1
except Exception as e:
print('未知错误' + str(e))
# print(get_AccessToken(''))
if __name__ == '__main__':
main()
try:
send_notification_message(title='天翼云盘签到') # 发送通知
except Exception as e:
print('推送出错:' + str(e))

View File

@@ -0,0 +1,540 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/jtc.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/jtc.py
# Repo: lksky8/sign-ql
# Path: jtc.py
# UploadedAt: 2025-10-26T12:24:47Z
# SHA256: d7fa5acdc107ddb45fd772c4bb0c9491fd48e8e3d7d18ae5a4286579151676ef
# Category: 微信小程序/抓包版
# Evidence: appid/openid/session_key/encryptedData等小程序字段
"""
捷停车签到
作者https://github.com/lksky8/sign-ql
最后更新日期2025-10-26
食用方法打开捷停车app抓请求url=https://sytgate.jslife.com.cn/core-gateway/user/login/verify/token里面的deviceId和token(一般在请求参数里面)在环境变量输入export jtc_token=账号1#deviceId#token1&账号2#deviceId#token2
支持多用户运行
多用户用&或者@隔开
例如账号1账号1#C5A59624-6666-4682-9876-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9.... 账号2#C5A59624-5555-1234-9E41-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9....
则变量为
export jtc_token="账号1#C5A59624-6666-4682-9876-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9....&账号2#C5A59624-5555-1234-9E41-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9...."
cron: 12 2 * * *
"""
import requests
import time
import hashlib
import os
import re
import uuid
import json
import random
def generate_nonce():
"""生成符合要求的UUID格式字符串"""
return str(uuid.uuid4()).upper()
if 'jtc_token' in os.environ:
jtc_token = re.split("@|&",os.environ.get("jtc_token"))
print(f'查找到{len(jtc_token)}个账号\n')
else:
jtc_token = []
print('无jtc_token变量\n')
send_msg = ''
one_msg = ''
def Log(cont=''):
global send_msg, one_msg
if cont:
one_msg += f'\n{cont}'
send_msg += f'\n{cont}'
def send_notification_message(title):
try:
from notify import send
print("加载通知服务成功!")
send(title, send_msg)
except Exception as e:
if e:
print('发送通知消息失败!')
api_headers = {
'Host': 'sytgate.jslife.com.cn',
'Content-Type': 'application/json;charset=utf-8',
'applicationVersion': '60406',
'Accept': '*/*',
'User-Agent': 'JTC/6.4.6 (iPhone; iOS 15.8.3; Scale/3.00)',
'Accept-Language': 'zh-Hans-CN;q=1',
}
longitude = f'113.07{random.randint(100, 999)}'
latitude = f'22.888624{random.randint(100, 999)}'
def md5_encrypt(text):
return hashlib.md5(text.encode('utf-8')).hexdigest().upper()
def refresh_token(user_phone,user_deviceid,user_token):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce() # 生成nonce
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&deviceId={user_deviceid}&nonce={nonce}&osType=iOS&signType=MD5&timestamp={timestamp}&token={user_token}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'deviceId': user_deviceid,
'osType': 'iOS',
'signType': 'MD5',
'applictionType': 'APP',
'applictionVersion': '60406',
'token': user_token,
'timestamp': timestamp,
'sign': sign,
'nonce': nonce
}
try:
response = requests.post('https://sytgate.jslife.com.cn/core-gateway/user/login/verify/token',headers=api_headers,json=json_data)
response_json = response.json()
if response_json['resultCode'] == '0' and response_json['message'] == '成功':
print(f'[{user_phone}] 刷新token成功')
return {'new_token': response_json['obj']['token'], 'new_user_id': response_json['obj']['userId']}
elif response_json['resultCode'] == '10011' and response_json['message'] == '用户已在其他平台登录':
print(f'[{user_phone}] 刷新token失败请重新获取token')
elif response_json['resultCode'] == '3126' and response_json['message'] == 'token已过期':
print(f'[{user_phone}] 刷新token失败token已过期请重新获取')
return None
else:
print(f'[{user_phone}] 刷新token失败{response_json}')
return None
except requests.exceptions.RequestException as e:
print(f'刷新token发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'刷新token发生解析错误: {str(e)}')
except Exception as e:
print(f'刷新token发生未知错误: {str(e)}')
def get_coin(token,user_id,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce() # 生成nonce
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5&timestamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'userId': user_id,
'signType': 'MD5',
'reqSource': 'APP_JTC',
'applictionType': 'APP',
'applictionVersion': '60406',
'token': token,
'timestamp': timestamp,
'sign': sign,
'nonce': nonce,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/balance/query', headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
print(f'[{user_mobile}] 积分:{response_json["data"]["accountAmt"]},可抵扣:{response_json["data"]["deductAmount"]}')
Log(f'[{user_mobile}] 积分:{response_json["data"]["accountAmt"]},可抵扣:{response_json["data"]["deductAmount"]}')
else:
print(f'[{user_mobile}] 查询积分失败:{response_json["message"]}')
Log(f'[{user_mobile}] 查询积分失败:{response_json["message"]}')
except requests.exceptions.RequestException as e:
print(f'查询用户积分发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'查询用户积分发生解析错误: {str(e)}')
except Exception as e:
print(f'查询用户积分发生未知错误: {str(e)}')
def get_userinfo(token,user_id):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce() # 生成nonce
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5&timestamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'userId': user_id,
'signType': 'MD5',
'sign': sign,
'charset': 'UTF-8',
'reqSource': 'APP_JTC',
'applictionType': 'APP',
'version': 'V1.0',
'token': token,
'timestamp': timestamp,
'applictionVersion': '60406',
'nonce': nonce,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/member/queryUserBenefitInfo',headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
if response_json['data']['mobile'] is None:
return None
else:
return response_json['data']['mobile']
else:
print(f'查询用户信息失败:{response_json["message"]}')
return None
except requests.exceptions.RequestException as e:
print(f'查询用户信息发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'查询用户信息发生解析错误: {str(e)}')
except Exception as e:
print(f'查询用户信息发生未知错误: {str(e)}')
def do_userinfo(user_id,user_mobile):
timestamp = str(int(time.time() * 1000))
json_data = {
'userId': user_id,
'openId': '',
'gender': 'MALE',
'birthday': '2000-01-01',
'province': '广东省',
'city': '广州市',
'platformType': 'APP_JTC',
}
try:
response = requests.post(f'https://sytgate.jslife.com.cn/core-gateway/user/update/extend-info?t={timestamp}',headers=api_headers, json=json_data)
response_json = response.json()
if response_json['resultCode'] == '0':
print(f'[{user_mobile}] 更新用户信息成功:{user_id}')
if response_json['obj']:
print(f'[{user_mobile}] 个人信息已完善并获得30停车币')
except requests.exceptions.RequestException as e:
print(f'更新用户信息发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'更新用户信息发生解析错误: {str(e)}')
except Exception as e:
print(f'更新用户信息发生未知错误: {str(e)}')
def query_task(user_token, user_id, user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5&timestamp={timestamp}&token={user_token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'osType': 'IOS',
'signType': 'MD5',
'userId': user_id,
'nonce': nonce,
'applictionType': 'APP',
'reqVersion': 'V2.0',
'applictionVersion': '60406',
'token': user_token,
'timestamp': timestamp,
'sign': sign,
'platformType': 'APP',
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/query',headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
daily_tasks = [item for item in response_json['data'] if item["taskType"] == "每日任务"]
task_list = daily_tasks[0]['taskList']
all_tasks = []
for task_item in task_list:
task_id = task_item['taskNo']
task_name = task_item['showTitle']
all_tasks.append({
'task_id': task_id,
'task_name': task_name
})
print(f'[{user_mobile}] 查询任务成功: 已获取到 {len(task_list)} 个任务')
return all_tasks
else:
print(f'查询任务失败:{response_json["message"]}')
return None
except requests.exceptions.RequestException as e:
print(f'查询任务发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'查询任务发生解析错误: {str(e)}')
except Exception as e:
print(f'查询任务发生未知错误: {str(e)}')
def do_task(token,user_id,task_id,task_name,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&osType=IOS&platformType=APP&receiveTag=false&reqSource=APP_JTC&signType=MD5&taskNo={task_id}&timestamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'nonce': nonce,
'taskNo': task_id,
'reqSource': 'APP_JTC',
'receiveTag': 'false',
'applictionVersion': '60406',
'timestamp': timestamp,
'osType': 'IOS',
'userId': user_id,
'applictionType': 'APP',
'token': token,
'platformType': 'APP',
'signType': 'MD5',
'sign': sign,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/complete',headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
print(f'[{user_mobile}]【{task_name}】 任务成功,获得 {response_json["data"]["integralValue"]} 停车币')
elif response_json['code'] == '1' or response_json['code'] == 'INTER006':
print(f'[{user_mobile}]【{task_name}】 任务失败: {response_json["message"]}')
else:
print(f'[{user_mobile}]【{task_name}】 任务未知错误')
print(response_json)
except requests.exceptions.RequestException as e:
print(f'完成任务发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'完成任务发生解析错误: {str(e)}')
except Exception as e:
print(f'完成任务发生未知错误: {str(e)}')
def task_report(deviceId,user_id,token,user_mobile):
timestamp = str(int(time.time() * 1000))
event = '{"referrer":"PersonalCenterPage","pageEventName":"PointsTaskPage"}'
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=MoreTaskClick&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5&timestamp={timestamp}&token={token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
json_data = {
'dataSourceType': '原生',
'eventType': 'activity',
'opSystem': 'iOS',
'deviceId': deviceId,
'opSystemVersion': '14.6',
'phoneModel': 'iPhone10,3',
'latitude': latitude,
'eventName': 'MoreTaskClick',
'netType': 'NET_WIFI',
'signType': 'MD5',
'nonce': nonce,
'sign': sign,
'token': token,
'timestamp': timestamp,
'eventProperty': {
'referrer': 'PersonalCenterPage',
'pageEventName': 'PointsTaskPage',
},
'longitude': longitude,
'serviceProviders': '未知',
'applictionVersion': '60406',
'screenResolution': '375*812',
'productName': '捷停车APP',
'applictionType': 'APP',
'productVersion': '6.4.6',
'userId': user_id,
}
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
if response.json()['resultCode'] == '0' and response.json()['success'] :
print(f'[{user_mobile}] 任务数据上报成功')
else:
print(f'[{user_mobile}] 任务数据上报失败')
def task_report2(deviceId,user_id,user_token,task_name,user_mobile):
nonce = generate_nonce()
timestamp = str(int(time.time() * 1000))
event = json.dumps({"referrer":"PersonalCenterPage","pageEventName":"PointsTaskPage","TaskName":task_name}, separators=(',', ':'))
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=ShowGoToFinish&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5&timestamp={timestamp}&token={user_token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
json_data = {
'dataSourceType': '原生',
'eventType': 'activity',
'opSystem': 'iOS',
'deviceId': deviceId,
'opSystemVersion': '14.6',
'phoneModel': 'iPhone10,3',
'latitude': latitude,
'eventName': 'ShowGoToFinish',
'netType': 'NET_WIFI',
'signType': 'MD5',
'nonce': nonce,
'sign': sign,
'token': user_token,
'timestamp': timestamp,
'eventProperty': {
'referrer': 'PointsDetailPage',
'pageEventName': 'PointsTaskPage',
'TaskName': task_name,
},
'longitude': longitude,
'serviceProviders': '未知',
'applictionVersion': '60408',
'screenResolution': '375*812',
'productName': '捷停车APP',
'applictionType': 'APP',
'productVersion': '6.4.8',
'userId': user_id,
}
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
if response.json()['resultCode'] == '0' and response.json()['success'] :
print(f'[{user_mobile}] 数据上报成功')
else:
print(f'[{user_mobile}] 数据上报失败')
def find_report(deviceId,user_id,token,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
event = json.dumps({"referrer":"PointsTaskPage","pageEventName":"FindPreferentialPage"}, separators=(',', ':'))
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=ShowGoToClaim&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5&timestamp={timestamp}&token={token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
json_data = {
'dataSourceType': '原生',
'eventType': 'activity',
'opSystem': 'iOS',
'deviceId': deviceId,
'opSystemVersion': '14.6',
'phoneModel': 'iPhone10,3',
'latitude': latitude,
'eventName': 'ShowGoToClaim',
'netType': 'NET_WIFI',
'signType': 'MD5',
'nonce': nonce,
'sign': sign,
'token': token,
'timestamp': timestamp,
'eventProperty': {
'referrer': 'PointsTaskPage',
'pageEventName': 'FindPreferentialPage',
},
'longitude': longitude,
'serviceProviders': '未知',
'applictionVersion': '60406',
'screenResolution': '375*812',
'productName': '捷停车APP',
'applictionType': 'APP',
'productVersion': '6.4.6',
'userId': user_id,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
if response.json()['resultCode'] == '0' and response.json()['success'] :
print(f'[{user_mobile}]【去找优惠】任务数据上报成功')
else:
print(f'{[user_mobile]}【去找优惠】任务数据上报失败')
except requests.exceptions.RequestException as e:
print(f'【去找优惠】任务数据上报发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'【去找优惠】任务数据上报发生解析错误: {str(e)}')
except Exception as e:
print(f'【去找优惠】任务数据上报发生未知错误: {str(e)}')
def query_day_sign(token, userid,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&signType=MD5&timestamp={timestamp}&token={token}&userId={userid}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'userId': userid,
'signType': 'MD5',
'applictionType': 'APP',
'applictionVersion': '60406',
'token': token,
'timestamp': timestamp,
'sign': sign,
'nonce': nonce,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/sign-in-task/query', headers=api_headers,json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
# print(f'[{user_mobile}] 每日签到查询成功')
if not response_json['data']['todaySingInTag']:
print(f'[{user_mobile}] 每日签到未完成')
task_receive(token,userid,response_json['data']['taskNo'],'每日签到',user_mobile)
else:
print(f'[{user_mobile}] 每日签到已完成')
Log(f'[{user_mobile}] 每日签到已完成')
else:
print(f'[{user_mobile}] 每日签到查询失败:{response_json["message"]}')
except requests.exceptions.RequestException as e:
print(f'查询每日签到发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'查询每日签到发生解析错误: {str(e)}')
except Exception as e:
print(f'查询每日签到发生未知错误: {str(e)}')
def task_receive(token,userid,task_id,task_name,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&osType=IOS&platformType=APP&reqSource=APP_JTC&signType=MD5&taskNo={task_id}&timestamp={timestamp}&token={token}&userId={userid}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'nonce': nonce,
'taskNo': task_id,
'reqSource': 'APP_JTC',
'applictionVersion': '60406',
'timestamp': timestamp,
'osType': 'IOS',
'userId': userid,
'applictionType': 'APP',
'token': token,
'platformType': 'APP',
'signType': 'MD5',
'sign': sign,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/receive', headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
print(f'[{user_mobile}]【{task_name}】 获得 {response_json["data"]} 停车币')
Log(f'[{user_mobile}]【{task_name}】 获得 {response_json["data"]} 停车币')
else:
print(f'[{user_mobile}]【{task_name}】 领取任务奖励失败:{response_json["message"]}')
except requests.exceptions.RequestException as e:
print(f'领取任务奖励发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'领取任务奖励发生解析错误: {str(e)}')
except Exception as e:
print(f'领取任务奖励发生未知错误: {str(e)}')
if __name__ == '__main__':
try:
if jtc_token:
z = 1
for item in jtc_token:
print('-' * 50)
print(f'登录第{z}个账号>>>>>>')
phone = item.split('#')[0]
device_id = item.split('#')[1]
token = item.split('#')[2]
user_data = refresh_token(phone, device_id, token)
if user_data:
new_userid = user_data['new_user_id']
new_token = user_data['new_token']
query_day_sign(new_token, new_userid, phone)
print('-' * 50)
task_report(device_id, new_userid, new_token, phone)
tasks = query_task(new_token, new_userid, phone)
if tasks:
for task in tasks:
task_report2(device_id, new_userid, new_token, task['task_name'], phone)
if task['task_name'] == '看视频':
print(f'[{phone}]【看视频】跳过任务')
# 破解不了直接跳过
continue
if task['task_name'] == '去找优惠':
find_report(device_id, new_userid, new_token, phone)
time.sleep(5)
do_task(new_token, new_userid, task['task_id'], task['task_name'], phone)
time.sleep(3)
task_receive(new_token, new_userid, task['task_id'], task['task_name'], phone)
time.sleep(2)
# do_userinfo(userid, user_phone)
print('-' * 50)
get_coin(new_token, new_userid, phone)
print('*' * 50)
Log('\n')
else:
print(f'{z}个账号用户信息获取失败')
Log(f'{z}个账号用户信息获取失败')
z += 1
else:
print('请先填入jtc_token变量')
Log('请先填入jtc_token变量')
except Exception as e:
print(f'发生错误: {str(e)}')
try:
send_notification_message(title='捷停车') # 发送通知
except Exception as e:
print('推送失败:' + str(e))

View File

@@ -0,0 +1,540 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/jtc.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/jtc.py
# Repo: lksky8/sign-ql
# Path: jtc.py
# UploadedAt: 2025-10-26T12:24:47Z
# SHA256: d7fa5acdc107ddb45fd772c4bb0c9491fd48e8e3d7d18ae5a4286579151676ef
# Category: 微信小程序/抓包版
# Evidence: appid/openid/session_key/encryptedData等小程序字段
"""
捷停车签到
作者https://github.com/lksky8/sign-ql
最后更新日期2025-10-26
食用方法打开捷停车app抓请求url=https://sytgate.jslife.com.cn/core-gateway/user/login/verify/token里面的deviceId和token(一般在请求参数里面)在环境变量输入export jtc_token=账号1#deviceId#token1&账号2#deviceId#token2
支持多用户运行
多用户用&或者@隔开
例如账号1账号1#C5A59624-6666-4682-9876-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9.... 账号2#C5A59624-5555-1234-9E41-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9....
则变量为
export jtc_token="账号1#C5A59624-6666-4682-9876-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9....&账号2#C5A59624-5555-1234-9E41-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9...."
cron: 12 2 * * *
"""
import requests
import time
import hashlib
import os
import re
import uuid
import json
import random
def generate_nonce():
"""生成符合要求的UUID格式字符串"""
return str(uuid.uuid4()).upper()
if 'jtc_token' in os.environ:
jtc_token = re.split("@|&",os.environ.get("jtc_token"))
print(f'查找到{len(jtc_token)}个账号\n')
else:
jtc_token = []
print('无jtc_token变量\n')
send_msg = ''
one_msg = ''
def Log(cont=''):
global send_msg, one_msg
if cont:
one_msg += f'\n{cont}'
send_msg += f'\n{cont}'
def send_notification_message(title):
try:
from notify import send
print("加载通知服务成功!")
send(title, send_msg)
except Exception as e:
if e:
print('发送通知消息失败!')
api_headers = {
'Host': 'sytgate.jslife.com.cn',
'Content-Type': 'application/json;charset=utf-8',
'applicationVersion': '60406',
'Accept': '*/*',
'User-Agent': 'JTC/6.4.6 (iPhone; iOS 15.8.3; Scale/3.00)',
'Accept-Language': 'zh-Hans-CN;q=1',
}
longitude = f'113.07{random.randint(100, 999)}'
latitude = f'22.888624{random.randint(100, 999)}'
def md5_encrypt(text):
return hashlib.md5(text.encode('utf-8')).hexdigest().upper()
def refresh_token(user_phone,user_deviceid,user_token):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce() # 生成nonce
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&deviceId={user_deviceid}&nonce={nonce}&osType=iOS&signType=MD5&timestamp={timestamp}&token={user_token}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'deviceId': user_deviceid,
'osType': 'iOS',
'signType': 'MD5',
'applictionType': 'APP',
'applictionVersion': '60406',
'token': user_token,
'timestamp': timestamp,
'sign': sign,
'nonce': nonce
}
try:
response = requests.post('https://sytgate.jslife.com.cn/core-gateway/user/login/verify/token',headers=api_headers,json=json_data)
response_json = response.json()
if response_json['resultCode'] == '0' and response_json['message'] == '成功':
print(f'[{user_phone}] 刷新token成功')
return {'new_token': response_json['obj']['token'], 'new_user_id': response_json['obj']['userId']}
elif response_json['resultCode'] == '10011' and response_json['message'] == '用户已在其他平台登录':
print(f'[{user_phone}] 刷新token失败请重新获取token')
elif response_json['resultCode'] == '3126' and response_json['message'] == 'token已过期':
print(f'[{user_phone}] 刷新token失败token已过期请重新获取')
return None
else:
print(f'[{user_phone}] 刷新token失败{response_json}')
return None
except requests.exceptions.RequestException as e:
print(f'刷新token发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'刷新token发生解析错误: {str(e)}')
except Exception as e:
print(f'刷新token发生未知错误: {str(e)}')
def get_coin(token,user_id,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce() # 生成nonce
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5&timestamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'userId': user_id,
'signType': 'MD5',
'reqSource': 'APP_JTC',
'applictionType': 'APP',
'applictionVersion': '60406',
'token': token,
'timestamp': timestamp,
'sign': sign,
'nonce': nonce,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/balance/query', headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
print(f'[{user_mobile}] 积分:{response_json["data"]["accountAmt"]},可抵扣:{response_json["data"]["deductAmount"]}')
Log(f'[{user_mobile}] 积分:{response_json["data"]["accountAmt"]},可抵扣:{response_json["data"]["deductAmount"]}')
else:
print(f'[{user_mobile}] 查询积分失败:{response_json["message"]}')
Log(f'[{user_mobile}] 查询积分失败:{response_json["message"]}')
except requests.exceptions.RequestException as e:
print(f'查询用户积分发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'查询用户积分发生解析错误: {str(e)}')
except Exception as e:
print(f'查询用户积分发生未知错误: {str(e)}')
def get_userinfo(token,user_id):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce() # 生成nonce
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5&timestamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'userId': user_id,
'signType': 'MD5',
'sign': sign,
'charset': 'UTF-8',
'reqSource': 'APP_JTC',
'applictionType': 'APP',
'version': 'V1.0',
'token': token,
'timestamp': timestamp,
'applictionVersion': '60406',
'nonce': nonce,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/member/queryUserBenefitInfo',headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
if response_json['data']['mobile'] is None:
return None
else:
return response_json['data']['mobile']
else:
print(f'查询用户信息失败:{response_json["message"]}')
return None
except requests.exceptions.RequestException as e:
print(f'查询用户信息发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'查询用户信息发生解析错误: {str(e)}')
except Exception as e:
print(f'查询用户信息发生未知错误: {str(e)}')
def do_userinfo(user_id,user_mobile):
timestamp = str(int(time.time() * 1000))
json_data = {
'userId': user_id,
'openId': '',
'gender': 'MALE',
'birthday': '2000-01-01',
'province': '广东省',
'city': '广州市',
'platformType': 'APP_JTC',
}
try:
response = requests.post(f'https://sytgate.jslife.com.cn/core-gateway/user/update/extend-info?t={timestamp}',headers=api_headers, json=json_data)
response_json = response.json()
if response_json['resultCode'] == '0':
print(f'[{user_mobile}] 更新用户信息成功:{user_id}')
if response_json['obj']:
print(f'[{user_mobile}] 个人信息已完善并获得30停车币')
except requests.exceptions.RequestException as e:
print(f'更新用户信息发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'更新用户信息发生解析错误: {str(e)}')
except Exception as e:
print(f'更新用户信息发生未知错误: {str(e)}')
def query_task(user_token, user_id, user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5&timestamp={timestamp}&token={user_token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'osType': 'IOS',
'signType': 'MD5',
'userId': user_id,
'nonce': nonce,
'applictionType': 'APP',
'reqVersion': 'V2.0',
'applictionVersion': '60406',
'token': user_token,
'timestamp': timestamp,
'sign': sign,
'platformType': 'APP',
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/query',headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
daily_tasks = [item for item in response_json['data'] if item["taskType"] == "每日任务"]
task_list = daily_tasks[0]['taskList']
all_tasks = []
for task_item in task_list:
task_id = task_item['taskNo']
task_name = task_item['showTitle']
all_tasks.append({
'task_id': task_id,
'task_name': task_name
})
print(f'[{user_mobile}] 查询任务成功: 已获取到 {len(task_list)} 个任务')
return all_tasks
else:
print(f'查询任务失败:{response_json["message"]}')
return None
except requests.exceptions.RequestException as e:
print(f'查询任务发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'查询任务发生解析错误: {str(e)}')
except Exception as e:
print(f'查询任务发生未知错误: {str(e)}')
def do_task(token,user_id,task_id,task_name,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&osType=IOS&platformType=APP&receiveTag=false&reqSource=APP_JTC&signType=MD5&taskNo={task_id}&timestamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'nonce': nonce,
'taskNo': task_id,
'reqSource': 'APP_JTC',
'receiveTag': 'false',
'applictionVersion': '60406',
'timestamp': timestamp,
'osType': 'IOS',
'userId': user_id,
'applictionType': 'APP',
'token': token,
'platformType': 'APP',
'signType': 'MD5',
'sign': sign,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/complete',headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
print(f'[{user_mobile}]【{task_name}】 任务成功,获得 {response_json["data"]["integralValue"]} 停车币')
elif response_json['code'] == '1' or response_json['code'] == 'INTER006':
print(f'[{user_mobile}]【{task_name}】 任务失败: {response_json["message"]}')
else:
print(f'[{user_mobile}]【{task_name}】 任务未知错误')
print(response_json)
except requests.exceptions.RequestException as e:
print(f'完成任务发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'完成任务发生解析错误: {str(e)}')
except Exception as e:
print(f'完成任务发生未知错误: {str(e)}')
def task_report(deviceId,user_id,token,user_mobile):
timestamp = str(int(time.time() * 1000))
event = '{"referrer":"PersonalCenterPage","pageEventName":"PointsTaskPage"}'
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=MoreTaskClick&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5&timestamp={timestamp}&token={token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
json_data = {
'dataSourceType': '原生',
'eventType': 'activity',
'opSystem': 'iOS',
'deviceId': deviceId,
'opSystemVersion': '14.6',
'phoneModel': 'iPhone10,3',
'latitude': latitude,
'eventName': 'MoreTaskClick',
'netType': 'NET_WIFI',
'signType': 'MD5',
'nonce': nonce,
'sign': sign,
'token': token,
'timestamp': timestamp,
'eventProperty': {
'referrer': 'PersonalCenterPage',
'pageEventName': 'PointsTaskPage',
},
'longitude': longitude,
'serviceProviders': '未知',
'applictionVersion': '60406',
'screenResolution': '375*812',
'productName': '捷停车APP',
'applictionType': 'APP',
'productVersion': '6.4.6',
'userId': user_id,
}
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
if response.json()['resultCode'] == '0' and response.json()['success'] :
print(f'[{user_mobile}] 任务数据上报成功')
else:
print(f'[{user_mobile}] 任务数据上报失败')
def task_report2(deviceId,user_id,user_token,task_name,user_mobile):
nonce = generate_nonce()
timestamp = str(int(time.time() * 1000))
event = json.dumps({"referrer":"PersonalCenterPage","pageEventName":"PointsTaskPage","TaskName":task_name}, separators=(',', ':'))
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=ShowGoToFinish&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5&timestamp={timestamp}&token={user_token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
json_data = {
'dataSourceType': '原生',
'eventType': 'activity',
'opSystem': 'iOS',
'deviceId': deviceId,
'opSystemVersion': '14.6',
'phoneModel': 'iPhone10,3',
'latitude': latitude,
'eventName': 'ShowGoToFinish',
'netType': 'NET_WIFI',
'signType': 'MD5',
'nonce': nonce,
'sign': sign,
'token': user_token,
'timestamp': timestamp,
'eventProperty': {
'referrer': 'PointsDetailPage',
'pageEventName': 'PointsTaskPage',
'TaskName': task_name,
},
'longitude': longitude,
'serviceProviders': '未知',
'applictionVersion': '60408',
'screenResolution': '375*812',
'productName': '捷停车APP',
'applictionType': 'APP',
'productVersion': '6.4.8',
'userId': user_id,
}
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
if response.json()['resultCode'] == '0' and response.json()['success'] :
print(f'[{user_mobile}] 数据上报成功')
else:
print(f'[{user_mobile}] 数据上报失败')
def find_report(deviceId,user_id,token,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
event = json.dumps({"referrer":"PointsTaskPage","pageEventName":"FindPreferentialPage"}, separators=(',', ':'))
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=ShowGoToClaim&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5&timestamp={timestamp}&token={token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
json_data = {
'dataSourceType': '原生',
'eventType': 'activity',
'opSystem': 'iOS',
'deviceId': deviceId,
'opSystemVersion': '14.6',
'phoneModel': 'iPhone10,3',
'latitude': latitude,
'eventName': 'ShowGoToClaim',
'netType': 'NET_WIFI',
'signType': 'MD5',
'nonce': nonce,
'sign': sign,
'token': token,
'timestamp': timestamp,
'eventProperty': {
'referrer': 'PointsTaskPage',
'pageEventName': 'FindPreferentialPage',
},
'longitude': longitude,
'serviceProviders': '未知',
'applictionVersion': '60406',
'screenResolution': '375*812',
'productName': '捷停车APP',
'applictionType': 'APP',
'productVersion': '6.4.6',
'userId': user_id,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
if response.json()['resultCode'] == '0' and response.json()['success'] :
print(f'[{user_mobile}]【去找优惠】任务数据上报成功')
else:
print(f'{[user_mobile]}【去找优惠】任务数据上报失败')
except requests.exceptions.RequestException as e:
print(f'【去找优惠】任务数据上报发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'【去找优惠】任务数据上报发生解析错误: {str(e)}')
except Exception as e:
print(f'【去找优惠】任务数据上报发生未知错误: {str(e)}')
def query_day_sign(token, userid,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&signType=MD5&timestamp={timestamp}&token={token}&userId={userid}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'userId': userid,
'signType': 'MD5',
'applictionType': 'APP',
'applictionVersion': '60406',
'token': token,
'timestamp': timestamp,
'sign': sign,
'nonce': nonce,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/sign-in-task/query', headers=api_headers,json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
# print(f'[{user_mobile}] 每日签到查询成功')
if not response_json['data']['todaySingInTag']:
print(f'[{user_mobile}] 每日签到未完成')
task_receive(token,userid,response_json['data']['taskNo'],'每日签到',user_mobile)
else:
print(f'[{user_mobile}] 每日签到已完成')
Log(f'[{user_mobile}] 每日签到已完成')
else:
print(f'[{user_mobile}] 每日签到查询失败:{response_json["message"]}')
except requests.exceptions.RequestException as e:
print(f'查询每日签到发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'查询每日签到发生解析错误: {str(e)}')
except Exception as e:
print(f'查询每日签到发生未知错误: {str(e)}')
def task_receive(token,userid,task_id,task_name,user_mobile):
timestamp = str(int(time.time() * 1000))
nonce = generate_nonce()
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&osType=IOS&platformType=APP&reqSource=APP_JTC&signType=MD5&taskNo={task_id}&timestamp={timestamp}&token={token}&userId={userid}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
json_data = {
'nonce': nonce,
'taskNo': task_id,
'reqSource': 'APP_JTC',
'applictionVersion': '60406',
'timestamp': timestamp,
'osType': 'IOS',
'userId': userid,
'applictionType': 'APP',
'token': token,
'platformType': 'APP',
'signType': 'MD5',
'sign': sign,
}
try:
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/receive', headers=api_headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['success']:
print(f'[{user_mobile}]【{task_name}】 获得 {response_json["data"]} 停车币')
Log(f'[{user_mobile}]【{task_name}】 获得 {response_json["data"]} 停车币')
else:
print(f'[{user_mobile}]【{task_name}】 领取任务奖励失败:{response_json["message"]}')
except requests.exceptions.RequestException as e:
print(f'领取任务奖励发生网络错误: {str(e)}')
except (ValueError, KeyError, TypeError) as e:
print(f'领取任务奖励发生解析错误: {str(e)}')
except Exception as e:
print(f'领取任务奖励发生未知错误: {str(e)}')
if __name__ == '__main__':
try:
if jtc_token:
z = 1
for item in jtc_token:
print('-' * 50)
print(f'登录第{z}个账号>>>>>>')
phone = item.split('#')[0]
device_id = item.split('#')[1]
token = item.split('#')[2]
user_data = refresh_token(phone, device_id, token)
if user_data:
new_userid = user_data['new_user_id']
new_token = user_data['new_token']
query_day_sign(new_token, new_userid, phone)
print('-' * 50)
task_report(device_id, new_userid, new_token, phone)
tasks = query_task(new_token, new_userid, phone)
if tasks:
for task in tasks:
task_report2(device_id, new_userid, new_token, task['task_name'], phone)
if task['task_name'] == '看视频':
print(f'[{phone}]【看视频】跳过任务')
# 破解不了直接跳过
continue
if task['task_name'] == '去找优惠':
find_report(device_id, new_userid, new_token, phone)
time.sleep(5)
do_task(new_token, new_userid, task['task_id'], task['task_name'], phone)
time.sleep(3)
task_receive(new_token, new_userid, task['task_id'], task['task_name'], phone)
time.sleep(2)
# do_userinfo(userid, user_phone)
print('-' * 50)
get_coin(new_token, new_userid, phone)
print('*' * 50)
Log('\n')
else:
print(f'{z}个账号用户信息获取失败')
Log(f'{z}个账号用户信息获取失败')
z += 1
else:
print('请先填入jtc_token变量')
Log('请先填入jtc_token变量')
except Exception as e:
print(f'发生错误: {str(e)}')
try:
send_notification_message(title='捷停车') # 发送通知
except Exception as e:
print('推送失败:' + str(e))

View File

@@ -0,0 +1,793 @@
// # Source: https://github.com/DearSong15/ql-scripts/blob/main/ks_dual.js
// # Raw: https://raw.githubusercontent.com/DearSong15/ql-scripts/main/ks_dual.js
// # Repo: DearSong15/ql-scripts
// # Path: ks_dual.js
// # UploadedAt: 2026-05-11T15:03:30Z
// # SHA256: aa4fbaa74f4c00599fa2a8c1e358c99c6f393dc9b180b7c8260162ddd20b1e0f
// # Category: 微信小程序/抓包版
// # Evidence: appid/openid/session_key/encryptedData等小程序字段
//
//new Env("快手双端")
const axios = require("axios");
const querystring = require("querystring");
const { SocksProxyAgent } = require("socks-proxy-agent");
const dns = require("dns");
dns.setDefaultResultOrder("ipv4first");
dns.setServers(["8.8.8.8", "114.114.114.114", "223.5.5.5"]);
// ==============================================
// 自定义签名接口KUAISHOU=81端口 NEBULA=82端口
// ==============================================
const SIGN_API_KUAISHOU = "http://127.0.0.1:81"; // 普通版(kpn=KUAISHOU)
const SIGN_API_NEBULA = "http://127.0.0.1:82"; // 极速版(kpn=NEBULA)
console.log("💡 普通版签名API: " + SIGN_API_KUAISHOU);
console.log("💡 极速版签名API: " + SIGN_API_NEBULA);
// 全局配置(原配置未改动)
const CONFIG = {
SEARCH_KEYWORDS: process.env.KS_SEARCH_KEYWORDS?.split(",") || ["短剧小说", "热门视频", "美食教程"],
DEFAULT_TASKS: process.env.KS_DEFAULT_TASKS?.split(",") || ["box", "look", "food", "search"],
CYCLE_ROUNDS: parseInt(process.env.KS_CYCLE_ROUNDS || 0),
WATCH_MIN: parseInt(process.env.KS_WATCH_MIN || 30),
WATCH_MAX: parseInt(process.env.KS_WATCH_MAX || 40),
AD_FAIL_LIMIT: parseInt(process.env.KS_AD_FAIL_LIMIT || 10),
CONTINUOUS_1COIN_LIMIT: parseInt(process.env.KS_CONTINUOUS_1COIN_LIMIT || 3),
APPEND_REST_INTERVAL: parseInt(process.env.KS_APPEND_INTERVAL || 5),
APPEND_REST_MIN: parseInt(process.env.KS_APPEND_MIN || 5000),
APPEND_REST_MAX: parseInt(process.env.KS_APPEND_MAX || 10000),
LOW_REWARD_THRESHOLD: parseInt(process.env.KS_LOW_REWARD_THRESHOLD || 10),
LOW_REWARD_LIMIT: parseInt(process.env.KS_LOW_REWARD_LIMIT || 3),
PLATFORM_CONFIG: {
KUAISHOU: {
name: "KS",
accountInfoUrl: "https://encourage.kuaishou.com/rest/wd/encourage/account/basicInfo",
host: "encourage.kuaishou.com",
appId: "kuaishou",
packageName: "com.smile.gifmaker",
appName: "快手",
displayName: "快手",
kpn: "KUAISHOU",
adClientKey: "3c2cd3f3",
reportClientKey: "3c2cd3f3"
},
NEBULA: {
name: "JSB",
accountInfoUrl: "https://nebula.kuaishou.com/rest/n/nebula/activity/earn/overview/basicInfo",
host: "nebula.kuaishou.com",
appId: "kuaishou_nebula",
packageName: "com.kuaishou.nebula",
appName: "快手极速版",
displayName: "快手极速版",
kpn: "NEBULA",
adClientKey: "2ac2a76d",
reportClientKey: "2ac2a76d"
}
},
TASK_CONFIGS: {
KUAISHOU: {
box: {
name: "宝箱广告",
businessId: 604, posId: 20345, subPageId: 100024063,
requestSceneType: 1, taskType: 1, pageId: 100011251
},
look: {
name: "看广告得金币",
businessId: 671, posId: 24068, subPageId: 100026368,
requestSceneType: 1, taskType: 1, pageId: 100011251
},
food: {
name: "饭补广告",
businessId: 921, posId: 29742, subPageId: 100029908,
requestSceneType: 7, taskType: 2, pageId: 100011251
},
search: {
name: "搜索广告",
businessId: 7077, posId: 216267, subPageId: 100161535,
pageId: 10014, requestSceneType: 1, taskType: 2,
linkUrl: "eyJwYWdlSWQiOjEwMDE0LCJzdWJQYWdlSWQiOjEwMDE2MTUzNSwicG9zSWQiOjIxNjI2NywiYnVzaW5lc3NJZCI6NzA3NywiZXh0UGFyYW1zIjoiYzc4OWI1ZTAzMjMxOTUwZjcyM2ZjMWE1ZGJjYzgwNmYzMDE1OTcyZWE0Mzc2NmNlNDYwNTk2ZDgzMGVjNTE5MDM0OGEwNTlkOTA2NWYwZGY1ZjkwY2YwMjEwMGVhMmQzYzU0YjUyZDBlNGUxY2Q0NmMxN2ExZDU3YmRhY2EyMzVlM2U1NjYzN2JmZGQzMThiZWMzNTgzOWU1YzIxNWUyNzMzY2IyMzQ2ZGQ1NDYyODc1NDdlMjc4OWYxMjZjZWU5NWZhYzg4N2IxMzM2MzBlZTEzYTVmYTlhODYzNDYxODQ5MjM0NDk3ZGY3ZTRmOWYyYzk2ZjQ5YzViMGExNzQ2NGE2MGM0MDg1MzU2NTY2ZDc4NGIxYjY3NzY3MzYzYjg3IiwiY3VzdG9tRGF0YSI6eyJleGl0SW5mbyI6eyJ0b2FzdERlc2MiOm51bGwsInRvYXN0SW1nVXJsIjpudWxsfX0sInBlbmRhbnRUeXBlIjoxLCJkaXNwbGF5VHlwZSI6Miwic2luZ2xlUGFnZUlkIjowLCJzaW5nbGVTdWJQYWdlSWQiOjAsImNoYW5uZWwiOjAsImNvdW50ZG93blJlcG9ydCI6ZmFsc2UsInRoZW1lVHlwZSI6MCwibWl4ZWRBZCI6dHJ1ZSwiZnVsbE1peGVkIjp0cnVlLCJhdXRvUmVwb3J0Ijp0cnVlLCJmcm9tVGFza0NlbnRlciI6dHJ1ZSwic2VhcmNoSW5zcGlyZVNjaGVtZUluZm8iOm51bGwsImFtb3VudCI6MH0="
}
},
NEBULA: {
box: {
name: "宝箱广告",
pageId: 11101, subPageId: 100024064, businessId: 606, posId: 20346,
requestSceneType: 1, taskType: 1
},
look: {
name: "看广告得金币",
pageId: 11101, subPageId: 100026367, businessId: 672, posId: 24067,
requestSceneType: 1, taskType: 1
},
food: {
name: "饭补广告",
pageId: 11101, subPageId: 100026367, businessId: 9362, posId: 24067,
requestSceneType: 7, taskType: 2
},
search: {
name: "搜索广告",
pageId: 11014, subPageId: 100161537, businessId: 7076, posId: 216268,
requestSceneType: 1, taskType: 1,
linkUrl: "eyJwYWdlSWQiOjExMDE0LCJzdWJQYWdlSWQiOjEwMDE2MTUzNywicG9zSWQiOjIxNjI2OCwiYnVzaW5lc3NJZCI6NzA3NiwiZXh0UGFyYW1zIjoiYjc4OWI1ZTAzMjMxOTUwZjcyM2ZjMWE1ZGJjYzgwNmYzMDE1OTcyZWE0Mzc2NmNlNDYwNTk2ZDgzMGVjNTE5MDM0OGEwNTlkOTA2NWYwZGY1ZjkwY2YwMjEwMGVhMmQzYzU0YjUyZDBlNGUxY2Q0NmMxN2ExZDU3YmRhY2EyMzVlM2U1NjYzN2JmZGQzMThiZWMzNTgzOWU1YzIxNWUyNzMzY2IyMzQ2ZGQ1NDYyODc1NDdlMjc4OWYxMjZjZWU5NWZhYzg4N2IxMzM2MzBlZTEzYTVmYTlhODYzNDYxODQ5MjM0NDk3ZGY3ZTRmOWYyYzk2ZjQ5YzViMGExNzQ2NGE2MGM0MDg1MzU2NTY2ZDc4NGIxYjY3NzY3MzYzYjg3IiwiY3VzdG9tRGF0YSI6eyJleGl0SW5mbyI6eyJ0b2FzdERlc2MiOm51bGwsInRvYXN0SW1nVXJsIjpudWxsfX0sInBlbmRhbnRUeXBlIjoxLCJkaXNwbGF5VHlwZSI6Miwic2luZ2xlUGFnZUlkIjowLCJzaW5nbGVTdWJQYWdlSWQiOjAsImNoYW5uZWwiOjAsImNvdW50ZG93blJlcG9ydCI6ZmFsc2UsInRoZW1lVHlwZSI6MCwibWl4ZWRBZCI6dHJ1ZSwiZnVsbE1peGVkIjp0cnVlLCJhdXRvUmVwb3J0Ijp0cnVlLCJmcm9tVGFza0NlbnRlciI6dHJ1ZSwic2VhcmNoSW5zcGlyZVNjaGVtZUluZm8iOm51bGwsImFtb3VudCI6MH0="
},
follow: {
name: "关注广告",
pageId: 11101, subPageId: 100026367, businessId: 672, posId: 24067,
requestSceneType: 2, taskType: 1
},
content: {
name: "内容广告",
pageId: 11101, subPageId: 100141480, businessId: 7054, posId: 186550,
requestSceneType: 1, taskType: 1
}
}
}
};
let localPublicIP = null;
// ==============================================
// 工具函数(原代码未改动)
// ==============================================
function getTime() {
return new Date().toLocaleTimeString("zh-CN", {
timeZone: "Asia/Shanghai", hour12: false,
hour: "2-digit", minute: "2-digit", second: "2-digit"
});
}
function getProxyTag(useProxy) { return useProxy ? "[代理]" : "[直连]"; }
function maskProxyUrl(proxy) {
if (!proxy) return null;
try {
const match = proxy.match(/^(socks5:\/\/)([^:@]+)(?::([^@]+))?@(.+)$/);
if (match) {
const [, protocol, user, , host] = match;
return `${protocol}${user}:***@${host}`;
}
} catch (e) {}
return proxy;
}
function log(useProxy, appName, msg) {
const tag = getProxyTag(useProxy);
const app = appName === "快手极速版" ? "快手极速版" : "快手";
console.log(`${tag}<${app}>(${getTime()}): ${msg}`);
}
function print(msg) { console.log(msg); }
// ==============================================
// 网络请求封装(原代码未改动)
// ==============================================
async function request(options, proxy = null, title = "请求") {
try {
const axiosOptions = {
method: options.method || "GET",
url: options.url,
headers: options.headers || {},
data: options.body || options.form,
timeout: options.timeout || 12000,
validateStatus: () => true
};
if (proxy) {
const agent = new SocksProxyAgent(proxy, { timeout: 10000, keepAlive: false });
axiosOptions.httpAgent = agent;
axiosOptions.httpsAgent = agent;
} else {
axiosOptions.proxy = false;
}
if (options.form && options.method === "POST" && !axiosOptions.headers["Content-Type"]) {
axiosOptions.headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8";
axiosOptions.data = querystring.stringify(options.form);
}
const resp = await axios(axiosOptions);
return { body: resp.data, status: resp.status };
} catch (e) {
console.log(`[请求失败] ${title}: ${e.message}`);
return { body: null, status: 0 };
}
}
async function checkLocalIP() {
print("正在检测本地直连公网IP...");
const urls = ["http://icanhazip.com", "http://ipinfo.io/ip", "http://httpbin.org/ip"];
for (const url of urls) {
try {
const res = await axios.get(url, { timeout: 5000, responseType: "text", proxy: false });
const ip = res.data.trim().match(/\d+\.\d+\.\d+\.\d+/)?.[0];
if (ip) {
localPublicIP = ip;
print("本地直连公网IP: " + ip);
return ip;
}
} catch (e) { continue; }
}
print("本地直连公网IP检测失败");
process.exit(1);
}
async function checkProxyIP(proxy) {
const urls = ["http://icanhazip.com", "http://ipinfo.io/ip", "http://httpbin.org/ip"];
for (const url of urls) {
try {
const { body } = await request({ method: "GET", url, timeout: 8000 }, proxy, "代理IP检测");
if (!body) continue;
const ip = body.toString().trim().match(/\d+\.\d+\.\d+\.\d+/)?.[0];
if (ip) return ip;
} catch (e) { continue; }
}
return null;
}
// ==============================================
// 签名接口 - 核心修改按kpn自动切换接口
// ==============================================
async function getEncSign(base64Data, proxy, appName, remark, kpnType) {
// 按kpn选签名接口KUAISHOU=81 NEBULA=82
const SIGN_API_URL = kpnType === "KUAISHOU" ? SIGN_API_KUAISHOU : SIGN_API_NEBULA;
try {
const { body } = await request({
method: "POST",
url: SIGN_API_URL + "/encsign",
headers: { "Content-Type": "application/json", "User-Agent": "Mozilla/5.0" },
body: JSON.stringify({ data: base64Data }),
timeout: 15000
}, null, `获取加密签名`);
if (body && body.status) return body.data;
log(proxy, appName, `${remark} encsign 失败: ${body?.message || body?.error || "无响应"}`);
return null;
} catch (e) {
log(proxy, appName, `${remark} encsign 异常: ${e.message}`);
return null;
}
}
async function getNsSign(reqInfo, proxy, appName, remark, kpnType) {
// 按kpn选签名接口KUAISHOU=81 NEBULA=82
const SIGN_API_URL = kpnType === "KUAISHOU" ? SIGN_API_KUAISHOU : SIGN_API_NEBULA;
try {
const payload = {
path: reqInfo.urlpath,
data: reqInfo.reqdata,
salt: reqInfo.salt
};
const { body } = await request({
method: "POST",
url: SIGN_API_URL + "/nssig",
headers: { "Content-Type": "application/json", "User-Agent": "Mozilla/5.0" },
body: JSON.stringify(payload),
timeout: 15000
}, null, `获取nssig签名`);
if (body && body.data) {
return {
sig: body.data.sig,
__NStokensig: body.data.nstokensig,
__NS_sig3: body.data.nssig3,
__NS_xfalcon: body.data.nssig4 || body.data.xfalcon || ""
};
}
log(proxy, appName, `${remark} nssig 失败: ${body?.error || body?.message || "无响应"}`);
return null;
} catch (e) {
log(proxy, appName, `${remark} nssig 异常: ${e.message}`);
return null;
}
}
// ==============================================
// 账号信息获取(原代码未改动)
// ==============================================
async function getUserInfo(cookie, platform, proxy) {
try {
const { body } = await request({
method: "GET",
url: platform.accountInfoUrl,
headers: {
Host: platform.host,
"User-Agent": "kwai-android aegon/3.56.0",
Cookie: cookie,
"Content-Type": "application/x-www-form-urlencoded"
},
timeout: 12000
}, proxy, "获取账号信息");
if (body && body.result === 1 && body.data) {
let coin = 0, cash = 0;
if (platform.name === "KS") {
coin = Number(body.data.coinAmount) || 0;
cash = Number(body.data.cashAmountDisplay) || 0;
} else {
coin = Number(body.data.totalCoin) || 0;
cash = Number(body.data.allCash) || 0;
}
return {
nickname: body.data.userData?.nickname || null,
totalCoin: coin, allCash: cash,
success: true, ckExpired: false
};
}
return { nickname: null, totalCoin: 0, allCash: 0, success: false, ckExpired: true };
} catch (e) {
return { nickname: null, totalCoin: 0, allCash: 0, success: false, ckExpired: true };
}
}
// ==============================================
// 账号任务类 - 仅传kpnType到签名函数其余未改
// ==============================================
class KuaishouAccount {
constructor({ index = 1, salt, cookie, remark = "未命名", proxyUrl = null, tasksToExecute = CONFIG.DEFAULT_TASKS }) {
this.index = index;
this.salt = salt;
this.cookie = cookie;
this.remark = remark;
this.proxyUrl = proxyUrl;
this.platform = this.getPlatformByCookie(cookie);
this.kpnType = this.platform.kpn; // 新增获取kpn类型(KUAISHOU/NEBULA)
this.tasksToRun = tasksToExecute.filter(Boolean);
this.taskConfigs = CONFIG.TASK_CONFIGS[this.platform.kpn === "NEBULA" ? "NEBULA" : "KUAISHOU"];
this.lowRewardCount = 0;
this.lowRewardStreak = 0;
this.adFailCount = 0;
this.continuous1Coin = 0;
this.stopAll = false;
this.taskStats = {};
this.taskLimit = {};
this.taskDisabled = {};
this.tasksToRun.forEach(task => {
this.taskStats[task] = { success: 0, failed: 0, totalReward: 0 };
this.taskLimit[task] = false;
this.taskDisabled[task] = false;
});
this.isCycleMode = CONFIG.CYCLE_ROUNDS > 0;
this.cycleRounds = CONFIG.CYCLE_ROUNDS;
this.currentRound = 0;
this.currentTaskIndex = 0;
this.parseCookie();
this.clientIP = null;
}
getPlatformByCookie(cookie) {
const match = cookie.match(/kpn=([^;]+)/);
const kpn = match ? match[1].toUpperCase() : "KUAISHOU";
return kpn === "NEBULA" ? CONFIG.PLATFORM_CONFIG.NEBULA : CONFIG.PLATFORM_CONFIG.KUAISHOU;
}
parseCookie() {
try {
this.mod = this.cookie.match(/mod=([^;]+)/)?.[1] || "Xiaomi(23116PN5BC)";
this.egid = this.cookie.match(/egid=([^;]+)/)?.[1] || "";
this.did = this.cookie.match(/did=([^;]+)/)?.[1] || "";
this.userId = this.cookie.match(/userId=([^;]+)/)?.[1] || "";
this.apiSt = this.cookie.match(/kuaishou\.api_st=([^;]+)/)?.[1] || "";
this.appver = this.cookie.match(/appver=([^;]+)/)?.[1] || "13.7.20.10468";
this.queryParams = `mod=${this.mod}&appver=${this.appver}&egid=${this.egid}&did=${this.did}`;
} catch (e) {
log(this.proxyUrl, this.platform.displayName, `${this.remark} 解析cookie失败: ${e.message}`);
}
}
async initIP() {
try {
if (this.proxyUrl) {
log(null, this.platform.displayName, `账号 [${this.remark}] 代理: ${maskProxyUrl(this.proxyUrl)}`);
const ip = await checkProxyIP(this.proxyUrl);
if (!ip) {
this.stopAll = true;
log(this.proxyUrl, this.platform.displayName, `${this.remark} 初始化失败代理IP检测无有效结果`);
return;
}
this.clientIP = ip;
log(this.proxyUrl, this.platform.displayName, `${this.remark} 代理出口IP: ${ip}`);
} else {
if (!localPublicIP) await checkLocalIP();
this.clientIP = localPublicIP;
}
} catch (e) {
this.stopAll = true;
log(this.proxyUrl, this.platform.displayName, `${this.remark} 初始化失败:${e.message}`);
}
}
async retry(fn, desc, times = 3, delay = 2000) {
let cnt = 0;
while (cnt < times && !this.stopAll) {
try {
const res = await fn();
if (res) return res;
} catch (e) {}
cnt++;
if (cnt < times && !this.stopAll) await new Promise(r => setTimeout(r, delay));
}
return null;
}
getImpExt(task) {
if (task.name.includes("搜索")) {
const word = CONFIG.SEARCH_KEYWORDS[Math.floor(Math.random() * CONFIG.SEARCH_KEYWORDS.length)];
return JSON.stringify({
openH5AdCount: 2,
sessionLookedCompletedCount: "1",
sessionType: "1",
searchKey: word,
triggerType: "2",
disableReportToast: "true",
businessEnterAction: "7",
neoParams: task.linkUrl || ""
});
}
return "{}";
}
async getAdInfo(taskKey) {
const task = this.taskConfigs[taskKey];
if (!task) return null;
const adUrl = "/rest/e/reward/mixed/ad";
const commonData = {
encData: "|encData|",
sign: "|sign|",
cs: "false",
client_key: this.platform.adClientKey,
videoModelCrowdTag: "1_23",
os: "android",
"kuaishou.api_st": this.apiSt,
uQaTag: "1##swLdgl:99#ecPp:-9#cmNt:-0#cmHs:-3#cmMnsl:-0"
};
const deviceData = {
earphoneMode: "1", mod: this.mod, appver: this.appver,
isp: "CUCC", language: "zh-cn", ud: this.userId,
did_tag: "0", net: "WIFI", kcv: "1599", app: "0",
kpf: "ANDROID_PHONE", ver: "11.6", android_os: "0",
boardPlatform: "pineapple", kpn: this.platform.kpn,
androidApiLevel: "35", country_code: "cn", sys: "ANDROID_15",
sw: "1080", sh: "2400", abi: "arm64", userRecoBit: "0"
};
const impData = {
appInfo: {
appId: this.platform.appId, name: this.platform.appName,
packageName: this.platform.packageName, version: this.appver, versionCode: -1
},
deviceInfo: { osType: 1, osVersion: "15", deviceId: this.did, screenSize: { width: 1080, height: 2249 }, ftt: "" },
userInfo: { userId: this.userId, age: 0, gender: "" },
impInfo: [{
pageId: task.pageId || 100011251,
subPageId: task.subPageId,
action: 0,
browseType: task.name.includes("搜索") ? 4 : 3,
impExtData: this.getImpExt(task),
mediaExtData: "{}"
}]
};
const base64Imp = Buffer.from(JSON.stringify(impData)).toString("base64");
// 传kpnType到签名函数
const encSign = await this.retry(
() => getEncSign(base64Imp, this.proxyUrl, this.platform.displayName, this.remark, this.kpnType),
"获取广告加密签名"
);
if (!encSign) return null;
commonData.encData = encSign.encdata;
commonData.sign = encSign.sign;
// 传kpnType到签名函数
const nsSign = await this.retry(
() => getNsSign({
urlpath: adUrl,
reqdata: querystring.stringify(commonData) + "&" + querystring.stringify(deviceData),
salt: this.salt
}, this.proxyUrl, this.platform.displayName, this.remark, this.kpnType),
"获取广告请求nssig"
);
if (!nsSign) return null;
const reqQuery = {
...deviceData,
sig: nsSign.sig,
__NS_sig3: nsSign.__NS_sig3,
__NS_xfalcon: nsSign.__NS_xfalcon,
__NStokensig: nsSign.__NStokensig
};
const finalUrl = "https://api.e.kuaishou.com" + adUrl + "?" + querystring.stringify(reqQuery);
const { body } = await request({
method: "POST",
url: finalUrl,
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
Host: "api.e.kuaishou.com",
"User-Agent": "kwai-android aegon/3.56.0",
Cookie: this.cookie
},
form: commonData,
timeout: 12000
}, this.proxyUrl, "获取广告");
if (!body) {
this.adFailCount++;
if (this.adFailCount >= CONFIG.AD_FAIL_LIMIT) this.stopAll = true;
return null;
}
if (body.errorMsg === "OK" && body.feeds?.[0]?.ad) {
const ad = body.feeds[0];
const title = (ad.caption || ad.ad?.caption || "").slice(0, 30) + "...";
let coin = 0;
try {
const ext = JSON.parse(ad.ad.extData);
coin = Number(ext.awardCoin) || 0;
if (coin === 0) {
coin = ad.ad.adDataV2?.inspirePersonalize?.awardValue ||
ad.ad.adDataV2?.inspireAdInfo?.inspirePersonalize?.neoValue || 0;
}
} catch (e) {}
if (coin === 5) return null;
log(this.proxyUrl, this.platform.displayName, `${this.remark} 获取广告成功:${title}`);
log(null, this.platform.displayName, `${this.remark} 预计获得: ${coin} 金币`);
return {
cid: ad.ad.creativeId,
llsid: ad.exp_tag?.split("/")?.[1]?.split("_")?.[0] || "",
hasRewardEnd: ad.ad.adDataV2?.onceAgainRewardInfo?.hasMore || false,
expectedCoins: coin,
taskConfig: task
};
}
this.adFailCount++;
if (this.adFailCount >= CONFIG.AD_FAIL_LIMIT) this.stopAll = true;
return null;
}
async genReportSign(cid, llsid, task) {
try {
const bizStr = JSON.stringify({
businessId: task.businessId,
endTime: Date.now(),
extParams: "",
mediaScene: "video",
neoInfos: [{
creativeId: cid, extInfo: "", llsid,
requestSceneType: task.requestSceneType,
taskType: task.taskType,
watchExpId: "", watchStage: 0
}],
pageId: task.pageId || 100011251,
posId: task.posId,
reportType: 0,
sessionId: "",
startTime: Date.now() - 30000,
subPageId: task.subPageId
});
const postData = `bizStr=${encodeURIComponent(bizStr)}&cs=false&client_key=${this.platform.reportClientKey}`;
const qs = this.queryParams + "&" + postData;
// 传kpnType到签名函数
const sign = await this.retry(
() => getNsSign({
urlpath: "/rest/r/ad/task/report",
reqdata: qs,
salt: this.salt
}, this.proxyUrl, this.platform.displayName, this.remark, this.kpnType),
"生成报告签名"
);
if (!sign) return null;
return {
sig: sign.sig, sig3: sign.__NS_sig3,
xfalcon: sign.__NS_xfalcon, sigtoken: sign.__NStokensig,
post: postData
};
} catch (e) {
return null;
}
}
async submitReport(cid, llsid, taskKey, task) {
const sign = await this.genReportSign(cid, llsid, task);
if (!sign) return { success: false, reward: 0 };
const url = "https://api.e.kuaishou.com/rest/r/ad/task/report?" +
`${this.queryParams}&sig=${sign.sig}&__NS_sig3=${sign.sig3}&__NS_xfalcon=${sign.xfalcon}&__NStokensig=${sign.sigtoken}`;
const { body } = await request({
method: "POST",
url,
headers: {
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
Host: "api.e.kuaishou.com",
Cookie: this.cookie,
"User-Agent": "kwai-android aegon/3.56.0"
},
form: querystring.parse(sign.post),
timeout: 12000
}, this.proxyUrl, "提交任务报告");
if (!body) return { success: false, reward: 0 };
if (body.result === 1) {
const coin = Number(body.data?.neoAmount) || 0;
this.taskStats[taskKey].totalReward += coin;
if (coin === 1) {
this.continuous1Coin++;
if (this.continuous1Coin >= CONFIG.CONTINUOUS_1COIN_LIMIT) {
log(this.proxyUrl, this.platform.displayName, `${this.remark} 连续${CONFIG.CONTINUOUS_1COIN_LIMIT}次1金币停止任务`);
this.stopAll = true;
}
} else {
this.continuous1Coin = 0;
}
if (coin <= CONFIG.LOW_REWARD_THRESHOLD) {
this.lowRewardStreak++;
if (this.lowRewardStreak >= CONFIG.LOW_REWARD_LIMIT) {
log(this.proxyUrl, this.platform.displayName, `${this.remark} 连续低奖励超限,停止任务`);
this.stopAll = true;
}
} else {
this.lowRewardStreak = 0;
}
return { success: true, reward: coin };
}
if ([20107, 20108, 1003, 415].includes(body.result)) {
return { success: false, reward: 0, limitReached: true };
}
return { success: false, reward: 0 };
}
async runTask(taskKey) {
if (this.taskDisabled[taskKey] || this.taskLimit[taskKey] || this.stopAll) return { success: false, reward: 0 };
let adInfo = null;
while (!adInfo && !this.stopAll) {
adInfo = await this.getAdInfo(taskKey);
if (!adInfo && !this.stopAll) await new Promise(r => setTimeout(r, 3000));
}
if (!adInfo) {
this.taskStats[taskKey].failed++;
return { success: false, reward: 0 };
}
const watchMs = Math.floor(Math.random() * (CONFIG.WATCH_MAX - CONFIG.WATCH_MIN) + CONFIG.WATCH_MIN) * 1000;
log(this.proxyUrl, this.platform.displayName, `${this.remark} 观看广告中,等待 ${Math.round(watchMs/1000)} 秒...`);
await new Promise(r => setTimeout(r, watchMs));
log(this.proxyUrl, this.platform.displayName, `${this.remark} 观看完成,提交任务报告`);
const result = await this.submitReport(adInfo.cid, adInfo.llsid, taskKey, adInfo.taskConfig);
if (result.success) {
this.taskStats[taskKey].success++;
log(this.proxyUrl, this.platform.displayName, `${this.remark} ✅ 提交成功!获得 ${result.reward} 金币`);
return { success: true, reward: result.reward, hasRewardEnd: adInfo.hasRewardEnd };
}
if (result.limitReached) this.taskLimit[taskKey] = true;
this.taskStats[taskKey].failed++;
return { success: false, reward: 0, limitReached: result.limitReached || false };
}
nextTask() {
const available = this.tasksToRun.filter(t => !this.taskLimit[t] && !this.taskDisabled[t]);
if (available.length === 0 || this.stopAll) return null;
this.currentTaskIndex = (this.currentTaskIndex + 1) % available.length;
return available[this.currentTaskIndex];
}
async restAfterAd(count) {
if (count > 0 && count % CONFIG.APPEND_REST_INTERVAL === 0) {
const ms = Math.floor(Math.random() * (CONFIG.APPEND_REST_MAX - CONFIG.APPEND_REST_MIN)) + CONFIG.APPEND_REST_MIN;
await new Promise(r => setTimeout(r, ms));
}
}
async run() {
await this.initIP();
if (this.stopAll) {
return { success: false, remark: this.remark, platform: this.platform.name, taskCount: 0, totalReward: 0, exitIP: this.clientIP, stopReason: "初始化失败" };
}
const user = await getUserInfo(this.cookie, this.platform, this.proxyUrl);
if (!user.success || user.ckExpired) {
log(this.proxyUrl, this.platform.displayName, `${this.remark} Cookie已过期或无效`);
return { success: false, remark: this.remark, platform: this.platform.name, taskCount: 0, totalReward: 0, exitIP: this.clientIP, stopReason: "Cookie过期" };
}
log(this.proxyUrl, this.platform.displayName,
`${this.remark} 登录成功 | 昵称: ${user.nickname || "未知"} | 金币: ${user.totalCoin} | 余额: ${user.allCash.toFixed(2)}`);
let totalTasks = 0, appendTasks = 0, stopReason = "正常结束";
while (!this.stopAll) {
if (this.isCycleMode && this.currentRound >= this.cycleRounds) {
stopReason = `已完成${this.cycleRounds}轮任务`;
break;
}
const task = this.nextTask();
if (!task) { stopReason = "无可用任务"; this.stopAll = true; break; }
const res = await this.runTask(task);
totalTasks++;
if (res.hasRewardEnd) {
appendTasks++;
await this.restAfterAd(appendTasks);
await this.runTask(task);
}
if (this.adFailCount >= CONFIG.AD_FAIL_LIMIT) { stopReason = "广告获取失败达上限"; this.stopAll = true; }
if (this.nextTask() && !this.stopAll) {
const delay = Math.floor(Math.random() * 5 + 5) * 1000;
await new Promise(r => setTimeout(r, delay));
}
if (this.isCycleMode && this.currentTaskIndex === this.tasksToRun.length - 1) this.currentRound++;
}
const totalReward = Object.values(this.taskStats).reduce((s, t) => s + t.totalReward, 0);
log(this.proxyUrl, this.platform.displayName,
`${this.remark} 结束 | 执行任务: ${totalTasks} | 总获金币: ${totalReward} | 原因: ${stopReason}`);
for (const [k, s] of Object.entries(this.taskStats)) {
const cfg = this.taskConfigs[k];
if (cfg) log(null, this.platform.displayName, `${cfg.name}: 成功${s.success}次 失败${s.failed}次 奖励${s.totalReward}金币`);
}
return { success: true, remark: this.remark, platform: this.platform.name, taskCount: totalTasks, appendCount: appendTasks, totalReward, exitIP: this.clientIP, stopReason };
}
}
// ==============================================
// 账号解析 & 批量执行(原代码未改动)
// ==============================================
function parseAccountLine(line, index) {
if (!line || typeof line !== "string") return null;
const parts = line.split("#");
if (parts.length < 3) return null;
const remark = parts[0].trim() || `账号${index}`;
const cookie = parts[1].trim();
const salt = parts[2].trim();
let proxy = parts[3]?.trim() || null;
if (!cookie || !salt) return null;
if (proxy && proxy.includes("|")) {
const [host, port, user, pwd] = proxy.split("|");
proxy = `socks5://${user}:${pwd}@${host}:${port}`;
}
if (proxy && !/^socks5:\/\//i.test(proxy)) {
console.log(`⚠️ 账号${index} 代理格式非socks5已忽略: ${proxy}`);
proxy = null;
}
return { cookie, salt, remark, proxyUrl: proxy };
}
function loadAllAccounts() {
const accounts = [];
const exists = new Set();
let index = 1;
let proxyCount = 0;
const mainCk = process.env.ksck;
if (mainCk) {
mainCk.split("&").forEach(line => {
line = line.trim();
if (line && !exists.has(line)) {
const acc = parseAccountLine(line, index++);
if (acc) { accounts.push(acc); exists.add(line); if (acc.proxyUrl) proxyCount++; }
}
});
}
for (let i = 1; i <= 666; i++) {
const line = process.env[`ksck${i}`]?.trim();
if (line && !exists.has(line)) {
const acc = parseAccountLine(line, index++);
if (acc) { accounts.push(acc); exists.add(line); if (acc.proxyUrl) proxyCount++; }
}
}
print(`\n✅ 共加载账号: ${accounts.length} 个(其中代理账号: ${proxyCount} 个)`);
return accounts;
}
async function runAccountList(accounts) {
const results = [];
for (let i = 0; i < accounts.length; i++) {
const acc = accounts[i];
print(`\n${"=".repeat(60)}`);
print(`🚀 开始执行账号 ${i+1}/${accounts.length}: ${acc.remark}`);
print(`${"=".repeat(60)}`);
const instance = new KuaishouAccount({ ...acc, index: i + 1 });
const result = await instance.run();
results.push(result);
}
return results;
}
function printSummary(results) {
print(`\n${"=".repeat(60)}`);
print(" 📊 全部账号执行结果汇总");
print(`${"=".repeat(60)}`);
let totalReward = 0;
results.forEach((r, i) => {
const tag = r.platform === "JSB" ? "[极速版]" : "[快手 ]";
print(`${tag} 账号${i+1} ${r.remark} | 任务数:${r.taskCount} | 金币:${r.totalReward} | ${r.stopReason}`);
totalReward += r.totalReward || 0;
});
print(`${"=".repeat(60)}`);
print(` 🎉 全部完成 | 账号数: ${results.length} | 总金币: ${totalReward}`);
print(`${"=".repeat(60)}`);
}
// ==============================================
// 启动(原代码未改动)
// ==============================================
print("================================================================================");
print(" ⭐ 快手双端脚本 ⭐ ");
print(" 支持快手 & 快手极速版 · 无需卡密授权 · 按kpn自动切换签名接口 ");
print("================================================================================");
print(`\n🎯 默认任务: ${CONFIG.DEFAULT_TASKS.join(", ")}`);
print(`⏱ 观看时长: ${CONFIG.WATCH_MIN}-${CONFIG.WATCH_MAX}`);
print(`🔄 循环轮数: ${CONFIG.CYCLE_ROUNDS > 0 ? CONFIG.CYCLE_ROUNDS : "无限制"}`);
print("\n📋 环境变量说明:");
print(" ksck = 账号配置,格式: 备注#cookie#salt#socks5代理(可选)");
print(" ksck1~ksck666 = 多账号扩展");
print(" KS_DEFAULT_TASKS = 任务列表,逗号分隔,可选: box,look,food,search");
print(" KS_CYCLE_ROUNDS = 循环轮数 (0=无限)");
print(" KS_WATCH_MIN/MAX = 广告观看秒数范围");
print(" KS_LOW_REWARD_THRESHOLD = 低奖励阈值");
print(" KS_LOW_REWARD_LIMIT = 连续低奖励停止次数");
print("================================================================================\n");
(async () => {
const accounts = loadAllAccounts();
if (accounts.length === 0) {
print("❌ 未检测到账号配置,请设置 ksck 环境变量");
print(" 格式: 备注#cookie字符串#salt值");
print(" 示例: 我的账号#did=xxx;userId=yyy;...#abcdef1234");
process.exit(1);
}
const results = await runAccountList(accounts);
printSummary(results);
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long