Initial Qinglong script classification corpus
This commit is contained in:
487
脚本库/微信小程序/抓包版/cloud189/2025-09-06_cloud189_7c90c2eb.py
Normal file
487
脚本库/微信小程序/抓包版/cloud189/2025-09-06_cloud189_7c90c2eb.py
Normal 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里面即可
|
||||
支持多用户运行
|
||||
多用户用&或者@隔开
|
||||
例如账号1:10086 账号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))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
540
脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd.py
Normal file
540
脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd.py
Normal 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×tamp={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×tamp={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×tamp={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×tamp={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}×tamp={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×tamp={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×tamp={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×tamp={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×tamp={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}×tamp={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))
|
||||
540
脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd_2.py
Normal file
540
脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd_2.py
Normal 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×tamp={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×tamp={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×tamp={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×tamp={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}×tamp={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×tamp={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×tamp={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×tamp={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×tamp={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}×tamp={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))
|
||||
793
脚本库/微信小程序/抓包版/快手双端/2026-05-11_ks_dual_aa4fbaa7.js
Normal file
793
脚本库/微信小程序/抓包版/快手双端/2026-05-11_ks_dual_aa4fbaa7.js
Normal 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);
|
||||
})();
|
||||
999
脚本库/微信小程序/抓包版/滴滴果园/2025-01-11_ddgy_236924d1.js
Normal file
999
脚本库/微信小程序/抓包版/滴滴果园/2025-01-11_ddgy_236924d1.js
Normal file
File diff suppressed because one or more lines are too long
291
脚本库/微信小程序/抓包版/索尼中国/2025-01-11_sonybbs_359e1e49.js
Normal file
291
脚本库/微信小程序/抓包版/索尼中国/2025-01-11_sonybbs_359e1e49.js
Normal file
File diff suppressed because one or more lines are too long
1577
脚本库/微信小程序/抓包版/统一茄皇-修复版/2023-01-03_tyqh_2fe80596.js
Normal file
1577
脚本库/微信小程序/抓包版/统一茄皇-修复版/2023-01-03_tyqh_2fe80596.js
Normal file
File diff suppressed because it is too large
Load Diff
643
脚本库/微信小程序/抓包版/统一茄皇互助/2023-01-03_qhhz_07a8e366.js
Normal file
643
脚本库/微信小程序/抓包版/统一茄皇互助/2023-01-03_qhhz_07a8e366.js
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user