Initial Qinglong script classification corpus

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

View File

@@ -0,0 +1,292 @@
// # Source: https://github.com/huwangkeji/juejin_checkin/blob/main/juejin-extension/popup.js
// # Raw: https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin-extension/popup.js
// # Repo: huwangkeji/juejin_checkin
// # Path: juejin-extension/popup.js
// # UploadedAt: 2026-05-19T14:34:11Z
// # SHA256: 0a4d49831a306fa984f62b0d1b3f26f7fc1274a625d08b5f4622ba94121b8469
// # Category: web版/抓包
// # Evidence: web/H5关键词 + cookie/token/header
//
/**
* 掘金参数提取器 - Popup脚本
*/
// 参数配置key、显示名、青龙环境变量名
const PARAM_CONFIG = [
{ key: 'cookie', name: 'Cookie', env: 'JUEJIN_COOKIE', isLong: true },
{ key: 'aid', name: 'AID', env: 'JUEJIN_AID', isLong: false },
{ key: 'uuid', name: 'UUID', env: 'JUEJIN_UUID', isLong: true },
{ key: 'msToken', name: 'msToken', env: 'JUEJIN_MSTOKEN', isLong: true },
{ key: 'a_bogus', name: 'a_bogus', env: 'JUEJIN_A_BOGUS', isLong: true },
];
let currentData = null;
// 加载数据
async function loadData() {
return new Promise((resolve) => {
chrome.storage.local.get('juejinData', (result) => {
resolve(result.juejinData || null);
});
});
}
// 渲染界面
async function render() {
currentData = await loadData();
const emptyState = document.getElementById('emptyState');
const paramsList = document.getElementById('paramsList');
const actionsBar = document.getElementById('actionsBar');
const statusDot = document.getElementById('statusDot');
const statusText = document.getElementById('statusText');
const captureTime = document.getElementById('captureTime');
if (!currentData || !currentData.cookie) {
// 无数据
emptyState.style.display = 'block';
paramsList.style.display = 'none';
actionsBar.style.display = 'none';
statusDot.className = 'status-dot empty';
statusText.textContent = '等待捕获...';
captureTime.textContent = '';
return;
}
// 有数据
emptyState.style.display = 'none';
paramsList.style.display = 'block';
actionsBar.style.display = 'flex';
statusDot.className = 'status-dot captured';
statusText.textContent = '✅ 参数已捕获';
captureTime.textContent = currentData.captureTime || '';
// 渲染参数列表
paramsList.innerHTML = PARAM_CONFIG.map((config) => {
const value = currentData[config.key] || '';
const isEmpty = !value;
const displayValue = isEmpty ? '未捕获到' : value;
const valueClass = isEmpty ? 'param-value empty' : 'param-value';
return `
<div class="param-item">
<div class="param-header">
<span class="param-name">${config.name}</span>
<div style="display:flex;align-items:center;gap:6px;">
<span class="param-env">${config.env}</span>
<button class="copy-btn" data-key="${config.key}" title="复制${config.name}">复制</button>
</div>
</div>
<div class="${valueClass}" title="${displayValue}">${displayValue}</div>
</div>
`;
}).join('');
// 绑定复制按钮
paramsList.querySelectorAll('.copy-btn').forEach((btn) => {
btn.addEventListener('click', () => {
const key = btn.dataset.key;
const value = currentData[key] || '';
copyToClipboard(value, btn);
});
});
}
// 复制到剪贴板
function copyToClipboard(text, btn) {
navigator.clipboard.writeText(text).then(() => {
if (btn) {
const original = btn.textContent;
btn.textContent = '已复制 ✓';
btn.classList.add('copied');
setTimeout(() => {
btn.textContent = original;
btn.classList.remove('copied');
}, 1500);
}
});
}
// 生成青龙面板环境变量格式
function generateQinglongFormat() {
if (!currentData) return '';
const lines = [];
lines.push('# 掘金签到脚本 - 青龙面板环境变量');
lines.push('# 复制以下内容到青龙面板 -> 环境变量');
lines.push('');
lines.push(`JUEJIN_COOKIE='${currentData.cookie || ''}'`);
lines.push(`JUEJIN_AID='${currentData.aid || '2608'}'`);
lines.push(`JUEJIN_UUID='${currentData.uuid || ''}'`);
lines.push(`JUEJIN_MSTOKEN='${currentData.msToken || ''}'`);
lines.push(`JUEJIN_A_BOGUS='${currentData.a_bogus || ''}'`);
lines.push('');
lines.push(`# 捕获时间: ${currentData.captureTime || '未知'}`);
lines.push('# 参数有效期约30天过期需重新获取');
return lines.join('\n');
}
// 绑定事件
document.getElementById('copyAllBtn').addEventListener('click', () => {
const text = generateQinglongFormat();
copyToClipboard(text, document.getElementById('copyAllBtn'));
});
document.getElementById('goJuejinBtn').addEventListener('click', () => {
chrome.tabs.create({ url: 'https://juejin.cn' });
});
document.getElementById('refreshBtn').addEventListener('click', () => {
render();
});
// "从当前页面提取"按钮
document.getElementById('extractNowBtn').addEventListener('click', async () => {
const btn = document.getElementById('extractNowBtn');
const originalText = btn.textContent;
btn.textContent = '⏳ 提取中...';
btn.disabled = true;
try {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
if (!tab || !tab.url || !tab.url.includes('juejin.cn')) {
alert('请先在掘金网站 (juejin.cn) 页面点击此按钮');
btn.textContent = originalText;
btn.disabled = false;
return;
}
// 在页面中执行提取脚本:主动发请求 -> 等待 hook 捕获 -> 读取 sessionStorage
const results = await chrome.scripting.executeScript({
target: { tabId: tab.id, allFrames: false },
world: 'MAIN',
func: () => {
return new Promise((resolve) => {
const data = {
cookie: '',
aid: '',
uuid: '',
msToken: '',
a_bogus: '',
spider: '',
captureTime: new Date().toLocaleString('zh-CN'),
captureUrl: location.href,
};
// 辅助:从 URL 提取参数
function extractFromUrl(url) {
try {
const u = new URL(url);
return {
aid: u.searchParams.get('aid') || '',
uuid: u.searchParams.get('uuid') || '',
msToken: u.searchParams.get('msToken') || '',
a_bogus: u.searchParams.get('a_bogus') || '',
spider: u.searchParams.get('spider') || '',
};
} catch (e) { return null; }
}
// 1. 获取 cookie
try { data.cookie = document.cookie; } catch (e) {}
// 2. 扫描 performance entries
try {
const entries = performance.getEntriesByType('resource');
for (const entry of entries) {
if (entry.name && entry.name.includes('api.juejin.cn')) {
const p = extractFromUrl(entry.name);
if (p) {
if (p.aid) data.aid = p.aid;
if (p.uuid && p.uuid.length > 5) data.uuid = p.uuid;
if (p.msToken && p.msToken.length > 5) data.msToken = p.msToken;
if (p.a_bogus && p.a_bogus.length > 5) data.a_bogus = p.a_bogus;
if (p.spider) data.spider = p.spider;
}
}
}
} catch (e) {}
// 3. 从 content script 的 sessionStorage 读取(如果 content.js 已捕获)
try {
const stored = JSON.parse(sessionStorage.getItem('__juejin_extractor_data__') || '{}');
if (stored.cookie) data.cookie = stored.cookie;
if (stored.aid) data.aid = stored.aid;
if (stored.uuid) data.uuid = stored.uuid;
if (stored.msToken) data.msToken = stored.msToken;
if (stored.a_bogus) data.a_bogus = stored.a_bogus;
if (stored.spider) data.spider = stored.spider;
} catch (e) {}
// 4. 主动触发一个请求来诱捕参数content.js 的 MAIN world hook 会捕获)
const needsTrigger = !data.uuid || !data.msToken || !data.a_bogus;
if (needsTrigger) {
try {
fetch('https://api.juejin.cn/growth_api/v1/get_today_status?aid=2608', {
credentials: 'include',
headers: { 'Accept': 'application/json' },
}).catch(() => {});
fetch('https://api.juejin.cn/user_api/v1/user/get?aid=2608', {
credentials: 'include',
headers: { 'Accept': 'application/json' },
}).catch(() => {});
} catch (e) {}
// 等待 hook 处理后再读取
setTimeout(() => {
try {
const stored2 = JSON.parse(sessionStorage.getItem('__juejin_extractor_data__') || '{}');
if (stored2.cookie) data.cookie = stored2.cookie;
if (stored2.aid) data.aid = stored2.aid;
if (stored2.uuid) data.uuid = stored2.uuid;
if (stored2.msToken) data.msToken = stored2.msToken;
if (stored2.a_bogus) data.a_bogus = stored2.a_bogus;
if (stored2.spider) data.spider = stored2.spider;
} catch (e) {}
resolve(data);
}, 800);
} else {
resolve(data);
}
});
},
});
const extracted = results[0]?.result;
if (extracted) {
// 合并到已有数据
chrome.storage.local.get('juejinData', (result) => {
const existing = result.juejinData || {};
const merged = {
...existing,
...Object.fromEntries(
Object.entries(extracted).filter(([_, v]) => v && v !== '')
),
};
chrome.storage.local.set({ juejinData: merged }, () => {
render();
btn.textContent = '✅ 提取完成';
setTimeout(() => {
btn.textContent = originalText;
btn.disabled = false;
}, 1500);
});
});
} else {
alert('未能从当前页面提取到参数,请刷新页面后重试');
btn.textContent = originalText;
btn.disabled = false;
}
} catch (e) {
console.error(e);
alert('提取失败: ' + e.message);
btn.textContent = originalText;
btn.disabled = false;
}
});
// 初始渲染
render();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,574 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/notify.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/notify.py
# Repo: lksky8/sign-ql
# Path: notify.py
# UploadedAt: 2025-01-11T18:39:35Z
# SHA256: 9961f57695cfba609fbfda0c314ab632f147c0d068b0f0338eaaa1ef796eedf8
# Category: web版/抓包
# Evidence: web/H5关键词 + cookie/token/header
#!/usr/bin/env python3
# _*_ coding:utf-8 _*_
import base64
import hashlib
import hmac
import json
import os
import re
import threading
import time
import urllib.parse
import requests
# 原先的 print 函数和主线程的锁
_print = print
mutex = threading.Lock()
# 定义新的 print 函数
def print(text, *args, **kw):
"""
使输出有序进行,不出现多线程同一时间输出导致错乱的问题。
"""
with mutex:
_print(text, *args, **kw)
# 通知服务
# fmt: off
push_config = {
'HITOKOTO': False, # 启用一言(随机句子)
'BARK_PUSH': '', # bark IP 或设备码https://api.day.app/DxHcxxxxxRxxxxxxcm/
'BARK_ARCHIVE': '', # bark 推送是否存档
'BARK_GROUP': '', # bark 推送分组
'BARK_SOUND': '', # bark 推送声音
'BARK_ICON': '', # bark 推送图标
'CONSOLE': True, # 控制台输出
'DD_BOT_SECRET': '', # 钉钉机器人的 DD_BOT_SECRET
'DD_BOT_TOKEN': '', # 钉钉机器人的 DD_BOT_TOKEN
'FSKEY': '', # 飞书机器人的 FSKEY
'GOBOT_URL': '', # go-cqhttp
# 推送到个人QQhttp://127.0.0.1/send_private_msg
# 群http://127.0.0.1/send_group_msg
'GOBOT_QQ': '', # go-cqhttp 的推送群或用户
# GOBOT_URL 设置 /send_private_msg 时填入 user_id=个人QQ
# /send_group_msg 时填入 group_id=QQ群
'GOBOT_TOKEN': '', # go-cqhttp 的 access_token
'GOTIFY_URL': '', # gotify地址,如https://push.example.de:8080
'GOTIFY_TOKEN': '', # gotify的消息应用token
'GOTIFY_PRIORITY': 0, # 推送消息优先级,默认为0
'IGOT_PUSH_KEY': '', # iGot 聚合推送的 IGOT_PUSH_KEY
'PUSH_KEY': '', # server 酱的 PUSH_KEY兼容旧版与 Turbo 版
'DEER_KEY': '', # PushDeer 的 PUSHDEER_KEY
'PUSH_PLUS_TOKEN': '', # push+ 微信推送的用户令牌
'PUSH_PLUS_USER': '', # push+ 微信推送的群组编码
'QMSG_KEY': '', # qmsg 酱的 QMSG_KEY
'QMSG_TYPE': '', # qmsg 酱的 QMSG_TYPE
'QYWX_AM': '', # 企业微信应用
'QYWX_KEY': '', # 企业微信机器人
'TG_BOT_TOKEN': '', # tg 机器人的 TG_BOT_TOKEN1407203283:AAG9rt-6RDaaX0HBLZQq0laNOh898iFYaRQ
'TG_USER_ID': '', # tg 机器人的 TG_USER_ID1434078534
'TG_API_HOST': '', # tg 代理 api
'TG_PROXY_AUTH': '', # tg 代理认证参数
'TG_PROXY_HOST': '', # tg 机器人的 TG_PROXY_HOST
'TG_PROXY_PORT': '', # tg 机器人的 TG_PROXY_PORT
}
notify_function = []
# fmt: on
# 首先读取 面板变量 或者 github action 运行变量
for k in push_config:
if os.getenv(k):
v = os.getenv(k)
push_config[k] = v
def bark(title: str, content: str) -> None:
"""
使用 bark 推送消息。
"""
if not push_config.get("BARK_PUSH"):
print("bark 服务的 BARK_PUSH 未设置!!\n取消推送")
return
print("bark 服务启动")
if push_config.get("BARK_PUSH").startswith("http"):
url = f'{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
else:
url = f'https://api.day.app/{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
bark_params = {
"BARK_ARCHIVE": "isArchive",
"BARK_GROUP": "group",
"BARK_SOUND": "sound",
"BARK_ICON": "icon",
}
params = ""
for pair in filter(
lambda pairs: pairs[0].startswith("BARK_")
and pairs[0] != "BARK_PUSH"
and pairs[1]
and bark_params.get(pairs[0]),
push_config.items(),
):
params += f"{bark_params.get(pair[0])}={pair[1]}&"
if params:
url = url + "?" + params.rstrip("&")
response = requests.get(url).json()
if response["code"] == 200:
print("bark 推送成功!")
else:
print("bark 推送失败!")
def console(title: str, content: str) -> None:
"""
使用 控制台 推送消息。
"""
print(f"{title}\n\n{content}")
def dingding_bot(title: str, content: str) -> None:
"""
使用 钉钉机器人 推送消息。
"""
if not push_config.get("DD_BOT_SECRET") or not push_config.get("DD_BOT_TOKEN"):
print("钉钉机器人 服务的 DD_BOT_SECRET 或者 DD_BOT_TOKEN 未设置!!\n取消推送")
return
print("钉钉机器人 服务启动")
timestamp = str(round(time.time() * 1000))
secret_enc = push_config.get("DD_BOT_SECRET").encode("utf-8")
string_to_sign = "{}\n{}".format(timestamp, push_config.get("DD_BOT_SECRET"))
string_to_sign_enc = string_to_sign.encode("utf-8")
hmac_code = hmac.new(
secret_enc, string_to_sign_enc, digestmod=hashlib.sha256
).digest()
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
url = f'https://oapi.dingtalk.com/robot/send?access_token={push_config.get("DD_BOT_TOKEN")}&timestamp={timestamp}&sign={sign}'
headers = {"Content-Type": "application/json;charset=utf-8"}
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
response = requests.post(
url=url, data=json.dumps(data), headers=headers, timeout=15
).json()
if not response["errcode"]:
print("钉钉机器人 推送成功!")
else:
print("钉钉机器人 推送失败!")
def feishu_bot(title: str, content: str) -> None:
"""
使用 飞书机器人 推送消息。
"""
if not push_config.get("FSKEY"):
print("飞书 服务的 FSKEY 未设置!!\n取消推送")
return
print("飞书 服务启动")
url = f'https://open.feishu.cn/open-apis/bot/v2/hook/{push_config.get("FSKEY")}'
data = {"msg_type": "text", "content": {"text": f"{title}\n\n{content}"}}
response = requests.post(url, data=json.dumps(data)).json()
if response.get("StatusCode") == 0:
print("飞书 推送成功!")
else:
print("飞书 推送失败!错误信息如下:\n", response)
def go_cqhttp(title: str, content: str) -> None:
"""
使用 go_cqhttp 推送消息。
"""
if not push_config.get("GOBOT_URL") or not push_config.get("GOBOT_QQ"):
print("go-cqhttp 服务的 GOBOT_URL 或 GOBOT_QQ 未设置!!\n取消推送")
return
print("go-cqhttp 服务启动")
url = f'{push_config.get("GOBOT_URL")}?access_token={push_config.get("GOBOT_TOKEN")}&{push_config.get("GOBOT_QQ")}&message=标题:{title}\n内容:{content}'
response = requests.get(url).json()
if response["status"] == "ok":
print("go-cqhttp 推送成功!")
else:
print("go-cqhttp 推送失败!")
def gotify(title:str,content:str) -> None:
"""
使用 gotify 推送消息。
"""
if not push_config.get("GOTIFY_URL") or not push_config.get("GOTIFY_TOKEN"):
print("gotify 服务的 GOTIFY_URL 或 GOTIFY_TOKEN 未设置!!\n取消推送")
return
print("gotify 服务启动")
url = f'{push_config.get("GOTIFY_URL")}/message?token={push_config.get("GOTIFY_TOKEN")}'
data = {"title": title,"message": content,"priority": push_config.get("GOTIFY_PRIORITY")}
response = requests.post(url,data=data).json()
if response.get("id"):
print("gotify 推送成功!")
else:
print("gotify 推送失败!")
def iGot(title: str, content: str) -> None:
"""
使用 iGot 推送消息。
"""
if not push_config.get("IGOT_PUSH_KEY"):
print("iGot 服务的 IGOT_PUSH_KEY 未设置!!\n取消推送")
return
print("iGot 服务启动")
url = f'https://push.hellyw.com/{push_config.get("IGOT_PUSH_KEY")}'
data = {"title": title, "content": content}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
response = requests.post(url, data=data, headers=headers).json()
if response["ret"] == 0:
print("iGot 推送成功!")
else:
print(f'iGot 推送失败!{response["errMsg"]}')
def serverJ(title: str, content: str) -> None:
"""
通过 serverJ 推送消息。
"""
if not push_config.get("PUSH_KEY"):
print("serverJ 服务的 PUSH_KEY 未设置!!\n取消推送")
return
print("serverJ 服务启动")
data = {"text": title, "desp": content.replace("\n", "\n\n")}
if push_config.get("PUSH_KEY").index("SCT") != -1:
url = f'https://sctapi.ftqq.com/{push_config.get("PUSH_KEY")}.send'
else:
url = f'https://sc.ftqq.com/${push_config.get("PUSH_KEY")}.send'
response = requests.post(url, data=data).json()
if response.get("errno") == 0 or response.get("code") == 0:
print("serverJ 推送成功!")
else:
print(f'serverJ 推送失败!错误码:{response["message"]}')
def pushdeer(title: str, content: str) -> None:
"""
通过PushDeer 推送消息
"""
if not push_config.get("DEER_KEY"):
print("PushDeer 服务的 DEER_KEY 未设置!!\n取消推送")
return
print("PushDeer 服务启动")
data = {"text": title, "desp": content, "type": "markdown", "pushkey": push_config.get("DEER_KEY")}
url = 'https://api2.pushdeer.com/message/push'
response = requests.post(url, data=data).json()
if len(response.get("content").get("result")) > 0:
print("PushDeer 推送成功!")
else:
print("PushDeer 推送失败!错误信息:", response)
def pushplus_bot(title: str, content: str) -> None:
"""
通过 push+ 推送消息。
"""
if not push_config.get("PUSH_PLUS_TOKEN"):
print("PUSHPLUS 服务的 PUSH_PLUS_TOKEN 未设置!!\n取消推送")
return
print("PUSHPLUS 服务启动")
url = "http://www.pushplus.plus/send"
data = {
"token": push_config.get("PUSH_PLUS_TOKEN"),
"title": title,
"content": content,
"topic": push_config.get("PUSH_PLUS_USER"),
}
body = json.dumps(data).encode(encoding="utf-8")
headers = {"Content-Type": "application/json"}
response = requests.post(url=url, data=body, headers=headers).json()
if response["code"] == 200:
print("PUSHPLUS 推送成功!")
else:
url_old = "http://pushplus.hxtrip.com/send"
headers["Accept"] = "application/json"
response = requests.post(url=url_old, data=body, headers=headers).json()
if response["code"] == 200:
print("PUSHPLUS(hxtrip) 推送成功!")
else:
print("PUSHPLUS 推送失败!")
def qmsg_bot(title: str, content: str) -> None:
"""
使用 qmsg 推送消息。
"""
if not push_config.get("QMSG_KEY") or not push_config.get("QMSG_TYPE"):
print("qmsg 的 QMSG_KEY 或者 QMSG_TYPE 未设置!!\n取消推送")
return
print("qmsg 服务启动")
url = f'https://qmsg.zendee.cn/{push_config.get("QMSG_TYPE")}/{push_config.get("QMSG_KEY")}'
payload = {"msg": f'{title}\n\n{content.replace("----", "-")}'.encode("utf-8")}
response = requests.post(url=url, params=payload).json()
if response["code"] == 0:
print("qmsg 推送成功!")
else:
print(f'qmsg 推送失败!{response["reason"]}')
def wecom_app(title: str, content: str) -> None:
"""
通过 企业微信 APP 推送消息。
"""
if not push_config.get("QYWX_AM"):
print("QYWX_AM 未设置!!\n取消推送")
return
QYWX_AM_AY = re.split(",", push_config.get("QYWX_AM"))
if 4 < len(QYWX_AM_AY) > 5:
print("QYWX_AM 设置错误!!\n取消推送")
return
print("企业微信 APP 服务启动")
corpid = QYWX_AM_AY[0]
corpsecret = QYWX_AM_AY[1]
touser = QYWX_AM_AY[2]
agentid = QYWX_AM_AY[3]
try:
media_id = QYWX_AM_AY[4]
except IndexError:
media_id = ""
wx = WeCom(corpid, corpsecret, agentid)
# 如果没有配置 media_id 默认就以 text 方式发送
if not media_id:
message = title + "\n\n" + content
response = wx.send_text(message, touser)
else:
response = wx.send_mpnews(title, content, media_id, touser)
if response == "ok":
print("企业微信推送成功!")
else:
print("企业微信推送失败!错误信息如下:\n", response)
class WeCom:
def __init__(self, corpid, corpsecret, agentid):
self.CORPID = corpid
self.CORPSECRET = corpsecret
self.AGENTID = agentid
def get_access_token(self):
url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
values = {
"corpid": self.CORPID,
"corpsecret": self.CORPSECRET,
}
req = requests.post(url, params=values)
data = json.loads(req.text)
return data["access_token"]
def send_text(self, message, touser="@all"):
send_url = (
"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
+ self.get_access_token()
)
send_values = {
"touser": touser,
"msgtype": "text",
"agentid": self.AGENTID,
"text": {"content": message},
"safe": "0",
}
send_msges = bytes(json.dumps(send_values), "utf-8")
respone = requests.post(send_url, send_msges)
respone = respone.json()
return respone["errmsg"]
def send_mpnews(self, title, message, media_id, touser="@all"):
send_url = (
"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
+ self.get_access_token()
)
send_values = {
"touser": touser,
"msgtype": "mpnews",
"agentid": self.AGENTID,
"mpnews": {
"articles": [
{
"title": title,
"thumb_media_id": media_id,
"author": "Author",
"content_source_url": "",
"content": message.replace("\n", "<br/>"),
"digest": message,
}
]
},
}
send_msges = bytes(json.dumps(send_values), "utf-8")
respone = requests.post(send_url, send_msges)
respone = respone.json()
return respone["errmsg"]
def wecom_bot(title: str, content: str) -> None:
"""
通过 企业微信机器人 推送消息。
"""
if not push_config.get("QYWX_KEY"):
print("企业微信机器人 服务的 QYWX_KEY 未设置!!\n取消推送")
return
print("企业微信机器人服务启动")
url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={push_config.get('QYWX_KEY')}"
headers = {"Content-Type": "application/json;charset=utf-8"}
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
response = requests.post(
url=url, data=json.dumps(data), headers=headers, timeout=15
).json()
if response["errcode"] == 0:
print("企业微信机器人推送成功!")
else:
print("企业微信机器人推送失败!")
def telegram_bot(title: str, content: str) -> None:
"""
使用 telegram 机器人 推送消息。
"""
if not push_config.get("TG_BOT_TOKEN") or not push_config.get("TG_USER_ID"):
print("tg 服务的 bot_token 或者 user_id 未设置!!\n取消推送")
return
print("tg 服务启动")
if push_config.get("TG_API_HOST"):
url = f"https://{push_config.get('TG_API_HOST')}/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
else:
url = (
f"https://api.telegram.org/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
)
headers = {"Content-Type": "application/x-www-form-urlencoded"}
payload = {
"chat_id": str(push_config.get("TG_USER_ID")),
"text": f"{title}\n\n{content}",
"disable_web_page_preview": "true",
}
proxies = None
if push_config.get("TG_PROXY_HOST") and push_config.get("TG_PROXY_PORT"):
if push_config.get("TG_PROXY_AUTH") is not None and "@" not in push_config.get(
"TG_PROXY_HOST"
):
push_config["TG_PROXY_HOST"] = (
push_config.get("TG_PROXY_AUTH")
+ "@"
+ push_config.get("TG_PROXY_HOST")
)
proxyStr = "http://{}:{}".format(
push_config.get("TG_PROXY_HOST"), push_config.get("TG_PROXY_PORT")
)
proxies = {"http": proxyStr, "https": proxyStr}
response = requests.post(
url=url, headers=headers, params=payload, proxies=proxies
).json()
if response["ok"]:
print("tg 推送成功!")
else:
print("tg 推送失败!")
def one() -> str:
"""
获取一条一言。
:return:
"""
url = "https://v1.hitokoto.cn/"
res = requests.get(url).json()
return res["hitokoto"] + " ----" + res["from"]
if push_config.get("BARK_PUSH"):
notify_function.append(bark)
if push_config.get("CONSOLE"):
notify_function.append(console)
if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"):
notify_function.append(dingding_bot)
if push_config.get("FSKEY"):
notify_function.append(feishu_bot)
if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"):
notify_function.append(go_cqhttp)
if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"):
notify_function.append(gotify)
if push_config.get("IGOT_PUSH_KEY"):
notify_function.append(iGot)
if push_config.get("PUSH_KEY"):
notify_function.append(serverJ)
if push_config.get("DEER_KEY"):
notify_function.append(pushdeer)
if push_config.get("PUSH_PLUS_TOKEN"):
notify_function.append(pushplus_bot)
if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"):
notify_function.append(qmsg_bot)
if push_config.get("QYWX_AM"):
notify_function.append(wecom_app)
if push_config.get("QYWX_KEY"):
notify_function.append(wecom_bot)
if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"):
notify_function.append(telegram_bot)
def send(title: str, content: str) -> None:
if not content:
print(f"{title} 推送内容为空!")
return
hitokoto = push_config.get("HITOKOTO")
text = one() if hitokoto else ""
content += "\n\n" + text
ts = [
threading.Thread(target=mode, args=(title, content), name=mode.__name__)
for mode in notify_function
]
[t.start() for t in ts]
[t.join() for t in ts]
def main():
send("title", "content")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,483 @@
# Source: https://github.com/DearSong15/ql-scripts/blob/main/ks_query.py
# Raw: https://raw.githubusercontent.com/DearSong15/ql-scripts/main/ks_query.py
# Repo: DearSong15/ql-scripts
# Path: ks_query.py
# UploadedAt: 2026-05-11T14:51:55Z
# SHA256: 848504df99018b6b2f9d7bac940671dc65777b8d973c1610e2a3111c88d36480
# Category: web版/抓包
# Evidence: web/H5关键词 + cookie/token/header
import json
import os
import requests
import time
from datetime import datetime, timedelta
from openpyxl import Workbook
from openpyxl.styles import Alignment, Font, PatternFill
def print_disclaimer():
"""打印免责声明"""
print("=" * 60)
print("【免责声明】")
print("1. 本程序仅为技术学习和个人账号信息查询使用,请勿用于商业用途或非法操作。")
print("2. 使用本程序需确保您对所查询的快手账号拥有合法所有权或使用权,严禁查询他人账号信息。")
print("3. 快手平台API可能随时变更导致程序无法正常运行开发者不保证程序的稳定性和可用性。")
print("4. 任何因使用本程序违反快手平台用户协议、法律法规或侵犯他人权益的行为,均由使用者自行承担全部责任。")
print("5. 开发者对使用本程序产生的任何直接或间接损失不承担任何法律责任。")
print("6. 本程序为临时查询工具建议您在使用完毕后24小时内删除程序及相关账号配置信息以保障账号安全。")
print("确认了解并同意以上条款后,程序将继续运行...")
print("快手极速版以及普通版本cookie有的账号是通用的普通版(kpn=KUAISHOU) 极速版(kpn=NEBULA)更改cookie的kpn即可")
print("\n请设置环境变量 ksck格式为:")
print("备注#cookie#salt#ip|端口|用户名|密码|到期日期")
print("=" * 60 + "\n")
# 比率映射关系
RATIO_MAP = {
19: 0.00009,
28: 0.00008,
37: 0.00007,
46: 0.00006,
55: 0.00005,
64: 0.00004,
73: 0.00003,
82: 0.00002,
91: 0.00001
}
# 读取环境变量中的参数默认46
SELECTED_PARAM = int(os.getenv("RATIO_PARAM", 46))
class KuaishouClient:
def __init__(self, index, cookie, remark=""):
self.index = index
self.remark = remark
self.cookie = cookie
self.user_name = "未知用户"
# 余额信息
self.coin_balance = 0
self.cash_balance = 0
self.total_balance = 0
# 今日和昨日金币
self.today_coin = 0
self.yesterday_coin = 0
# 兑换后金额
self.today_coin_cash = 0
self.yesterday_coin_cash = 0
# 流水记录
self.coin_records = []
self.cash_records = []
# 基础配置
self.headers = {
'User-Agent': "Mozilla/5.0 (Linux; Android 16; PTP-AN00 Build/HONORPTP-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/139.0.7258.158 Mobile Safari/537.36 Yoda/3.2.17-rc2 Kwai/13.9.30.44872 OS_PRO_BIT/64 MAX_PHY_MEM/15272 KDT/PHONE AZPREFIX/az1 ICFO/0 StatusHT/38 TitleHT/44 NetType/NR ISLP/0 ISDM/0 ISLB/0 locale/zh-cn SHP/2665 SWP/1264 SD/3.5 CT/0 ISLM/0",
'Accept-Encoding': "gzip, deflate, br, zstd",
'sec-ch-ua-platform': "\"Android\"",
'sec-ch-ua': "\"Not;A=Brand\";v=\"99\", \"Android WebView\";v=\"139\", \"Chromium\";v=\"139\"",
'sec-ch-ua-mobile': "?1",
'X-Requested-With': "com.smile.gifmaker",
'Sec-Fetch-Site': "same-origin",
'Sec-Fetch-Mode': "cors",
'Sec-Fetch-Dest': "empty",
'Referer': "https://encourage.kuaishou.com/kwai/profit?tab=coin&layoutType=4",
'Accept-Language': "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
'Cookie': self.cookie
}
def send_request(self, url, method="get", params=None):
"""发送请求"""
try:
if method == "get":
response = requests.get(url, headers=self.headers, params=params, timeout=10)
else:
response = requests.post(url, headers=self.headers, data=params, timeout=10)
if response.status_code == 200:
return response.json()
else:
print(f"请求失败,状态码: {response.status_code}")
return None
except Exception as e:
print(f"请求异常: {e}")
return None
def query_withdraw_info(self):
"""查询提现信息(包含用户名和余额)"""
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/withdraw/info"
params = {
"source": "normal",
"imei": "",
"oaid": "279b0911-a941-4e80-b5fd-91f1c1ea2644",
"idfa": ""
}
result = self.send_request(url, params=params)
if result and result.get("result") == 1:
data = result.get("data", {})
# 获取用户名
self.user_name = data.get("nickname", "未知用户")
# 获取账户信息
account = data.get("account", {})
self.coin_balance = account.get("coinAmount", 0)
self.cash_balance = account.get("cashAmount", 0) # 单位:分
self.total_balance = account.get("accumulativeAmount", 0) # 单位:分
return True
return False
def query_cash_records(self):
"""查询现金流水记录"""
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/detail"
params = {
"__NS_sig3": "6272350512f90404a43e5b3d3a3b5b3320a219ee1616ba201b5f2d2d2b2b28291636",
"sigCatVer": "1",
"accountType": "cash",
"cursor": ""
}
result = self.send_request(url, params=params)
if result and result.get("result") == 1:
data = result.get("data", {})
records = data.get("datas", [])
for record in records[:3]:
self.cash_records.append({
'time': self._format_timestamp(record.get("createTime", 0)),
'title': record.get("title", ""),
'amount': record.get("displayAmount", "0"),
'direction': record.get("direction", "")
})
return True
return False
def query_coin_records(self):
"""查询金币流水记录"""
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/detail"
params = {
"__NS_sig3": "7262251502e91414b42e4a2d2a2b6006895f03fe0606aa3024c33d3d3b3b38390626",
"sigCatVer": "1",
"accountType": "coin",
"cursor": ""
}
result = self.send_request(url, params=params)
if result and result.get("result") == 1:
data = result.get("data", {})
records = data.get("datas", [])
for record in records[:3]:
self.coin_records.append({
'time': self._format_timestamp(record.get("createTime", 0)),
'title': record.get("title", ""),
'amount': record.get("displayAmount", "0"),
'direction': record.get("direction", "")
})
return True
return False
def _format_timestamp(self, timestamp):
"""格式化时间戳"""
if timestamp:
try:
dt = datetime.fromtimestamp(timestamp / 1000)
return dt.strftime("%Y-%m-%d %H:%M")
except:
return "未知时间"
return "未知时间"
def calculate_coin_stats(self):
"""计算今日和昨日金币收入及兑换后金额"""
today = datetime.now().date()
yesterday = today - timedelta(days=1)
self.today_coin = 0
self.yesterday_coin = 0
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/detail"
params = {
"__NS_sig3": "7262251502e91414b42e4a2d2a2b6006895f03fe0606aa3024c33d3d3b3b38390626",
"sigCatVer": "1",
"accountType": "coin",
"cursor": ""
}
result = self.send_request(url, params=params)
if result and result.get("result") == 1:
data = result.get("data", {})
records = data.get("datas", [])
for record in records:
if record.get("direction") != "IN":
continue
amount = record.get("amount", 0)
create_time = record.get("createTime", 0)
if create_time:
record_date = datetime.fromtimestamp(create_time / 1000).date()
if record_date == today:
self.today_coin += amount
elif record_date == yesterday:
self.yesterday_coin += amount
# 计算兑换后金额
ratio = RATIO_MAP.get(SELECTED_PARAM, 0.00006) # 默认46对应的比率
self.today_coin_cash = round(self.today_coin * ratio, 2)
self.yesterday_coin_cash = round(self.yesterday_coin * ratio, 2)
return True
def query_all_data(self):
"""查询所有数据"""
print(f"正在查询账号[{self.index}] {self.remark}...")
# 查询提现信息(包含用户名和余额)
if not self.query_withdraw_info():
print(f"账号[{self.index}] {self.remark} 提现信息查询失败")
return False
# 查询现金流水
if not self.query_cash_records():
print(f"账号[{self.index}] {self.remark} 现金流水查询失败")
# 查询金币流水
if not self.query_coin_records():
print(f"账号[{self.index}] {self.remark} 金币流水查询失败")
# 计算金币统计
self.calculate_coin_stats()
return True
def get_display_data(self):
"""获取显示数据"""
# 现金余额从分转换为元
cash_yuan = self.cash_balance / 100 if self.cash_balance else 0
total_yuan = self.total_balance / 100 if self.total_balance else 0
return {
"index": self.index,
"user_name": self.user_name,
"remark": self.remark,
"today_coin": self.today_coin,
"yesterday_coin": self.yesterday_coin,
"today_coin_cash": self.today_coin_cash,
"yesterday_coin_cash": self.yesterday_coin_cash,
"coin_balance": self.coin_balance,
"cash_balance": round(cash_yuan, 2),
"total_balance": round(total_yuan, 2),
"coin_records": self.coin_records,
"cash_records": self.cash_records,
"ratio_param": SELECTED_PARAM
}
def load_cookies_from_env():
"""从环境变量ksck加载cookie配置格式备注#cookie#salt#ip|端口|用户名|密码|到期日期"""
cookies = []
ksck_env = os.getenv('ksck')
if not ksck_env:
print("未找到环境变量 ksck")
return cookies
lines = ksck_env.strip().split('&')
for i, line in enumerate(lines):
line = line.strip()
if not line:
continue
parts = line.split('#')
if len(parts) < 3:
print(f"{i + 1}行格式错误,跳过: {line}")
continue
remark = parts[0].strip()
cookie = parts[1].strip()
salt = parts[2].strip() # 暂时不使用
if not cookie:
print(f"{i + 1}行cookie为空跳过")
continue
# 不再检查socName直接添加
cookies.append({
"cookie": cookie,
"remark": remark
})
print(f"从环境变量 ksck 加载了 {len(cookies)} 个账号")
return cookies
def create_excel_summary(data_list, filename="快手金币数据汇总.xlsx"):
"""创建Excel汇总表格"""
wb = Workbook()
ws = wb.active
ws.title = "金币数据汇总"
# 设置表头
headers = ["序号", "用户名", "备注", "今日金币", "昨日金币", "当前金币",
f"今日{SELECTED_PARAM}后(元)", f"昨日{SELECTED_PARAM}后(元)", "当前现金(元)", "累计收益(元)",
"最近金币流水", "最近现金流水"]
for col, header in enumerate(headers, 1):
cell = ws.cell(row=1, column=col)
cell.value = header
cell.font = Font(bold=True)
cell.alignment = Alignment(horizontal="center")
cell.fill = PatternFill(start_color="E6F3FF", end_color="E6F3FF", fill_type="solid")
# 填充数据
for row, data in enumerate(data_list, 2):
ws.cell(row=row, column=1, value=data["index"]).alignment = Alignment(horizontal="center")
ws.cell(row=row, column=2, value=data["user_name"])
ws.cell(row=row, column=3, value=data["remark"])
ws.cell(row=row, column=4, value=data["today_coin"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=5, value=data["yesterday_coin"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=6, value=data["coin_balance"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=7, value=data["today_coin_cash"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=8, value=data["yesterday_coin_cash"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=9, value=data["cash_balance"]).alignment = Alignment(horizontal="right")
ws.cell(row=row, column=10, value=data["total_balance"]).alignment = Alignment(horizontal="right")
# 格式化流水记录
coin_flow = "\n".join([f"{r['time']} {r['title']} +{r['amount']}" for r in data["coin_records"]])
cash_flow = "\n".join([f"{r['time']} {r['title']} {r['amount']}" for r in data["cash_records"]])
ws.cell(row=row, column=11, value=coin_flow)
ws.cell(row=row, column=12, value=cash_flow)
# 设置列宽
column_widths = {
'A': 8, # 序号
'B': 20, # 用户名
'C': 20, # 备注
'D': 12, # 今日金币
'E': 12, # 昨日金币
'F': 12, # 当前金币
'G': 18, # 今日兑换后
'H': 18, # 昨日兑换后
'I': 15, # 当前现金
'J': 15, # 累计收益
'K': 30, # 最近金币流水
'L': 30 # 最近现金流水
}
for col, width in column_widths.items():
ws.column_dimensions[col].width = width
# 设置行高
for row in range(2, len(data_list) + 2):
ws.row_dimensions[row].height = 60
# 保存文件
wb.save(filename)
print(f"\nExcel表格已生成: {filename}")
# 打印汇总统计
total_today = sum(data["today_coin"] for data in data_list)
total_yesterday = sum(data["yesterday_coin"] for data in data_list)
total_today_cash = sum(data["today_coin_cash"] for data in data_list)
total_yesterday_cash = sum(data["yesterday_coin_cash"] for data in data_list)
total_coins = sum(data["coin_balance"] for data in data_list)
total_cash = sum(data["cash_balance"] for data in data_list)
total_accumulative = sum(data["total_balance"] for data in data_list)
ratio = RATIO_MAP.get(SELECTED_PARAM, 0.00006)
print(f"\n汇总统计 (使用比率参数 {SELECTED_PARAM}, 比率: {ratio}):")
print(f"今日金币总数: {total_today}")
print(f"今日金币兑换后: {total_today_cash}")
print(f"昨日金币总数: {total_yesterday}")
print(f"昨日金币兑换后: {total_yesterday_cash}")
print(f"当前金币总数: {total_coins}")
print(f"当前现金总数: {total_cash}")
print(f"累计收益总数: {total_accumulative}")
def main():
"""主函数"""
print_disclaimer()
print("开始查询快手账号数据...")
print("=" * 50)
print(f"当前使用比率参数: {SELECTED_PARAM}, 兑换比率: {RATIO_MAP.get(SELECTED_PARAM, 0.00006)}")
print("=" * 50)
# 从环境变量加载cookie配置
cookies_config = load_cookies_from_env()
if not cookies_config:
print("错误: 未找到有效的cookie配置")
print("\n请设置环境变量 ksck格式为:")
print("备注#cookie#salt#ip|端口|用户名|密码|到期日期")
print("每行一个账号,用&分隔,例如:")
print("我的账号1#kuaishou.api_st=xxx; token=xxx#salt1#&我的账号2#kuaishou.api_st=yyy; token=yyy#salt2#")
return
all_data = []
success_count = 0
for i, account in enumerate(cookies_config):
if not account.get("cookie"):
print(f"账号[{i + 1}] cookie为空跳过")
continue
client = KuaishouClient(
index=i + 1,
cookie=account["cookie"],
remark=account["remark"]
)
if client.query_all_data():
data = client.get_display_data()
all_data.append(data)
success_count += 1
# 打印单个账号信息
print(f"\n账号[{i + 1}] 用户名: {data['user_name']} 备注: {account['remark']} 查询成功:")
print(f" 今日金币: {data['today_coin']}{data['today_coin_cash']}")
print(f" 昨日金币: {data['yesterday_coin']}{data['yesterday_coin_cash']}")
print(f" 当前金币: {data['coin_balance']}")
print(f" 当前现金: {data['cash_balance']}")
print(f" 累计收益: {data['total_balance']}")
if data['coin_records']:
print(" 最近金币流水:")
for record in data['coin_records']:
print(f" {record['time']} {record['title']} +{record['amount']}")
if data['cash_records']:
print(" 最近现金流水:")
for record in data['cash_records']:
print(f" {record['time']} {record['title']} {record['amount']}")
else:
print(f"\n账号[{i + 1}] {account['remark']} 查询失败")
# 添加0.5秒延迟,避免请求过于频繁
if i < len(cookies_config) - 1: # 最后一个账号不需要延迟
print("等待0.5秒后继续下一个账号...")
time.sleep(0.5)
# 生成Excel表格
if all_data:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"快手金币数据汇总_{SELECTED_PARAM}后_{timestamp}.xlsx"
create_excel_summary(all_data, filename)
print(f"\n成功查询 {success_count}/{len(cookies_config)} 个账号")
else:
print("没有成功查询到任何账号数据")
if __name__ == "__main__":
main()

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,563 @@
// # Source: https://github.com/huwangkeji/juejin_checkin/blob/main/juejin_checkin.js
// # Raw: https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin_checkin.js
// # Repo: huwangkeji/juejin_checkin
// # Path: juejin_checkin.js
// # UploadedAt: 2026-05-19T14:34:11Z
// # SHA256: 6f8a138b51c397220444c9312040dbe3407af5aeed4fa4467a36672aeb8bcfd1
// # Category: web版/账密
// # Evidence: web/H5关键词 + username/password/login
//
/*
* @name 掘金自动签到脚本
* @description 掘金社区每日签到 + 免费抽奖 + 沾喜气 + Bug消除支持Cookie自动签到
* @namespace https://juejin.cn
* @version 1.0.0
* @author CodeBuddy
*
* 【青龙面板使用说明】
* 1. 依赖管理 -> NodeJS -> 添加依赖: axios
* 2. 环境变量 (必填):
* - JUEJIN_COOKIE: 掘金Cookie (从浏览器开发者工具复制)
* - JUEJIN_AID: API参数aid (通常为2608)
* - JUEJIN_UUID: API参数uuid
* - JUEJIN_MSTOKEN: API参数msToken
* - JUEJIN_A_BOGUS: API参数a_bogus
* 3. 环境变量 (可选):
* - JUEJIN_COOKIE_2 ~ JUEJIN_COOKIE_5: 多账号Cookie
* - JUEJIN_NOTIFY: 是否推送通知 (默认true)
* 4. 定时规则: 30 6 * * * (每天早上6:30执行)
*
* 【参数获取方式】
* 1. 浏览器打开 https://juejin.cn 并登录
* 2. 按F12打开开发者工具 -> Network(网络)标签
* 3. 刷新页面,找到任意一个 api.juejin.cn 的请求
* 4. 在 Request Headers 中复制完整的 Cookie 值
* 5. 在 Query String Parameters 中复制 aid, uuid, msToken, a_bogus
* 6. 粘贴到青龙面板对应的环境变量中
* 7. Cookie和参数有效期约30天过期后需重新获取
*
* 【功能列表】
* - Cookie自动签到支持多账号
* - 每日签到
* - 免费抽奖
* - 沾喜气
* - Bug消除
* - 查询矿石余额/签到天数/幸运值
* - 青龙面板通知推送
*/
const axios = require('axios');
// ==================== 配置区域 ====================
const API_BASE = 'https://api.juejin.cn';
// 请求头
const DEFAULT_HEADERS = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
'Referer': 'https://juejin.cn/',
'Origin': 'https://juejin.cn',
'Content-Type': 'application/json',
'sec-ch-ua': '"Not/A)Brand";v="99", "Chromium";v="148"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
};
// ==================== 工具函数 ====================
function log(msg) {
const now = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
console.log(`[${now}] ${msg}`);
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* 创建带Cookie和参数的axios实例
*/
function createApiClient(cookie, params) {
const instance = axios.create({
baseURL: API_BASE,
headers: {
...DEFAULT_HEADERS,
Cookie: cookie,
},
timeout: 30000,
});
// 请求拦截 - 自动添加查询参数
instance.interceptors.request.use((config) => {
if (params && Object.keys(params).length > 0) {
config.params = { ...config.params, ...params };
}
// POST请求body为空对象
if (config.method === 'post' && !config.data) {
config.data = {};
}
return config;
});
// 响应拦截
instance.interceptors.response.use(
(response) => {
const data = response.data;
// 处理空响应
if (data === '' || data === null || data === undefined) {
throw new Error('API返回空响应可能需要更新参数');
}
if (typeof data === 'object' && data.err_no !== 0) {
throw new Error(`API错误: [${data.err_no}] ${data.err_msg || '未知错误'}`);
}
return data.data;
},
(error) => {
if (error.response) {
const data = error.response.data;
if (data && typeof data === 'object' && data.err_no !== undefined) {
throw new Error(`API错误: [${data.err_no}] ${data.err_msg || '未知错误'}`);
}
throw new Error(`HTTP错误: ${error.response.status} ${error.response.statusText}`);
}
throw error;
}
);
return instance;
}
// ==================== API 调用 ====================
/**
* 检查今日签到状态
*/
async function getTodayStatus(api) {
try {
const data = await api.get('/growth_api/v1/get_today_status');
return data === true;
} catch (e) {
log('⚠️ 查询签到状态失败: ' + e.message);
return null;
}
}
/**
* 执行签到
*/
async function checkIn(api) {
try {
const data = await api.post('/growth_api/v1/check_in');
log('✅ 签到成功!');
return { success: true, data };
} catch (e) {
if (e.message.includes('15001') || e.message.includes('已签到') || e.message.includes('duplicate')) {
log('📌 今日已签到,无需重复签到');
return { success: true, already: true };
}
if (e.message.includes('3013')) {
log('📌 今日已签到 (3013)');
return { success: true, already: true };
}
if (e.message.includes('空响应')) {
log('⚠️ API返回空响应参数可能已过期建议重新获取');
return { success: false, error: e.message };
}
log('❌ 签到失败: ' + e.message);
return { success: false, error: e.message };
}
}
/**
* 获取签到天数统计
*/
async function getCounts(api) {
try {
const data = await api.get('/growth_api/v1/get_counts');
return data;
} catch (e) {
log('⚠️ 获取签到统计失败: ' + e.message);
return null;
}
}
/**
* 获取当前矿石数
*/
async function getCurrentPoint(api) {
try {
const data = await api.get('/growth_api/v1/get_cur_point');
return data;
} catch (e) {
log('⚠️ 获取矿石余额失败: ' + e.message);
return null;
}
}
/**
* 获取抽奖配置
*/
async function getLotteryConfig(api) {
try {
const data = await api.get('/growth_api/v1/lottery_config/get');
return data;
} catch (e) {
log('⚠️ 获取抽奖配置失败: ' + e.message);
return null;
}
}
/**
* 免费抽奖
*/
async function drawLottery(api) {
try {
const data = await api.post('/growth_api/v1/lottery/draw');
log('🎉 抽奖成功!奖品: ' + (data.lottery_name || '未知'));
return { success: true, data };
} catch (e) {
log('❌ 抽奖失败: ' + e.message);
return { success: false, error: e.message };
}
}
/**
* 沾喜气
*/
async function dipLucky(api) {
try {
// 先获取幸运用户列表
const luckyUsers = await api.post('/growth_api/v1/lottery_history/global_big', {
page_no: 1,
page_size: 5,
});
if (luckyUsers && luckyUsers.lotteries && luckyUsers.lotteries.length > 0) {
const historyId = luckyUsers.lotteries[0].history_id;
const data = await api.post('/growth_api/v1/lottery_lucky/dip_lucky', {
lottery_history_id: historyId,
});
log('🍀 沾喜气成功!幸运值: ' + (data.dip_value || 0));
return { success: true, data };
}
log('⚠️ 暂无可沾喜气的用户');
return { success: false };
} catch (e) {
log('❌ 沾喜气失败: ' + e.message);
return { success: false, error: e.message };
}
}
/**
* 获取我的幸运值
*/
async function getMyLucky(api) {
try {
const data = await api.post('/growth_api/v1/lottery_lucky/my_lucky');
return data;
} catch (e) {
log('⚠️ 获取幸运值失败: ' + e.message);
return null;
}
}
/**
* 查询用户信息 (验证Cookie有效性)
*/
async function getUserInfo(api) {
try {
const data = await api.get('/user_api/v1/user/get');
return data;
} catch (e) {
log('⚠️ Cookie无效或已过期: ' + e.message);
return null;
}
}
/**
* 获取Bug消除配置
*/
async function getBugFixConfig(api) {
try {
const data = await api.get('/growth_api/v1/bugfix/not_collect');
return data;
} catch (e) {
log('⚠️ 获取Bug配置失败: ' + e.message);
return null;
}
}
/**
* 消除Bug
*/
async function fixBug(api, bugId) {
try {
const data = await api.post('/growth_api/v1/bugfix/collect', {
bug_type: bugId,
});
log('🐛 Bug消除成功');
return { success: true, data };
} catch (e) {
log('❌ Bug消除失败: ' + e.message);
return { success: false, error: e.message };
}
}
// ==================== 青龙面板通知 ====================
/**
* 青龙面板通知推送
*/
async function sendNotify(title, content) {
if (process.env.JUEJIN_NOTIFY === 'false') {
log('📢 通知已禁用');
return;
}
try {
// 尝试加载青龙面板的通知模块
const notifyPath = require('path').join(process.cwd(), 'notify.js');
if (require('fs').existsSync(notifyPath)) {
const sendNotifyFn = require(notifyPath);
if (typeof sendNotifyFn === 'function') {
await sendNotifyFn(title, content);
log('📢 青龙通知已发送');
return;
}
}
// 尝试从全局加载
try {
const { sendNotify: qinglongNotify } = require('qlnotify');
await qinglongNotify(title, content);
log('📢 青龙通知已发送');
return;
} catch (e) {
// 忽略
}
log('📢 青龙通知模块未找到,仅控制台输出');
} catch (e) {
log('⚠️ 发送通知失败: ' + e.message);
}
}
// ==================== 单个账号签到流程 ====================
async function runAccount(cookie, params, index) {
const prefix = index > 1 ? `[账号${index}] ` : '';
log('');
log(`${prefix}═══════════════════════════════════════`);
log(`${prefix} 开始处理账号 ${index}`);
log(`${prefix}═══════════════════════════════════════`);
if (!cookie || cookie.trim().length === 0) {
log(`${prefix}❌ Cookie为空跳过`);
return null;
}
// 创建API客户端
const api = createApiClient(cookie, params);
// 验证Cookie有效性
log(`${prefix}🔍 验证Cookie...`);
const userInfo = await getUserInfo(api);
if (!userInfo) {
log(`${prefix}❌ Cookie已失效请重新获取`);
return {
success: false,
error: 'Cookie已失效',
userName: '未知用户',
};
}
const userName = userInfo.user_name || userInfo.nick_name || '未知用户';
log(`${prefix}✅ Cookie有效用户: ${userName}`);
// 签到
log(`${prefix}📅 执行签到...`);
const todayStatus = await getTodayStatus(api);
let signInResult = { success: true, already: todayStatus === true };
if (todayStatus === true) {
log(`${prefix}📌 今日已签到,跳过`);
} else if (todayStatus === false) {
signInResult = await checkIn(api);
if (!signInResult.success) {
log(`${prefix}🔄 签到失败1秒后重试...`);
await sleep(1000);
signInResult = await checkIn(api);
}
} else {
log(`${prefix}⚠️ 无法查询签到状态,直接尝试签到...`);
signInResult = await checkIn(api);
}
// 抽奖
log(`${prefix}🎰 执行抽奖...`);
const lotteryConfig = await getLotteryConfig(api);
let lotteryResult = { success: false };
if (lotteryConfig && lotteryConfig.free_count > 0) {
log(`${prefix}🎁 有 ${lotteryConfig.free_count} 次免费抽奖机会`);
lotteryResult = await drawLottery(api);
} else if (lotteryConfig) {
log(`${prefix}📌 今日免费抽奖次数已用完`);
}
// 沾喜气
log(`${prefix}🍀 沾喜气...`);
const dipResult = await dipLucky(api);
// Bug消除
log(`${prefix}🐛 消除Bug...`);
const bugConfig = await getBugFixConfig(api);
let bugFixResult = { success: false };
if (bugConfig && Array.isArray(bugConfig) && bugConfig.length > 0) {
const bug = bugConfig[0];
log(`${prefix}🔧 发现未消除的Bug: ${bug.bug_type}`);
bugFixResult = await fixBug(api, bug.bug_type);
} else {
log(`${prefix}📌 暂无Bug可消除`);
}
// 查询统计信息
log(`${prefix}📊 查询统计...`);
const counts = await getCounts(api);
const point = await getCurrentPoint(api);
const lucky = await getMyLucky(api);
if (counts) {
log(`${prefix}📅 连续签到: ${counts.cont_count || 0}`);
log(`${prefix}📅 累计签到: ${counts.sum_count || 0}`);
}
if (point !== null) {
log(`${prefix}💰 当前矿石: ${point}`);
}
if (lucky) {
log(`${prefix}🍀 幸运值: ${lucky.total_value || 0}`);
}
log(`${prefix}✅ 账号处理完成`);
return {
success: true,
userName,
signIn: signInResult,
lottery: lotteryResult,
dip: dipResult,
bugFix: bugFixResult,
counts,
point,
lucky,
};
}
// ==================== 主流程 ====================
async function main() {
log('═══════════════════════════════════════');
log(' 掘金自动签到脚本 v1.0.0');
log('═══════════════════════════════════════');
// 收集所有账号的配置
const accounts = [];
// 主账号
const mainCookie = process.env.JUEJIN_COOKIE || '';
const mainParams = {
aid: process.env.JUEJIN_AID || '2608',
uuid: process.env.JUEJIN_UUID || '',
msToken: process.env.JUEJIN_MSTOKEN || '',
a_bogus: process.env.JUEJIN_A_BOGUS || '',
spider: '0',
};
if (mainCookie) {
accounts.push({ cookie: mainCookie, params: mainParams });
}
// 多账号支持
for (let i = 2; i <= 5; i++) {
const cookie = process.env[`JUEJIN_COOKIE_${i}`] || '';
if (cookie) {
accounts.push({
cookie,
params: {
aid: process.env[`JUEJIN_AID_${i}`] || mainParams.aid,
uuid: process.env[`JUEJIN_UUID_${i}`] || '',
msToken: process.env[`JUEJIN_MSTOKEN_${i}`] || '',
a_bogus: process.env[`JUEJIN_A_BOGUS_${i}`] || '',
spider: '0',
},
});
}
}
if (accounts.length === 0) {
log('');
log('❌ 未配置Cookie请设置环境变量 JUEJIN_COOKIE');
log('');
log('【参数获取方式】');
log('1. 浏览器打开 https://juejin.cn 并登录');
log('2. 按F12打开开发者工具 -> Network(网络)标签');
log('3. 刷新页面,找到任意一个 api.juejin.cn 的请求');
log('4. 在 Request Headers 中复制完整的 Cookie 值');
log('5. 在 Query String Parameters 中复制 aid, uuid, msToken, a_bogus');
log('6. 粘贴到青龙面板对应的环境变量中');
log('');
process.exit(1);
}
log(`📱 共配置 ${accounts.length} 个账号`);
// 执行每个账号的签到
const results = [];
for (let i = 0; i < accounts.length; i++) {
const result = await runAccount(accounts[i].cookie, accounts[i].params, i + 1);
if (result) results.push(result);
}
// 生成通知内容
log('');
log('📢 发送通知...');
let notifyTitle = '掘金每日签到报告';
let notifyContent = '';
for (let i = 0; i < results.length; i++) {
const r = results[i];
const prefix = results.length > 1 ? `【账号${i + 1}` : '';
if (!r.success) {
notifyContent += `${prefix}${r.userName}: ${r.error}\n`;
continue;
}
notifyContent += `${prefix}👤 ${r.userName}\n`;
notifyContent += ` 📅 连续签到: ${r.counts?.cont_count || 0}\n`;
notifyContent += ` 📅 累计签到: ${r.counts?.sum_count || 0}\n`;
notifyContent += ` 💰 当前矿石: ${r.point ?? '未知'}\n`;
notifyContent += ` 🍀 幸运值: ${r.lucky?.total_value || 0}\n`;
notifyContent += ` ✅ 签到: ${r.signIn.already ? '今日已签到' : r.signIn.success ? '成功' : '失败'}\n`;
notifyContent += ` 🎰 抽奖: ${r.lottery.success ? '成功 - ' + (r.lottery.data?.lottery_name || '') : '未抽奖/失败'}\n`;
notifyContent += ` 🍀 沾喜气: ${r.dip.success ? '成功' : '失败'}\n`;
notifyContent += ` 🐛 Bug消除: ${r.bugFix.success ? '成功' : '无/失败'}\n`;
notifyContent += '\n';
}
await sendNotify(notifyTitle, notifyContent);
log('');
log('═══════════════════════════════════════');
log(' 脚本执行完成!');
log('═══════════════════════════════════════');
}
// 执行主函数
main().catch((error) => {
log('💥 脚本异常退出: ' + error.message);
console.error(error);
process.exit(1);
});

View File

@@ -0,0 +1,352 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/3dmgame.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/3dmgame.py
# Repo: lksky8/sign-ql
# Path: 3dmgame.py
# UploadedAt: 2026-03-27T20:17:30Z
# SHA256: 2262c9f7c2d40c8ef9822325fadd2e8ed3c43ba0f609c072a27c49b02edc2eaa
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
"""
作者https://github.com/lksky8/sign-ql/
日期2026-3-28
网站3dmgame论坛签到
功能:签到、抽奖,金币可换现金买游戏
食用方法登录论坛后浏览器F12打开抓包https://bbs.3dmgame.com/home.php?mod=spacecp&ac=credit&showcredit=1抓这个url请求头的cookie包
变量bbs3dmck='cookie' 多个账号用换行分割
定时一天三次
青龙需要安装lxml模块
cron: 0 9 */8 * * *
"""
import time
import requests
from lxml import etree
import re
import random
import os
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:
print('发送通知消息失败!' + str(e))
class ThreeDMGame:
def __init__(self, cookies):
headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Content-Type': 'application/x-www-form-urlencoded',
'Origin': 'https://bbs.3dmgame.com',
'Pragma': 'no-cache',
'Sec-Fetch-Dest': 'iframe',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-User': '?1',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36',
'sec-ch-ua': '"Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'Cookie': cookies,
}
self.session = requests.Session()
self.session.headers.update(headers)
def user_info(self):
try:
response = self.session.get('https://bbs.3dmgame.com/home.php?mod=spacecp&ac=credit&showcredit=1')
html = etree.HTML(response.text)
user_id = html.xpath('//*[@id="hd"]/div/div[1]/p/strong/a/text()')[0]
points = html.xpath('//*[@id="extcreditmenu"]/text()')[0]
gold = html.xpath('//*[@id="ct"]/div[1]/div/ul[2]/li[1]/text()')[0]
print(f'用户ID[{user_id}] {points} 金元:{gold}')
Log(f'\n用户ID[{user_id}] {points} 金元:{gold}')
except Exception as e:
print('3dmgame论坛用户信息获取失败', e)
Log(f'\n3dmgame论坛用户信息获取失败')
def task_view(self, t_id):
try:
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=view&id={t_id}')
html = etree.HTML(response.text)
task_name = html.xpath('//h1[contains(@class, "xs2") and contains(@class, "ptm") and contains(@class, "pbm")]/text()')[0].strip()
if 'do=apply' in response.text:
print(f'任务:《{task_name}》 可申请')
elif '后可以再次申请' in response.text:
print(f'任务:《{task_name}》 未到申请时间')
elif '您所在的用户组无法申请此任务' in response.text:
print(f'任务:《{task_name}》 您所在的用户组无法申请此任务')
elif 'static/image/task/reward.gif' in response.text:
print(f'任务:《{task_name}》 任务已完成,待领取奖励')
else:
print(f'任务:《{task_name}》 未知状态')
except Exception as e:
print(f'查看任务信息失败:{t_id} {e}')
def check_task(self):
try:
response = self.session.get('https://bbs.3dmgame.com/home.php?mod=task')
# print(response.text)
html = etree.HTML(response.text)
task_rows = html.xpath('//div[@class="ptm"]//table//tr')
# for row in task_rows:
# # 提取任务名称
# task_name = row.xpath('.//td[2]//h3/a/text()')[0] if row.xpath('.//td[2]//h3/a/text()') else ""
#
# # 提取任务描述
# description = row.xpath('.//td[2]/p/text()')[0] if row.xpath('.//td[2]/p/text()') else ""
#
# # 提取任务奖励
# reward = row.xpath('.//td[3]/text()')[0].strip() if row.xpath('.//td[3]/text()') else ""
#
# # 提取任务状态(可申请/不可申请)
# is_available = len(row.xpath('.//td[4]//img[@alt="apply"]')) > 0
#
# apply_link = row.xpath('.//td[4]/a[contains(@href, "do=apply")]/@href')[0] if row.xpath('.//td[4]/a[contains(@href, "do=apply")]/@href') else "无可用申请链接"
#
# print(f"任务名称: {task_name}")
# print(f"申请链接: {apply_link}")
# print(f"描述: {description}")
# print(f"奖励: {reward}")
# print(f"是否可申请: {'是' if is_available else '否'}")
# print("---")
task_list = {}
for row in task_rows:
task_name = row.xpath('.//td[2]//h3/a/text()')[0] if row.xpath('.//td[2]//h3/a/text()') else ""
description = row.xpath('.//td[2]/p/text()')[0] if row.xpath('.//td[2]/p/text()') else ""
reward = row.xpath('.//td[3]/text()')[0].strip() if row.xpath('.//td[3]/text()') else ""
apply_links = row.xpath('.//td[4]/a[contains(@href, "do=apply")]/@href')
# 只处理有可用申请链接的任务
if apply_links:
apply_link = apply_links[0]
print(f"任务名称: {task_name}")
print(f"描述: {description}")
print(f"奖励: {reward}")
# print(f"任务id: {apply_link.split('id=')[-1]}")
print("-" * 50)
task_list.update({task_name: apply_link.split('id=')[-1]})
if len(task_list) > 0:
print(f'获取到{len(task_list)}个可接任务')
for name, link_id in task_list.items():
print('*' * 30)
print(f'尝试领取任务:{name}')
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=apply&id={link_id}')
if 'do=draw' in response.text:
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=draw&id={link_id}')
if '恭喜您,任务已成功完成,您将收到奖励通知,请注意查收' in response.text:
print(f'任务:{name} 直接完成')
else:
print(f'任务:{name} 失败' + response.text)
elif '申请此任务需要先完成另一个任务' in response.text:
html_message = etree.HTML(response.text)
qianzhi_task = html_message.xpath('//div[@id="messagetext"]//p[@class="alert_btnleft"]/a/@href')[0].split("id=")[-1]
print(f'任务:{name} 领取失败 | 原因是前置任务未完成跳转前置任务id{qianzhi_task}')
self.task_view(qianzhi_task)
elif '任务申请成功' in response.text:
print(f'任务:{name} 领取成功')
elif '不是进行中的任务' in response.text:
print(f'任务:{name} 无法直接完成')
else:
print(f'任务:{name} 领取失败')
print(response.text)
time.sleep(1)
print('-' * 50)
else:
print('没有可接任务')
# Log(f'\n没有可接任务')
print('-' * 50)
except Exception as e:
print(f'检查任务信息失败:{e}')
def check_task_doing(self):
try:
response = self.session.get('https://bbs.3dmgame.com/home.php?mod=task&item=doing')
# print(response.text)
html = etree.HTML(response.text)
task_rows = html.xpath('//div[@class="ptm"]//table//tr')
task_list = []
for row in task_rows:
# 提取任务名称
task_name = row.xpath('.//td[2]//h3/a/text()')[0] if row.xpath('.//td[2]//h3/a/text()') else ""
# 提取任务ID
task_id = row.xpath('.//td[2]//h3/a/@href')[0].split('id=')[-1] if row.xpath('.//td[2]//h3/a/@href') else ""
# 提取do=view链接任务详情链接
# view_link = row.xpath('.//td[2]//h3/a[contains(@href, "do=view")]/@href')[0] if row.xpath('.//td[2]//h3/a[contains(@href, "do=view")]/@href') else ""
# 提取领取链接(do=draw类型)
# draw_links = row.xpath('.//td[4]/p/a[contains(@href, "do=draw")]/@href')[0] if row.xpath('.//td[4]/p/a/@href') else ""
print(f"进行中的任务: 《{task_name}")
task_list.append({task_name: task_id})
print('-' * 30)
if len(task_list) > 0:
return task_list
else:
print('没有进行中的任务')
# Log(f'\n没有进行中的任务')
return []
except Exception as e:
print(f'检查任务进行中失败:{e}')
def do_task(self, tk_list):
print(f'获取到{len(tk_list)}个待完成任务')
for task_name, task_id in tk_list.items():
print(f'尝试完成任务:《{task_name}')
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=view&id={task_id}')
if 'static/image/task/reward.gif' in response.text:
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=draw&id={task_id}')
if '恭喜您,任务已成功完成,您将收到奖励通知,请注意查收' in response.text:
print(f'任务:《{task_name}》 完成')
else:
print(f'任务:《{task_name}》 失败')
print(response.text)
elif '完成此任务所需条件' in response.text:
print(f'任务:《{task_name}》 无完成条件')
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=draw&id={task_id}')
if '恭喜您,任务已成功完成,您将收到奖励通知,请注意查收' in response.text:
print(f'任务:《{task_name}》 完成')
else:
print(f'任务:《{task_name}》 失败')
print(response.text)
else:
print(f'任务:《{task_name}》 有完成条件')
tree = etree.HTML(response.text)
tables = tree.xpath("//table[@class='tfm']//td[@class='bbda']/a/@href")[0]
# print(tables)
reply_td = tree.xpath("//table[@class='tfm']//td[@class='bbda'][contains(., '')]/text()[normalize-space()]")[1]
reply_td = reply_td.replace(' ', '')
# print(reply_td)
reply_count = re.search(r'(\d+)次', reply_td).group(1) if re.search(r'(\d+)次', reply_td) else "未知"
if 'thread' in tables:
response = self.session.get(f'https://bbs.3dmgame.com/{tables}')
formhash = re.search(r'name="formhash" value="(\w+)"', response.text).group(1)
fid_match = re.search(r"fid\s*=\s*parseInt\('(\d+)'\)", response.text).group(1)
tid_match = re.search(r"tid\s*=\s*parseInt\('(\d+)'\)", response.text).group(1)
print('回复次数:' + reply_count)
if int(reply_count) > 5:
print('回复次数大于5次任务跳过')
else:
for _ in range(int(reply_count)):
for i in range(3):
result = self.reply(tid_match, fid_match, formhash)
if result:
break
time.sleep(10)
time.sleep(35)
print(f'已完成任务 《{task_name}》 回复指定文章要求')
else:
response = self.session.get(f'https://bbs.3dmgame.com/{tables}')
result = re.findall(r'mod=redirect&tid=(\d+)&goto', response.text)
if len(result) > 0:
response = self.session.get(f'https://bbs.3dmgame.com/thread-{random.choice(result)}-1-1.html')
formhash = re.search(r'name="formhash" value="(\w+)"', response.text).group(1)
fid_match = re.search(r"fid\s*=\s*parseInt\('(\d+)'\)", response.text).group(1)
tid_match = re.search(r"tid\s*=\s*parseInt\('(\d+)'\)", response.text).group(1)
for _ in range(int(reply_count)):
for i in range(3):
result = self.reply(tid_match, fid_match, formhash)
if result:
break
time.sleep(10)
time.sleep(35)
print(f'已完成任务 《{task_name}》 回复指定主题要求')
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=draw&id={task_id}')
if '恭喜您,任务已成功完成,您将收到奖励通知,请注意查收' in response.text:
print(f'任务:《{task_name}》 完成')
elif '您已完成该任务的' in response.text:
html = etree.HTML(response.text)
b = html.xpath('//div[@id="messagetext"]/p/text()')[0]
print(f'任务:《{task_name}》 失败:' + b.strip())
elif '您还没有开始执行任务,赶快哦' in response.text:
print(f'任务:《{task_name}》 失败:因任务特殊跳过该任务')
elif '您还没有开始执行任务' in response.text:
print(f'任务:《{task_name}》 失败:因任务特殊跳过该任务')
else:
print(f'任务:《{task_name}》 失败')
print(response.text)
time.sleep(3)
def reply(self, tid, fid, formhash):
response = requests.get("https://www.mxnzp.com/api/jokes/list?page=1&app_id=vqohyieoq7qklmgp&app_secret=FCc9Uf0h1c0LNkqeLRolebStTGfds3Fx")
response_json = response.json()
if response_json['code'] == 1 :
message = response_json['data']['list'][0]['content']
else:
message = '我是新玩家,搞不懂' + random.choice(['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'])
data = {
'file': '',
'message': message,
'posttime': str(int(time.time())),
'formhash': formhash,
'usesig': '1',
'subject': ' ',
}
response = self.session.post(f'https://bbs.3dmgame.com/forum.php?mod=post&action=reply&fid={fid}&tid={tid}&extra=page%3D1&replysubmit=yes&infloat=yes&handlekey=fastpost&inajax=1', data=data)
if '回复发布成功' in response.text:
print('回帖成功,等待35秒后回复下个帖子')
return True
else:
print('回复失败,未知原因')
return False
def main(self):
self.user_info()
print('-' * 50)
print('开始做论坛任务-->>>>>>>>')
self.check_task()
task_list = self.check_task_doing()
if task_list:
for task in task_list:
self.do_task(task)
print('等待30秒进行下一个账号')
self.session.close()
print('*' * 50)
time.sleep(30)
Log('-' * 30)
if __name__ == '__main__':
try:
if 'bbs3dmck' in os.environ:
bbs3dmck = re.split("@|&", os.environ.get("bbs3dmck"))
print(f'查找到{len(bbs3dmck)}个账号\n')
else:
bbs3dmck = None
print('无bbs3dmck变量')
Log(f'\n未填入bbs3dmck变量')
if bbs3dmck:
z = 1
for ck in bbs3dmck:
print(f'登录第{z}个账号')
threeDM = ThreeDMGame(ck)
threeDM.main()
z+= 1
except Exception as e:
print(e)
try:
send_notification_message(title='3dmgame论坛签到') # 发送通知
except Exception as e:
print(e)

View File

@@ -0,0 +1,388 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/PPark.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/PPark.py
# Repo: lksky8/sign-ql
# Path: PPark.py
# UploadedAt: 2025-09-22T11:01:17Z
# SHA256: 120e73308bc1ccfb9db8ebd87357364850257a25ba1bc039d67c2967fe6c8e19
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
"""
PP停车签到
作者https://github.com/lksky8/sign-ql
最后更新日期2025-9-22
食用方法变量输入export pp_token=账号1#token1&账号2#token2
支持多用户运行
多用户用&或者@隔开
例如账号113800000000#eyJhbGciOiJIUzI1NiJ9.eyj 账号2 139000000000#eyJhbGciOiJIUzI1NiJ9.eyj
则变量为
export pp_token="13800000000#eyJhbGciOiJIUzI1NiJ9.eyj&13900000000#eyJhbGciOiJIUzI1NiJ9.eyj"
每天运行两次否则token会过期
cron: 0 40 0,12 * * *
"""
import requests
import base64
from urllib.parse import quote
import json
import hashlib
import time
import os
import re
KEY_ENCRYPT = "2363ECDFC54A5AF12477D3D45333A19F" # key1 用于加密
KEY_DECRYPT = "466d67cf8f9810707404fae5ed172b8e" # key2 用于解密
WX_ENCRYPT = "riegh^ee:w0fok5je5eeS{eecaes1nep"
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': 'api.660pp.com',
'accept': '*/*',
'content-type': 'application/x-www-form-urlencoded',
'rest_api_type': '1',
'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 Parking/4.3.2 (iOS 16.6.1; iPhone15,2; Build/1312) NetType/WIFI',
'accept-language': 'zh_CN',
}
wx_headers = {
'Host': 'user-api.4pyun.com',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541022) XWEB/16467',
'xweb_xhr': '1',
'content-type': 'application/x-www-form-urlencoded',
'accept': '*/*',
'sec-fetch-site': 'cross-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://servicewechat.com/wxa204074068ad40ef/879/page-frame.html',
'accept-language': 'zh-CN,zh;q=0.9',
'priority': 'u=1, i',
}
def transform(bytes_data: bytearray, key: str) -> bytearray:
len_key = len(key)
len_b = len(bytes_data)
for i in range(len_b):
index = (len_b - i) % len_key
key_byte = ord(key[index])
in_byte = bytes_data[i]
flipped = in_byte ^ 0xFF
bytes_data[i] = key_byte ^ flipped
return bytes_data
def encrypt(arg: str, key: str) -> str:
"""加密,对应提供的 encrypt 方法"""
bytes_data = bytearray(arg.encode('utf-8'))
transformed = transform(bytes_data, key)
return base64.b64encode(transformed).decode('utf-8')
def decrypt(arg: str) -> str:
"""解密,对应提供的 decrypt 方法"""
bytes_data = bytearray(base64.b64decode(arg))
transformed = transform(bytes_data, KEY_DECRYPT)
return transformed.decode('utf-8')
def save_or_update_phone_data(phone_key, new_data, file_path='PPark_data.json'):
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
existing_data = json.load(f)
else:
existing_data = {}
if phone_key in existing_data:
existing_data[phone_key].update(new_data) # 合并新旧数据
print(f"[{phone_key}] 数据已更新!")
else:
existing_data[phone_key] = new_data # 新增数据
print(f"[{phone_key}] 新增数据!")
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(existing_data, f, ensure_ascii=False, indent=4)
def get_user_ids_and_tokens(file_path='PPark_data.json'):
try:
with open(file_path, 'r', encoding='utf-8') as f:
phone_data = json.load(f)
results = []
for phone_key, data in phone_data.items():
token = data.get('refresh_token')
if token:
results.append({
'phone_key': phone_key,
'refresh_token': token,
'user_name': data.get('user_name'),
'user_id': data.get('user_id')
})
return results
except FileNotFoundError:
print(f"文件 {file_path} 不存在!")
return []
except json.JSONDecodeError:
print(f"文件 {file_path} 格式错误!")
return []
def get_userdata(u):
user_phone = u.split('#')[0]
user_token = u.split('#')[1]
try:
with open('PPark_data.json', 'r', encoding='utf-8') as f:
cache_data = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
cache_data = {}
if user_phone not in cache_data:
print(f'[{user_phone}] 不存在于缓存中,尝试初始化数据')
init_refresh_token(user_phone,user_token)
else:
print(f'[{user_phone}] 已存在于缓存中,直接读取数据')
refresh_token(user_phone,user_token,cache_data[user_phone]['refresh_token'])
old_user_token = cache_data[user_phone]['init_token']
if old_user_token != user_token:
print(f'[{user_phone}] token已更新尝试刷新')
init_refresh_token(user_phone,user_token)
def md5_encrypt(s: str):
return hashlib.md5(s.encode('utf-8')).hexdigest()
def get_user_info(phone: str, token: str):
headers = wx_headers.copy()
headers['authorization'] = f'Bearer {token}'
try:
response = requests.get('https://user-api.4pyun.com/rest/2.0/user/whoami',headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
print(f"[{response_json['payload']['nickname']}] 获取用户信息:成功")
return response_json['payload']['nickname'], response_json['payload']['identity']
else:
print(f"[{phone}] 获取用户信息:失败:{response_json}")
return None
except requests.RequestException as e:
print(f"[{phone}] 获取用户信息_请求异常{e}")
except json.JSONDecodeError:
print(f"[{phone}] 获取用户信息_响应不是有效的JSON格式")
except Exception as e:
print(f"[{phone}] 获取用户信息_其他异常{e}")
def refresh_token(mobile: str, i_token: str, r_token: str):
headers = api_headers.copy()
headers['rest_api_token'] = r_token
try:
response = requests.put('https://api.660pp.com/rest/1.6/user/token', headers=headers)
response_json = response.json()
# print(response_json)
if response_json['code'] == '1001':
result = json.loads(decrypt(response_json['result']))
print(f"[{mobile}] 刷新token成功")
save_or_update_phone_data(mobile,{'init_token': i_token,'refresh_token': result['token']})
elif response_json['code'] == '401':
print(f"[{mobile}] 刷新token失败token已失效")
Log(f"[{mobile}] 刷新token失败token已失效")
else:
print(f"[{mobile}] 刷新token失败{response_json}")
except requests.RequestException as e:
print(f"[{mobile}] 刷新token_请求异常{e}")
except json.JSONDecodeError:
print(f"[{mobile}] 刷新token_响应不是有效的JSON格式")
except Exception as e:
print(f"[{mobile}] 刷新token_其他异常{e}")
def init_refresh_token(mobile: str, token: str):
headers = api_headers.copy()
headers['rest_api_token'] = token
try:
response = requests.put('https://api.660pp.com/rest/1.6/user/token', headers=headers)
response_json = response.json()
# print(response_json)
if response_json['code'] == '1001':
result = json.loads(decrypt(response_json['result']))
user_name, user_id = get_user_info(mobile, token)
save_or_update_phone_data(mobile,{'user_name': user_name, 'user_id': user_id, 'init_token': token, 'refresh_token': result['token']})
print(f"[{mobile}] 刷新token成功")
elif response_json['code'] == '401':
print(f"[{mobile}] 刷新token失败token已失效")
Log(f"[{mobile}] 刷新token失败token已失效")
else:
print(f"[{mobile}] 刷新token失败{response_json}")
except requests.RequestException as e:
print(f"[{mobile}] 刷新token_请求异常{e}")
except json.JSONDecodeError:
print(f"[{mobile}] 刷新token_响应不是有效的JSON格式")
except Exception as e:
print(f"[{mobile}] 刷新token_其他异常{e}")
def day_sign(nickname: str, token: str):
headers = api_headers.copy()
headers['rest_api_token'] = token
try:
response = requests.get('https://api.660pp.com/rest/1.6/reward/bonus?yc7OyqO6qQ%3D%3D=rL7JhL/NrriG2tPZ2aegog%3D%3D', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
result = json.loads(decrypt(response_json['result']))
message = result['message'].replace('\r\n', '')
if '签到获得' in result['message'] or '已连续签到'in result['message']:
print(f"[{nickname}] 签到成功:{message} 已累计获得:{result['combo']} 积分")
Log(f"[{nickname}] 签到成功:{message} 已累计获得:{result['combo']} 积分")
elif message == '您已签到成功' :
print(f"[{nickname}] 签到失败:已签到")
Log(f"[{nickname}] 已签到")
else:
print(f"[{nickname}] 签到失败:{message}")
Log(f"[{nickname}] 签到失败:{message}")
else:
print(f"[{nickname}] 获取签到数据失败:{response_json}")
except requests.RequestException as e:
print(f"[{nickname}] 签到_请求异常{e}")
except json.JSONDecodeError:
print(f"[{nickname}] 签到_响应不是有效的JSON格式")
except Exception as e:
print(f"[{nickname}] 签到_其他异常{e}")
def get_task(nickname: str, token: str):
headers = wx_headers.copy()
headers['authorization'] = f'Bearer {token}'
try:
response = requests.get('https://user-api.4pyun.com/rest/2.0/bonus/reward/task/list?%2B9Hnx%2FPy=7bL7p%2FqgoK77uPOi%2B8WjqP%2Fw', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
video_task = [task for task in response_json['payload']['row'] if task['name'] == '看视频得积分'][0]
referer_url = video_task['referer_url']
print(f'[{nickname}] 获取视频任务数据成功')
return referer_url.split('&voucher=')[1]
else:
print(f"[{nickname}] 获取任务_失败{response_json}")
Log(f"[{nickname}] 获取视频任务数据失败:{response_json}")
return None
except requests.RequestException as e:
print(f"[{nickname}] 获取任务_请求异常{e}")
except json.JSONDecodeError:
print(f"[{nickname}] 获取任务_响应不是有效的JSON格式")
except Exception as e:
print(f"[{nickname}] 获取任务_其他异常{e}")
def complete_task(nickname: str, token: str, task_id: str):
headers = wx_headers.copy()
headers['authorization'] = f'Bearer {token}'
headers['content-type'] = 'application/json;charset=utf-8'
try:
data = '{"app_id":"wxa204074068ad40ef","purpose":"reward:motivate:advertising","voucher":"voucher_data"}'.replace('voucher_data', task_id)
encrypt_data = encrypt(data,WX_ENCRYPT)
response = requests.post('https://user-api.4pyun.com/rest/2.0/bonus/reward/task/complete', headers=headers, data=encrypt_data)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
print(f"[{nickname}] 看视频:任务完成")
headers['content-type'] = 'application/x-www-form-urlencoded'
response = requests.get('https://user-api.4pyun.com/rest/2.0/bonus/reward/acquire?%2B9Hnx%2FPy=7bL7p%2FqgoK77uPOi%2B8WjqP%2Fw&6u%2FT5%2Ffp8w%3D%3D=%2Fv%2Fp%2Fej%2BvsH17qPs9L7xqvir%2FqDo7sjk8fTx', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
print(f"[{nickname}] 看视频:任务奖励已领取,{response_json['payload']['message']}")
Log(f"[{nickname}] 看视频:任务奖励已领取,{response_json['payload']['message']}")
elif response_json['message'] == '已达积分领取次数上限':
print(f"[{nickname}] 看视频:积分已领取")
else:
print(f"[{nickname}] 看视频:{response_json['message']}")
Log(f"[{nickname}] 看视频:{response_json['message']}")
else:
print(f"[{nickname}] 看视频任务失败:{response_json}")
Log(f"[{nickname}] 看视频任务失败:{response_json}")
except requests.RequestException as e:
print(f"[{nickname}] 看视频任务_请求异常{e}")
except json.JSONDecodeError:
print(f"[{nickname}] 看视频任务_响应不是有效的JSON格式")
except Exception as e:
print(f"[{nickname}] 看视频任务_其他异常{e}")
def reward_balance(nickname: str, token: str, user_id: str):
headers = wx_headers.copy()
headers['authorization'] = f'Bearer {token}'
try:
response = requests.get(f'https://user-api.4pyun.com/rest/2.0/reward/balance?rP7%2Fz%2BPx7u8%3D={quote(encrypt(user_id,WX_ENCRYPT))}&7%2BnE5cfz8g%3D%3D={quote(encrypt(user_id,WX_ENCRYPT))}&%2Fbb%2F6P7j4erz=pw%3D%3D', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == '1001':
print(f"[{nickname}] 积分余额:{response_json['payload']['balance']}")
Log(f"[{nickname}] 积分余额:{response_json['payload']['balance']}")
else:
print(f"[{nickname}] 获取积分余额_失败{response_json}")
Log(f"[{nickname}] 获取积分余额_失败{response_json}")
except requests.RequestException as e:
print(f"[{nickname}] 获取积分余额_请求异常{e}")
except json.JSONDecodeError:
print(f"[{nickname}] 获取积分余额_响应不是有效的JSON格式")
except Exception as e:
print(f"[{nickname}] 获取积分余额_其他异常{e}")
if __name__ == '__main__':
if 'pp_token' in os.environ:
pp_token = re.split("@|&", os.environ.get("pp_token"))
print(f'查找到{len(pp_token)}个账号')
else:
pp_token = []
print('请填入pp_token变量')
Log('请填入pp_token变量')
try:
if pp_token:
for pp_token_item in pp_token:
get_userdata(pp_token_item)
user_data = get_user_ids_and_tokens()
if user_data:
print(f"配置缓存中读取到{len(user_data)}个账号")
print('*' * 50)
z = 1
for item in user_data:
print('-' * 50)
print(f'登录第{z}个账号>>>>>>')
phone_key = item.get('phone_key')
new_token = item.get('refresh_token')
user_name = item.get('user_name')
user_id = item.get('user_id')
if new_token:
day_sign(user_name,new_token)
for _ in range(2):
voucher = get_task(user_name, new_token)
if voucher:
complete_task(user_name, new_token, voucher)
time.sleep(5)
reward_balance(user_name,new_token,user_id)
time.sleep(3)
Log('-'*30)
z += 1
else:
print("未读取到用户数据,程序退出")
exit(0)
except Exception as e:
print(f'程序异常:{e}')
try:
send_notification_message(title='PP停车') # 发送通知
except Exception as e:
print('推送失败:' + str(e))

View File

@@ -0,0 +1,341 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/invalid/tyqh.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/tyqh.py
# Repo: lksky8/sign-ql
# Path: invalid/tyqh.py
# UploadedAt: 2026-05-23T06:33:20Z
# SHA256: 4c779933563a21d73534721d588cf8fd5aa9e6d6ced3e3b3bb414c91fb576708
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
"""
统一茄皇
作者https://github.com/lksky8/sign-ql
最后更新日期2025-12-11
食用方法抓包url https://api.zhumanito.cn/api/login 请求体json {"wid":"12345678910"}
支持多用户运行
多用户用&或者@隔开
例如账号112345678910 账号2 12345678911
则变量为
export tyqh="12345678910@12345678911"
cron: 11 11 * * *
"""
import requests
import os
import re
import time
# 推送开关True为开启False为关闭
sendnotify = True
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': 'api.zhumanito.cn',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541022) XWEB/16571',
'authorization': '',
'accept': '*/*',
'origin': 'https://h5.zhumanito.cn',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://h5.zhumanito.cn/',
'accept-language': 'zh-CN,zh;q=0.9',
'priority': 'u=1, i',
}
def login(wid):
headers = {
'Host': 'api.zhumanito.cn',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541022) XWEB/16571',
'content-type': 'application/json;charset=UTF-8',
'accept': '*/*',
'origin': 'https://h5.zhumanito.cn',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://h5.zhumanito.cn/',
'accept-language': 'zh-CN,zh;q=0.9',
'priority': 'u=1, i',
}
try:
response = requests.post('https://api.zhumanito.cn/api/login', headers=headers, json={'wid': wid})
response.raise_for_status()
response_json = response.json()
if response_json['code'] == 200 and response_json['msg'] == '成功':
print(f"登录成功用户ID: {wid},拥有番茄:{response_json['data']['user']['fruit_num']}")
Log(f"登录成功用户ID: {wid},拥有番茄:{response_json['data']['user']['fruit_num']}")
if '"seed_stage":0' in response.text:
print(f"未种植番茄")
Log(f"未种植番茄")
time.sleep(1)
seed_tomato(response_json['data']['token'])
return response_json['data']['token']
else:
print(f"用户ID: {wid} 登录失败: {response_json['msg']}")
Log(f"用户ID: {wid} 登录失败: {response_json['msg']}")
return None
except requests.RequestException as e:
print(f"获取用户数据网络请求失败: {e}")
except ValueError as e:
print(f"获取用户数据解析JSON响应失败: {e}")
except KeyError as e:
print(f"获取用户数据JSON响应中缺少键: {e}")
except Exception as e:
print(f"获取用户数据时发生未知错误: {e}")
def get_tomato(user_token):
headers = api_headers.copy()
headers['authorization'] = user_token
try:
response = requests.post('https://api.zhumanito.cn/api/harvest', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == 200 and response_json['msg'] == '成功':
print(f"番茄收获成功,获得番茄:{response_json['data']['fruit_up']}")
Log(f"番茄收获成功,获得番茄:{response_json['data']['fruit_up']}")
seed_tomato(user_token)
else:
print(f"收获番茄失败: {response_json['msg']}")
Log(f"收获番茄失败: {response_json['msg']}")
except requests.RequestException as e:
print(f"收获番茄网络请求失败: {e}")
except ValueError as e:
print(f"收获番茄解析JSON响应失败: {e}")
except KeyError as e:
print(f"收获番茄JSON响应中缺少键: {e}")
except Exception as e:
print(f"收获番茄时发生未知错误: {e}")
def seed_tomato(user_token):
headers = api_headers.copy()
headers['authorization'] = user_token
try:
response = requests.post('https://api.zhumanito.cn/api/seed', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == 200 and response_json['msg'] == '成功':
print(f"番茄种植成功")
Log(f"番茄种植成功")
else:
print(f"番茄种植失败: {response_json['msg']}")
Log(f"番茄种植失败: {response_json['msg']}")
except requests.RequestException as e:
print(f"番茄种植网络请求失败: {e}")
except ValueError as e:
print(f"番茄种植解析JSON响应失败: {e}")
except KeyError as e:
print(f"番茄种植JSON响应中缺少键: {e}")
except Exception as e:
print(f"番茄种植时发生未知错误: {e}")
def get_task(user_token):
headers = api_headers.copy()
headers['authorization'] = user_token
try:
response = requests.get('https://api.zhumanito.cn/api/task?', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == 200 and response_json['msg'] == '成功':
print(f"获取任务成功")
task_lists = []
for task_list in response_json['data']['task']:
task_name = task_list['content']
reward_water = task_list['water_num']
reward_sun = task_list['sun_num']
if task_list['status'] == 1:
print(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 已完成")
else:
print(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 未完成")
task_lists.append({
'task_id': task_list['id'],
'task_name': task_name,
})
return task_lists
else:
print(f"获取任务失败: {response_json['msg']}")
return None
except requests.RequestException as e:
print(f"获取任务数据网络请求失败: {e}")
except ValueError as e:
print(f"获取任务数据解析JSON响应失败: {e}")
except KeyError as e:
print(f"获取任务数据JSON响应中缺少键: {e}")
except Exception as e:
print(f"获取任务数据时发生未知错误: {e}")
def get_task_again(user_token):
headers = api_headers.copy()
headers['authorization'] = user_token
try:
response = requests.get('https://api.zhumanito.cn/api/task?', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == 200 and response_json['msg'] == '成功':
print(f"获取任务成功")
for task_list in response_json['data']['task']:
task_name = task_list['content']
reward_water = task_list['water_num']
reward_sun = task_list['sun_num']
if task_list['status'] == 1:
print(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 已完成")
Log(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 已完成")
else:
print(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 未完成")
Log(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 未完成")
else:
print(f"获取任务失败: {response_json['msg']}")
Log(f"获取任务失败: {response_json['msg']}")
return None
except requests.RequestException as e:
print(f"获取任务数据网络请求失败: {e}")
except ValueError as e:
print(f"获取任务数据解析JSON响应失败: {e}")
except KeyError as e:
print(f"获取任务数据JSON响应中缺少键: {e}")
except Exception as e:
print(f"获取任务数据时发生未知错误: {e}")
def task_complete(user_token, task_id,task_name):
headers = api_headers.copy()
headers['authorization'] = user_token
headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
try:
response = requests.post('https://api.zhumanito.cn/api/task/complete', headers=headers, data=f'task_id={task_id}&')
response.raise_for_status()
response_json = response.json()
if response_json['code'] == 200 and response_json['msg'] == '成功':
for task_status in response_json['data']['task']:
if task_status['task_id'] == task_id and task_status['status']:
print(f"任务: {task_name} 成功,剩余水: {response_json['data']['user']['water_num']}, 剩余阳光: {response_json['data']['user']['sun_num']}")
else:
print(f"任务: {task_name} 失败: {response_json['msg']}")
except requests.RequestException as e:
print(f"完成任务: {task_name} 时网络请求失败: {e}")
except ValueError as e:
print(f"完成任务: {task_name} 时解析JSON响应失败: {e}")
except KeyError as e:
print(f"完成任务: {task_name} 时JSON响应中缺少键: {e}")
except Exception as e:
print(f"完成任务: {task_name} 时发生未知错误: {e}")
def water(user_token):
headers = api_headers.copy()
headers['authorization'] = user_token
headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
try:
response = requests.post('https://api.zhumanito.cn/api/water', headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['code'] == 200 and response_json['msg'] == '成功':
print(f"浇水成功,剩余水: {response_json['data']['user']['water_num']}, 剩余阳光: {response_json['data']['user']['sun_num']}")
Log(f"浇水成功,剩余水: {response_json['data']['user']['water_num']}, 剩余阳光: {response_json['data']['user']['sun_num']}")
return True
elif response_json['code'] == 10006 and response_json['msg'] == '能量值不足了,可以坚持做任务获取哦~':
print("不够水了")
Log("不够水了")
return False
elif response_json['code'] == 10007 and response_json['msg'] == '今日浇水已达到上限,请明天再来哦~':
print("今日浇水次数已达到上限")
Log("今日浇水次数已达到上限")
return False
elif response_json['code'] == 10008 and response_json['msg'] == '已成熟,不必浇灌':
print("番茄已成熟,自动收获")
Log("番茄已成熟,自动收获")
get_tomato(user_token)
return True
else:
print(f"浇水失败: {response_json['msg']}")
return False
except requests.RequestException as e:
print(f"浇水时网络请求失败: {e}")
except ValueError as e:
print(f"浇水时解析JSON响应失败: {e}")
except KeyError as e:
print(f"浇水时JSON响应中缺少键: {e}")
except Exception as e:
print(f"浇水时发生未知错误: {e}")
finally:
time.sleep(3)
def view_page(wid):
headers = {
'Host': 'api.zhumanito.cn',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'sec-fetch-site': 'same-site',
'sec-fetch-dest': 'document',
'accept-language': 'zh-CN,zh-Hans;q=0.9',
'sec-fetch-mode': 'navigate',
'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 MicroMessenger/8.0.64(0x1800402b) NetType/WIFI Language/zh_CN miniProgram/wx532ecb3bdaaf92f9',
'referer': 'https://h5.zhumanito.cn/',
}
requests.get(f'https://api.zhumanito.cn/?wid={wid}', headers=headers)
if __name__ == '__main__':
if 'tyqh' in os.environ:
tyqh_session = re.split("@|&", os.environ.get("tyqh"))
print(f'查找到{len(tyqh_session)}个账号')
else:
tyqh_session = []
if tyqh_session:
z = 1
for wid in tyqh_session:
print('*'*50)
print(f'开始处理第{z}个账号')
Log(f'处理第{z}个账号:')
print('-' * 30)
token = login(wid)
print('-' * 30)
all_task = get_task(token)
print('-'*30)
print('开始做任务')
for task in all_task:
if task['task_name'] == '浏览指定页面':
view_page(wid)
print('任务: 浏览指定页面 成功')
time.sleep(3)
continue
task_complete(token, task['task_id'], task['task_name'])
time.sleep(3)
print('-' * 30)
while water(token):
pass
get_task_again(token)
Log('\n')
z += 1
time.sleep(10)
else:
print('请填入tyqh变量')
Log('请填入tyqh变量')
if sendnotify:
try:
send_notification_message(title='统一茄皇') # 发送通知
except Exception as e:
print('推送失败:' + str(e))

View File

@@ -0,0 +1,584 @@
// # Source: https://github.com/DearSong15/ql-scripts/blob/main/zsp_video.js
// # Raw: https://raw.githubusercontent.com/DearSong15/ql-scripts/main/zsp_video.js
// # Repo: DearSong15/ql-scripts
// # Path: zsp_video.js
// # UploadedAt: 2026-05-11T15:03:30Z
// # SHA256: 960b2e28799c40a00eb4bd75dcda1e61b3ab747374716073995c75053c3083ee
// # Category: web版/账密
// # Evidence: web/H5关键词 + username/password/login
//
//走个码吧,谢谢兄弟们了
//后台注册地址https://zsp.99panel.top/#/register?inviteCode=lzwbaleD
//前台https://a.zsp55.app/
//变量格式:备注#SecretId#SecretKey#deviceld
const ENV_NAME = "中视频";
const USER_AGENT = "Mozilla/5.0 (Linux; Android 15; 23013RK75C Build/AQ3A.250226.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.260 Mobile Safari/537.36 (Immersed/39.42857) Html5Plus/1.0";
const BASE_URL = "https://x1.zsptv.online";
// 工具函数
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// HTTP请求函数
async function httpRequest(options) {
return new Promise((resolve, reject) => {
const url = new URL(options.url);
const https = url.protocol === 'https:' ? require('https') : require('http');
const req = https.request({
hostname: url.hostname,
port: url.port || (url.protocol === 'https:' ? 443 : 80),
path: url.pathname + url.search,
method: options.method || 'GET',
headers: options.headers || {}
}, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
// 调试:记录响应
if (res.statusCode === 403) {
console.log(`🔍 响应体: ${data.substring(0, 200)}...`);
}
resolve({
statusCode: res.statusCode,
headers: res.headers,
body: data
});
});
});
req.on('error', (err) => {
reject(err);
});
if (options.body) {
req.write(options.body);
}
req.end();
});
}
// Unicode解码函数
function decodeUnicode(str) {
if (!str) return '';
return str.replace(/\\u[\dA-F]{4}/gi,
match => String.fromCharCode(parseInt(match.replace(/\\u/g, ''), 16)));
}
// 主函数
async function main() {
console.log(`🔔 脚本开始运行,时间: ${new Date().toLocaleString()}\n`);
// 读取环境变量
const accounts = loadAccounts();
if (accounts.length === 0) {
console.log("❌ 未找到有效的账号配置,请检查环境变量格式!");
return;
}
console.log(`✅ 找到 ${accounts.length} 个账号\n`);
// 遍历所有账号
for (let i = 0; i < accounts.length; i++) {
const account = accounts[i];
console.log(`\n📱 开始处理账号 ${i+1}: ${account.remark}`);
console.log("=".repeat(30));
try {
await processAccount(account);
} catch (error) {
console.log(`❌ 处理账号 ${account.remark} 时出错: ${error.message}`);
}
// 账号间延迟
if (i < accounts.length - 1) {
console.log("\n⏳ 等待5秒后处理下一个账号...");
await wait(5000);
}
}
console.log(`\n🎉 所有账号处理完成!`);
}
// 加载账号信息
function loadAccounts() {
const accounts = [];
// 尝试从不同环境变量名称读取
const envNames = ['ZSP', 'AD_WATCH_ACCOUNTS'];
let envValue = '';
for (const envName of envNames) {
if (process.env[envName]) {
envValue = process.env[envName];
console.log(`📋 从环境变量 ${envName} 读取配置`);
break;
}
}
if (!envValue) {
console.log("⚠️ 请设置环境变量 ZSP 或 AD_WATCH_ACCOUNTS");
return accounts;
}
const accountStrs = envValue.split("\n").filter(str => str.trim());
for (const str of accountStrs) {
const parts = str.split("#");
if (parts.length >= 4) {
accounts.push({
remark: parts[0] || "未命名账号",
secretId: parts[1],
secretKey: parts[2],
deviceId: parts[3]
});
console.log(`✅ 加载账号: ${parts[0] || "未命名账号"}`);
} else {
console.log(`⚠️ 忽略格式错误的环境变量: ${str}`);
}
}
return accounts;
}
// 处理单个账号
async function processAccount(account) {
// 1. 登录获取token
const token = await login(account);
if (!token) {
console.log("❌ 登录失败,跳过此账号");
return;
}
console.log(`✅ 登录成功token获取完成`);
// 2. 检测并执行签到
const signed = await checkAndSign(token, account);
if (!signed) {
console.log("❌ 签到失败,跳过广告任务");
return;
}
console.log(`\n📺 开始执行广告观看任务`);
console.log("-".repeat(30));
let successCount = 0;
let failCount = 0;
let totalReward = 0;
let consecutiveErrors = 0;
const maxAds = 50; // 最多执行50次广告任务
for (let adCount = 0; adCount < maxAds; adCount++) {
console.log(`\n🔄 第 ${adCount + 1}/${maxAds} 次广告任务`);
// 如果连续出现3次错误重新登录获取新token
if (consecutiveErrors >= 3) {
console.log("⚠️ 连续3次错误尝试重新登录...");
const newToken = await login(account);
if (newToken) {
token = newToken;
console.log("✅ 重新登录成功,继续任务");
consecutiveErrors = 0;
} else {
console.log("❌ 重新登录失败,跳过此账号");
break;
}
}
try {
// 获取广告信息
const adInfo = await getNextAd(token, account);
if (!adInfo) {
console.log(` ⚠️ 获取广告失败`);
failCount++;
consecutiveErrors++;
await wait(3000);
continue;
}
console.log(` 📱 广告标题: ${adInfo.title}`);
console.log(` ⏱️ 需要观看: ${adInfo.duration}`);
console.log(` 🪙 预期奖励: ${adInfo.reward || 0}`);
// 开始播放广告
console.log(` ▶️ 开始播放广告...`);
const playResult = await claimReward(token, account, adInfo.id, adInfo.duration);
if (playResult && playResult.success) {
console.log(` ✅ 广告观看成功!`);
console.log(` 💰 获得奖励: ${playResult.reward || 0}`);
successCount++;
totalReward += parseInt(playResult.reward) || 0;
consecutiveErrors = 0; // 重置错误计数
// 任务间延迟 (避免请求过快)
if (adCount < maxAds - 1) {
const randomDelay = Math.floor(Math.random() * 3000) + 3000; // 3-6秒随机延迟
console.log(` ⏳ 等待${Math.round(randomDelay/1000)}秒后处理下一个广告...`);
await wait(randomDelay);
}
} else {
console.log(` ❌ 广告观看失败`);
failCount++;
consecutiveErrors++;
await wait(3000);
}
} catch (error) {
console.log(` ❌ 广告任务出错: ${error.message}`);
failCount++;
consecutiveErrors++;
await wait(3000);
}
}
console.log("\n" + "=".repeat(30));
console.log(`📊 任务完成统计:`);
console.log(` ✅ 成功: ${successCount}`);
console.log(` ❌ 失败: ${failCount}`);
console.log(` 💰 总计奖励: ${totalReward}`);
console.log(` 📈 成功率: ${((successCount/maxAds)*100).toFixed(1)}%`);
}
// 登录接口
async function login(account) {
const url = `${BASE_URL}/api/app/v1/auth/secretKeyLogin`;
const body = {
secretId: account.secretId,
secretKey: account.secretKey
};
const headers = {
"Accept": "*/*",
"User-Agent": USER_AGENT,
"app-device": JSON.stringify({
"id": account.deviceId,
"brand": "xiaomi",
"model": "23013RK75C",
"platform": "android",
"system": "Android 15"
}),
"Content-Type": "application/json",
"Host": "x1.zsptv.online"
};
try {
const response = await httpRequest({
url: url,
method: "POST",
headers: headers,
body: JSON.stringify(body)
});
if (response.statusCode !== 200) {
console.log(`❌ 登录请求失败,状态码: ${response.statusCode}`);
return null;
}
const data = JSON.parse(response.body);
if (data.code === 0 && data.data && data.data.token) {
return data.data.token;
} else {
console.log(`❌ 登录失败: ${data.message || "未知错误"}`);
return null;
}
} catch (error) {
console.log(`❌ 登录请求失败: ${error.message}`);
return null;
}
}
// 检测并执行签到
async function checkAndSign(token, account) {
const url = `${BASE_URL}/api/app/v1/device/userSign`;
const headers = {
"Accept": "*/*",
"User-Agent": USER_AGENT,
"Authorization": `Bearer ${token}`,
"app-device": JSON.stringify({
"id": account.deviceId,
"brand": "xiaomi",
"model": "23013RK75C",
"platform": "android",
"system": "Android 15"
}),
"Content-Type": "application/json",
"Host": "x1.zsptv.online"
};
try {
const response = await httpRequest({
url: url,
method: "POST",
headers: headers,
body: "{}"
});
if (response.statusCode !== 200) {
console.log(`❌ 签到请求失败,状态码: ${response.statusCode}`);
return false;
}
const data = JSON.parse(response.body);
if (data.code === 0) {
const message = decodeUnicode(data.message);
console.log(`✅ 签到结果: ${message}`);
if (data.data) {
console.log(` 🪙 获得签到金币: ${data.data.qiandao_money || 0}`);
console.log(` 📅 连续签到天数: ${data.data.continuousDays || 1}`);
}
return true;
} else {
const errorMsg = decodeUnicode(data.message || "未知错误");
console.log(`❌ 签到失败: ${errorMsg}`);
// 如果已签到也返回true继续执行广告任务
if (errorMsg && errorMsg.includes("已签到")) {
console.log(` 今日已签到,继续执行广告任务`);
return true;
}
return false;
}
} catch (error) {
console.log(`❌ 签到请求失败: ${error.message}`);
return false;
}
}
// 获取下一个广告
async function getNextAd(token, account) {
const url = `${BASE_URL}/api/app/v1/ad/next`;
const headers = {
"Accept": "*/*",
"User-Agent": USER_AGENT,
"Authorization": `Bearer ${token}`,
"app-device": JSON.stringify({
"id": account.deviceId,
"brand": "xiaomi",
"model": "23013RK75C",
"platform": "android",
"system": "Android 15"
}),
"Content-Type": "application/json",
"Host": "x1.zsptv.online"
};
try {
const response = await httpRequest({
url: url,
method: "GET",
headers: headers
});
if (response.statusCode !== 200) {
console.log(` ❌ 获取广告失败,状态码: ${response.statusCode}`);
if (response.body) {
const errorData = JSON.parse(response.body);
console.log(` 🔍 错误信息: ${errorData.message || "未知错误"}`);
}
return null;
}
const data = JSON.parse(response.body);
if (data.code === 0 && data.data && data.data.result) {
const ad = data.data.result;
return {
id: ad.id,
title: decodeUnicode(ad.title),
description: decodeUnicode(ad.description),
duration: parseInt(ad.video?.duration || 30), // 默认30秒
videoUrl: ad.video?.url || "",
playUrl: ad.video?.play_url || "",
reward: ad.reward
};
} else {
const errorMsg = decodeUnicode(data.message || "未知错误");
console.log(` ❌ 获取广告失败: ${errorMsg}`);
return null;
}
} catch (error) {
console.log(` ❌ 获取广告请求失败: ${error.message}`);
return null;
}
}
// 观看广告并获取奖励(整合播放和结束确认)
async function claimReward(token, account, adId, duration) {
const startTime = new Date().toISOString();
// 1. 开始播放广告
console.log(` 📅 播放开始时间: ${startTime}`);
const playResult = await startVideoPlay(token, account, adId, startTime);
if (!playResult || !playResult.playRecordId) {
console.log(` ❌ 广告播放开始失败`);
return { success: false };
}
console.log(` ✅ 播放开始成功! 记录ID: ${playResult.playRecordId}`);
console.log(` 💰 初始奖励: ${playResult.initialReward || 0}`);
// 2. 等待广告播放时间
const waitTime = duration * 1000;
console.log(` ⌛ 广告播放中,等待 ${duration} 秒...`);
await wait(waitTime);
// 3. 广告播放结束确认
console.log(` ⏹️ 广告播放完成,确认结束...`);
const endResult = await endVideoPlay(token, account, playResult.playRecordId);
if (endResult.success) {
console.log(` 🎉 广告观看完整流程完成!`);
return {
success: true,
reward: playResult.reward || 0,
playRecordId: playResult.playRecordId
};
} else {
console.log(` ⚠️ 广告观看完成,但结束确认失败`);
// 即使结束确认失败,也视为成功(因为已经播放完成)
return {
success: true,
reward: playResult.reward || 0,
playRecordId: playResult.playRecordId
};
}
}
// 开始播放广告
async function startVideoPlay(token, account, adId, playTime) {
const url = `${BASE_URL}/api/app/v1/ad/video/play`;
const body = {
clientIp: "",
deviceInfo: {
deviceId: account.deviceId,
platform: "android"
},
id: adId.toString(),
playTime: playTime
};
const headers = {
"Accept": "*/*",
"User-Agent": USER_AGENT,
"Authorization": `Bearer ${token}`,
"app-device": JSON.stringify({
"id": account.deviceId,
"brand": "xiaomi",
"model": "23013RK75C",
"platform": "android",
"system": "Android 15"
}),
"Content-Type": "application/json",
"Host": "x1.zsptv.online"
};
try {
const response = await httpRequest({
url: url,
method: "POST",
headers: headers,
body: JSON.stringify(body)
});
if (response.statusCode !== 200) {
console.log(` ❌ 开始播放广告失败,状态码: ${response.statusCode}`);
return null;
}
const data = JSON.parse(response.body);
if (data.code === 0 && data.data) {
return {
playRecordId: data.data.id,
initialReward: data.data.reward || 0,
reward: data.data.reward || 0
};
} else {
console.log(` ❌ 开始播放广告失败: ${data.message || "未知错误"}`);
return null;
}
} catch (error) {
console.log(` ❌ 开始播放广告请求失败: ${error.message}`);
return null;
}
}
// 结束广告播放
async function endVideoPlay(token, account, playRecordId) {
const url = `${BASE_URL}/api/app/v1/ad/video/ended`;
const endTime = new Date().toISOString();
const body = {
clientIp: "",
deviceInfo: {
deviceId: account.deviceId,
platform: "android"
},
id: playRecordId.toString(),
playTime: endTime
};
const headers = {
"Accept": "*/*",
"User-Agent": USER_AGENT,
"Authorization": `Bearer ${token}`,
"app-device": JSON.stringify({
"id": account.deviceId,
"brand": "xiaomi",
"model": "23013RK75C",
"platform": "android",
"system": "Android 15"
}),
"Content-Type": "application/json",
"Host": "x1.zsptv.online"
};
try {
const response = await httpRequest({
url: url,
method: "POST",
headers: headers,
body: JSON.stringify(body)
});
if (response.statusCode !== 200) {
console.log(` ⚠️ 广告结束确认失败,状态码: ${response.statusCode}`);
// 即使结束确认失败也返回成功避免403错误导致任务中断
return { success: true };
}
const data = JSON.parse(response.body);
if (data.code === 0) {
return { success: true };
} else {
console.log(` ⚠️ 广告结束确认返回异常: ${data.message || "未知错误"}`);
return { success: false };
}
} catch (error) {
console.log(` ⚠️ 广告结束确认请求失败: ${error.message}`);
return { success: false };
}
}
// 执行主函数
if (require.main === module) {
main().catch(console.error);
}

View File

@@ -0,0 +1,586 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/yxw_appsign.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/yxw_appsign.py
# Repo: lksky8/sign-ql
# Path: yxw_appsign.py
# UploadedAt: 2025-09-28T06:42:50Z
# SHA256: c6d91db16e3a84bf5dfc1e2c7d6cb38fb3f6d38f5829d7f496ba308fa7a77a10
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
'''
作者https://github.com/lksky8/sign-ql/
日期2025-9-28
网站游侠网APP签到
功能:签到、抽奖,金币可换现金买游戏,配合金币脚本使用可获得更多金币
变量yxwlogin='账号&密码' 多个账号用@或者#分割
定时:一天一次
cron45 8 * * *
'''
from json import JSONDecodeError
import requests
import hashlib
import time
import json
import os
import re
import datetime
if 'yxwlogin' in os.environ:
yxwlogin = re.split("@|#",os.environ.get("yxwlogin"))
print(f'查找到{len(yxwlogin)}个账号')
else:
yxwlogin = []
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': 'api3.ali213.net',
'accept': '*/*',
'user-agent': 'ali213app',
'accept-language': 'zh-Hans-CN;q=1',
}
def get_user_ids_and_tokens(file_path='youxia_data.json'):
try:
# 1. 读取JSON文件
with open(file_path, 'r', encoding='utf-8') as f:
phone_data = json.load(f)
# 2. 遍历每个手机号
results = []
for phone_key, data in phone_data.items():
user_name = data.get('nickname')
user_token = data.get('token')
if user_name and user_token: # 确保userId和token存在
results.append({
'phone_key': phone_key,
'user_name': user_name,
'token': user_token
})
# print(f"手机号: {phone_key}, userId: {user_id}, token: {token}")
return results
except FileNotFoundError:
print(f"文件 {file_path} 不存在!")
return []
except json.JSONDecodeError:
print(f"文件 {file_path} 格式错误!")
return []
def save_or_update_phone_data(phone_key, new_data, file_path='youxia_data.json'):
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
existing_data = json.load(f)
else:
existing_data = {}
if phone_key in existing_data:
existing_data[phone_key].update(new_data) # 合并新旧数据
print(f"账号 [{phone_key}] 数据已更新!")
else:
existing_data[phone_key] = new_data # 新增数据
print(f"账号 [{phone_key}] 新增数据!")
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(existing_data, f, ensure_ascii=False, indent=4)
def get_userdata(u):
phone_user = u.split('&')[0]
phone_password = u.split('&')[1]
try:
with open('youxia_data.json', 'r', encoding='utf-8') as f:
cache_data = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
cache_data = {}
if phone_user not in cache_data:
print(f'账号 {phone_user} 不存在于缓存中,尝试初始化数据')
login(phone_user, phone_password)
else:
print(f'账号 {phone_user} 已存在于缓存中,直接读取数据')
def md5_encode(string):
md5 = hashlib.md5()
md5.update(string.encode('utf-8'))
return md5.hexdigest()
def check_token(phone,token): # 检查token是否有效并返回新的token
try:
response = requests.get(f'https://api3.ali213.net/feedearn/checktoken?token={token}', headers=api_headers)
response_json = response.json()
if response_json['status'] == 1:
print(f'账号 [{phone}] token 有效')
save_or_update_phone_data(phone, {'token': response_json['token']})
return response_json['token']
else:
print(f'账号 [{phone}] token 无效')
log(f'账号 [{phone}] token 无效\n')
return None
except JSONDecodeError as e:
print(f'账号 [{phone}] 检查token失败: {e}')
except Exception as e:
print(f'账号 [{phone}] 检查token失败: {e}')
def token_exchanger(token):
headers = {
'Host': 'api3.ali213.net',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'sec-fetch-site': 'none',
'sec-fetch-mode': 'navigate',
'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 ali213app',
'accept-language': 'zh-CN,zh-Hans;q=0.9',
'sec-fetch-dest': 'document',
}
response = requests.get('https://api3.ali213.net/feedearn/tokenexchanger?token='+token+'&redirectUrl=https://api3.ali213.net/feedearn/luckybox',headers=headers)
print(response.text)
def userinfo(phone,token):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/userbaseinfo?token={token}', headers=api_headers)
response_json = response.json()
if '"status":0' in response.text:
print(f'账号 [{phone}] 登录过期,需要重新登录')
log(f'账号 [{phone}] 登录过期,需要重新登录\n')
else:
experience = response_json['experience']
nextgrade_experience = response_json['nextgrade']['experience']
nextgrade_experience_coin = response_json['nextgrade']['coin']
money = response_json['money'] / 100
# 计算百分比
percent = (experience / nextgrade_experience) * 100
print(f'账号 [{response_json["nickname"]}] Lv.{response_json["grade"]} 目前金币:{response_json["coins"]} 现金:{money} 剩余{percent:.2f}% 即可升级获得{nextgrade_experience_coin}金币')
log(f'账号 [{response_json["nickname"]}] Lv.{response_json["grade"]} 目前金币:{response_json["coins"]} 现金:{money} 剩余{percent:.2f}% 即可升级获得{nextgrade_experience_coin}金币\n')
except requests.exceptions.RequestException as e:
print(f'账号 [{phone}] 获取用户信息失败: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{phone}] 获取用户信息失败: {e}')
except Exception as e:
print(f'账号 [{phone}] 获取用户信息失败: {e}')
def check_sign(name,token):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/signing?action=set&token={token}', headers=api_headers)
if r'\u7528\u6237\u672a\u767b\u5f55\u6216\u767b\u5f55\u5df2\u8d85\u65f6' in response.text:
print(f'账号 [{name}] 登录过期,需要重新登录')
else:
response_json = response.json()
if response_json['data']['status'] == 1:
print(f'账号 [{name}] {response_json["data"]["msg"]},获得金币:{response_json["data"]["coins"]}')
log(f'账号 [{name}] {response_json["data"]["msg"]},获得金币:{response_json["data"]["coins"]}\n')
elif response_json['data']['status'] == 0:
print(f'账号 [{name}] {response_json["data"]["msg"]}')
log(f'账号 [{name}] {response_json["data"]["msg"]}\n')
else:
print(f'账号 [{name}] 签到失败:{response.text}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 签到失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 签到失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 签到失败[其他]: {e}')
def login(phone, password):
headers = {
'Host': 'i.ali213.net',
'accept': '*/*',
'user-agent': 'ali213app',
'accept-language': 'zh-Hans-CN;q=1',
}
time10 = str(int(time.time()))
params = {
'action': 'login',
'from': 'feedearn',
'passwd': password,
'signature': md5_encode(f'username-{phone}-time-{time10}-passwd-{password}-from-feedearn-action-loginBGg)K6ng4?&x9sCIuO%C2%' + '{@TJ?fnFJ,bZKy/[/EWnw9UsC$@1'),
'time': time10,
'username': phone,
}
try:
response = requests.get('https://i.ali213.net/api.html', params=params, headers=headers)
response.raise_for_status()
response_json = response.json()
if response_json['status'] == 1 and response_json['msg'] == '登录成功':
print('登录成功: ' + response_json['data']['userinfo']['nickname'])
log(f'账号 [{response_json["data"]["userinfo"]["nickname"]}] 登录成功\n')
new_data = {
'uid': response_json['data']['userinfo']['uid'],
'nickname': response_json['data']['userinfo']['nickname'],
'token': response_json['data']['token'],
}
save_or_update_phone_data(phone, new_data)
elif response_json['status'] == 0:
print('登录失败: ' + response_json['msg'])
log(f'登录失败: {response_json["msg"]}\n')
else:
print('登录失败: ' + response_json)
except requests.exceptions.RequestException as e:
print(e)
def newusercheck(name, token):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/newusercheck?token={token}', headers=api_headers)
response_json = response.json()
if response_json['status'] == 1 and response_json['msg'] == '您是老用户,所以还是跳老活动页面吧' or response_json['msg'] == '您参与完新用户活动了,现在去老活动页面吧':
# print(f'账号 [{name}] 老用户了,去周签')
olduser_sign(name, token)
elif response_json['status'] == 3 and response_json['msg'] == '您是最新用户,可以跳最新活动页面了':
# print(f'账号 [{name}] 新用户,去首月福利签到')
newuser_sign(name, token)
else:
print(f'账号 [{name}] 未知状态: {response_json}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 检查新用户失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 检查新用户失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 检查新用户失败[其他]: {e}')
def newuser_sign(name, token):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/newuseractivitysign?token={token}', headers=api_headers)
response_json = response.json()
if response_json['status'] == 1:
print(f'账号 [{name}] 新用户福利: {response_json["msg"]}')
log(f'账号 [{name}] 新用户福利: {response_json["msg"]}\n')
newuser_monthsigncheck(name, token)
elif response_json['status'] == 0:
print(f'账号 [{name}] 新用户福利: {response_json["msg"]}')
log(f'账号 [{name}] 新用户福利: {response_json["msg"]}\n')
newuser_monthsigncheck(name, token)
else:
print(f'账号 [{name}] 新用户福利:签到失败 {response.text}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 新用户福利签到失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 新用户福利签到失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 新用户福利签到失败[其他]: {e}')
def newuser_monthsigncheck(name, token):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/newusermonthactivity?token={token}', headers=api_headers)
response_json = response.json()
if response_json['status'] == 1:
prize = response_json['data']['prize']
today = datetime.datetime.now().strftime('%Y-%m-%d')
for item in prize:
if item['date'] == today:
print(f"账号 [{name}] 【新用户首月福利】 今天({today})的签到信息:")
log(f'账号 [{name}] 【新用户首月福利】 今天({today})的签到信息:\n')
newuser_kjl(name, token, item['con'], item['tit'], item['typeid'])
break
else:
print('没有获取到当天签到数据')
log('没有获取到当天签到数据\n')
month_day = response_json["data"]["qztime"].split(',')
print(f'账号 [{name}] 【新用户首月福利】已签到: {response_json["data"]["wcday"]}天,已领取{response_json["data"]["totalcoin"]}金币')
log(f'账号 [{name}] 【新用户首月福利】已签到: {response_json["data"]["wcday"]}天,已领取{response_json["data"]["totalcoin"]}金币\n')
print(f'账号 [{name}] 【新用户首月福利】从{month_day[0]}开始,到{month_day[1]}结束。记得绑定Steam账号才能领取奖励')
elif response_json['status'] == 0:
print(f'账号 [{name}] 新用户月签查询失败: {response_json["msg"]}')
log(f'账号 [{name}] 新用户月签查询失败: {response_json["msg"]}\n')
else:
print(f'账号 [{name}] 新用户月签查询失败: {response.text}')
log(f'账号 [{name}] 新用户月签查询失败: {response.text}\n')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 新用户月签查询失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 新用户月签查询失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 新用户月签查询失败[其他]: {e}')
def olduser_sign(name, token):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/olduseractivitysign?token={token}', headers=api_headers)
response_json = response.json()
if response_json['status'] == 1:
print(f'账号 [{name}] 老用户福利: {response_json["msg"]}')
log(f'账号 [{name}] 老用户福利: {response_json["msg"]}\n')
olduser_weeksigncheck(name, user_token)
elif response_json['status'] == 0:
print(f'账号 [{name}] 老用户福利: {response_json["msg"]}')
log(f'账号 [{name}] 老用户福利: {response_json["msg"]}\n')
olduser_weeksigncheck(name, user_token)
else:
print(f'账号 [{name}] 老用户福利:签到失败 {response.text}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 老用户福利签到失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 老用户福利签到失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 老用户福利签到失败[其他]: {e}')
def olduser_weeksigncheck(name, token):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/oldusermonthactivity?token={token}', headers=api_headers)
response_json = response.json()
if response_json['status'] == 1:
print(f'账号 [{name}] 【第{response_json["data"]["prizingno"]}阶段】已达成连续签到: {response_json["data"]["signday"]}')
log(f'账号 [{name}] 【第{response_json["data"]["prizingno"]}阶段】已达成连续签到: {response_json["data"]["signday"]}\n')
if response_json["data"]["signday"] == 7:
print(f'账号 [{name}] 第七天了,可领取奖励')
time.sleep(5)
kjl(name, token)
elif response_json['status'] == 0:
print(f'账号 [{name}] 周签查询失败: {response_json["msg"]}')
log(f'账号 [{name}] 周签查询失败: {response_json["msg"]}\n')
else:
print(f'账号 [{name}] 周签查询失败: {response.text}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 周签查询失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 周签查询失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 周签查询失败[其他]: {e}')
def kjl(name, token):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/olduseractivityprizing?token={token}', headers=api_headers)
response_json = response.json()
if response_json['status'] == 1 and response_json['msg'] == '恭喜中奖':
print(f'账号 [{name}] 已领取奖励: 《{response_json["data"]["name"]}')
log(f'账号 [{name}] 已领取奖励: 《{response_json["data"]["name"]}\n')
elif response_json['status'] == 0:
print(f'账号 [{name}] 领取奖励失败: {response_json["msg"]}')
log(f'账号 [{name}] 领取奖励失败: {response_json["msg"]}\n')
else:
print(f'账号 [{name}] 领取奖励失败: {response.text}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 领取奖励失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 领取奖励失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 领取奖励失败[其他]: {e}')
def newuser_kjl(name,token,coin,mem,typeid):
try:
params = {
"coin": coin,
"mem": mem,
"token": token,
"typeid": str(typeid)
}
response = requests.post("https://api3.ali213.net/feedearn/newuserprizing", params=params, headers=api_headers)
response_json = response.json()
if response_json['status'] == 1 and response_json['msg'] == '成功':
print(f'账号 [{name}] 【新用户首月福利】已领取奖励: {coin}')
log(f'账号 [{name}] 【新用户首月福利】已领取奖励: {coin}\n')
elif response_json['status'] == 0:
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败: {response_json["msg"]}')
log(f'账号 [{name}] 【新用户首月福利】领取奖励失败: {response_json["msg"]}\n')
else:
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败: {response.text}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败[其他]: {e}')
def luckbox_cookies(phone, token):
headers = {
'Host': 'api3.ali213.net',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'sec-fetch-site': 'none',
'sec-fetch-mode': 'navigate',
'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 ali213app',
'accept-language': 'zh-CN,zh-Hans;q=0.9',
'sec-fetch-dest': 'document',
}
try:
response = requests.get(f'https://api3.ali213.net/feedearn/tokenexchanger?token={token}&redirectUrl=https://api3.ali213.net/feedearn/luckybox', headers=headers)
api3AliSSO = response.cookies.get_dict()
if api3AliSSO:
print(f'账号 [{phone}] 获取神秘宝箱cookies成功')
save_or_update_phone_data(phone, api3AliSSO)
else:
print(f'账号 [{phone}] 获取神秘宝箱cookies失败')
log(f'账号 [{phone}] 获取神秘宝箱cookies失败\n')
except requests.exceptions.RequestException as e:
print(f'账号 [{phone}] 获取神秘宝箱cookies失败[请求]: {e}')
except Exception as e:
print(f'账号 [{phone}] 获取神秘宝箱cookies失败[其他]: {e}')
def usermission(name,token):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/usermission?token={token}', headers=api_headers)
response_json = response.json()
if response_json['status'] == 1:
print(f'账号 [{name}] 任务查询成功')
common_mission = response_json['data']['common']
if common_mission:
for mission in common_mission:
mission_name = mission['title']
mission_experience = mission['experience']
mission_total = mission['total']
mission_prize = mission['prize']
print(f'任务名称: {mission_name}, 每日次数: {mission_total}, 奖励经验: {mission_experience}, {mission_prize}')
elif response_json['status'] == 0:
print(f'账号 [{name}] 任务查询失败: {response_json["msg"]}')
else:
print(f'账号 [{name}] 任务查询失败: {response.text}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 任务查询失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 任务查询失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 任务查询失败[其他]: {e}')
def share(name,token,entity_id):
try:
response = requests.get(f'https://api3.ali213.net/feedearn/sharearticle?channelID=1&entityID={entity_id}&token={token}', headers=api_headers)
response_json = response.json()
if response_json['status'] == 1:
print(f'账号 [{name}] 分享成功,奖励: {response_json["msg"]}金币')
elif response_json['status'] == 0:
print(f'账号 [{name}] 分享失败: {response_json["msg"]}')
else:
print(f'账号 [{name}] 分享失败: {response.text}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 分享失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 分享失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 分享失败[其他]: {e}')
def get_recommendList():
try:
response = requests.get('https://newapi.ali213.net/app/v1/recommendList?confirmNo=0&keyword=&lastId=&navId=2&pageNo=1&pageNum=10', headers=api_headers)
response_json = response.json()
if response_json['code'] == 200:
print('推荐列表数据获取成功')
data = response_json['data']['list']
integer_jump_urls = []
for item in data:
if isinstance(item.get('jumpUrl'), int):
integer_jump_urls.append(item['jumpUrl'])
return integer_jump_urls
else:
print('推荐列表数据获取失败')
log(f'推荐列表数据获取失败\n')
return []
except requests.exceptions.RequestException as e:
print(f'推荐列表数据获取失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'推荐列表数据获取失败[JSON]: {e}')
except Exception as e:
print(f'推荐列表数据获取失败[其他]: {e}')
def get_square():
try:
response = requests.get('https://club.ali213.net/application/forum/square?id=0', headers=api_headers)
response_json = response.json()
if response_json['code'] == 111 and response_json['msg'] == 'success':
print('BBS社区数据获取成功')
threadList = response.json()['data']['threadList']
thread_id = []
for item in threadList:
thread_id.append(item['id'])
return thread_id
else:
print('BBS社区数据获取失败')
log(f'BBS社区数据获取失败\n')
return []
except requests.exceptions.RequestException as e:
print(f'BBS社区数据获取失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'BBS社区数据获取失败[JSON]: {e}')
except Exception as e:
print(f'BBS社区数据获取失败[其他]: {e}')
def readingreward(name,token,threadid):
try:
response = requests.get(f'https://club.ali213.net/application/thread/readingreward?threadid={threadid}&token={token}', headers=api_headers)
response_json = response.json()
if response_json['code'] == 111 and response_json['msg'] == 'success':
print(f'账号 [{name}] 阅读奖励成功,奖励: {response_json["data"]}金币')
elif response_json['code'] == -1 and response_json['msg'] == 'failed':
print(f'账号 [{name}] 阅读奖励失败: 已领取过奖励')
else:
print(f'账号 [{name}] 阅读奖励失败: {response.text}')
except requests.exceptions.RequestException as e:
print(f'账号 [{name}] 阅读奖励失败[请求]: {e}')
except json.JSONDecodeError as e:
print(f'账号 [{name}] 阅读奖励失败[JSON]: {e}')
except Exception as e:
print(f'账号 [{name}] 阅读奖励失败[其他]: {e}')
if __name__ == '__main__':
print('*'*50)
all_user = len(yxwlogin)
print(f"检测到环境变量中存在{all_user}个账号")
for yxwlogin_item in yxwlogin:
get_userdata(yxwlogin_item)
user_data = get_user_ids_and_tokens()
if not user_data:
print("未读取到用户数据,程序退出")
exit(0)
else:
print(f"读取到{len(user_data)}个账号")
recommendList = get_recommendList()
square = get_square()
print('*'*50)
for item in user_data:
print('-' * 50)
log('-' * 35)
user_phone = item['phone_key']
user_name = item['user_name']
user_token = item['token']
new_user_token = check_token(user_phone,user_token)
if new_user_token:
check_sign(user_name, new_user_token)
newusercheck(user_name, new_user_token)
luckbox_cookies(user_phone, user_token)
# usermission(user_name, new_user_token)
if recommendList:
for entity_id in recommendList:
share(user_name, new_user_token, entity_id)
time.sleep(1)
else:
print(f'账号 [{user_phone}] 推荐列表为空')
if square:
for thread_id in square:
readingreward(user_name, new_user_token, thread_id)
time.sleep(1)
else:
print(f'账号 [{user_phone}] BBS社区列表为空')
userinfo(user_phone, new_user_token)
else:
print(f'账号 [{user_phone}] 获取数据失败')
continue
try:
send_notification_message(title='游侠网开宝箱') # 发送通知
except Exception as e:
print('推送失败:' + str(e))

View File

@@ -0,0 +1,118 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/yxw_luckbox.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/yxw_luckbox.py
# Repo: lksky8/sign-ql
# Path: yxw_luckbox.py
# UploadedAt: 2025-08-21T12:12:12Z
# SHA256: 7951192443b96cec1fe801de769343a2e080be439b46c9b2bfb4372a4cdfe2e1
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
'''
作者https://github.com/lksky8/sign-ql/
日期2025-8-21
软件:游侠网-开宝箱
功能每隔三小时自动开宝箱领取50金币
定时0,5 */3 * * *
'''
import json
import requests
import time
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 get_user_ids_and_tokens(file_path='youxia_data.json'):
try:
# 1. 读取JSON文件
with open(file_path, 'r', encoding='utf-8') as f:
phone_data = json.load(f)
# 2. 遍历每个手机号
results = []
for phone_key, data in phone_data.items():
user_name = data.get('nickname')
user_token = data.get('token')
api3AliSSO_cookie = data.get('api3AliSSO')
if user_name and user_token: # 确保userId和token存在
results.append({
'phone_key': phone_key,
'user_name': user_name,
'api3AliSSO': api3AliSSO_cookie
})
# print(f"手机号: {phone_key}, userId: {user_id}, token: {token}")
return results
except FileNotFoundError:
print(f"文件 {file_path} 不存在!")
return []
except json.JSONDecodeError:
print(f"文件 {file_path} 格式错误!")
return []
def do_sign(phone, user_name, ck):
headers = {
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 ali213app"
}
cookies = {
"api3AliSSO": ck
}
try:
response = requests.get("https://api3.ali213.net/feedearn/luckybox?action=get", headers=headers,cookies=cookies)
response.raise_for_status()
response_json = response.json()
if response_json['logined']:
print(f"账号 [{phone}][{user_name}] 登录成功CK有效")
print(f"账号 [{phone}][{user_name}] {response_json['data']['msg']}")
if response_json['data']['status'] == 1 and response_json['data']['msg'] == '领取成功':
print(f"账号 [{phone}][{user_name}] 获得{response_json['data']['coins']}金币")
else:
print(f"账号 [{phone}][{user_name}] 登录失败CK无效")
log(f"账号 [{phone}][{user_name}] 登录失败CK无效")
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
except json.JSONDecodeError as e:
print(f"JSON解析错误: {e}")
except Exception as e:
print(f"其他错误: {e}")
if __name__ == '__main__':
user_data = get_user_ids_and_tokens()
if not user_data:
print("未读取到用户数据,程序退出")
exit(0)
else:
print(f"读取到{len(user_data)}个账号")
for item in user_data:
phone = item['phone_key']
user_name = item['user_name']
ck = item['api3AliSSO']
do_sign(phone, user_name, ck)
time.sleep(1)
print("-" * 50)
try:
send_notification_message(title='游侠网开宝箱') # 发送通知
except Exception as e:
print('推送失败:' + str(e))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,297 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/jksign.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/jksign.py
# Repo: lksky8/sign-ql
# Path: jksign.py
# UploadedAt: 2025-12-07T17:42:50Z
# SHA256: b722f903ef41b1cab2540fc2a7b84bb51cb2e8d354783a225e3c364b0799a4e6
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
"""
方舟健客app签到
作者https://github.com/lksky8/sign-ql
日期2025-12-5
使用方法APP抓登录包获取refresh_token填入jktoken
支持多用户运行,多用户用&或者@隔开
则变量为
export jktoken="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9........&eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9........"
每日签到一次即可
cron: 0 5 * * *
const $ = new Env("方舟健客签到");
"""
import time
import requests
import re
import os
import datetime
import hashlib
#推送开关开启为True关闭为False
push_message = True
def md5_encrypt(text):
md5_hash = hashlib.md5()
md5_hash.update(text.encode('utf-8'))
md5_result = md5_hash.hexdigest()
return md5_result
def time13():
now = datetime.datetime.now()
timestamp_ms = int(now.timestamp() * 1000) + (now.microsecond // 1000)
return timestamp_ms
def get_jkx():
a = time13() - 1500000000000
j = a % 999983
j2 = a % 9973
h = "6470"
md5_1 = md5_encrypt(f"39CC231D-C1F9-48DC-93DA-4CA0EA53C141{j}{h}")
md5_2 = md5_encrypt(f"{md5_1}{j2}{h}")
return f'{j}#{md5_2}#{j2}#{h}'
api_headers = {
'Host': 'acgi.jianke.com',
'Accept': 'application/json, text/plain, */*',
'Sec-Fetch-Site': 'same-site',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'platform': 'APP',
'Sec-Fetch-Mode': 'cors',
'Origin': 'https://app-hybrid.jianke.com',
'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 jiankeMall/6.47.0 JiankeMall/6.47.0',
'Referer': 'https://app-hybrid.jianke.com/',
'Content-Type': 'application/json;charset=utf-8',
'Sec-Fetch-Dest': 'empty',
}
api_headers2 = {
'Host': 'fe-acgi.jianke.com',
'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 jiankeMall/6.47.0',
'versionName': '6.47.0',
'X-JK-UDID': '39CC231D-C1F9-48DC-93DA-4CA0EA53C141',
'versionCode': '6470',
'X-JK-X': get_jkx(),
'platform': 'APP',
'Accept-Language': 'zh-Hans-CN;q=1',
'Accept': 'application/json',
'Content-Type': 'application/json',
}
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 refresh_token(token):
headers = {'Content-Type': 'application/json; charset=utf-8','User-Agent': 'Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.135 Mobile Safari/537.36 jiankeMall/6.26.0(w1080*h2029)','Host': 'acgi.jianke.com','organizationCode': 'app.jianke'}
data = {'refreshToken': token }
response = requests.post('https://acgi.jianke.com/passport/account/refreshToken', json=data, headers=headers)
if '授权失败' in response.text:
print('账号刷新token已失效请重新获取')
Log('账号刷新token已失效请重新获取')
return False
else:
response_json = response.json()
if response_json['token_type'] == 'bearer':
print("账号token刷新成功新的access_token已填入:\n" + response_json['access_token'])
return response_json['access_token']
else:
print("Failed to send POST request. Status Code:", response.status_code)
print("出错了:", response.text)
def do_sign(new_token,user_name):
# headers = api_headers2.copy()
# headers['Authorization'] = f'bearer {new_token}'
headers = {'Authorization':'bearer ' + new_token,'User-Agent': 'Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.135 Mobile Safari/537.36 jiankeMall/6.26.0(w1080*h2029)','X-JK-X': get_jkx(),'versionName': '6.47.0','X-JK-UDID': '39CC231D-C1F9-48DC-93DA-4CA0EA53C141'}
dl = requests.put('https://acgi.jianke.com/v2/member/signConfig/sign', headers=headers)
dl_json = dl.json()
if dl.status_code == 200:
print(f"[{user_name}] 本次签到获得:{dl_json['coinNum']}金币,今天是本周第{dl_json['cumulativeNum']}天签到")
Log(f"\n{user_name}] 本次签到获得:{dl_json['coinNum']}金币,今天是本周第{dl_json['cumulativeNum']}天签到")
elif dl_json['message'] == '今日已签到':
print(f'[{user_name}] 今天已经签到了')
Log(f'\n[{user_name}] 今天已经签到了')
else:
print("出错了:", dl.text)
def today_question(new_token,task_id,user_name):
headers = api_headers.copy()
headers['Authorization'] = f'bearer {new_token}'
response = requests.get('https://acgi.jianke.com/support/coin/task/daily-tasks/today-question', headers=headers)
response_json = response.json()
if response_json['code'] == '0' and response_json['message'] == 'success':
print(f'[{user_name}]【每日一答】 任务获取成功')
question_id = response_json['data']['id']
rightChoice = response_json['data']['rightChoice']
json_data = {
'id': str(task_id),
'questionItem': {
'id': question_id,
'rightChoice': rightChoice,
'userChoice': rightChoice,
'roundNum': 1,
},
}
response = requests.post('https://acgi.jianke.com/support/coin/task/complete', headers=headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['message'] == 'success':
print(f'[{user_name}]【每日一答】 任务完成')
Log(f'[{user_name}]【每日一答】 任务完成')
else:
print(f'[{user_name}]【每日一答】 {response_json["message"]}')
Log(f'[{user_name}]【每日一答】 {response_json["message"]}')
else:
print(f'[{user_name}]【每日一答】 任务获取失败')
Log(f'[{user_name}]【每日一答】 任务获取失败')
print(response.text)
def get_today_tasks(new_token, user_name):
headers = api_headers.copy()
headers['Authorization'] = f'bearer {new_token}'
response = requests.get('https://acgi.jianke.com/support/coin/task/daily-tasks', headers=headers)
if response.status_code == 200:
response_json = response.json()
task_list = []
for item in response_json['data']:
task_id = item['id']
task_name = item['taskName']
task_list.append({'task_id': task_id, 'task_name': task_name})
return task_list
else:
print(f'{user_name} 获取任务数据失败')
print(response.text)
return None
def do_task(new_token,user_name, task_id, task_name):
headers = api_headers.copy()
headers['Authorization'] = f'bearer {new_token}'
json_data = {
'id': str(task_id)
}
response = requests.post('https://acgi.jianke.com/support/coin/task/complete', headers=headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['message'] == 'success':
print(f'[{user_name}]【{task_name}】 任务完成')
Log(f'[{user_name}]【{task_name}】 任务完成')
else:
print(f'[{user_name}]【{task_name}{response_json["message"]}')
Log(f'[{user_name}]【{task_name}{response_json["message"]}')
def task_receive(new_token, user_name, task_id,task_name):
headers = api_headers.copy()
headers['Authorization'] = f'bearer {new_token}'
json_data = {
'id': task_id,
}
response = requests.post('https://acgi.jianke.com/support/coin/task/receive', headers=headers, json=json_data)
response_json = response.json()
if response_json['code'] == '0' and response_json['message'] == 'success':
print(f'[{user_name}]【{task_name}】 任务奖励:领取成功')
elif response_json['message'] == '奖励领取失败':
print(f'[{user_name}]【{task_name}】 任务奖励:领取失败')
Log(f'[{user_name}]【{task_name}】 任务奖励:领取失败')
else:
print('奖励领取失败')
print(response.text)
def get_coin(new_token, user_name):
headers = api_headers.copy()
headers['Authorization'] = f'bearer {new_token}'
response = requests.get('https://acgi.jianke.com/v1/coin/balance', headers=headers)
if response.status_code == 200:
response_json = response.json()
print(f'[{user_name}] 当前健康币:{response_json["balance"]}')
Log(f'[{user_name}] 当前健康币:{response_json["balance"]}')
else:
print('获取金币数失败')
print(response.text)
def get_userinfo(new_token):
headers = api_headers2.copy()
headers['Authorization'] = f'bearer {new_token}'
response = requests.get('https://fe-acgi.jianke.com/v5/userCenter', headers=headers)
response_json = response.json()
if response_json['statusCode'] == 200:
return response_json['data']['memberInfo']['nickName']
else:
print('获取用户信息失败')
print(response.text)
return None
if __name__ == '__main__':
if 'jktoken' in os.environ:
jktoken = re.split("@|&", os.environ.get("jktoken"))
print(f'查找到{len(jktoken)}个账号')
else:
jktoken = []
print('未填写 jktoken 变量')
if jktoken:
try:
z = 1
for ck in jktoken:
print(f'登录第{z}个账号')
print('----------------------\n')
access_token = refresh_token(ck)
if access_token:
user_nickname = get_userinfo(access_token)
print(f'[{user_nickname}] 刷新token成功')
print('\n开始签到操作>>>>>>>>>>\n')
do_sign(access_token, user_nickname)
print('\n开始执行任务>>>>>>>>>>\n')
task_data = get_today_tasks(access_token, user_nickname)
if task_data:
for task in task_data:
task_id = task['task_id']
task_name = task['task_name']
# print(f'[{user_nickname}] 开始执行任务:{task_name}')
if task_name == '每日一答':
today_question(access_token, task_id, user_nickname)
time.sleep(1)
task_receive(access_token, user_nickname, task_id, task_name)
time.sleep(2)
continue
if task_name == '下单返币':
continue
if task_name == '打开健客医生App':
continue
do_task(access_token, user_nickname, task_id, task_name)
time.sleep(1)
task_receive(access_token, user_nickname, task_id, task_name)
time.sleep(3)
get_coin(access_token, user_nickname)
print('\n----------------------')
z = z + 1
except Exception as e:
print('未知错误:' + str(e))
if push_message:
try:
send_notification_message(title='方舟健客') # 发送通知
except Exception as e:
print('推送失败:' + str(e))

View File

@@ -0,0 +1,389 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/xxcd.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/xxcd.py
# Repo: lksky8/sign-ql
# Path: xxcd.py
# UploadedAt: 2025-09-01T15:45:21Z
# SHA256: 40e3aef421127efd0fe80201c786cf341993dd4e8318fe4f8456a912aef026e0
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
"""
星星充电签到
作者https://github.com/lksky8/sign-ql
日期2025-09-01
使用方法打开app随便抓一个包把头部'Authorization'内容填入 export startoken=""
另外可以再填入cityid(抓包获取), export starcityid=""可填可不填
支持多用户运行,多用户用&或者@隔开
export startoken="eyJ0eXAiOiJKV1QiLCJhbGciOiJIU1NiJ9..&eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1J9.."
export starcityid=""
每天运行一次即可
cron: 0 7 * * *
const $ = new Env("星星充电签到");
"""
import requests
import re
import os
import datetime
import hashlib
import time
if 'startoken' in os.environ:
startoken = re.split("@|&",os.environ.get("startoken"))
print(f'查找到{len(startoken)}个账号\n')
else:
startoken =['']
print('无startoken变量')
if 'starcityid' in os.environ:
cityid = os.environ.get("starcityid")
print(f'已填入cityid:{cityid}')
else:
cityid = '440000'
print('没有填写cityid,系统默认使用440000')
def md5_encrypt(text):
md5_hash = hashlib.md5()
md5_hash.update(text.encode('utf-8'))
md5_result = md5_hash.hexdigest()
return md5_result
def time13():
now = datetime.datetime.now()
timestamp_ms = int(now.timestamp() * 1000) + (now.microsecond // 1000)
return str(timestamp_ms)
def find_task_ids(data):
this_week_task_id = None
this_month_task_id = None
for model in data:
for task in model['taskList']:
if task['taskName'] == '本周充电任务':
this_week_task_id = task['taskId']
elif task['taskName'] == '本月充电任务':
this_month_task_id = task['taskId']
return this_week_task_id, this_month_task_id
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 sign(token):
try:
timestamp = time13()
signature = md5_encrypt(f'nonce=2b4aa7d9-4137-4e51-94e3-7b7355bf202a&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
'appVersion': '7.40.0',
'Origin': 'https://scm-app-h5.starcharge.com',
'signature': signature,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Site': 'same-site',
'referrer': 'web',
'timestamp': timestamp,
'positCity': cityid,
'Authorization': token,
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Accept': 'application/json, text/plain, */*',
'channel-id': '98',
'Sec-Fetch-Mode': 'cors',
'Content-Type': 'application/x-www-form-urlencoded',
}
data = {
'nonce': '2b4aa7d9-4137-4e51-94e3-7b7355bf202a',
'timestamp': timestamp,
'userId': '',
}
response = requests.post('https://gateway.starcharge.com/apph5/webApiV2/starPoint/sign',headers=headers, data=data)
response_json = response.json()
if response_json['code'] == '200':
print(f"签到成功:获得{response_json['data']['basePoint']}积分,已连续签到{response_json['data']['continuousDay']}")
Log(f"签到成功:获得{response_json['data']['basePoint']}积分,已连续签到{response_json['data']['continuousDay']}")
return True
elif response_json['code'] == '402':
print('用户数据获取失败,重新尝试获取数据')
return False
else:
print("签到失败:", response.text)
return False
except requests.exceptions.RequestException as e:
print("Failed to send POST request. Status Code:", response.status_code)
except Exception as e:
print("签到出错了:", e)
def Get_list(token):
try:
timestamp = time13()
signature = md5_encrypt(f'city={cityid}&nonce=1b93f289-32ee-4616-a860-5aef04c6c048&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'Accept': 'application/json, text/plain, */*',
'memberAdType': '0-0',
'Authorization': token,
'timestamp': timestamp,
'appVersion': '7.40.0',
'channel-id': '98',
'referrer': 'web',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'signature': signature,
'positCity': cityid,
'Origin': 'https://scm-app-h5.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/userTask/model/list?city={cityid}&nonce=1b93f289-32ee-4616-a860-5aef04c6c048',headers=headers)
response_json = response.json()
if response_json['code'] == '200':
return response_json['data']
else:
print("获取任务列表失败:", response.text)
return False
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("获取任务列表出错了:", e)
def Do_task(task_id,token):
try:
timestamp = time13()
signature = md5_encrypt(f'nonce=4f63ecd8-e342-4e33-94a4-81bdfd040235&taskId={task_id}&taskType=1&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'Accept': 'application/json, text/plain, */*',
'memberAdType': '0-0',
'Authorization': token,
'timestamp': timestamp,
'appVersion': '7.40.0',
'channel-id': '98',
'referrer': 'web',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'signature': signature,
'positCity': cityid,
'Origin': 'https://scm-app-h5.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/userTask/get?taskId={task_id}&taskType=1&nonce=4f63ecd8-e342-4e33-94a4-81bdfd040235', headers=headers)
response_json = response.json()
if response_json['code'] == None:
return response_json['text']
elif response_json['code'] == '200' and response_json['text'] == None :
return '任务已领取'
else:
print("做任务:", response.text)
return False
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
def Get_info(token):
try:
timestamp = time13()
signature = md5_encrypt(f'city={cityid}&nonce=b7e92ec1-813f-4ec2-ab8a-e91289604733&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
'appVersion': '7.40.0',
'Origin': 'https://scm-app-h5.starcharge.com',
'signature': signature,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Site': 'same-site',
'referrer': 'web',
'timestamp': timestamp,
'positCity': cityid,
'Authorization': token,
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Accept': 'application/json, text/plain, */*',
'channel-id': '98',
'Sec-Fetch-Mode': 'cors',
'Content-Type': 'application/x-www-form-urlencoded',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/v2/webApiV2/star/point/user?city={cityid}&nonce=b7e92ec1-813f-4ec2-ab8a-e91289604733', headers=headers)
response_json = response.json()
if response_json['code'] == '200':
print(f'用户({response_json["data"]["nickName"]})目前金币:{response_json["data"]["points"]}')
Log(f'用户({response_json["data"]["nickName"]})目前金币:{response_json["data"]["points"]}\n')
else:
print('用户数据查询失败:' + response.text)
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("查询用户数据出错了:", e)
def Get_user_info(token):
try:
timestamp = time13()
signature = md5_encrypt(f'cityCode={cityid}&nonce=b6efee74-2ad5-43b3-bf3f-2435613c7c9d&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'Accept': 'application/json, text/plain, */*',
'Authorization': token,
'timestamp': timestamp,
'Sec-Fetch-Site': 'same-site',
'appVersion': '7.40.0',
'channel-id': '98',
'referrer': 'web',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'signature': signature,
'Sec-Fetch-Mode': 'cors',
'Origin': 'https://scm-app-h5.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
'positCity': cityid,
'Sec-Fetch-Dest': 'empty',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/user/getUserBaseInfo?cityCode={cityid}&nonce=b6efee74-2ad5-43b3-bf3f-2435613c7c9d', headers=headers)
response_data = response.json()
if response_data['code'] == '200':
if response_data['data']['appVipType'] == 1:
print(f'用户({response_data["data"]["nickName"]})已开通VIP到期日{response_data["data"]["appVipExpiration"]}')
vip_sign(token)
check_vip_sign(token)
else:
print(f'用户({response_data["data"]["nickName"]}) 未开通VIP')
else:
print('查询是否VIP失败:' + response.text)
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("查询是否VIP出错了:", e)
def vip_sign(token):
try:
timestamp = time13()
signature = md5_encrypt('nonce=8f396424-3729-4f50-bf67-bfb8fe38b9c5&timestamp='+timestamp+'&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
'appVersion': '7.40.0',
'Origin': 'https://scm-app-h5.starcharge.com',
'signature': signature,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Site': 'same-site',
'referrer': 'web',
'timestamp': timestamp,
'positCity': '440600',
'Authorization': token,
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Accept': 'application/json, text/plain, */*',
'channel-id': '98',
'Sec-Fetch-Mode': 'cors',
'Content-Type': 'application/x-www-form-urlencoded',
}
data = {
'nonce': '8f396424-3729-4f50-bf67-bfb8fe38b9c5',
'timestamp': timestamp,
'userId': '',
}
response = requests.post('https://gateway.starcharge.com/apph5/webApiV2/member/v5/home/sign',headers=headers, data=data).json()
if response['code'] == '200':
print(f"VIP任务签到成功")
else:
print("VIP任务签到失败" + response['text'])
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("出错了:", e)
def check_vip_sign(token):
try:
timestamp = time13()
signature = md5_encrypt(f'cycleType=1&nonce=2d3d2147-dbce-42b4-8fa9-9268b4fa580f&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'memberAdType': '0-0',
'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',
'Referer': 'https://app-taro.starcharge.com/',
'appVersion': '7.40.0',
'Origin': 'https://app-taro.starcharge.com',
'signature': signature,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Site': 'same-site',
'referrer': 'web',
'timestamp': timestamp,
'positCity': '440600',
'Authorization': token,
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Accept': '*/*',
'Content-Type': 'application/x-www-form-urlencoded',
'channel-id': '98',
'Sec-Fetch-Mode': 'cors',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/member/v5/home/sign/records?cycleType=1&nonce=2d3d2147-dbce-42b4-8fa9-9268b4fa580f&timestamp={timestamp}&userId=',headers=headers).json()
if response['code'] == '200':
print(f"VIP任务已连续签到{response['data']['continuousDays']}")
else:
print("VIP任务查询失败" + response)
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("出错了:", e)
def main():
z = 1
for ck in startoken:
try:
print(f'登录第{z}个账号')
print('----------------------')
print('\n开始签到操作>>>>>>>>>>\n')
while True:
if sign(ck):
break
time.sleep(3)
print('\n完成日常任务>>>>>>>>>>\n')
this_week_id, this_month_id = find_task_ids(Get_list(ck))
print("本周充电任务:", Do_task(this_week_id,ck))
print("本月充电任务:", Do_task(this_month_id,ck))
print('\n获取用户信息>>>>>>>>>>\n')
Get_info(ck)
Get_user_info(ck)
print('\n----------------------')
z = z + 1
except Exception as e:
print(e)
if __name__ == '__main__':
try:
main()
except Exception as e:
print(e)
try:
send_notification_message(title='星星充电') # 发送通知
except Exception as e:
print(e)

View File

@@ -0,0 +1,389 @@
# Source: https://github.com/lksky8/sign-ql/blob/main/xxcd.py
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/xxcd.py
# Repo: lksky8/sign-ql
# Path: xxcd.py
# UploadedAt: 2026-05-23T06:33:21Z
# SHA256: 40e3aef421127efd0fe80201c786cf341993dd4e8318fe4f8456a912aef026e0
# Category: web版/账密
# Evidence: web/H5关键词 + username/password/login
"""
星星充电签到
作者https://github.com/lksky8/sign-ql
日期2025-09-01
使用方法打开app随便抓一个包把头部'Authorization'内容填入 export startoken=""
另外可以再填入cityid(抓包获取), export starcityid=""可填可不填
支持多用户运行,多用户用&或者@隔开
export startoken="eyJ0eXAiOiJKV1QiLCJhbGciOiJIU1NiJ9..&eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1J9.."
export starcityid=""
每天运行一次即可
cron: 0 7 * * *
const $ = new Env("星星充电签到");
"""
import requests
import re
import os
import datetime
import hashlib
import time
if 'startoken' in os.environ:
startoken = re.split("@|&",os.environ.get("startoken"))
print(f'查找到{len(startoken)}个账号\n')
else:
startoken =['']
print('无startoken变量')
if 'starcityid' in os.environ:
cityid = os.environ.get("starcityid")
print(f'已填入cityid:{cityid}')
else:
cityid = '440000'
print('没有填写cityid,系统默认使用440000')
def md5_encrypt(text):
md5_hash = hashlib.md5()
md5_hash.update(text.encode('utf-8'))
md5_result = md5_hash.hexdigest()
return md5_result
def time13():
now = datetime.datetime.now()
timestamp_ms = int(now.timestamp() * 1000) + (now.microsecond // 1000)
return str(timestamp_ms)
def find_task_ids(data):
this_week_task_id = None
this_month_task_id = None
for model in data:
for task in model['taskList']:
if task['taskName'] == '本周充电任务':
this_week_task_id = task['taskId']
elif task['taskName'] == '本月充电任务':
this_month_task_id = task['taskId']
return this_week_task_id, this_month_task_id
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 sign(token):
try:
timestamp = time13()
signature = md5_encrypt(f'nonce=2b4aa7d9-4137-4e51-94e3-7b7355bf202a&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
'appVersion': '7.40.0',
'Origin': 'https://scm-app-h5.starcharge.com',
'signature': signature,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Site': 'same-site',
'referrer': 'web',
'timestamp': timestamp,
'positCity': cityid,
'Authorization': token,
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Accept': 'application/json, text/plain, */*',
'channel-id': '98',
'Sec-Fetch-Mode': 'cors',
'Content-Type': 'application/x-www-form-urlencoded',
}
data = {
'nonce': '2b4aa7d9-4137-4e51-94e3-7b7355bf202a',
'timestamp': timestamp,
'userId': '',
}
response = requests.post('https://gateway.starcharge.com/apph5/webApiV2/starPoint/sign',headers=headers, data=data)
response_json = response.json()
if response_json['code'] == '200':
print(f"签到成功:获得{response_json['data']['basePoint']}积分,已连续签到{response_json['data']['continuousDay']}")
Log(f"签到成功:获得{response_json['data']['basePoint']}积分,已连续签到{response_json['data']['continuousDay']}")
return True
elif response_json['code'] == '402':
print('用户数据获取失败,重新尝试获取数据')
return False
else:
print("签到失败:", response.text)
return False
except requests.exceptions.RequestException as e:
print("Failed to send POST request. Status Code:", response.status_code)
except Exception as e:
print("签到出错了:", e)
def Get_list(token):
try:
timestamp = time13()
signature = md5_encrypt(f'city={cityid}&nonce=1b93f289-32ee-4616-a860-5aef04c6c048&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'Accept': 'application/json, text/plain, */*',
'memberAdType': '0-0',
'Authorization': token,
'timestamp': timestamp,
'appVersion': '7.40.0',
'channel-id': '98',
'referrer': 'web',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'signature': signature,
'positCity': cityid,
'Origin': 'https://scm-app-h5.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/userTask/model/list?city={cityid}&nonce=1b93f289-32ee-4616-a860-5aef04c6c048',headers=headers)
response_json = response.json()
if response_json['code'] == '200':
return response_json['data']
else:
print("获取任务列表失败:", response.text)
return False
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("获取任务列表出错了:", e)
def Do_task(task_id,token):
try:
timestamp = time13()
signature = md5_encrypt(f'nonce=4f63ecd8-e342-4e33-94a4-81bdfd040235&taskId={task_id}&taskType=1&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'Accept': 'application/json, text/plain, */*',
'memberAdType': '0-0',
'Authorization': token,
'timestamp': timestamp,
'appVersion': '7.40.0',
'channel-id': '98',
'referrer': 'web',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'signature': signature,
'positCity': cityid,
'Origin': 'https://scm-app-h5.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/userTask/get?taskId={task_id}&taskType=1&nonce=4f63ecd8-e342-4e33-94a4-81bdfd040235', headers=headers)
response_json = response.json()
if response_json['code'] == None:
return response_json['text']
elif response_json['code'] == '200' and response_json['text'] == None :
return '任务已领取'
else:
print("做任务:", response.text)
return False
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
def Get_info(token):
try:
timestamp = time13()
signature = md5_encrypt(f'city={cityid}&nonce=b7e92ec1-813f-4ec2-ab8a-e91289604733&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
'appVersion': '7.40.0',
'Origin': 'https://scm-app-h5.starcharge.com',
'signature': signature,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Site': 'same-site',
'referrer': 'web',
'timestamp': timestamp,
'positCity': cityid,
'Authorization': token,
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Accept': 'application/json, text/plain, */*',
'channel-id': '98',
'Sec-Fetch-Mode': 'cors',
'Content-Type': 'application/x-www-form-urlencoded',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/v2/webApiV2/star/point/user?city={cityid}&nonce=b7e92ec1-813f-4ec2-ab8a-e91289604733', headers=headers)
response_json = response.json()
if response_json['code'] == '200':
print(f'用户({response_json["data"]["nickName"]})目前金币:{response_json["data"]["points"]}')
Log(f'用户({response_json["data"]["nickName"]})目前金币:{response_json["data"]["points"]}\n')
else:
print('用户数据查询失败:' + response.text)
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("查询用户数据出错了:", e)
def Get_user_info(token):
try:
timestamp = time13()
signature = md5_encrypt(f'cityCode={cityid}&nonce=b6efee74-2ad5-43b3-bf3f-2435613c7c9d&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'Accept': 'application/json, text/plain, */*',
'Authorization': token,
'timestamp': timestamp,
'Sec-Fetch-Site': 'same-site',
'appVersion': '7.40.0',
'channel-id': '98',
'referrer': 'web',
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'signature': signature,
'Sec-Fetch-Mode': 'cors',
'Origin': 'https://scm-app-h5.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
'positCity': cityid,
'Sec-Fetch-Dest': 'empty',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/user/getUserBaseInfo?cityCode={cityid}&nonce=b6efee74-2ad5-43b3-bf3f-2435613c7c9d', headers=headers)
response_data = response.json()
if response_data['code'] == '200':
if response_data['data']['appVipType'] == 1:
print(f'用户({response_data["data"]["nickName"]})已开通VIP到期日{response_data["data"]["appVipExpiration"]}')
vip_sign(token)
check_vip_sign(token)
else:
print(f'用户({response_data["data"]["nickName"]}) 未开通VIP')
else:
print('查询是否VIP失败:' + response.text)
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("查询是否VIP出错了:", e)
def vip_sign(token):
try:
timestamp = time13()
signature = md5_encrypt('nonce=8f396424-3729-4f50-bf67-bfb8fe38b9c5&timestamp='+timestamp+'&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'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',
'Referer': 'https://scm-app-h5.starcharge.com/',
'appVersion': '7.40.0',
'Origin': 'https://scm-app-h5.starcharge.com',
'signature': signature,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Site': 'same-site',
'referrer': 'web',
'timestamp': timestamp,
'positCity': '440600',
'Authorization': token,
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Accept': 'application/json, text/plain, */*',
'channel-id': '98',
'Sec-Fetch-Mode': 'cors',
'Content-Type': 'application/x-www-form-urlencoded',
}
data = {
'nonce': '8f396424-3729-4f50-bf67-bfb8fe38b9c5',
'timestamp': timestamp,
'userId': '',
}
response = requests.post('https://gateway.starcharge.com/apph5/webApiV2/member/v5/home/sign',headers=headers, data=data).json()
if response['code'] == '200':
print(f"VIP任务签到成功")
else:
print("VIP任务签到失败" + response['text'])
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("出错了:", e)
def check_vip_sign(token):
try:
timestamp = time13()
signature = md5_encrypt(f'cycleType=1&nonce=2d3d2147-dbce-42b4-8fa9-9268b4fa580f&timestamp={timestamp}&userId=')[0:18].upper()
headers = {
'Host': 'gateway.starcharge.com',
'memberAdType': '0-0',
'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',
'Referer': 'https://app-taro.starcharge.com/',
'appVersion': '7.40.0',
'Origin': 'https://app-taro.starcharge.com',
'signature': signature,
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Site': 'same-site',
'referrer': 'web',
'timestamp': timestamp,
'positCity': '440600',
'Authorization': token,
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
'Accept': '*/*',
'Content-Type': 'application/x-www-form-urlencoded',
'channel-id': '98',
'Sec-Fetch-Mode': 'cors',
}
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/member/v5/home/sign/records?cycleType=1&nonce=2d3d2147-dbce-42b4-8fa9-9268b4fa580f&timestamp={timestamp}&userId=',headers=headers).json()
if response['code'] == '200':
print(f"VIP任务已连续签到{response['data']['continuousDays']}")
else:
print("VIP任务查询失败" + response)
except requests.exceptions.RequestException as e:
print("An error occurred:", e)
except Exception as e:
print("出错了:", e)
def main():
z = 1
for ck in startoken:
try:
print(f'登录第{z}个账号')
print('----------------------')
print('\n开始签到操作>>>>>>>>>>\n')
while True:
if sign(ck):
break
time.sleep(3)
print('\n完成日常任务>>>>>>>>>>\n')
this_week_id, this_month_id = find_task_ids(Get_list(ck))
print("本周充电任务:", Do_task(this_week_id,ck))
print("本月充电任务:", Do_task(this_month_id,ck))
print('\n获取用户信息>>>>>>>>>>\n')
Get_info(ck)
Get_user_info(ck)
print('\n----------------------')
z = z + 1
except Exception as e:
print(e)
if __name__ == '__main__':
try:
main()
except Exception as e:
print(e)
try:
send_notification_message(title='星星充电') # 发送通知
except Exception as e:
print(e)