fix daily miniapp code login scripts

This commit is contained in:
smallfawn committed 2026-06-01 14:22:21 +08:00
1 parent 8b0679680d
commit 4babb0ba12
14 files changed
+2576 -1643

No files matched your search

+217 -72
View File
@@ -1,6 +1,7 @@
#by:哆啦A梦
#入口:http://mx.qrurl.net/h5/wxa/link?sid=26407uif5Oq
#抓包breoplus.breo.cn的域名下的token,多账号换行分割
#BREO变量填写wx_server里的openid/账号标识,多账号换行分割
#需要配置wx_server_url、wx_auth,用于获取wx.login code
#账号变量名:BREO
#new Env("BREO")
#cron 8 9,10,11 * * *
@@ -9,7 +10,182 @@
import requests
import json
import os
import sys
import time
from pathlib import Path
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
if hasattr(sys.stderr, "reconfigure"):
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
MINI_APP_ID = "wx61457400e4212cec"
WX_SERVER_URL = os.getenv("wx_server_url", "http://192.168.31.196:8787").rstrip("/")
WX_AUTH = os.getenv("wx_auth", "")
TOKEN_CACHE_PATH = Path(__file__).with_name("BREO_token_cache.json")
LOGIN_BASE = "https://breoplus.breo.cn/app/minic"
APP_BASE = "https://breoplus.breo.cn/breo-app"
DEFAULT_UA = "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"
session = requests.Session()
def read_token_cache():
try:
if not TOKEN_CACHE_PATH.exists():
return {}
return json.loads(TOKEN_CACHE_PATH.read_text(encoding="utf-8")) or {}
except Exception:
return {}
def write_token_cache(cache):
try:
TOKEN_CACHE_PATH.write_text(json.dumps(cache, ensure_ascii=False, indent=2), encoding="utf-8")
except Exception as e:
print(f"⚠️ 写入token缓存失败: {e}")
def mask_token(token):
if not token:
return ""
return f"{token[:6]}***{token[-6:]}"
def is_success(result):
return result.get("success") is True or str(result.get("code")) in ("0000", "200", "200.0")
def is_token_error(message):
text = str(message)
return any(key in text for key in ["40101", "40102", "token", "登录", "授权", "过期", "失效"])
def wx_headers():
return {
"auth": WX_AUTH,
"User-Agent": DEFAULT_UA,
"Content-Type": "application/json",
}
def app_headers(token=None):
headers = {
"User-Agent": DEFAULT_UA,
"content-Type": "application/json",
"Content-Type": "application/json",
"deviceInfo": "{}",
"Referer": "https://servicewechat.com/wx61457400e4212cec/390/page-frame.html",
}
if token:
headers["token"] = token
return headers
def breo_task_headers(token):
return {
"token": token,
"device-type": "Xiaomi",
"device-version": "10",
"channel": "Breo",
"version_code": "30201",
"version": "3.2.1",
"encrypt": "1",
"Content-Type": "application/json; charset=UTF-8",
"Referer": "https://servicewechat.com/wx61457400e4212cec/390/page-frame.html",
"User-Agent": DEFAULT_UA,
}
def get_wx_code(account_id):
if not WX_AUTH:
raise RuntimeError("缺少wx_auth,无法从wx_server获取code")
resp = session.post(
f"{WX_SERVER_URL}/wx/code",
json={"appid": MINI_APP_ID, "openid": account_id},
headers=wx_headers(),
timeout=30,
)
resp.raise_for_status()
data = resp.json()
code = data.get("code") or (data.get("data") or {}).get("code")
if not code:
raise RuntimeError(f"wx_server未返回code: {data}")
return code
def login_with_code(account_id):
code = get_wx_code(account_id)
login_resp = session.get(
f"{LOGIN_BASE}/login/{code}",
headers=app_headers(),
timeout=30,
)
login_resp.raise_for_status()
login_data = login_resp.json()
if str(login_data.get("code")) != "200" or not login_data.get("data"):
raise RuntimeError(f"code登录失败: {login_data}")
user_info = login_data["data"]
uid = user_info.get("uid")
open_id = user_info.get("openId")
union_id = user_info.get("unionId")
if not uid:
raise RuntimeError(f"登录响应缺少uid: {login_data}")
token_resp = session.post(
f"{APP_BASE}/customer/loginByUid",
json={"uid": uid, "openId": open_id, "unionId": union_id},
headers=app_headers(),
timeout=30,
)
token_resp.raise_for_status()
token_data = token_resp.json()
if not is_success(token_data) or not (token_data.get("result") or {}).get("token"):
raise RuntimeError(f"业务token登录失败: {token_data}")
return {
"token": token_data["result"]["token"],
"uid": uid,
"openId": open_id,
"unionId": union_id,
"userInfo": user_info,
"customer": token_data.get("result", {}),
"updatedAt": int(time.time()),
}
def get_cached_token(account_id):
return read_token_cache().get(account_id)
def save_cached_token(account_id, auth_info):
cache = read_token_cache()
cache[account_id] = auth_info
write_token_cache(cache)
def remove_cached_token(account_id):
cache = read_token_cache()
if account_id in cache:
del cache[account_id]
write_token_cache(cache)
def validate_token(token):
try:
resp = session.post(
f"{APP_BASE}/getUserLevelInfoByUid",
headers=app_headers(token),
timeout=15,
)
if resp.status_code != 200:
return False
data = resp.json()
if is_success(data):
return True
return not is_token_error(data)
except Exception:
return False
def get_token_for_account(account_id, index):
cached = get_cached_token(account_id)
if cached and cached.get("token"):
print(f"账号 {index} 使用缓存token: {mask_token(cached['token'])}")
if validate_token(cached["token"]):
return cached["token"]
print(f"账号 {index} 缓存token失效,重新登录")
remove_cached_token(account_id)
auth_info = login_with_code(account_id)
save_cached_token(account_id, auth_info)
user_info = auth_info.get("userInfo") or {}
print(f"账号 {index} code登录成功: {user_info.get('nickname') or user_info.get('telephone') or auth_info.get('uid')}")
return auth_info["token"]
def get_random_one_word():
try:
@@ -54,16 +230,7 @@ def get_proclamation():
def post_to_breo(token, content, title):
url = "https://breoplus.breo.cn/breo-app/communityBaseInfo/releasePost"
headers = {
"token": token,
"device-type": "Xiaomi",
"device-version": "10",
"channel": "Breo",
"version_code": "30201",
"version": "3.2.1",
"encrypt": "1",
"Content-Type": "application/json; charset=UTF-8"
}
headers = breo_task_headers(token)
data = {
"anonymoused": 1,
"content": content,
@@ -94,16 +261,7 @@ def post_to_breo(token, content, title):
def collect_post(token, post_id):
url = "https://breoplus.breo.cn/breo-app/communityBaseInfo/collect"
headers = {
"token": token,
"device-type": "Xiaomi",
"device-version": "10",
"channel": "Breo",
"version_code": "30201",
"version": "3.2.1",
"encrypt": "1",
"Content-Type": "application/json; charset=UTF-8"
}
headers = breo_task_headers(token)
data = {
"postId": post_id
}
@@ -113,8 +271,9 @@ def collect_post(token, post_id):
result = response.json()
if result.get("success", False):
print("✅ 收藏成功!")
print(f"获得点数: {result['result']['point']}")
print(f"成长值: {result['result']['grow']}")
reward = result.get("result") or {}
print(f"获得点数: {reward.get('point', 0)}")
print(f"成长值: {reward.get('grow', 0)}")
else:
print(f"❌ 收藏失败,错误信息:{result.get('message', '未知错误')}")
else:
@@ -126,16 +285,7 @@ def comment_post(token, post_id):
for _ in range(2): # 评论2次
comment_content = get_random_one_word() # 使用随机一言作为评论内容
url = "https://breoplus.breo.cn/breo-app/communityBaseInfo/comment"
headers = {
"token": token,
"device-type": "Xiaomi",
"device-version": "10",
"channel": "Breo",
"version_code": "30201",
"version": "3.2.1",
"encrypt": "1",
"Content-Type": "application/json; charset=UTF-8"
}
headers = breo_task_headers(token)
data = {
"anonymoused": 0,
"commentText": comment_content,
@@ -147,9 +297,11 @@ def comment_post(token, post_id):
result = response.json()
if result.get("success", False):
print("✅ 评论成功!")
print(f"评论内容: {result['result']['rootOutVO']['commentText']}")
print(f"获得点数: {result['result']['point']}")
print(f"成长值: {result['result']['grow']}")
reward = result.get("result") or {}
root = reward.get("rootOutVO") or {}
print(f"评论内容: {root.get('commentText', comment_content)}")
print(f"获得点数: {reward.get('point', 0)}")
print(f"成长值: {reward.get('grow', 0)}")
else:
print(f"❌ 评论失败,错误信息:{result.get('message', '未知错误')}")
else:
@@ -160,23 +312,16 @@ def comment_post(token, post_id):
def browse_mall(token):
url = "https://breoplus.breo.cn/breo-app/user/po-task-info/mall"
headers = {
"token": token,
"device-type": "Xiaomi",
"device-version": "10",
"channel": "Breo",
"version_code": "30201",
"version": "3.2.1",
"encrypt": "1"
}
headers = breo_task_headers(token)
try:
response = requests.post(url, headers=headers)
if response.status_code == 200:
result = response.json()
if result.get("success", False):
print("✅ 浏览商城成功!")
print(f"获得点数: {result['result']['point']}")
print(f"成长值: {result['result']['grow']}")
reward = result.get("result") or {}
print(f"获得点数: {reward.get('point', 0)}")
print(f"成长值: {reward.get('grow', 0)}")
else:
print(f"❌ 浏览商城失败,错误信息:{result.get('message', '未知错误')}")
else:
@@ -186,25 +331,16 @@ def browse_mall(token):
def punch_in(token):
url = "https://breoplus.breo.cn/breo-app/user/po-task-info/punch"
headers = {
"Host": "breoplus.breo.cn",
"Connection": "keep-alive",
"Content-Length": "0",
"content-type": "application/json",
"token": token,
"charset": "utf-8",
"Referer": "https://servicewechat.com/wx61457400e4212cec/304/page-frame.html",
"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/134.0.6998.136 Mobile Safari/537.36 XWEB/1340043 MMWEBSDK/20241202 MMWEBID/3628 MicroMessenger/8.0.56.2800(0x2800385E) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android",
"Accept-Encoding": "gzip, deflate, br"
}
headers = breo_task_headers(token)
try:
response = requests.post(url, headers=headers)
if response.status_code == 200:
result = response.json()
if result.get("success", False):
print("✅ 签到成功!")
print(f"获得点数: {result['result']['point']}")
print(f"成长值: {result['result']['grow']}")
reward = result.get("result") or {}
print(f"获得点数: {reward.get('point', 0)}")
print(f"成长值: {reward.get('grow', 0)}")
else:
print(f"❌ 签到失败,错误信息:{result.get('message', '未知错误')}")
else:
@@ -216,19 +352,28 @@ if __name__ == "__main__":
# 获取公告
#get_proclamation()
# 从环境变量读取 token
tokens = os.getenv("BREO", "").splitlines()
# 从环境变量读取 wx_server 账号标识/openid
accounts = [item.strip() for item in os.getenv("BREO", "").replace("&", "\n").splitlines() if item.strip()]
if not tokens:
if not accounts:
print("❌ 未检测到 账号信息,退出脚本。")
else:
skip_community = os.getenv("BREO_SKIP_COMMUNITY", "").lower() in ("1", "true", "yes")
print("=============== 开始执行任务 ===============")
for i, token in enumerate(tokens, 1):
if token.strip(): # 跳过空行
print(f"\n-------------- 账号 {i} 开始 --------------")
print("🚀 正在签到...")
punch_in(token)
for i, account in enumerate(accounts, 1):
print(f"\n-------------- 账号 {i} 开始 --------------")
try:
token = get_token_for_account(account, i)
except Exception as e:
print(f"❌ 账号 {i} 登录失败: {e}")
continue
print("🚀 正在签到...")
punch_in(token)
if skip_community:
print("\n📝 已跳过发帖/收藏/评论任务")
else:
print("\n📝 正在发布帖子...")
post_id = post_to_breo(token, "这是一个自动发布的帖子", "自动化测试")
if post_id:
@@ -240,9 +385,9 @@ if __name__ == "__main__":
else:
print("❌ 发帖失败,跳过后续操作。")
print("\n🛒 正在浏览商城...")
browse_mall(token)
print("\n🛒 正在浏览商城...")
browse_mall(token)
print(f"-------------- 账号 {i} 结束 --------------")
print(f"-------------- 账号 {i} 结束 --------------")
print("\n=============== 所有任务执行完毕 ===============")
print("\n=============== 所有任务执行完毕 ===============")
+232 -73
View File
@@ -1,122 +1,281 @@
/*
爱玛会员俱乐部 - 自动签到脚本(2026年2月修复版)
✅ 修复点:使用域名替代失效IP,更新活动ID为100001180
✅ 支持环境:Node.js
✅ 变量名:aima
✅ 变量值:access-token(支持多账号,用 & 或换行分隔)
爱玛会员俱乐部 - 自动签到脚本
变量名:aima
变量值:账号标识/openid(支持多账号,用 & 或换行分隔)
CODE登录依赖:wx_server_url、wx_auth
*/
const { Env } = require("../tools/env")
const { Env } = require("../tools/env");
const $ = new Env("爱玛会员俱乐部");
const axios = require('axios')
const axios = require("axios");
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
// ================== 配置区 ==================
const ACTIVITY_ID = "100001192"; // 2026年2月活动ID
const BASE_URL = "https://scrm.aimatech.com"; // 使用官方域名,不再硬编码IP
const ACTIVITY_ID = "100001192";
const BASE_URL = "https://scrm.aimatech.com";
const WXCLIENT_URL = `${BASE_URL}/aima/wxclient`;
const MINI_APPID = "wx2dcfb409fd5ddfb4";
const APP_ID = "scrm";
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/142.0.7444.173 Mobile Safari/537.36 XWEB/1420229 MMWEBSDK/20251101 MMWEBID/6369 MicroMessenger/8.0.67.3000(0x28004333) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android";
const TOKEN_CACHE_FILE = path.join(__dirname, "aima_token_cache.json");
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/142.0.7444.173 Mobile Safari/537.36 XWEB/1420229 MMWEBSDK/20251101 MMWEBID/6369 MicroMessenger/8.0.67.3000(0x28004333) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android";
// ================== 工具函数 ==================
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
function md5(str) {
const crypto = require('crypto');
return crypto.createHash('md5').update(str).digest('hex');
return crypto.createHash("md5").update(str).digest("hex");
}
function maskToken(token = "") {
if (!token) return "";
if (token.length <= 12) return `${token.slice(0, 3)}***`;
return `${token.slice(0, 6)}***${token.slice(-6)}`;
}
function isToken(value = "") {
return /^eyJ/.test(value.trim()) || value.length > 120;
}
function readCache() {
try {
if (!fs.existsSync(TOKEN_CACHE_FILE)) return {};
return JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, "utf8"));
} catch (e) {
return {};
}
}
function writeCache(cache) {
try {
fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify(cache, null, 2));
} catch (e) {
$.log(`⚠️ token缓存写入失败: ${e.message}`);
}
}
function updateCachedToken(account, token) {
if (!account || !token || isToken(account)) return;
const cache = readCache();
cache[account] = {
token,
updatedAt: new Date().toISOString(),
};
writeCache(cache);
}
function getResponseToken(headers = {}) {
return (
headers["set-access-token"] ||
headers["Set-Access-Token"] ||
headers["SET-ACCESS-TOKEN"] ||
""
);
}
function buildHeaders(token = "") {
const timestamp = Date.now().toString();
const traceLogId = generateUUID();
const signToken = token ? token.substring(50, 80) : "";
const signStr = `App-Id${APP_ID}Time-Stamp${timestamp}TraceLog-Id${traceLogId}Access-Token${signToken}AimaScrm321_^`;
return {
"App-Id": APP_ID,
"Time-Stamp": timestamp,
"TraceLog-Id": traceLogId,
"Access-Token": token,
Sign: md5(signStr).toLowerCase(),
"content-type": "application/json",
charset: "utf-8",
Referer: "https://servicewechat.com/wx2dcfb409fd5ddfb4/223/page-frame.html",
"User-Agent": USER_AGENT,
};
}
async function request(method, url, token, options = {}) {
const res = await axios({
method,
url,
headers: buildHeaders(token),
timeout: 15000,
validateStatus: () => true,
...options,
});
const newToken = getResponseToken(res.headers);
if (newToken && options.account) {
options.onToken?.(newToken);
updateCachedToken(options.account, newToken);
}
return res;
}
async function getWxCode(account) {
const wxServerUrl = process.env.wx_server_url;
const wxAuth = process.env.wx_auth;
if (!wxServerUrl || !wxAuth) {
throw new Error("未配置 wx_server_url 或 wx_auth,无法获取code登录");
}
const res = await axios.post(
`${wxServerUrl.replace(/\/$/, "")}/wx/operatedata`,
{
appid: MINI_APPID,
openid: account,
},
{
headers: {
auth: wxAuth,
"content-type": "application/json",
},
timeout: 15000,
validateStatus: () => true,
}
);
const code = res.data?.code || res.data?.data?.code;
if (res.status !== 200 || !code) {
throw new Error(`获取code失败: HTTP ${res.status} ${JSON.stringify(res.data)}`);
}
return code;
}
async function loginByCode(account) {
$.log("🔐 正在获取code并登录...");
const code = await getWxCode(account);
const res = await request("post", `${WXCLIENT_URL}/user/members:login`, "", {
data: { code },
account,
});
const token = getResponseToken(res.headers);
if (res.status !== 200 || res.data?.code !== 200 || !token) {
throw new Error(`登录失败: HTTP ${res.status} ${JSON.stringify(res.data)}`);
}
updateCachedToken(account, token);
$.log(`✅ 登录成功,已缓存token: ${maskToken(token)}`);
return token;
}
async function validateToken(account, token) {
const res = await request("get", `${WXCLIENT_URL}/member/IndexInfo`, token, {
account,
});
const ok = res.status === 200 && res.data?.code === 200;
if (!ok) {
$.log(`⚠️ 缓存token失效: HTTP ${res.status} ${JSON.stringify(res.data)}`);
}
return ok;
}
async function getAccessToken(account) {
const value = account.trim();
if (isToken(value)) {
$.log(`ℹ️ 检测到旧token变量,将直接使用: ${maskToken(value)}`);
return value;
}
const cache = readCache();
const cachedToken = cache[value]?.token;
if (cachedToken) {
$.log(`🔎 使用缓存token校验: ${maskToken(cachedToken)}`);
if (await validateToken(value, cachedToken)) {
$.log("✅ 缓存token有效");
return cachedToken;
}
}
return loginByCode(value);
}
// ================== 核心逻辑 ==================
async function signIn(token, index) {
try {
const timestamp = Date.now();
const traceLogId = generateUUID();
async function signIn(account, index) {
let token = await getAccessToken(account);
const setToken = (newToken) => {
token = newToken;
};
// 构造通用请求头
const headers = {
"App-Id": APP_ID,
"Time-Stamp": timestamp.toString(),
"TraceLog-Id": traceLogId,
"Access-Token": token.trim(),
"content-type": "application/json",
"User-Agent": USER_AGENT,
"charset": "utf-8",
"Referer": "https://servicewechat.com/wx2dcfb409fd5ddfb4/215/page-frame.html"
};
// 生成签名(按规则拼接)
const signStr = `${APP_ID}${timestamp}${traceLogId}${token.trim()}AimaScrm321_^`;
headers["Sign"] = md5(signStr).toLowerCase();
// 1. 查询签到状态
$.log(`🚀 账号【${index}】查询签到状态...`);
const searchRes = await axios.post(
`${BASE_URL}/aima/wxclient/mkt/activities/sign:search`,
{ activityId: ACTIVITY_ID },
{ headers, timeout: 10000 }
);
const data = searchRes.data;
if (data.content && data.content.signStatus === 1) {
$.log(`✅ 账号【${index}】今日已签到!`);
return;
$.log(`🚀 账号【${index}】查询签到状态...`);
const searchRes = await request(
"post",
`${WXCLIENT_URL}/mkt/activities/sign:search`,
token,
{
data: { activityId: ACTIVITY_ID },
account,
onToken: setToken,
}
);
// 2. 执行签到
$.log(`⏳ 账号【${index}】正在签到...`);
const joinRes = await axios.post(
`${BASE_URL}/aima/wxclient/mkt/activities/sign:join`,
{ activityId: ACTIVITY_ID, activitySceneId: null },
{ headers, timeout: 10000 }
);
if (searchRes.status !== 200 || searchRes.data?.code !== 200) {
throw new Error(`查询签到状态失败: HTTP ${searchRes.status} ${JSON.stringify(searchRes.data)}`);
}
if (joinRes.data.code === 200 || joinRes.data.code === 0) {
const point = joinRes.data.content?.point || 10;
$.log(`🎉 账号【${index}】签到成功!获得 ${point} 积分`);
} else {
throw new Error(`签到失败: ${JSON.stringify(joinRes.data)}`);
const signStatus = searchRes.data?.content?.signStatus;
if (signStatus === 1) {
$.log(`✅ 账号【${index}】今日已签到!`);
return;
}
$.log(`⏳ 账号【${index}】正在签到...`);
const joinRes = await request(
"post",
`${WXCLIENT_URL}/mkt/activities/sign:join`,
token,
{
data: { activityId: ACTIVITY_ID, activitySceneId: null },
account,
onToken: setToken,
}
);
} catch (e) {
throw new Error(e.message || e);
if (joinRes.status === 200 && joinRes.data?.code === 200) {
const point = joinRes.data.content?.point || joinRes.data.content?.points || 0;
$.log(`🎉 账号【${index}】签到成功!${point ? `获得 ${point} 积分` : ""}`);
} else {
throw new Error(`签到失败: HTTP ${joinRes.status} ${JSON.stringify(joinRes.data)}`);
}
}
// ================== 主函数 ==================
!(async () => {
console.log(`\n🔔 爱玛会员俱乐部, 开始!`);
console.log("\n🔔 爱玛会员俱乐部, 开始!");
// 获取 access-token(支持多账号)
let tokens = [];
let accounts = [];
if ($.isNode()) {
const env = process.env.aima;
if (env) {
tokens = env.split(/&|\n/).filter(t => t.trim());
accounts = env.split(/&|\n/).map((t) => t.trim()).filter(Boolean);
}
}
if (tokens.length === 0) {
$.msg("❌ 未找到 access-token,请配置变量 'aima'");
if (accounts.length === 0) {
$.msg("❌ 未找到账号标识,请配置变量 'aima'");
return;
}
console.log(`共找到${tokens.length}个账号`);
console.log(`共找到${accounts.length}个账号`);
for (let i = 0; i < tokens.length; i++) {
for (let i = 0; i < accounts.length; i++) {
try {
console.log(`\n🚀 user:【${i + 1}】 start work`);
await signIn(tokens[i], i + 1);
await signIn(accounts[i], i + 1);
} catch (e) {
console.log(`❌ 账号【${i + 1}】执行失败: ${e.message}`);
}
}
// 发送通知
//await $.sendMsg($.logs.join("\n"));
// await $.sendMsg($.logs.join("\n"));
})()
.catch((e) => console.log(e))
.finally(() => $.done());
-124
View File
@@ -1,124 +0,0 @@
/*
------------------------------------------
@Author: sm
@Date: 2024.06.07 19:15
@Description: babycare
cron: 30 8 * * *
------------------------------------------
#Notice:
微信小程序抓包的https://api.bckid.com.cn请求头authorization
⚠️【免责声明】
------------------------------------------
1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
*/
const { Env } = require("../tools/env")
const $ = new Env("babycare");
let ckName = `babycare`;
const strSplitor = "#";
const axios = require("axios");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.token = this.user[0];
}
async run() {
await this.info()
await this.signIn()
}
async signIn() {
let options = {
method: 'POST',
url: `https://api.bckid.com.cn/operation/front/bonus/userSign/v3/sign`,
headers: {
'Host': 'api.bckid.com.cn',
'authorization': this.token,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
data: {
}
};
let { data: result } = await axios.request(options);
if (result?.code == '200') {
//打印签到结果
$.log(`🌸账号[${this.index}]` + `🕊当前已签到${result.body.signDaysCountMod}天🎉`);
} else {
$.log(`🌸账号[${this.index}] 签到-失败:${result.message}❌`)
}
}
async info() {
let options = {
url: 'https://api.bckid.com.cn/operation/front/bonus/userBonus/getUserBonus',
headers: {
'Host': 'api.bckid.com.cn',
'authorization': this.token,
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
method: 'POST',
data: {}
}
let { data: result } = await axios.request(options);
if (result?.code == '200') {
//打印签到结果
$.log(`🌸账号[${this.index}]` + `🕊账户当前积分[${result.body.userBonus}],历史积分[${result.body.sumBonus}]💰`);
} else {
$.log(`🌸账号[${this.index}]积分查询失败:${result.message}❌`)
}
}
}
!(async () => {
await getNotice()
$.checkEnv(ckName);
for (let user of $.userList) {
await new Task(user).run();
}
})()
.catch((e) => console.log(e))
.finally(() => $.done());
async function getNotice() {
try {
let options = {
url: `https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json`,
headers: {
"User-Agent": defaultUserAgent,
},
timeout:3000
}
let {
data: res
} = await axios.request(options);
$.log(res)
return res
} catch (e) {}
}
+299 -180
View File
@@ -1,15 +1,18 @@
/*
------------------------------------------
@Author: sm
@Date: 2024.06.07 19:15
@Date: 2026.06.01
@Description: 七彩虹微信小程序 签到&点赞
cron: 30 10 * * *
------------------------------------------
#Notice:
#Notice:
变量名:colorful
抓取
https://interface.skycolorful.com/api 请求头的authorization去掉Bearer # x-authorization去掉Bearer
多账户&或换行
变量值:wx_server 里的 openid/账号标识,多账户&或换行
需要配置:wx_server_url、wx_auth
说明:小程序当前登录链路为 wx.login code -> /api/User/OnLogin 获取 OpenId,
首次换取业务 Token 还需要微信手机号授权 code;现有 wx_server 只能提供 wx.login code。
脚本会复用本地 token 缓存,缓存失效或首次运行时会自动验证 code 登录能力并给出明确原因。
⚠️【免责声明】
------------------------------------------
@@ -22,200 +25,316 @@ https://interface.skycolorful.com/api 请求头的authorization去掉Bearer # x-
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
*/
const { Env } = require("../tools/env")
const { Env } = require("../tools/env.js");
const $ = new Env("colorful七彩虹");
let ckName = `colorful`;
const strSplitor = "#";
const axios = require("axios");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const WeChatServer = require("../wxapp/wcs.js");
const ckName = "colorful";
const strSplitor = "#";
const MINI_APP_ID = "wx49018277e65fc3e1";
const PAGE_VERSION = "91";
const API_BASE = "https://interface.skycolorful.com";
const TOKEN_CACHE_FILE = path.join(__dirname, "colorful_token_cache.json");
const defaultUserAgent =
"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(0xf254173b) XWEB/19027";
const wechat = new WeChatServer({
url: process.env.wx_server_url || "http://192.168.31.196:8787",
appid: MINI_APP_ID,
auth: process.env.wx_auth || "",
});
function readTokenCache() {
try {
if (!fs.existsSync(TOKEN_CACHE_FILE)) return {};
return JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, "utf8")) || {};
} catch (e) {
return {};
}
}
function writeTokenCache(cache) {
try {
fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify(cache, null, 2), "utf8");
} catch (e) {
$.log(`写入token缓存失败: ${e.message || e}`);
}
}
function shortToken(token = "") {
const value = String(token || "").replace(/^Bearer\s+/i, "");
return value ? `${value.slice(0, 6)}***${value.slice(-6)}` : "";
}
function maskPhone(phone = "") {
return String(phone).replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2");
}
function md5(str) {
return crypto.createHash("md5").update(str).digest("hex");
}
function isTokenError(message) {
return /401|403|token|登录|授权|未登录|无效|过期|失效/i.test(String(message || ""));
}
function isSuccess(result) {
return Number(result?.Code) === 0 && result?.Success !== false;
}
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.token = this.user[0];
this.token2 = this.user[1];
this.signStatus = false;
this.expireFlag = false;
}
constructor(env) {
this.index = $.userIdx++;
this.raw = String(env || "").trim();
this.user = this.raw.split(strSplitor);
this.accountId = this.user[0].trim();
this.token = "";
this.refreshToken = "";
this.openId = "";
this.userInfo = {};
this.signStatus = false;
this.isLegacyToken = this.user.length >= 2;
if (this.isLegacyToken) {
this.token = this.user[0].trim();
this.refreshToken = this.user[1].trim();
this.accountId = `legacy:${shortToken(this.token)}`;
}
}
async run() {
await this.getTokenExpireTime()
await this.getUserInfo()
await this.getSignInfo()
async run() {
if (this.isLegacyToken) {
$.log(`账号[${this.index}] 检测到旧版 token 格式,将仅用于迁移缓存`);
this.saveCachedToken();
} else {
const cached = this.getCachedToken();
if (cached?.token) {
this.applyToken(cached);
$.log(`账号[${this.index}] 使用缓存token: ${shortToken(this.token)}`);
if (!(await this.checkToken())) {
this.removeCachedToken();
$.log(`账号[${this.index}] 缓存token失效,重新尝试CODE登录`);
}
}
if (this.signStatus) {
$.log(`账号[${this.index}]已签到`)
return
}
await this.signInV2()
}
async getTokenExpireTime() {
let options = {
method: 'POST',
url: `https://interface.skycolorful.com/api/User/RefreshLoginTime`,
headers: {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/json",
"sec-fetch-dest": "empty",
},
data: { "phone": "" }
}
let { data: result } = await this.request(options);
if (result.Code != 0) {
this.expireFlag = true
}
if (!this.token) {
await this.loginByWxCode();
if (!this.token) return;
}
}
}
async refreshToken(DATA) {
let options = {
method: 'POST',
url: `https://interface.skycolorful.com/api/User/DecryptPhoneNumber`,
headers: {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/json",
"sec-fetch-dest": "empty",
},
data: DATA
}
let { data: result } = await this.request(options);
if (result.Code != 0) {
this.expireFlag = true
} else {
this.token = result.Data.Token
}
}
MD5(str) {
const crypto = require('crypto');
return crypto.createHash('md5').update(str).digest('hex');
}
request(options) {
let appid = "815d8026-9a52-4445-a42c-a5443134232e"
let uuid = $.uuid()
let timestamp = Date.now()
let sign = this.MD5(appid + timestamp + uuid + '2b5c01fb-7640-401a-8188-43a13190a626')
let baseHeaders = {
"User-Agent": defaultUserAgent,
"requestid": uuid,
"appid": appid,
"ticks": "" + timestamp,
"sign": sign,
"authorization": "Bearer " + this.token,
"x-authorization": "Bearer " + this.token2,
"source": "Wx",
"ucsource": "30",
"user-from": "xcx",
await this.getUserInfo();
await this.getSignInfo();
if (this.signStatus) {
$.log(`账号[${this.index}] 今日已签到`);
return;
}
await this.signInV2();
}
}
options.headers = Object.assign(baseHeaders, options.headers)
return axios.request(options)
}
cacheKey() {
return this.isLegacyToken ? this.accountId : this.raw;
}
async signInV2() {
let options = {
method: 'POST',
url: `https://interface.skycolorful.com/api/User/SignV2`,
headers: {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/json",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "cross-site",
"xweb_xhr": "1"
},
data: {
getCachedToken() {
const cache = readTokenCache();
return cache[this.cacheKey()] || null;
}
}
};
let { data: result } = await this.request(options);
if (result?.Code == '0') {
//打印签到结果
$.log(`🌸账号[${this.index}]` + `🕊签到${result.Message}🎉`);
} else {
$.log(`🌸账号[${this.index}] 签到-失败:${result.Message}❌`)
}
saveCachedToken() {
if (!this.token) return;
const cache = readTokenCache();
cache[this.cacheKey()] = {
token: this.token,
refreshToken: this.refreshToken,
openId: this.openId,
userInfo: this.userInfo,
updatedAt: new Date().toISOString(),
};
writeTokenCache(cache);
}
removeCachedToken() {
const cache = readTokenCache();
if (cache[this.cacheKey()]) {
delete cache[this.cacheKey()];
writeTokenCache(cache);
}
this.token = "";
this.refreshToken = "";
this.userInfo = {};
}
applyToken(data = {}) {
this.token = data.token || data.Token || "";
this.refreshToken = data.refreshToken || data.RefreshToken || "";
this.openId = data.openId || data.OpenId || "";
this.userInfo = data.userInfo || data.UserInfo || {};
}
signedHeaders(extra = {}, auth = true) {
const appid = "815d8026-9a52-4445-a42c-a5443134232e";
const requestId = crypto.randomUUID ? crypto.randomUUID() : $.uuid();
const ticks = Date.now();
const headers = {
"User-Agent": defaultUserAgent,
"Referer": `https://servicewechat.com/${MINI_APP_ID}/${PAGE_VERSION}/page-frame.html`,
"Accept": "*/*",
"Accept-Language": "zh-CN,zh;q=0.9",
"Content-Type": "application/json",
"requestId": requestId,
"AppId": appid,
"Ticks": String(ticks),
"Sign": md5(appid + ticks + requestId + "2b5c01fb-7640-401a-8188-43a13190a626"),
"source": "Wx",
"UcSource": "30",
"User-from": "xcx",
"version": "2.0.0",
"xweb_xhr": "1",
...extra,
};
if (auth) {
headers.Authorization = this.token ? `Bearer ${this.token}` : "";
headers["X-Authorization"] = this.refreshToken ? `Bearer ${this.refreshToken}` : "";
}
return headers;
}
}
async getSignInfo() {
let options = {
method: 'GET',
url: `https://interface.skycolorful.com/api/User/IsSignV2`,
headers: {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/json",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
}
}
let { data: result } = await this.request(options);
if (result?.Code == '0') {
//打印签到结果
this.signStatus = result.Data.IsSign
async request(apiPath, { method = "GET", data, params, auth = true } = {}) {
const options = {
method,
url: new URL(apiPath, API_BASE).toString(),
params,
headers: this.signedHeaders({}, auth),
timeout: 15000,
validateStatus: () => true,
};
if (data !== undefined) options.data = data;
const { data: result, status, headers } = await axios.request(options);
if (headers?.["access-token"]) this.token = headers["access-token"];
if (headers?.["x-access-token"]) this.refreshToken = headers["x-access-token"];
if (status === 401 || status === 403) throw new Error(`HTTP ${status}: ${result?.Message || JSON.stringify(result)}`);
if (status !== 200) throw new Error(`HTTP ${status}: ${JSON.stringify(result)}`);
if (!isSuccess(result)) throw new Error(`${result?.Code ?? ""} ${result?.Message || result?.msg || JSON.stringify(result)}`.trim());
if (this.token) this.saveCachedToken();
return result;
}
} else {
}
}
async getUserInfo() {
let options = {
method: 'GET',
url: `https://interface.skycolorful.com/api/User/GetUserInfo`,
headers: {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/json",
"sec-fetch-dest": "empty",
}
}
let { data: result } = await this.request(options);
if (result?.Code == '0') {
//打印签到结果
$.log(`🌸账号[${this.index}]` + `昵称:${result.Data.NickName}` + `积分:${result.Data.Point}`)
}
}
async getLoginCode() {
if (!process.env.wx_auth) throw new Error("缺少 wx_auth,无法从 wx_server 获取 code");
const { data } = await wechat.getCode(this.raw);
const code = data?.code || data?.data?.code;
if (!code) throw new Error(`wx_server 未返回 code: ${JSON.stringify(data)}`);
return code;
}
async loginByWxCode() {
try {
const code = await this.getLoginCode();
const result = await this.request("/api/User/OnLogin", {
method: "POST",
auth: false,
data: { Code: code },
});
this.openId = result?.Data?.OpenId || "";
const token = result?.Data?.Token || result?.Data?.token || "";
const refreshToken = result?.Data?.RefreshToken || result?.Data?.refreshToken || "";
if (token) {
this.token = token;
this.refreshToken = refreshToken;
this.saveCachedToken();
$.log(`账号[${this.index}] CODE登录成功: ${shortToken(this.token)}`);
return;
}
throw new Error(`OnLogin仅返回OpenId=${this.openId || "空"},首次业务登录仍需要微信手机号授权code`);
} catch (e) {
$.log(`账号[${this.index}] CODE登录失败: ${e.message || e}`);
}
}
async checkToken() {
try {
await this.request("/api/User/RefreshLoginTime", {
method: "POST",
data: { phone: "" },
});
return true;
} catch (e) {
return false;
}
}
async signInV2() {
try {
const result = await this.request("/api/User/SignV2", {
method: "POST",
data: {},
});
$.log(`🌸账号[${this.index}]🕊签到${result.Message || "成功"}🎉`);
} catch (e) {
const message = String(e.message || e);
if (/已签到|已签|重复/.test(message)) {
$.log(`🌸账号[${this.index}] 今日已签到`);
return;
}
$.log(`🌸账号[${this.index}] 签到失败:${message}❌`);
if (isTokenError(message)) this.removeCachedToken();
}
}
async getSignInfo() {
try {
const result = await this.request("/api/User/IsSignV2");
this.signStatus = Boolean(result?.Data?.IsSign);
} catch (e) {
const message = String(e.message || e);
$.log(`账号[${this.index}] 查询签到状态失败: ${message}`);
if (isTokenError(message)) this.removeCachedToken();
}
}
async getUserInfo() {
try {
const result = await this.request("/api/User/GetUserInfo");
this.userInfo = result?.Data || {};
this.saveCachedToken();
$.log(`🌸账号[${this.index}]昵称:${this.userInfo.NickName || maskPhone(this.userInfo.Mobile) || "未知"} 积分:${this.userInfo.Point ?? "未知"}`);
} catch (e) {
const message = String(e.message || e);
$.log(`账号[${this.index}] 查询用户失败: ${message}`);
if (isTokenError(message)) this.removeCachedToken();
}
}
}
!(async () => {
await getNotice()
$.checkEnv(ckName);
for (let user of $.userList) {
await new Task(user).run();
}
})()
.catch((e) => console.log(e))
.finally(() => $.done());
// 暂停主运行:当前七彩虹后端首次换取业务 Token 需要微信手机号授权 code,
// 现有 wx_server 只能提供 wx.login code,恢复前不要自动执行任务。
// !(async () => {
// await getNotice();
// $.checkEnv(ckName);
//
// for (const user of $.userList) {
// await new Task(user).run();
// }
// })()
// .catch((e) => console.log(e))
// .finally(() => $.done());
async function getNotice() {
try {
let options = {
url: `https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json`,
headers: {
"User-Agent": defaultUserAgent,
},
timeout: 3000
}
let {
data: res
} = await axios.request(options);
$.log(res)
return res
} catch (e) { }
try {
const options = {
url: "https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json",
headers: {
"User-Agent": defaultUserAgent,
},
timeout: 3000,
};
const { data: res } = await axios.request(options);
$.log(res);
return res;
} catch (e) {}
}
+243 -89
View File
@@ -1,15 +1,13 @@
/*
------------------------------------------
@Author: sm
@Date: 2024.06.07 19:15
@Date: 2026.06.01
@Description: fsdlb 微信小程序逢三得利吧 签到积分
cron: 30 9 * * *
------------------------------------------
#Notice:
https://xiaodian.miyatech.com 小程序逢三得利吧签到积分,使用前请先获取token,方法如下:
打开微信,进入逢三得利吧小程序,点击右下角“我的”,
打开抓包软件抓取https://xiaodian.miyatech.com 请求头的Authorization
抓取到的Authorization值即为token,去掉前面的"bearer ",将剩余部分作为token使用。
变量名:fsdlb
变量值:wx_server 里的 openid/账号标识,多账号用 & 或换行
需要配置:wx_server_url、wx_auth
⚠️【免责声明】
------------------------------------------
@@ -22,113 +20,269 @@ https://xiaodian.miyatech.com 小程序逢三得利吧签到积分,使用前
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
*/
const { Env } = require("../tools/env")
const { Env } = require("../tools/env.js");
const $ = new Env("逢三得利吧小程序");
let ckName = `fsdlb`;
const strSplitor = "#";
const axios = require("axios");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
const fs = require("fs");
const path = require("path");
const WeChatServer = require("../wxapp/wcs.js");
let ckName = "fsdlb";
const MINI_APP_ID = "wxb33ed03c6c715482";
const MERCHANT_APP_NAME = "20230130307725";
const TEMPLATE_VERSION = "0.6.4";
const X_VERSION = "2.3.5";
const CLIENT_ID = "saas-wechat-app";
const APP_PUBLISH_TYPE = 1;
const MINIAPP_ID = 159;
const API_BASE = "https://xiaodian.miyatech.com/api";
const TOKEN_CACHE_FILE = path.join(__dirname, "fsdlb_token_cache.json");
const USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) MicroMessenger/3.9.12 MiniProgramEnv/Windows WindowsWechat/WMPF";
const defaultUserAgent = USER_AGENT;
const wechat = new WeChatServer({
url: process.env.wx_server_url || "http://192.168.31.196:8787",
appid: MINI_APP_ID,
auth: process.env.wx_auth || "",
});
function readTokenCache() {
try {
if (!fs.existsSync(TOKEN_CACHE_FILE)) return {};
return JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, "utf8")) || {};
} catch (e) {
return {};
}
}
function writeTokenCache(cache) {
try {
fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify(cache, null, 2), "utf8");
} catch (e) {
$.log(`写入token缓存失败: ${e.message || e}`);
}
}
function shortToken(token = "") {
const value = String(token).replace(/^bearer\s+/i, "");
return value ? `${value.slice(0, 6)}***${value.slice(-6)}` : "";
}
function maskPhone(phone = "") {
return String(phone).replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2");
}
function pickToken(data = {}) {
return data?.tokenInfo?.access_token || data.accessToken || data.access_token || data.token || "";
}
function isSuccess(result) {
return String(result?.code) === "200";
}
function isTokenError(message) {
return /401|403|M401|M403|token|登录|授权|未登录|无效|过期/i.test(String(message || ""));
}
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.token = "bearer " + this.user[0];
constructor(openid) {
this.index = $.userIdx++;
this.openid = String(openid || "").trim();
this.token = "";
this.userInfo = {};
}
async run() {
await this.info()
await this.signIn()
const cached = this.getCachedToken();
if (cached) {
this.applyToken(cached);
$.log(`账号[${this.index}] 使用缓存token: ${shortToken(this.token)}`);
if (!(await this.checkToken())) {
this.removeCachedToken();
$.log(`账号[${this.index}] 缓存token失效,重新登录`);
}
}
if (!this.token) {
await this.loginByWxCode();
if (!this.token) return;
}
await this.info();
await this.signIn();
}
getCachedToken() {
const cache = readTokenCache();
return cache[this.openid] || null;
}
saveCachedToken() {
if (!this.token) return;
const cache = readTokenCache();
cache[this.openid] = {
accessToken: this.token,
userInfo: this.userInfo,
updatedAt: new Date().toISOString(),
};
writeTokenCache(cache);
}
removeCachedToken() {
const cache = readTokenCache();
if (cache[this.openid]) {
delete cache[this.openid];
writeTokenCache(cache);
}
this.token = "";
this.userInfo = {};
}
applyToken(data = {}) {
this.token = pickToken(data);
this.userInfo = data.userInfo || data.thirdUsrIf || {};
}
getHeaders(extra = {}, auth = true) {
const headers = {
componentSend: "1",
"HH-FROM": MERCHANT_APP_NAME,
"HH-APP": MINI_APP_ID,
"HH-VERSION": TEMPLATE_VERSION,
"X-VERSION": X_VERSION,
"Content-Type": "application/json",
appPublishType: APP_PUBLISH_TYPE,
"HH-CI": CLIENT_ID,
"MARKETING-PLAN-NO": "",
"USER-ENTRANCE-CHANNEL": "",
"USER-ENTRANCE-CHANNEL-KEY": "",
"ONE-ID": this.userInfo.oneId || "",
groupPosId: "",
"User-Agent": USER_AGENT,
...extra,
};
if (auth && this.token) headers.Authorization = `bearer ${this.token}`;
return headers;
}
async request({ method = "GET", path: apiPath, data, params, auth = true }) {
const options = {
method,
url: `${API_BASE}${apiPath.startsWith("/") ? apiPath : `/${apiPath}`}`,
headers: this.getHeaders({}, auth),
timeout: 15000,
validateStatus: () => true,
};
if (params) options.params = params;
if (data !== undefined) options.data = data;
const { data: result, status } = await axios.request(options);
if (status !== 200) throw new Error(`HTTP ${status}: ${JSON.stringify(result)}`);
if (!isSuccess(result)) throw new Error(result?.msg || JSON.stringify(result));
return result.data;
}
async getLoginCode() {
const { data } = await wechat.getCode(this.openid);
const code = data?.code || data?.data?.code;
if (!code) throw new Error(`wx_server 未返回 code: ${JSON.stringify(data)}`);
return code;
}
async loginByWxCode() {
try {
const code = await this.getLoginCode();
const data = await this.request({
method: "POST",
path: "/user/login/wx-jc",
auth: false,
data: {
jsCode: code,
clientId: CLIENT_ID,
myUnionId: "",
appPublishType: APP_PUBLISH_TYPE,
},
});
this.token = pickToken(data);
this.userInfo = data?.thirdUsrIf || {};
if (!this.token) throw new Error(`登录响应未返回token: ${JSON.stringify(data)}`);
this.saveCachedToken();
$.log(`账号[${this.index}] 登录成功: ${maskPhone(this.userInfo.phone) || this.userInfo.oid || ""}`);
} catch (e) {
$.log(`账号[${this.index}] 登录失败: ${e.message || e}`);
}
}
async checkToken() {
try {
await this.request({
path: "/user/auth/member/integral/union/flow/list",
params: { pageNo: 1, pageSize: 1, dataType: "SCORE" },
});
return true;
} catch (e) {
return false;
}
}
async signIn() {
let options = {
method: 'POST',
url: `https://xiaodian.miyatech.com/api/coupon/auth/signIn`,
headers: {
"X-VERSION": "2.1.3",
"Authorization": `${this.token}`,
"HH-VERSION": "0.2.8",
"HH-FROM": "20230130307725",
"HH-APP": "wxb33ed03c6c715482",
"HH-CI": "saas-wechat-app",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
},
data: {
"miniappId": 159
try {
const data = await this.request({
method: "POST",
path: "/coupon/auth/signIn",
data: {
miniappId: MINIAPP_ID,
},
});
$.log(`🕊账号[${this.index}] 签到成功:${data?.integralToastText || "成功"}🎉`);
} catch (e) {
const message = String(e.message || e);
if (/已签到|已签|重复/.test(message)) {
$.log(`🕊账号[${this.index}] 今日已签到`);
return;
}
$.log(`🕊账号[${this.index}] 签到失败:${message}🚫`);
if (isTokenError(message)) this.removeCachedToken();
}
let { data: result } = await axios.request(options)
if (result?.code == 200) {
//打印签到结果
$.log(`🕊账号[${this.index}] 签到成功:[${result.data.integralToastText}]🎉`);
} else {
$.log(`🕊账号[${this.index}] 签到失败:${result.msg}🚫`)
}
}
async info() {
let options = {
method: 'GET',
url: `https://xiaodian.miyatech.com/api/user/auth/member/integral/union/flow/list?pageNo=1&pageSize=10&dataType=SCORE`,
headers: {
"X-VERSION": "2.1.3",
"Authorization": `${this.token}`,
"HH-VERSION": "0.2.8",
"HH-FROM": "20230130307725",
"HH-APP": "wxb33ed03c6c715482",
"HH-CI": "saas-wechat-app",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
},
}
let { data: result } = await axios.request(options)
if (result?.code == 200) {
$.log(`🕊账号[${this.index}] 查询成功:总积分[${result.data.totalScore}]🎉`);
} else {
$.log(`🕊账号[${this.index}] 查询失败:${result.msg}🚫`)
try {
const data = await this.request({
path: "/user/auth/member/integral/union/flow/list",
params: { pageNo: 1, pageSize: 10, dataType: "SCORE" },
});
$.log(`🕊账号[${this.index}] 查询成功:总积分[${data?.totalScore ?? "未知"}]🎉`);
} catch (e) {
const message = String(e.message || e);
$.log(`🕊账号[${this.index}] 查询失败:${message}🚫`);
if (isTokenError(message)) this.removeCachedToken();
}
}
}
!(async () => {
await getNotice()
await getNotice();
$.checkEnv(ckName);
for (let user of $.userList) {
await new Task(user).run();
for (const openid of $.userList) {
await new Task(openid).run();
}
})()
.catch((e) => console.log(e))
.catch((e) => $.log(e.message || e))
.finally(() => $.done());
async function getNotice() {
try {
let options = {
url: `https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json`,
headers: {
"User-Agent": defaultUserAgent,
},
timeout:3000
}
let {
data: res
} = await axios.request(options);
$.log(res)
return res
} catch (e) {}
}
try {
const options = {
url: "https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json",
headers: {
"User-Agent": defaultUserAgent,
},
timeout: 3000,
};
const { data: res } = await axios.request(options);
$.log(res);
return res;
} catch (e) { }
}
+236 -85
View File
@@ -1,18 +1,15 @@
/*
------------------------------------------
@Author: sm
@Date: 2024.06.07 19:15
@Date: 2026.06.01
@Description: 国乐酱酒小程序
cron: 30 9 * * *
------------------------------------------
#Notice:
变量名:gyjj
国乐酱酒小程序签到,使用前请先获取token,方法如下:
打开微信,进入国乐酱酒小程序,点击右下角“我的”,
打开抓包软件抓取https://member.guoyuejiu.com/api/sign/daily/sign 请求头的Authorization
抓取到的Authorization值即为token
#Notice:
变量名: gyjj
变量值:wx_server 里的 openid/账号标识,多账号&或换行
需要配置:wx_server_url、wx_auth
⚠️【免责声明】
------------------------------------------
1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
@@ -24,94 +21,254 @@ cron: 30 9 * * *
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
*/
const { Env } = require("../tools/env")
const { Env } = require("../tools/env.js");
const $ = new Env("国乐酱酒");
let ckName = `gyjj`;
const strSplitor = "#";
const axios = require("axios");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
const fs = require("fs");
const path = require("path");
const ckName = "gyjj";
const strSplitor = "#";
const MINI_APP_ID = "wxeff120e4d11594c0";
const PAGE_VERSION = "87";
const API_BASE = "https://member.guoyuejiu.com/api";
const TOKEN_CACHE_FILE = path.join(__dirname, "gyjj_token_cache.json");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_7_15 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.70(0x1800462d) NetType/WIFI Language/zh_CN";
function readTokenCache() {
try {
if (!fs.existsSync(TOKEN_CACHE_FILE)) return {};
return JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, "utf8")) || {};
} catch (e) {
return {};
}
}
function writeTokenCache(cache) {
try {
fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify(cache, null, 2), "utf8");
} catch (e) {
$.log(`写入token缓存失败: ${e.message || e}`);
}
}
function shortToken(token = "") {
const value = String(token || "").replace(/^Mer/i, "");
return value ? `${value.slice(0, 6)}***${value.slice(-6)}` : "";
}
function isTokenError(message) {
return /1011|401|403|token|登录|授权|失效|过期/i.test(String(message || ""));
}
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.token = this.user[0];
this.index = $.userIdx++;
this.raw = String(env || "").trim();
this.user = this.raw.split(strSplitor);
this.accountId = this.user[0].trim();
this.token = "";
this.sessionKey = "";
this.userId = "";
this.userInfo = {};
this.isLegacyToken = /^Mer|eyJ/i.test(this.accountId) || this.user.length >= 2;
if (this.isLegacyToken) {
this.token = this.accountId.replace(/^Mer/i, "");
this.accountId = `legacy:${shortToken(this.token)}`;
}
}
async run() {
if (this.isLegacyToken) {
$.log(`账号[${this.index}] 检测到旧版token格式,先迁移到缓存`);
this.saveCachedToken();
} else {
const cached = this.getCachedToken();
if (cached?.token) {
this.applyToken(cached);
$.log(`账号[${this.index}] 使用缓存token: ${shortToken(this.token)}`);
if (!(await this.checkToken())) {
this.removeCachedToken();
$.log(`账号[${this.index}] 缓存token失效,重新CODE登录`);
}
}
await this.sign()
await this.account()
if (!this.token) {
await this.loginByWxCode();
if (!this.token) return;
}
}
await this.sign();
await this.account();
}
cacheKey() {
return this.isLegacyToken ? this.accountId : this.raw;
}
getCachedToken() {
const cache = readTokenCache();
return cache[this.cacheKey()] || null;
}
saveCachedToken() {
if (!this.token) return;
const cache = readTokenCache();
cache[this.cacheKey()] = {
token: this.token,
sessionKey: this.sessionKey,
userId: this.userId,
userInfo: this.userInfo,
updatedAt: new Date().toISOString(),
};
writeTokenCache(cache);
}
removeCachedToken() {
const cache = readTokenCache();
if (cache[this.cacheKey()]) {
delete cache[this.cacheKey()];
writeTokenCache(cache);
}
this.token = "";
this.sessionKey = "";
this.userId = "";
this.userInfo = {};
}
applyToken(data = {}) {
this.token = String(data.token || data.authorization || "").replace(/^Mer/i, "");
this.sessionKey = data.sessionKey || "";
this.userId = data.userId || "";
this.userInfo = data.userInfo || {};
}
headers(extra = {}) {
return {
"content-Type": "application/json",
Authorization: `Mer${this.token}`,
"User-Agent": defaultUserAgent,
Referer: `https://servicewechat.com/${MINI_APP_ID}/${PAGE_VERSION}/page-frame.html`,
...extra,
};
}
async request(pathname, { method = "GET", data, params, auth = true, headers = {} } = {}) {
const options = {
method,
url: `${API_BASE}${pathname}`,
params,
data,
headers: auth ? this.headers(headers) : {
"content-Type": "application/json",
"User-Agent": defaultUserAgent,
Referer: `https://servicewechat.com/${MINI_APP_ID}/${PAGE_VERSION}/page-frame.html`,
...headers,
},
timeout: 20000,
validateStatus: () => true,
};
const { data: result, status } = await axios.request(options);
if (status !== 200) throw new Error(`HTTP ${status}: ${JSON.stringify(result)}`);
if (Number(result?.code) !== 0) throw new Error(`${result?.code ?? ""} ${result?.message || JSON.stringify(result)}`.trim());
return result;
}
async getOperateData() {
if (!process.env.wx_auth) throw new Error("缺少 wx_auth,无法从 wx_server 获取登录数据");
const url = (process.env.wx_server_url || "http://192.168.31.196:8787").replace(/\/$/, "");
const { data } = await axios.post(`${url}/wx/operatedata`, {
appid: MINI_APP_ID,
openid: this.raw,
}, {
headers: { auth: process.env.wx_auth },
timeout: 45000,
validateStatus: () => true,
});
const result = data?.data || {};
if (!data?.status || !result.code) throw new Error(`wx_server 未返回code: ${JSON.stringify(data)}`);
let userInfo = {};
try {
userInfo = JSON.parse(result.data || "{}");
} catch (e) {}
return { code: result.code, userInfo };
}
async loginByWxCode() {
try {
const wxData = await this.getOperateData();
const user = wxData.userInfo || {};
const payload = {
avatarUrl: user.avatarUrl || "",
city: user.city || "",
country: user.country || "",
gender: user.gender || 0,
nickName: user.nickName || user.nickname || "微信用户",
province: user.province || "",
code: wxData.code,
source: 2,
};
const result = await this.request("/user/wxLogin", {
method: "POST",
data: payload,
auth: false,
});
const data = result?.data || {};
if (!data.authorization) throw new Error(`登录响应未返回authorization: ${JSON.stringify(result)}`);
this.token = data.authorization;
this.sessionKey = data.sessionKey || "";
this.userId = data.userId || "";
this.saveCachedToken();
$.log(`账号[${this.index}] CODE登录成功: ${shortToken(this.token)}`);
} catch (e) {
$.log(`账号[${this.index}] CODE登录失败: ${e.message || e}`);
}
}
async checkToken() {
try {
await this.request("/user/info");
return true;
} catch (e) {
return false;
}
}
async sign() {
try {
let options = {
method: 'get',
url: `https://member.guoyuejiu.com/api/sign/daily/sign`,
headers: {
"Authorization": this.token,
"User-Agent": 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_7_15 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.70(0x1800462d) NetType/WIFI Language/zh_CN',
"Referer": "https://servicewechat.com/wxeff120e4d11594c0/85/page-frame.html"
},
}
let { data: result } = await axios.request(options)
if (result?.code == 0) {
//打印签到结果
$.log(`🕊账号[${this.index}] 签到成功:签到[${result.data.spanSumDays}]天🎉`);
this.mist = result.data.spanSumDays
} else {
$.log(`🕊账号[${this.index}] 签到失败:${result.message}⛔`)
}
const result = await this.request("/sign/daily/sign");
$.log(`🕊账号[${this.index}] 签到成功:签到[${result.data?.spanSumDays ?? "未知"}]天🎉`);
} catch (e) {
console.log(e);
const message = String(e.message || e);
if (/已签|重复|今日/.test(message)) {
$.log(`🕊账号[${this.index}] 今日已签到`);
return;
}
$.log(`🕊账号[${this.index}] 签到失败:${message}⛔`);
if (isTokenError(message)) this.removeCachedToken();
}
}
//
async account() {
try {
let options = {
method: 'get',
url: `https://member.guoyuejiu.com/api/user/info`,
headers: {
"Authorization": this.token,
"User-Agent": 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_7_15 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.70(0x1800462d) NetType/WIFI Language/zh_CN',
"Referer": "https://servicewechat.com/wxeff120e4d11594c0/85/page-frame.html"
}
}
let { data: result } = await axios.request(options)
if (result?.code == 0) {
//打印签到结果
$.log(`🕊账号[${this.index}] 查询成功:总积分[${result.data.score}]🎉`);
} else {
$.log(`🕊账号[${this.index}] 查询失败:${result.message}🚫`)
}
const result = await this.request("/user/info");
this.userInfo = result.data || {};
this.saveCachedToken();
$.log(`🕊账号[${this.index}] 查询成功:总积分[${result.data?.score ?? "未知"}]🎉`);
} catch (e) {
console.log(e);
const message = String(e.message || e);
$.log(`🕊账号[${this.index}] 查询失败:${message}🚫`);
if (isTokenError(message)) this.removeCachedToken();
}
}
}
!(async () => {
await getNotice()
await getNotice();
$.checkEnv(ckName);
for (let user of $.userList) {
for (const user of $.userList) {
await new Task(user).run();
}
})()
@@ -119,19 +276,13 @@ class Task {
.finally(() => $.done());
async function getNotice() {
try {
let options = {
url: `https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json`,
headers: {
"User-Agent": defaultUserAgent,
},
timeout:3000
}
let {
data: res
} = await axios.request(options);
$.log(res)
return res
} catch (e) {}
}
try {
const { data: res } = await axios.request({
url: "https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json",
headers: { "User-Agent": defaultUserAgent },
timeout: 3000,
});
$.log(res);
return res;
} catch (e) {}
}
+422 -215
View File
@@ -1,13 +1,14 @@
/*
------------------------------------------
@Author: sm
@Date: 2024.06.07 19:15
@Date: 2026.06.01
@Description: 海天美味馆小程序
cron: 30 11 * * *
------------------------------------------
#Notice:
抓取https://cmallapi.xkmm.cn请求头的authorization和uuid参数,填入环境变量,格式如下:
authorization#uuid 多账号&或换行
#Notice:
变量名 haitian
变量值:wx_server 里的 openid/账号标识,多账号&或换行
需要配置:wx_server_url、wx_auth
⚠️【免责声明】
------------------------------------------
@@ -17,235 +18,447 @@ authorization#uuid 多账号&或换行
4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此免责声明。
*/
const { Env } = require("../tools/env")
const { Env } = require("../tools/env.js");
const $ = new Env("海天美味馆小程序");
let ckName = `haitian`;
const strSplitor = "#";
const axios = require("axios");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
const fs = require("fs");
const path = require("path");
const ckName = "haitian";
const strSplitor = "#";
const MINI_APP_ID = "wx7a890ea13f50d7b6";
const PAGE_VERSION = "772";
const API_BASE = "https://cmallapi.xkmm.cn/buyer-api";
const BASE_API = "https://cmallapi.xkmm.cn/base-api";
const TOKEN_CACHE_FILE = path.join(__dirname, "haitian_token_cache.json");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_7_15 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.70(0x1800462d) NetType/WIFI Language/zh_CN";
function readTokenCache() {
try {
if (!fs.existsSync(TOKEN_CACHE_FILE)) return {};
return JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, "utf8")) || {};
} catch (e) {
return {};
}
}
function writeTokenCache(cache) {
try {
fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify(cache, null, 2), "utf8");
} catch (e) {
$.log(`写入token缓存失败: ${e.message || e}`);
}
}
function shortToken(token = "") {
const value = String(token || "");
return value ? `${value.slice(0, 6)}***${value.slice(-6)}` : "";
}
function maskPhone(phone = "") {
return String(phone || "").replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2");
}
function randomUuid(len = 20) {
const chars = "abcdef0123456789";
let value = "";
for (let i = 0; i < len; i++) value += chars[Math.floor(Math.random() * chars.length)];
return value;
}
function isTokenError(message) {
return /401|403|token|登录|授权|失效|过期|no-show-toast/i.test(String(message || ""));
}
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.token = this.user[0];
this.index = $.userIdx++;
this.raw = String(env || "").trim();
this.user = this.raw.split(strSplitor);
this.accountId = this.user[0].trim();
this.token = "";
this.refreshToken = "";
this.communityToken = "";
this.uuid = randomUuid();
this.activity_code = "";
this.userFlag = false;
this.headers = {};
this.uuid = this.user[1]
this.headers = {
"Connection": "keep-alive",
"envVersion": "release",
"content-type": "application/json",
"Authorization": "" + this.token,
"uuid": "" + this.uuid,
"Accept-Encoding": "gzip,compress,br,deflate",
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_7_15 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.70(0x1800462d) NetType/WIFI Language/zh_CN",
"Referer": "https://servicewechat.com/wx7a890ea13f50d7b6/765/page-frame.html"
this.userInfo = {};
this.isLegacyToken = this.user.length >= 2;
if (this.isLegacyToken) {
this.token = this.user[0].trim();
this.uuid = this.user[1].trim() || this.uuid;
this.accountId = `legacy:${shortToken(this.token)}`;
}
}
async run() {
await this.getUserInfo()
if (this.userFlag) {
await this.task_1()
await this.task_2()
await this.getSignActivity()
if (this.activity_code) {
await this.signIn()
await this.getLotteryTaskList()
await this.getLotteryNum()
}
}
}
async getUserInfo() {
let options = {
method: 'GET',
url: `https://cmallapi.xkmm.cn/buyer-api/members`,
headers: this.headers
}
let { data: result } = await axios.request(options);
if (result?.member_id) {
$.log(`🌸账号[${this.index}] [${result.member_id}][${result.mobile}] 当前积分[${result.consum_point}]` + `🎉`);
this.userFlag = true;
if (this.isLegacyToken) {
$.log(`账号[${this.index}] 检测到旧版 authorization#uuid 格式,先迁移到缓存`);
this.saveCachedToken();
} else {
$.log(`🌸账号[${this.index}] 查询-失败:${JSON.stringify(result)}❌`)
}
}
async getSignActivity() {
let options = {
method: 'GET',
url: `https://cmallapi.xkmm.cn/buyer-api/sign/activity/code?activityCode=`,
headers: this.headers
}
let { data: result } = await axios.request(options);
if (result?.activity_code) {
$.log(`获取活动信息成功,活动ID:${result.activity_code}`)
this.activity_code = result.activity_code
}
else {
$.log(`获取活动信息失败:${JSON.stringify(result)}❌`)
}
}
async signIn() {
try {
let options = {
url: `https://cmallapi.xkmm.cn/buyer-api/sign/activity/sign`,
method: "POST",
headers: this.headers,
data: JSON.stringify({ "activity_code": this.activity_code, "fill_date": "" })
}
let { data: result } = await axios.request(options)
if (result.is_sign == true) {
$.log(`签到成功`)
} else {
$.log(`签到失败 [${result.message}]`)
}
} catch (e) {
$.log(`签到失败 [${JSON.stringify(e.message)}]`)
}
}
//浏览页面
async task_1() {
let options = {
url: `https://cmallapi.xkmm.cn/buyer-api/members/browsePage`,
method: "POST",
headers: this.headers,
data: JSON.stringify({})
}
let { data: result } = await axios.request(options)
if (result?.code == 200) {
$.log(`浏览界面 操作成功`)
} else {
$.log(`浏览界面 操作失败[${JSON.stringify(result)}]`)
}
}
//浏览社区
async task_2() {
let options = {
url: `https://cmallapi.xkmm.cn/buyer-api/members/commnity/brosing/duration/add?seconds=10`,
method: "POST",
headers: this.headers,
data: JSON.stringify({})
}
let { data: result } = await axios.request(options)
if (result?.statusCode == 200) {
$.log(`浏览社区 操作成功`)
} else {
$.log(`浏览社区 操作失败 貌似是正常的 [${result}]`)
}
}
async doLottery() {
let options = {
method: 'GET',
url: `https://cmallapi.xkmm.cn/buyer-api/lucky/activity/extract?activityCode=jfcj${this.activity_code}`,
headers: this.headers
}
let { data: result } = await axios.request(options);
if (result?.lucky_record_vo) {
$.log(`🌸账号[${this.index}]` + `🕊抽奖结果:${result.lucky_record_vo.prize_name}🎉`);
} else {
$.log(`🌸账号[${this.index}] 抽奖-失败:${JSON.stringify(result)}❌`)
}
}
async getLotteryTaskList() {
let options = {
method: 'GET',
url: `https://cmallapi.xkmm.cn/buyer-api/lucky/task/package/jfcj${this.activity_code}`,
headers: this.headers
}
let { data: result } = await axios.request(options);
if (result?.member_id) {
$.log(`🌸账号[${this.index}]` + `🕊抽奖次数任务🎉`);
for (let task of result.task_list) {
if (task.today_available_task_number >= 1 && task.today_obtained_task_number < task.today_available_task_number) {
if (task.task_key == "LOGIN") {
$.log(`🌸账号[${this.index}]` + `🕊正在完成任务:${task.task_name}🎉`);
let options = {
url: `https://cmallapi.xkmm.cn/buyer-api/lucky/task/getLoginOpporturnity/jfcj${this.activity_code}`,
method: "PUT",
headers: this.headers,
data: JSON.stringify({})
}
let { data: result } = await axios.request(options)
$.log(result)
}
if (task.task_key == "SHARE") {
}
if (task.task_key == "BROWSE_PAGE_TASK") {
$.log(`🌸账号[${this.index}]` + `🕊正在完成任务:${task.task_name}🎉`);
await this.lotteryTaskBrowser(task.link)
}
const cached = this.getCachedToken();
if (cached?.accessToken) {
this.applyToken(cached);
$.log(`账号[${this.index}] 使用缓存token: ${shortToken(this.token)}`);
if (!(await this.checkToken())) {
this.removeCachedToken();
$.log(`账号[${this.index}] 缓存token失效,重新CODE登录`);
}
}
} else {
$.log(`🌸账号[${this.index}] 抽奖次数任务-失败:${JSON.stringify(result)}❌`)
}
}
async lotteryTaskBrowser(link) {
let optionsStart = {
url: `https://cmallapi.xkmm.cn/buyer-api/lucky/task/browse/page/start/jfcj${this.activity_code}?pageUrl=${link}`,
method: "GET",
headers: this.headers
}
await axios.request(optionsStart)
await $.wait(20 * 1000)
let optionsEnd = {
url: `https://cmallapi.xkmm.cn/buyer-api/lucky/task/browse/page/end/jfcj${this.activity_code}?pageUrl=${link}`,
method: "GET",
headers: this.headers
}
await axios.request(optionsEnd)
}
async getLotteryNum() {
let options = {
url: `https://cmallapi.xkmm.cn/buyer-api/lucky/activity/opporturnity?activityCode=jfcj${this.activity_code}`,
method: "GET",
headers: this.headers
}
let { data: result } = await axios.request(options)
if (result.can_use > 0) {
$.log(`当前剩余抽奖次数:${result.can_use}`)
for (let can = 0; can < result.can_use; can++) {
await this.doLottery()
if (!this.token) {
await this.loginByWxCode();
if (!this.token) return;
}
} else {
$.log(`当前剩余抽奖次数0`)
}
await this.getUserInfo();
if (!this.userFlag) return;
await this.task_1();
await this.task_2();
await this.getSignActivity();
if (this.activity_code) {
await this.signIn();
await this.getLotteryTaskList();
await this.getLotteryNum();
}
}
cacheKey() {
return this.isLegacyToken ? this.accountId : this.raw;
}
getCachedToken() {
const cache = readTokenCache();
return cache[this.cacheKey()] || null;
}
saveCachedToken() {
if (!this.token) return;
const cache = readTokenCache();
cache[this.cacheKey()] = {
accessToken: this.token,
refreshToken: this.refreshToken,
communityToken: this.communityToken,
uuid: this.uuid,
userInfo: this.userInfo,
updatedAt: new Date().toISOString(),
};
writeTokenCache(cache);
}
removeCachedToken() {
const cache = readTokenCache();
if (cache[this.cacheKey()]) {
delete cache[this.cacheKey()];
writeTokenCache(cache);
}
this.token = "";
this.refreshToken = "";
this.communityToken = "";
this.userInfo = {};
}
applyToken(data = {}) {
this.token = data.accessToken || data.token || "";
this.refreshToken = data.refreshToken || "";
this.communityToken = data.communityToken || "";
this.uuid = data.uuid || this.uuid;
this.userInfo = data.userInfo || {};
}
headers(extra = {}, auth = true, isJson = false) {
const headers = {
"Connection": "keep-alive",
"envVersion": "release",
"Content-Type": isJson ? "application/json" : "application/x-www-form-urlencoded",
"uuid": this.uuid,
"Accept-Encoding": "gzip,compress,br,deflate",
"User-Agent": defaultUserAgent,
"Referer": `https://servicewechat.com/${MINI_APP_ID}/${PAGE_VERSION}/page-frame.html`,
...extra,
};
if (auth) {
headers.Authorization = this.token;
if (this.communityToken) headers["X-Haday-Token"] = this.communityToken;
}
return headers;
}
async request(pathname, { method = "GET", params, data, auth = true, isJson = false, base = API_BASE } = {}) {
const options = {
method,
url: `${base}${pathname}`,
params,
headers: this.headers({}, auth, isJson),
timeout: 20000,
validateStatus: () => true,
};
if (data !== undefined) options.data = isJson ? data : new URLSearchParams(data).toString();
const { data: result, status } = await axios.request(options);
if (status === 401 || status === 403) throw new Error(`HTTP ${status}: ${result?.message || JSON.stringify(result)}`);
if (status < 200 || status >= 300) throw new Error(`HTTP ${status}: ${JSON.stringify(result)}`);
if (result && typeof result === "object" && result.code && !["200", "0"].includes(String(result.code))) {
throw new Error(`${result.code} ${result.message || result.msg || JSON.stringify(result)}`.trim());
}
return result;
}
async getOperateData() {
if (!process.env.wx_auth) throw new Error("缺少 wx_auth,无法从 wx_server 获取登录数据");
const url = (process.env.wx_server_url || "http://192.168.31.196:8787").replace(/\/$/, "");
const { data } = await axios.post(`${url}/wx/operatedata`, {
appid: MINI_APP_ID,
openid: this.accountId,
}, {
headers: { auth: process.env.wx_auth },
timeout: 45000,
validateStatus: () => true,
});
const result = data?.data || {};
if (!data?.status || !result.code || !result.encryptedData || !result.iv) {
throw new Error(`wx_server 未返回完整登录数据: ${JSON.stringify(data)}`);
}
return result;
}
async getArticleIds() {
try {
const result = await this.request("/pages/REGISTRATION_AGREEMENT,PRIVACY_PROTECTION_CLAUSE/articles/list", {
base: BASE_API,
auth: false,
});
const ids = Array.isArray(result) ? result.map(item => item.article_id).filter(Boolean) : [];
return ids.join(",");
} catch (e) {
$.log(`账号[${this.index}] 获取协议ID失败,继续登录: ${e.message || e}`);
return "";
}
}
async loginByWxCode() {
try {
const wxData = await this.getOperateData();
const articleIds = await this.getArticleIds();
const params = {
edata: wxData.encryptedData,
iv: wxData.iv,
code: wxData.code,
uuid: this.uuid,
article_ids: articleIds,
app_versions: "1.0.0",
};
const result = await this.request("/wechat/mini/phoneNew/login", {
method: "POST",
params,
auth: false,
});
const token = result?.access_token || result?.accessToken || "";
if (!result?.success || !token) throw new Error(`登录响应未返回token: ${JSON.stringify(result)}`);
this.token = token;
this.refreshToken = result.refresh_token || result.refreshToken || "";
await this.loginCommunityToken().catch(() => {});
this.saveCachedToken();
$.log(`账号[${this.index}] CODE登录成功: ${shortToken(this.token)}`);
} catch (e) {
$.log(`账号[${this.index}] CODE登录失败: ${e.message || e}`);
}
}
async loginCommunityToken() {
if (!this.token) return;
const result = await this.request("/wx/auth/loginByToken", {
method: "POST",
base: "https://cmallwap.xkmm.cn/haday",
data: { access_token: this.token },
auth: false,
isJson: true,
});
this.communityToken = result?.data || result || "";
this.saveCachedToken();
}
async checkToken() {
try {
await this.request("/members");
return true;
} catch (e) {
return false;
}
}
async getUserInfo() {
try {
const result = await this.request("/members");
if (result?.member_id) {
this.userInfo = result;
this.saveCachedToken();
$.log(`🌸账号[${this.index}] [${result.member_id}][${maskPhone(result.mobile)}] 当前积分[${result.consum_point}]🎉`);
this.userFlag = true;
} else {
$.log(`🌸账号[${this.index}] 查询-失败:${JSON.stringify(result)}❌`);
}
} catch (e) {
const message = e.message || e;
$.log(`🌸账号[${this.index}] 查询-失败:${message}❌`);
if (isTokenError(message)) this.removeCachedToken();
}
}
async getSignActivity() {
try {
const result = await this.request("/sign/activity/code", {
params: { activityCode: "" },
});
if (result?.activity_code) {
$.log(`获取活动信息成功,活动ID:${result.activity_code}`);
this.activity_code = result.activity_code;
} else {
$.log(`获取活动信息失败:${JSON.stringify(result)}❌`);
}
} catch (e) {
$.log(`获取活动信息失败:${e.message || e}❌`);
}
}
async signIn() {
try {
const result = await this.request("/sign/activity/sign", {
method: "POST",
isJson: true,
data: { activity_code: this.activity_code, fill_date: "" },
});
if (result?.is_sign === true || result?.success === true) {
$.log("签到成功");
} else {
$.log(`签到失败 [${result?.message || JSON.stringify(result)}]`);
}
} catch (e) {
const message = String(e.message || e);
if (/已签|重复/.test(message)) {
$.log("今日已签到");
return;
}
$.log(`签到失败 [${message}]`);
}
}
async task_1() {
try {
const result = await this.request("/members/browsePage", {
method: "POST",
data: {},
});
if (result?.code == 200 || result?.statusCode == 200 || result === "") {
$.log("浏览界面 操作成功");
} else {
$.log(`浏览界面 操作失败[${JSON.stringify(result)}]`);
}
} catch (e) {
$.log(`浏览界面 操作失败[${e.message || e}]`);
}
}
async task_2() {
try {
const result = await this.request("/members/commnity/brosing/duration/add", {
method: "POST",
params: { seconds: 10 },
data: {},
});
if (result?.statusCode == 200 || result?.code == 200 || result === "") {
$.log("浏览社区 操作成功");
} else {
$.log(`浏览社区 操作失败 貌似是正常的 [${JSON.stringify(result)}]`);
}
} catch (e) {
$.log(`浏览社区 操作失败 貌似是正常的 [${e.message || e}]`);
}
}
async doLottery() {
try {
const result = await this.request("/lucky/activity/extract", {
params: { activityCode: `jfcj${this.activity_code}` },
});
if (result?.lucky_record_vo) {
$.log(`🌸账号[${this.index}]🕊抽奖结果:${result.lucky_record_vo.prize_name}🎉`);
} else {
$.log(`🌸账号[${this.index}] 抽奖-失败:${JSON.stringify(result)}❌`);
}
} catch (e) {
$.log(`🌸账号[${this.index}] 抽奖-失败:${e.message || e}❌`);
}
}
async getLotteryTaskList() {
try {
const result = await this.request(`/lucky/task/package/jfcj${this.activity_code}`);
if (result?.member_id) {
$.log(`🌸账号[${this.index}]🕊抽奖次数任务🎉`);
for (const task of result.task_list || []) {
if (task.today_available_task_number >= 1 && task.today_obtained_task_number < task.today_available_task_number) {
if (task.task_key === "LOGIN") {
$.log(`🌸账号[${this.index}]🕊正在完成任务:${task.task_name}🎉`);
const res = await this.request(`/lucky/task/getLoginOpporturnity/jfcj${this.activity_code}`, {
method: "PUT",
data: {},
});
$.log(JSON.stringify(res));
}
if (task.task_key === "BROWSE_PAGE_TASK") {
$.log(`🌸账号[${this.index}]🕊正在完成任务:${task.task_name}🎉`);
await this.lotteryTaskBrowser(task.link);
}
}
}
} else {
$.log(`🌸账号[${this.index}] 抽奖次数任务-失败:${JSON.stringify(result)}❌`);
}
} catch (e) {
$.log(`🌸账号[${this.index}] 抽奖次数任务-失败:${e.message || e}❌`);
}
}
async lotteryTaskBrowser(link) {
await this.request(`/lucky/task/browse/page/start/jfcj${this.activity_code}`, {
params: { pageUrl: link },
}).catch(() => {});
await $.wait(20 * 1000);
await this.request(`/lucky/task/browse/page/end/jfcj${this.activity_code}`, {
params: { pageUrl: link },
}).catch(() => {});
}
async getLotteryNum() {
try {
const result = await this.request("/lucky/activity/opporturnity", {
params: { activityCode: `jfcj${this.activity_code}` },
});
if (result?.can_use > 0) {
$.log(`当前剩余抽奖次数:${result.can_use}`);
for (let can = 0; can < result.can_use; can++) {
await this.doLottery();
}
} else {
$.log("当前剩余抽奖次数0");
}
} catch (e) {
$.log(`查询抽奖次数失败:${e.message || e}`);
}
}
}
!(async () => {
await getNotice()
await getNotice();
$.checkEnv(ckName);
for (let user of $.userList) {
for (const user of $.userList) {
await new Task(user).run();
}
})()
@@ -253,19 +466,13 @@ class Task {
.finally(() => $.done());
async function getNotice() {
try {
let options = {
url: `https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json`,
headers: {
"User-Agent": defaultUserAgent,
},
timeout:3000
}
let {
data: res
} = await axios.request(options);
$.log(res)
return res
} catch (e) {}
}
try {
const { data: res } = await axios.request({
url: "https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json",
headers: { "User-Agent": defaultUserAgent },
timeout: 3000,
});
$.log(res);
return res;
} catch (e) {}
}
+118 -18
View File
@@ -7,7 +7,8 @@ cron: 30 7 * * *
------------------------------------------
#Notice:
变量名hezj
抓取https://zjrs.haier.net请求头accounttoken 多账户&或换行
变量值填写 wx_server 里的 openid/账号标识,多账户&或换行
需要配置 wx_server_url、wx_auth
⚠️【免责声明】
------------------------------------------
@@ -25,47 +26,144 @@ const $ = new Env("海尔智家");
let ckName = `hezj`;
const strSplitor = "#";
const axios = require("axios");
const crypto = require("crypto");
const WeChatCodeServer = require("../wxapp/wcs");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
const MINI_APP_ID = "wxe24b2f1f4e378891";
const PAGE_VERSION = "475";
const HA_APP_ID = "MB-SHEZJAPPWXXCX-0000";
const HA_APP_KEY = "79ce99cc7f9804663939676031b8a427";
const API_HOST = "https://zj.haier.net";
const wechat = new WeChatCodeServer({
url: process.env.wx_server_url || "http://192.168.31.196:8787",
appid: MINI_APP_ID,
auth: process.env.wx_auth || "",
});
function sign256(path, body, timestamp) {
const bodyStr = body ? JSON.stringify(body) : "";
return crypto.createHash("sha256").update(path + bodyStr + HA_APP_ID + HA_APP_KEY + timestamp).digest("hex");
}
function maskToken(token = "") {
if (!token) return "";
return token.length > 14 ? `${token.slice(0, 6)}...${token.slice(-6)}` : token;
}
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.token = this.user[0];
this.openid = this.user[0].trim();
this.token = "";
this.clientId = `${Date.now()}${$.randomString(12)}`;
}
request(options) {
const path = options.path || new URL(options.url).pathname;
const timestamp = Date.now();
let baseHeaers = {
"host": "zj.haier.net",
"content-type": "application/json",
"accounttoken": this.token,
"appid": "MB-UZHSH-0001",
"Content-Type": "application/json;charset=UTF-8",
"appId": HA_APP_ID,
"appKey": HA_APP_KEY,
"timestamp": timestamp,
"platForm": "sc-mp-wx-zjapp",
"ENV": "",
"accessToken": options.isHeaderDelToken ? "" : this.token,
"accountToken": options.isHeaderDelToken ? "" : this.token,
"ak": options.isHeaderDelToken ? "" : this.token,
"clientId": this.clientId,
"accept": "*/*",
"sec-fetch-site": "same-site",
"appversion": "10.18.0",
//"clientid": "5D6FD623-11A7-4B62-88AD-D3D62D07B72F",
"accept-language": "zh-CN,zh-Hans;q=0.9",
"accept-encoding": "gzip, deflate, br",
"sec-fetch-mode": "cors",
"origin": "https://zjrs.haier.net",
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_7_15 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Hainer/Haier Simulation/Nebula App/Uplus Nebula mPaaSClient",
"referer": "https://zjrs.haier.net/",
"sec-fetch-dest": "empty"
"user-agent": defaultUserAgent,
"referer": `https://servicewechat.com/${MINI_APP_ID}/${PAGE_VERSION}/page-frame.html`,
}
options.headers = Object.assign(baseHeaers, options.headers)
if (options.isSign256) {
baseHeaers.sign = sign256(path, options.data, timestamp);
}
options.headers = Object.assign(baseHeaers, options.headers || {});
delete options.path;
delete options.isSign256;
delete options.isHeaderDelToken;
return axios.request(options)
}
async run() {
await this.loginByWxCode();
if (!this.token) return;
await this.pointInfo()
await this.signIn()
}
async getLoginCode() {
if (!process.env.wx_auth) throw new Error("缺少 wx_auth,无法从 wx_server 获取 code");
const { data } = await wechat.getCode(this.openid);
const code = data?.code || data?.data?.code;
if (!code) throw new Error(`wx_server 未返回 code: ${JSON.stringify(data)}`);
return code;
}
async loginByWxCode() {
try {
const code = await this.getLoginCode();
const tokenInfo = await this.jscode2session(code);
const accountToken = tokenInfo?.accountToken;
if (!accountToken) throw new Error(`登录响应未返回 accountToken: ${JSON.stringify(tokenInfo)}`);
await this.queryUserInfo(accountToken);
this.token = accountToken;
$.log(`账号[${this.index}] CODE登录成功: ${maskToken(this.token)}`);
} catch (e) {
$.log(`账号[${this.index}] CODE登录失败: ${e.message || e}`);
}
}
async jscode2session(code) {
const path = "/api-gw/oauthserver/applet/v1/jscode2session";
let options = {
method: "POST",
url: API_HOST + path,
path,
isSign256: true,
isHeaderDelToken: true,
data: { code },
};
const { data: result } = await this.request(options);
if (result?.retCode !== "00000" && result?.code !== 200 && !result?.success) {
throw new Error(result?.retInfo || result?.message || JSON.stringify(result));
}
return result?.data?.tokenInfo || result?.data || {};
}
async queryUserInfo(accountToken) {
const path = "/api-gw/oauthserver/applet/v1/userinfo/query";
let options = {
method: "POST",
url: API_HOST + path,
path,
isSign256: true,
isHeaderDelToken: true,
data: { accountToken },
};
const { data: result } = await this.request(options);
if (result?.retCode !== "00000" && result?.code !== 200 && !result?.success) {
throw new Error(result?.retInfo || result?.message || JSON.stringify(result));
}
const info = result?.data?.userinfo || {};
const name = info.nickName || info.nickname || info.userName || "未知用户";
const phone = info.mobile || info.phoneNumber || "";
$.log(`账号[${this.index}] 用户: ${name}${phone ? ` ${phone.slice(0, 3)}****${phone.slice(-4)}` : ""}`);
return info;
}
async pointInfo() {
const path = "/zjapi/zjBaseServer/signDetail/getUserPointsAndWallet";
let options = {
method: 'POST',
url: `https://zj.haier.net/zjapi/zjBaseServer/signDetail/getUserPointsAndWallet`,
url: API_HOST + path,
path,
headers: {},
data: {
@@ -82,9 +180,11 @@ class Task {
}
async signIn() {
const path = "/api-gw/zjBaseServer/daily/sign";
let options = {
method: 'POST',
url: `https://zj.haier.net/api-gw/zjBaseServer/daily/sign`,
url: API_HOST + path,
path,
headers: {},
data: {
+332 -249
View File
@@ -1,15 +1,14 @@
/*
------------------------------------------
@Author: sm
@Date: 2024.06.07 19:15
@Date: 2026.06.01
@Description: IQOO社区小程序 积分脚本
cron: 30 8 * * *
------------------------------------------
#Notice:
变量名iqoo
抓取方法:https://bbs-api.iqoo.com请求头authorization 去掉Bearer
多账户&或换行
#Notice:
变量名 iqoo
变量值:wx_server 里的 openid/账号标识,多账户&或换行
需要配置:wx_server_url、wx_auth
⚠️【免责声明】
------------------------------------------
@@ -22,274 +21,362 @@ cron: 30 8 * * *
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
*/
const { Env } = require("../tools/env")
const { Env } = require("../tools/env.js");
const $ = new Env("iqoo社区");
let ckName = `iqoo`;
const strSplitor = "#";
const axios = require("axios");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const ckName = "iqoo";
const strSplitor = "#";
const MINI_APP_ID = "wxcf4266fbc9463132";
const PAGE_VERSION = "253";
const API_BASE = "https://bbs-api.iqoo.com/api/";
const TOKEN_CACHE_FILE = path.join(__dirname, "iqoo_token_cache.json");
const SIGN_SECRET = "2618194b0ebb620055e19cf9811d3c13";
const 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(0xf254173b) XWEB/19027";
const defaultUserAgent = USER_AGENT;
function readTokenCache() {
try {
if (!fs.existsSync(TOKEN_CACHE_FILE)) return {};
return JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, "utf8")) || {};
} catch (e) {
return {};
}
}
function writeTokenCache(cache) {
try {
fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify(cache, null, 2), "utf8");
} catch (e) {
$.log(`写入token缓存失败: ${e.message || e}`);
}
}
function shortToken(token = "") {
const value = String(token || "").replace(/^Bearer\s+/i, "");
return value ? `${value.slice(0, 6)}***${value.slice(-6)}` : "";
}
function isSuccess(result) {
return Number(result?.Code) === 0;
}
function isTokenError(message) {
return /-4011|401|403|token|登录|授权|请先登录|跳转到登录页|访客没有权限/i.test(String(message || ""));
}
function maskName(value = "") {
const text = String(value || "");
return text.length > 10 ? `${text.slice(0, 4)}***${text.slice(-3)}` : text;
}
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.token = this.user[0];
this.postId = ''
this.threadId = ''
this.index = $.userIdx++;
this.user = String(env || "").trim().split(strSplitor);
this.openid = this.user[0].trim();
this.token = "";
this.refreshToken = "";
this.userId = "";
this.userInfo = {};
this.postId = "";
this.threadId = "";
this.visitor = crypto.createHash("md5").update(this.openid || String(Date.now())).digest("hex");
}
request(options) {
let baseHeaders = {
sign: this.getSign(options.method, options.url.split('https://bbs-api.iqoo.com')[1].split("?")[0], options.data ? options.data : ''),
'authorization': 'Bearer ' + this.token,
"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(0xf254173b) XWEB/19027",
"x-platform": "mini",
"x-visitor": "b89d8b0ffa920e96f3cb4c1f69ec2c66"
}
options.headers = Object.assign(baseHeaders, options.headers)
return axios.request(options)
}
async userInfo() {
let options = {
method: 'GET',
url: `https://bbs-api.iqoo.com/api/v3/v3/user?userId=${this.id}`,
headers: {
},
data: {
userId: this.id
}
};
let { data: result } = await this.request(options);
if (result?.Code == '0') {
$.log(`${this.index}账号[${this.index}] 获取用户信息成功`)
}
}
async run() {
await this.getTreadList()
const cached = this.getCachedToken();
if (cached?.accessToken) {
this.applyToken(cached);
$.log(`账号[${this.index}] 使用缓存token: ${shortToken(this.token)}`);
if (!(await this.checkToken())) {
this.removeCachedToken();
$.log(`账号[${this.index}] 缓存token失效,重新登录`);
}
}
if (!this.token) {
await this.loginByWxCode();
if (!this.token) return;
}
await this.userInfoRequest();
await this.getTreadList();
if (this.threadId && this.postId) {
await this.likePost(this.threadId, this.postId)
await $.wait(5000)
await this.sharePost(this.threadId)
await $.wait(5000)
await this.viewPost(this.threadId)
await $.wait(5000)
await this.commonPost(this.threadId)
await this.likePost(this.threadId, this.postId);
await $.wait(5000);
await this.sharePost(this.threadId);
await $.wait(5000);
await this.viewPost(this.threadId);
await $.wait(5000);
await this.commonPost(this.threadId);
}
await this.getDrawNum()
await this.signIn()
await this.getDrawNum();
await this.signIn();
}
getCachedToken() {
const cache = readTokenCache();
return cache[this.openid] || null;
}
saveCachedToken() {
if (!this.token) return;
const cache = readTokenCache();
cache[this.openid] = {
accessToken: this.token,
refreshToken: this.refreshToken,
userId: this.userId,
userInfo: this.userInfo,
visitor: this.visitor,
updatedAt: new Date().toISOString(),
};
writeTokenCache(cache);
}
removeCachedToken() {
const cache = readTokenCache();
if (cache[this.openid]) {
delete cache[this.openid];
writeTokenCache(cache);
}
this.token = "";
this.refreshToken = "";
this.userId = "";
this.userInfo = {};
}
applyToken(data = {}) {
this.token = data.accessToken || data.token || "";
this.refreshToken = data.refreshToken || "";
this.userId = data.userId || data.uid || data.userInfo?.userId || data.userInfo?.uid || "";
this.userInfo = data.userInfo || data.user || {};
this.visitor = data.visitor || this.visitor;
}
queryString(data = {}) {
const list = [];
for (const [key, value] of Object.entries(data || {})) {
if (value === undefined || value === null) continue;
list.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
}
return list.join("&");
}
getSign(method, apiPath, data = {}) {
const upperMethod = method.toUpperCase();
const timestamp = Math.floor(Date.now() / 1000);
const query = upperMethod === "GET" ? this.queryString(data) : "";
const body = upperMethod === "GET" ? "" : JSON.stringify(data || {});
const raw = `${upperMethod}&/api/${apiPath}&${query}&${body}&appid=1002&timestamp=${timestamp}`;
const signature = crypto.createHmac("sha256", SIGN_SECRET).update(raw).digest("base64");
return `IQOO-HMAC-SHA256 appid=1002,timestamp=${timestamp},signature=${signature}`;
}
headers(method, apiPath, data, extra = {}) {
return {
Authorization: this.token ? `Bearer ${this.token}` : "Bearer ",
"X-Visitor": this.visitor,
"X-Platform": "mini",
SIGN: this.getSign(method, apiPath, data),
"Content-Nonce": "",
"User-Agent": USER_AGENT,
Referer: `https://servicewechat.com/${MINI_APP_ID}/${PAGE_VERSION}/page-frame.html`,
...extra,
};
}
async request(apiPath, data = {}, options = {}) {
const method = (options.method || "POST").toUpperCase();
const req = {
method,
url: new URL(apiPath, API_BASE).toString(),
headers: this.headers(method, apiPath, data, options.headers || {}),
timeout: 20000,
validateStatus: () => true,
};
if (method === "GET") req.params = data;
else req.data = data || {};
const { data: result, status } = await axios.request(req);
if (status !== 200) throw new Error(`HTTP ${status}: ${JSON.stringify(result)}`);
if (!isSuccess(result)) throw new Error(`${result?.Code ?? ""} ${result?.Message || JSON.stringify(result)}`.trim());
return result;
}
async getOperateData() {
if (!process.env.wx_auth) throw new Error("缺少 wx_auth,无法从 wx_server 获取登录数据");
const url = (process.env.wx_server_url || "http://192.168.31.196:8787").replace(/\/$/, "");
const { data } = await axios.post(`${url}/wx/operatedata`, {
appid: MINI_APP_ID,
openid: this.openid,
}, {
headers: { auth: process.env.wx_auth },
timeout: 45000,
});
const result = data?.data || {};
if (!data?.status || !result.code || !result.encryptedData || !result.iv) {
throw new Error(`wx_server 未返回完整登录数据: ${JSON.stringify(data)}`);
}
return result;
}
async loginByWxCode() {
try {
const wxData = await this.getOperateData();
const payload = {
code: wxData.code,
encryptedData: wxData.encryptedData,
iv: wxData.iv,
from: 46,
};
const result = await this.request("v3/users/vivo/mini", payload);
const data = result?.Data || {};
const token = data.accessToken || data.token || "";
if (!token) throw new Error(`登录响应未返回token: ${JSON.stringify(result)}`);
this.token = token;
this.refreshToken = data.refreshToken || "";
this.userId = data.userId || data.uid || "";
this.userInfo = data.user || data;
this.saveCachedToken();
$.log(`账号[${this.index}] CODE登录成功: ${maskName(this.userInfo?.nickname || this.userInfo?.username || this.userId)}`);
} catch (e) {
$.log(`账号[${this.index}] CODE登录失败: ${e.message || e}`);
}
}
async checkToken() {
try {
if (!this.userId) return false;
await this.request("v3/user", { userId: this.userId }, { method: "GET" });
return true;
} catch (e) {
return false;
}
}
async userInfoRequest() {
if (!this.userId) return;
try {
const result = await this.request("v3/user", { userId: this.userId }, { method: "GET" });
this.userInfo = result?.Data || this.userInfo;
this.saveCachedToken();
const name = this.userInfo?.nickname || this.userInfo?.username || this.userInfo?.userName || this.userId;
const score = this.userInfo?.score ?? this.userInfo?.points ?? this.userInfo?.coolCoin ?? "未知";
$.log(`账号[${this.index}] 用户:${maskName(name)} 酷币:${score}`);
} catch (e) {
const message = String(e.message || e);
$.log(`账号[${this.index}] 获取用户信息失败:${message}`);
if (isTokenError(message)) this.removeCachedToken();
}
}
async getDrawNum() {
let options = {
method: 'GET',
url: `https://bbs-api.iqoo.com/api/v3/today.draw.count`,
headers: {
},
data: {}
};
let { data: result } = await this.request(options);
if (result?.Code == '0' && result.Data.count == 0) {
//可以免费抽一次
await this.draw()
} else {
//已签到
$.log(`${this.index}账号[${this.index}] 抽奖过`)
try {
const result = await this.request("v3/today.draw.count", {}, { method: "GET" });
if (result?.Data?.count === 0) {
await this.draw();
} else {
$.log(`账号[${this.index}] 今日已抽奖`);
}
} catch (e) {
$.log(`账号[${this.index}] 查询抽奖次数失败:${e.message || e}`);
}
}
async draw() {
let options = {
method: 'POST',
url: `https://bbs-api.iqoo.com/api/v3/luck.draw`,
headers: {
},
data: {}
};
let { data: result } = await this.request(options);
if (result?.Code == '0') {
$.log(`${this.index}账号[${this.index}] 抽奖成功 获得${result.Data.prize_name}`)
try {
const result = await this.request("v3/luck.draw", {});
$.log(`账号[${this.index}] 抽奖成功 获得${result?.Data?.prize_name || "奖励"}`);
} catch (e) {
$.log(`账号[${this.index}] 抽奖失败:${e.message || e}`);
}
}
async signIn() {
let options = {
method: 'POST',
url: `https://bbs-api.iqoo.com/api/v3/sign`,
headers: {
},
data: { "from": "group" }
};
let { data: result } = await this.request(options);
if (result?.Code == '0') {
//打印签到结果
$.log(`🌸账号[${this.index}]` + `🕊当前已签到${result.Data.serialDays}天🎉 获得积分${result.Data.score} 当前积分${result.Data.scoreCount}`);
} else {
$.log(`🌸账号[${this.index}] 签到-失败:${result.Message}❌`)
try {
const result = await this.request("v3/sign", { from: "group" });
$.log(`🌸账号[${this.index}]🕊当前已签到${result.Data.serialDays}天🎉 获得积分${result.Data.score} 当前积分${result.Data.scoreCount}`);
} catch (e) {
const message = String(e.message || e);
if (/已签|重复|今日|13006/.test(message)) {
$.log(`🌸账号[${this.index}] 今日已签到`);
return;
}
$.log(`🌸账号[${this.index}] 签到失败:${message}❌`);
if (isTokenError(message)) this.removeCachedToken();
}
}
async likePost(threadId, postId) {
let { data: likeResult } = await this.request({
method: 'POST',
url: `https://bbs-api.iqoo.com/api/v3/posts.update`,
headers: {
},
data: { "id": threadId, "postId": postId, "data": { "attributes": { "isLiked": true } } }
});
if (likeResult?.Code == '0') {
$.log(`${this.index}账号[${this.index}] 帖子点赞成功`)
} else {
$.log(`${this.index}账号[${this.index}] 帖子点赞失败:${likeResult.Message}❌`)
try {
await this.request("v3/posts.update", { id: threadId, postId, data: { attributes: { isLiked: true } } });
$.log(`账号[${this.index}] 帖子点赞成功`);
} catch (e) {
$.log(`账号[${this.index}] 帖子点赞失败:${e.message || e}❌`);
}
let { data: unlikeResult } = await this.request({
method: 'POST',
url: `https://bbs-api.iqoo.com/api/v3/posts.update`,
headers: {
},
data: { "id": threadId, "postId": postId, "data": { "attributes": { "isLiked": false } } }
});
if (unlikeResult?.Code == '0') {
$.log(`${this.index}账号[${this.index}] 帖子取消点赞成功`)
} else {
$.log(`${this.index}账号[${this.index}] 帖子取消点赞失败:${unlikeResult.Message}❌`)
try {
await this.request("v3/posts.update", { id: threadId, postId, data: { attributes: { isLiked: false } } });
$.log(`账号[${this.index}] 帖子取消点赞成功`);
} catch (e) {
$.log(`账号[${this.index}] 帖子取消点赞失败:${e.message || e}❌`);
}
}
async sharePost(threadId) {
let options = {
method: 'POST',
url: `https://bbs-api.iqoo.com/api/v3/thread.share`,
headers: {
},
data: { "threadId": threadId }
};
let { data: result } = await this.request(options);
if (result?.Code == '0') {
$.log(`${this.index}账号[${this.index}] 帖子分享成功`)
} else {
$.log(`${this.index}账号[${this.index}] 帖子分享失败:${result.Message}❌`)
try {
await this.request("v3/thread.share", { threadId });
$.log(`账号[${this.index}] 帖子分享成功`);
} catch (e) {
$.log(`账号[${this.index}] 帖子分享失败:${e.message || e}❌`);
}
}
async viewPost(threadId) {
let options = {
method: 'GET',
url: `https://bbs-api.iqoo.com/api/v3/view.count?threadId=` + threadId + `&type=0`,
headers: {
},
data: { "threadId": threadId, "type": 0 }
};
let { data: result } = await this.request(options);
if (result?.Code == '0') {
$.log(`${this.index}账号[${this.index}] 帖子浏览成功`)
} else {
$.log(`${this.index}账号[${this.index}] 帖子浏览失败:${result.Message}❌`)
try {
await this.request("v3/view.count", { threadId, type: 0 }, { method: "GET" });
$.log(`账号[${this.index}] 帖子浏览成功`);
} catch (e) {
$.log(`账号[${this.index}] 帖子浏览失败:${e.message || e}❌`);
}
}
async commonPost(threadId) {
let options = {
method: 'POST',
url: `https://bbs-api.iqoo.com/api/v3/posts.create`,
headers: {
},
data: { "id": threadId, "type": 0, "content": "666", "source": "", "attachments": [] }
};
let { data: result } = await this.request(options);
if (result?.Code == '0') {
$.log(`${this.index}账号[${this.index}] 帖子评论成功`)
} else {
$.log(`${this.index}账号[${this.index}] 帖子评论失败:${result.Message}❌`)
try {
await this.request("v3/posts.create", { id: threadId, type: 0, content: "666", source: "", attachments: [] });
$.log(`账号[${this.index}] 帖子评论成功`);
} catch (e) {
$.log(`账号[${this.index}] 帖子评论失败:${e.message || e}❌`);
}
}
async getTreadList() {
let options = {
method: 'GET',
url: `https://bbs-api.iqoo.com/api/v3/thread.list?scope=5&page=1&perPage=10&filter[sort]=4&filter[essence]=1&sequence=0`,
headers: {
},
data: { "filter[essence]": 1, "filter[sort]": 4, "page": 1, "perPage": 10, "scope": 5, "sequence": 0 }
};
let { data: result } = await this.request(options);
this.threadId = result.Data.pageData[0].threadId
this.postId = result.Data.pageData[0].postId
return
try {
const result = await this.request("v3/thread.list", {
scope: 5,
page: 1,
perPage: 10,
"filter[sort]": 4,
"filter[essence]": 1,
sequence: 0,
}, { method: "GET" });
const first = result?.Data?.pageData?.[0] || {};
this.threadId = first.threadId || "";
this.postId = first.postId || "";
} catch (e) {
$.log(`账号[${this.index}] 获取帖子列表失败:${e.message || e}`);
}
}
/**
*
* @param {*} e method
* @param {*} t path
* @param {*} n data
* @returns
*/
getSign(e, t, n) {
const time = Math.floor(Date.now() / 1e3);
const crypto = require("crypto-js");
var o, s, r, a = `${time}`,
c = "GET" == e ? function (e) {
var t, o = "", r;
if (typeof e === 'object' && e !== null) {
if (Array.isArray(e)) {
r = e.entries();
} else {
r = Object.entries(e);
}
try {
for (var entry of r) {
var a = encodeURIComponent(entry[0]), c = encodeURIComponent(entry[1]);
o += "".concat(a, "=").concat(c, "&");
}
} catch (e) {
console.error(e);
}
return o.slice(0, -1);
} else {
return '';
}
}(n) : "";
let l = "GET" == e ? "" : JSON.stringify(n);
o = "2618194b0ebb620055e19cf9811d3c13"
s = e + "&" + t + "&" + c + "&" + l + "&appid=1002&timestamp=" + a
r = crypto.HmacSHA256(s, o)
let sign = crypto.enc.Base64.stringify(r)
return `IQOO-HMAC-SHA256 appid=1002,timestamp=${time},signature=${sign}`
}
}
!(async () => {
await getNotice()
await getNotice();
$.checkEnv(ckName);
for (let user of $.userList) {
for (const user of $.userList) {
await new Task(user).run();
}
})()
@@ -297,20 +384,16 @@ class Task {
.finally(() => $.done());
async function getNotice() {
try {
let options = {
url: `https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json`,
headers: {
"User-Agent": defaultUserAgent,
},
timeout:3000
}
let {
data: res
} = await axios.request(options);
$.log(res)
return res
} catch (e) {}
try {
const options = {
url: "https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json",
headers: {
"User-Agent": defaultUserAgent,
},
timeout: 3000,
};
const { data: res } = await axios.request(options);
$.log(res);
return res;
} catch (e) {}
}
+249 -64
View File
@@ -1,14 +1,16 @@
/*
------------------------------------------
@Author: sm
@Date: 2024.06.07 19:15
@Date: 2026.06.01
@Description: 康师傅畅饮社
cron: 30 10 * * *
------------------------------------------
#Notice:
#Notice:
康师傅畅饮社小程序
变量名 ksfcys
账号格式:抓https://club.biqr.cn/api/请求头token 多账户&或换行
变量值:wx_server 里的 openid/账号标识,多账户&或换行
需要配置:wx_server_url、wx_auth
⚠️【免责声明】
------------------------------------------
1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
@@ -20,92 +22,275 @@ cron: 30 10 * * *
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
*/
const { Env } = require("../tools/env")
const { Env } = require("../tools/env.js");
const $ = new Env("康师傅畅饮社");
let ckName = `ksfcys`;
const strSplitor = "#";
const axios = require("axios");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
const fs = require("fs");
const path = require("path");
const WeChatServer = require("../wxapp/wcs.js");
const ckName = "ksfcys";
const MINI_APP_ID = "wx54f3e6a00f7973a7";
const API_BASE = "https://club.biqr.cn/";
const FORUM_BASE = "https://nclub.gdshcm.com/pro/";
const TOKEN_CACHE_FILE = path.join(__dirname, "kangshifu_token_cache.json");
const 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(0xf254173b) XWEB/19027";
const defaultUserAgent = USER_AGENT;
const wechat = new WeChatServer({
url: process.env.wx_server_url || "http://192.168.31.196:8787",
appid: MINI_APP_ID,
auth: process.env.wx_auth || "",
});
function readTokenCache() {
try {
if (!fs.existsSync(TOKEN_CACHE_FILE)) return {};
return JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, "utf8")) || {};
} catch (e) {
return {};
}
}
function writeTokenCache(cache) {
try {
fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify(cache, null, 2), "utf8");
} catch (e) {
$.log(`写入token缓存失败: ${e.message || e}`);
}
}
function shortToken(token = "") {
const value = String(token);
return value ? `${value.slice(0, 6)}***${value.slice(-6)}` : "";
}
function maskPhone(phone = "") {
return String(phone).replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2");
}
function isSuccess(result) {
return Number(result?.code) === 0;
}
function isTokenError(message) {
return /(^|[^0-9])600([^0-9]|$)|4002|token|登录|授权|未登录|无效|过期/i.test(String(message || ""));
}
function formBody(data = {}) {
return new URLSearchParams(data).toString();
}
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.token = this.user[0];
constructor(openid) {
this.index = $.userIdx++;
this.openid = String(openid || "").trim();
this.token = "";
this.member = {};
}
}
async run() {
const cached = this.getCachedToken();
if (cached?.token) {
this.token = cached.token;
this.member = cached.member || {};
$.log(`账号[${this.index}] 使用缓存token: ${shortToken(this.token)}`);
if (!(await this.checkToken())) {
this.removeCachedToken();
$.log(`账号[${this.index}] 缓存token失效,重新登录`);
}
}
async run() {
if (!this.token) {
await this.loginByWxCode();
if (!this.token) return;
}
await this.signIn()
}
await this.memberInfo();
await this.signIn();
await this.memberInfo("签到后");
}
async signIn() {
let options = {
url: `https://club.biqr.cn/api/signIn/integralSignIn`,
headers: {
'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(0xf254173b) XWEB/19027',
'Accept': 'application/json, text/plain, */*',
'xweb_xhr': '1',
'Content-Type': 'application/x-www-form-urlencoded;',
'Token': '' + this.token,
'Sec-Fetch-Site': 'cross-site',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Dest': 'empty',
'Referer': 'https://servicewechat.com/wx54f3e6a00f7973a7/795/page-frame.html',
'Accept-Language': 'zh-CN,zh;q=0.9'
},
method: 'POST',
data: {
getCachedToken() {
const cache = readTokenCache();
return cache[this.openid] || null;
}
}
}
let { data: result } = await axios.request(options);
if (result.code == 0) {
$.log(`账号[${this.index}]【${this.name}】 签到成功`);
} else {
$.log(result);
saveCachedToken() {
if (!this.token) return;
const cache = readTokenCache();
cache[this.openid] = {
token: this.token,
member: this.member,
updatedAt: new Date().toISOString(),
};
writeTokenCache(cache);
}
}
}
removeCachedToken() {
const cache = readTokenCache();
if (cache[this.openid]) {
delete cache[this.openid];
writeTokenCache(cache);
}
this.token = "";
this.member = {};
}
headers(extra = {}) {
const headers = {
"User-Agent": USER_AGENT,
"Accept": "application/json, text/plain, */*",
"xweb_xhr": "1",
"Referer": "https://servicewechat.com/wx54f3e6a00f7973a7/816/page-frame.html",
"Accept-Language": "zh-CN,zh;q=0.9",
...extra,
};
if (this.token) headers.token = this.token;
return headers;
}
async request(baseURL, apiPath, { method = "GET", data, params, auth = true, form = false } = {}) {
const options = {
method,
url: new URL(apiPath, baseURL).toString(),
params,
headers: this.headers(form ? {
"Content-Type": "application/x-www-form-urlencoded;",
} : {}),
timeout: 15000,
validateStatus: () => true,
};
if (!auth) delete options.headers.token;
if (data !== undefined) options.data = form ? formBody(data) : data;
const { data: result, status } = await axios.request(options);
if (status !== 200) throw new Error(`HTTP ${status}: ${JSON.stringify(result)}`);
if (!isSuccess(result)) throw new Error(`${result?.code ?? ""} ${result?.msg || result?.error || JSON.stringify(result)}`.trim());
return result;
}
async getLoginCode() {
if (!process.env.wx_auth) throw new Error("缺少 wx_auth,无法从 wx_server 获取 code");
const { data } = await wechat.getCode(this.openid);
const code = data?.code || data?.data?.code;
if (!code) throw new Error(`wx_server 未返回 code: ${JSON.stringify(data)}`);
return code;
}
async loginByWxCode() {
try {
const code = await this.getLoginCode();
const result = await this.request(FORUM_BASE, "whale-member/api/login/login", {
method: "POST",
auth: false,
data: {
code,
inviterId: "",
inviterType: "",
inviterMatchUserId: "",
spUrl: "",
},
});
const token = result?.data?.token || "";
if (!token) throw new Error(`登录响应未返回token: ${JSON.stringify(result)}`);
this.token = token;
this.member = result?.data?.member || {};
this.saveCachedToken();
$.log(`账号[${this.index}] 登录成功: ${this.member.nickname || maskPhone(this.member.phone) || this.member.id || ""}`);
} catch (e) {
$.log(`账号[${this.index}] 登录失败: ${e.message || e}`);
}
}
async checkToken() {
try {
await this.getMemberInfo();
return true;
} catch (e) {
return false;
}
}
async getMemberInfo() {
const result = await this.request(FORUM_BASE, "whale-member/api/member/getMemberInfo", {
params: { token: this.token },
});
this.member = result?.data || this.member || {};
this.saveCachedToken();
return this.member;
}
async memberInfo(prefix = "当前") {
try {
const data = await this.getMemberInfo();
const name = data?.nickname || maskPhone(data?.phone) || data?.id || "";
const integral = data?.integral ?? data?.point ?? data?.points ?? data?.score ?? "未知";
$.log(`账号[${this.index}] ${prefix}用户: ${name},积分: ${integral}`);
} catch (e) {
const message = String(e.message || e);
$.log(`账号[${this.index}] 查询用户失败: ${message}`);
if (isTokenError(message)) this.removeCachedToken();
}
}
async getSignStatus() {
const result = await this.request(API_BASE, "api/signIn/integralSignInList", {
method: "POST",
data: { token: this.token },
form: true,
});
return result?.data || {};
}
async signIn() {
try {
const status = await this.getSignStatus();
if (status?.signIs) {
$.log(`账号[${this.index}] 今日已签到`);
return;
}
const result = await this.request(API_BASE, "api/signIn/integralSignIn", {
method: "POST",
data: {},
form: true,
});
$.log(`账号[${this.index}] 签到成功: ${result?.msg || "成功"}`);
} catch (e) {
const message = String(e.message || e);
if (/已签到|已签|重复/.test(message)) {
$.log(`账号[${this.index}] 今日已签到`);
return;
}
$.log(`账号[${this.index}] 签到失败: ${message}`);
if (isTokenError(message)) this.removeCachedToken();
}
}
}
!(async () => {
await getNotice()
$.checkEnv(ckName);
await getNotice();
$.checkEnv(ckName);
for (let user of $.userList) {
await new Task(user).run();
}
for (const user of $.userList) {
await new Task(user).run();
}
})()
.catch((e) => console.log(e))
.finally(() => $.done());
.catch((e) => console.log(e))
.finally(() => $.done());
async function getNotice() {
try {
let options = {
url: `https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json`,
headers: {
"User-Agent": defaultUserAgent,
},
timeout: 3000
}
let {
data: res
} = await axios.request(options);
$.log(res)
return res
} catch (e) { }
try {
const options = {
url: "https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json",
headers: {
"User-Agent": defaultUserAgent,
},
timeout: 3000,
};
const { data: res } = await axios.request(options);
$.log(res);
return res;
} catch (e) {}
}
-387
View File
@@ -1,387 +0,0 @@
/*
------------------------------------------
@Author: sm
@Date: 2024.06.07 19:15
@Description: 麦斯威尔福利社小程序 签到 浇水 积分
cron: 30 9 * * *
------------------------------------------
#Notice: 麦斯威尔福利社小程序
抓jde.mtbcpt.com/api的POST请求中的openId 多账户&或换行
⚠️【免责声明】
------------------------------------------
1、此脚本仅用于学习研究,不保证其合法性、准确性、有效性,请根据情况自行判断,本人对此不承担任何保证责任。
2、由于此脚本仅用于学习研究,您必须在下载后 24 小时内将所有内容从您的计算机或手机或任何存储设备中完全删除,若违反规定引起任何事件本人对此均不负责。
3、请勿将此脚本用于任何商业或非法目的,若违反规定请自行对此负责。
4、此脚本涉及应用与本人无关,本人对因此引起的任何隐私泄漏或其他后果不承担任何责任。
5、本人对任何脚本引发的问题概不负责,包括但不限于由脚本错误引起的任何损失和损害。
6、如果任何单位或个人认为此脚本可能涉嫌侵犯其权利,应及时通知并提供身份证明,所有权证明,我们将在收到认证文件确认后删除此脚本。
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
*/
const { Env } = require("../tools/env")
const $ = new Env("麦斯威尔福利社小程序");
let ckName = `mswe`;
const strSplitor = "#";
const axios = require("axios");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.openId = this.user[0];
}
async run() {
await this.getMemberTaskInfo()
await this.getUserFarmGetWaterList()
for (let i = 0; i < 3; i++) {
await this.farmWatering();
}
}
md5(str) {
const crypto = require("crypto")
return crypto.createHash("md5").update(str).digest('hex');
}
// =============================================================================================================================
async getMemberTaskInfo() {
try {
let timestamp = Date.now();
let sign = this.md5(`timestamp=${timestamp}&openid=${this.openId}&key=JDEMaxwellminiapp#2021!`).toUpperCase();
let options = {
method: 'post',
url: 'https://jde.mtbcpt.com/api/JDEMaxwellApi/GetMemberTaskInfo',
headers: {
'Host': 'jde.mtbcpt.com',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
data: {
"openId": this.openId,
"timestamp": timestamp,
"sign": sign,
}
};
let { data: result } = await axios.request(options)
if (result?.state == true) {
$.log(`🌸账号[${this.index}]` + `查询任务成功🎉`);
if (result.data.dailySign != 1) {
$.log(`${this.index}账号[${this.index}]` + `未签到`);
await this.signDailyScore()
} else {
$.log(`${this.index}账号[${this.index}]` + `已签到`);
}
if (result.data.shareSign != 1) {
$.log(`${this.index}账号[${this.index}]` + `未分享`);
//分享
await this.shareDailyScore()
} else {
$.log(`${this.index}账号[${this.index}]` + `已分享`);
}
} else {
$.log(`🌸账号[${this.index}]查询任务-失败:${result.msg}❌`)
}
} catch (e) {
}
}
async signDailyScore() {
try {
let timestamp = Date.now();
let sign = this.md5(`timestamp=${timestamp}&openid=${this.openId}&key=JDEMaxwellminiapp#2021!`).toUpperCase();
let options = {
method: 'post',
url: 'https://jde.mtbcpt.com/api/JDEMaxwellApi/SignInDailyScore',
headers: {
'Host': 'jde.mtbcpt.com',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
data: {
"openId": this.openId,
"timestamp": timestamp,
"sign": sign,
}
};
let { data: result } = await axios.request(options)
if (result?.state == true) {
$.log(`🌸账号[${this.index}]` + `🕊${result.msg}🎉`);
} else {
$.log(`🌸账号[${this.index}]签到-失败:${result.msg}❌`)
}
} catch (e) {
}
}
//分享加积分
async shareDailyScore() {
try {
let timestamp = Date.now();
let sign = md5(`timestamp=${timestamp}&openid=${this.openId}&key=JDEMaxwellminiapp#2021!`).toUpperCase();
let options = {
method: 'post',
url: `https://jde.mtbcpt.com/api/JDEMaxwellApi/ShareDailyScore`,
headers: {
'Host': 'jde.mtbcpt.com',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
data: {
"through": true,
"openId": this.openId,
"timestamp": timestamp,
"sign": sign,
}
}
//
let { data: result } = await axios.request(options)
if (result?.state == true) {
//打印签到结果
$.log(`🌸账号[${user.index}]` + `🕊${result.msg}🎉`);
} if (result?.state == false) {
$.log(`🌸账号[${user.index}]分享-失败:${result.msg}❌`)
}
} catch (e) {
}
}
async getUserFarmGetWaterList() {
try {
let timestamp = Date.now();
let sign = this.md5(`timestamp=${timestamp}&openid=${this.openId}&key=JDEMaxwellminiapp#2021!`).toUpperCase();
let options = {
method: 'post',
url: 'https://jde.mtbcpt.com/api/JDEMaxwellApi/getUserFarmGetWaterList',
headers: {
'Host': 'jde.mtbcpt.com',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
data: {
"openId": this.openId,
"timestamp": timestamp,
"sign": sign,
}
};
let { data: result } = await axios.request(options)
if (result?.state == true) {
$.log(`🌸账号[${this.index}]` + `查询农场任务成功🎉`);
for (let task of result.data.list) {
if (task.status != 3) {
$.log(`${this.index}账号[${this.index}][${task.taskName}]` + `未执行`);
if (task.ptype == 1) {
await this.farmSign()
}
if (task.ptype == 2) {
await this.farmShare()
}
} else {
$.log(`${this.index}账号[${this.index}][${task.taskName}]` + `已执行`);
}
}
} else {
$.log(`🌸账号[${this.index}]查询任务-失败:${result.msg}❌`)
}
} catch (e) {
}
}
//浇水签到
async farmSign() {
try {
let timestamp = Date.now();
let sign = this.md5(`timestamp=${timestamp}&openid=${this.openId}&key=JDEMaxwellminiapp#2021!`).toUpperCase();
let options = {
method: 'post',
url: 'https://jde.mtbcpt.com/api/JDEMaxwellApi/UserSign',
headers: {
'Host': 'jde.mtbcpt.com',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
data: {
"openId": this.openId,
"timestamp": timestamp,
"sign": sign,
}
};
let { data: result } = await axios.request(options)
if (result?.state == true) {
$.log(`🌸账号[${this.index}]` + `🕊水滴签到-领取成功${result.msg}🎉`);
} else {
$.log(`🌸账号[${this.index}]水滴签到-失败:${result.msg}❌`)
}
} catch (e) {
}
}
//分享领水滴
async farmShare() {
try {
let timestamp = Date.now();
let sign = this.md5(`timestamp=${timestamp}&openid=${this.openId}&key=JDEMaxwellminiapp#2021!`).toUpperCase();
let options = {
method: 'post',
url: 'https://jde.mtbcpt.com/api/JDEMaxwellApi/UserShare',
headers: {
'Host': 'jde.mtbcpt.com',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
data: {
"openId": this.openId,
"timestamp": timestamp,
"sign": sign,
}
};
let { data: result } = await axios.request(options)
if (result?.state == true) {
$.log(`🌸账号[${this.index}]` + `🕊任务分享领水滴-领取成功${result.msg}🎉`);
} else {
$.log(`🌸账号[${this.index}]任务分享领水滴-失败:${result.msg}❌`)
}
} catch (e) {
}
}
//浇水
async farmWatering() {
try {
let timestamp = Date.now();
let sign = this.md5(`timestamp=${timestamp}&openid=${this.openId}&key=JDEMaxwellminiapp#2021!`).toUpperCase();
let options = {
method: 'post',
url: 'https://jde.mtbcpt.com/api/JDEMaxwellApi/UserWatering',
headers: {
'Host': 'jde.mtbcpt.com',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
data: {
"openId": this.openId,
"timestamp": timestamp,
"sign": sign,
}
};
let { data: result } = await axios.request(options)
if (result?.state == true) {
$.log(`🌸账号[${this.index}]` + `🕊浇水-成功${result.msg}🎉`);
} else {
$.log(`🌸账号[${this.index}]浇水-失败:${result.msg}❌`)
}
} catch (e) {
}
}
async getUserPoint() {
try {
let timestamp = Date.now()
let sign = this.md5(`timestamp=${timestamp}&openid=${this.openId}&key=JDEMaxwellminiapp#2021!`).toUpperCase();
let options = {
method: 'post',
url: 'https://jde.mtbcpt.com/api/JDEMWMall/GetUserPoint',
headers: {
'Host': 'jde.mtbcpt.com',
'content-type': 'application/json',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090b11) XWEB/9129',
},
data: {
"openId": this.openId,
"timestamp": timestamp,
"sign": sign,
}
};
let { data: result } = await axios.request(options)
if (result?.state == true) {
this.userFlag = false
$.log(`🌸账号[${this.index}]` + `🕊${result.msg}为[${result.data}]💰`);
} else {
$.log(`🌸账号[${this.index}]积分查询失败:${result.msg}❌`)
}
} catch (e) {
}
}
}
!(async () => {
await getNotice()
$.checkEnv(ckName);
for (let user of $.userList) {
await new Task(user).run();
}
})()
.catch((e) => console.log(e))
.finally(() => $.done());
async function getNotice() {
try {
let options = {
url: `https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json`,
headers: {
"User-Agent": defaultUserAgent,
},
timeout:3000
}
let {
data: res
} = await axios.request(options);
$.log(res)
return res
} catch (e) {}
}
+225 -85
View File
@@ -1,13 +1,14 @@
/*
------------------------------------------
@Author: sm
@Date: 2024.06.07 19:15
@Date: 2026.06.01
@Description: 植白说小程序
cron: 30 8 * * *
------------------------------------------
#Notice:
#Notice:
变量名称:zbs
值抓取https://www.kozbs.com/demo 请求头x-dts-token
变量值:wx_server 里的 openid/账号标识,多账号用 & 或换行
需要配置:wx_server_url、wx_auth
⚠️【免责声明】
------------------------------------------
@@ -20,93 +21,235 @@ cron: 30 8 * * *
7、所有直接或间接使用、查看此脚本的人均应该仔细阅读此声明。本人保留随时更改或补充此声明的权利。一旦您使用或复制了此脚本,即视为您已接受此免责声明。
*/
const { Env } = require("../tools/env")
const { Env } = require("../tools/env.js");
const $ = new Env("植白说小程序");
let ckName = `zbs`;
const strSplitor = "#";
const axios = require("axios");
const defaultUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.31(0x18001e31) NetType/WIFI Language/zh_CN miniProgram"
const fs = require("fs");
const path = require("path");
const WeChatServer = require("../wxapp/wcs.js");
const ckName = "zbs";
const MINI_APP_ID = "wx6b6c5243359fe265";
const API_BASE = "https://www.kozbs.com/demo/wx/";
const TOKEN_CACHE_FILE = path.join(__dirname, "zbs_token_cache.json");
const 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(0xf254173b) XWEB/19027";
const defaultUserAgent = USER_AGENT;
const wechat = new WeChatServer({
url: process.env.wx_server_url || "http://192.168.31.196:8787",
appid: MINI_APP_ID,
auth: process.env.wx_auth || "",
});
function readTokenCache() {
try {
if (!fs.existsSync(TOKEN_CACHE_FILE)) return {};
return JSON.parse(fs.readFileSync(TOKEN_CACHE_FILE, "utf8")) || {};
} catch (e) {
return {};
}
}
function writeTokenCache(cache) {
try {
fs.writeFileSync(TOKEN_CACHE_FILE, JSON.stringify(cache, null, 2), "utf8");
} catch (e) {
$.log(`写入token缓存失败: ${e.message || e}`);
}
}
function shortToken(token = "") {
const value = String(token);
return value ? `${value.slice(0, 6)}***${value.slice(-6)}` : "";
}
function maskPhone(phone = "") {
return String(phone).replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2");
}
function isTokenError(message) {
return /(^|[^0-9])501([^0-9]|$)|token|登录|授权|未登录|失效|过期/i.test(String(message || ""));
}
class Task {
constructor(env) {
this.index = $.userIdx++
this.user = env.split(strSplitor);
this.token = this.user[0];
constructor(openid) {
this.index = $.userIdx++;
this.openid = String(openid || "").trim();
this.token = "";
this.userInfo = {};
}
request(options) {
let baseHeraders = {
"accept": "*/*",
"accept-language": "zh-CN,zh;q=0.9",
"content-type": "application/json",
"priority": "u=1, i",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "cross-site",
"x-dts-token": "" + this.token,
"xweb_xhr": "1",
"User-Agent": defaultUserAgent,
}
options.headers = Object.assign(baseHeraders, options.headers)
return axios.request(options)
}
async run() {
const cached = this.getCachedToken();
if (cached?.token) {
this.token = cached.token;
this.userInfo = cached.userInfo || {};
$.log(`账号[${this.index}] 使用缓存token: ${shortToken(this.token)}`);
if (!(await this.checkToken())) {
this.removeCachedToken();
$.log(`账号[${this.index}] 缓存token失效,重新登录`);
}
}
await this.signIn()
if (!this.token) {
await this.loginByWxCode();
if (!this.token) return;
}
await this.getPoints("当前");
await this.signIn();
await this.getPoints("签到后");
}
get userId() {
return this.userInfo?.userId || this.userInfo?.id || 1;
}
getCachedToken() {
const cache = readTokenCache();
return cache[this.openid] || null;
}
saveCachedToken() {
if (!this.token) return;
const cache = readTokenCache();
cache[this.openid] = {
token: this.token,
userInfo: this.userInfo,
updatedAt: new Date().toISOString(),
};
writeTokenCache(cache);
}
removeCachedToken() {
const cache = readTokenCache();
if (cache[this.openid]) {
delete cache[this.openid];
writeTokenCache(cache);
}
this.token = "";
this.userInfo = {};
}
headers(extra = {}) {
const headers = {
"Content-Type": "application/json",
"User-Agent": USER_AGENT,
"Accept": "*/*",
"Accept-Language": "zh-CN,zh;q=0.9",
"Referer": "https://servicewechat.com/wx6b6c5243359fe265/171/page-frame.html",
"xweb_xhr": "1",
...extra,
};
if (this.token) headers["X-Dts-Token"] = this.token;
return headers;
}
async request(apiPath, { method = "GET", data = {}, auth = true } = {}) {
const options = {
method,
url: new URL(apiPath, API_BASE).toString(),
headers: this.headers(),
timeout: 15000,
validateStatus: () => true,
};
if (!auth) delete options.headers["X-Dts-Token"];
if (method.toUpperCase() === "GET") options.params = data;
else options.data = data;
const { data: result, status } = await axios.request(options);
if (status !== 200) throw new Error(`HTTP ${status}: ${JSON.stringify(result)}`);
if (Number(result?.errno) !== 0) throw new Error(`${result?.errno ?? ""} ${result?.errmsg || result?.message || JSON.stringify(result)}`.trim());
return result;
}
async getLoginCode() {
if (!process.env.wx_auth) throw new Error("缺少 wx_auth,无法从 wx_server 获取 code");
const { data } = await wechat.getCode(this.openid);
const code = data?.code || data?.data?.code;
if (!code) throw new Error(`wx_server 未返回 code: ${JSON.stringify(data)}`);
return code;
}
async loginByWxCode() {
try {
const code = await this.getLoginCode();
const result = await this.request("auth/login_by_weixin", {
method: "POST",
auth: false,
data: {
code,
userInfo: {},
shareUserId: 1,
},
});
const token = result?.data?.token || "";
if (!token) throw new Error(`登录响应未返回token: ${JSON.stringify(result)}`);
this.token = token;
this.userInfo = result?.data?.userInfo || {};
this.saveCachedToken();
$.log(`账号[${this.index}] 登录成功: ${this.userInfo.nickname || maskPhone(this.userInfo.mobile) || this.userId}`);
} catch (e) {
$.log(`账号[${this.index}] 登录失败: ${e.message || e}`);
}
}
async checkToken() {
try {
await this.request("user/getUserIntegral", {
data: { userId: this.userId },
});
return true;
} catch (e) {
return false;
}
}
async getPoints(prefix = "当前") {
try {
const result = await this.request("user/getUserIntegral", {
data: { userId: this.userId },
});
const integer = result?.data?.integer ?? result?.data?.integral ?? result?.data?.point ?? "未知";
$.log(`🌸账号[${this.index}] ${prefix}积分: ${integer}🎉`);
} catch (e) {
const message = String(e.message || e);
$.log(`🌸账号[${this.index}] 获取积分失败: ${message}❌`);
if (isTokenError(message)) this.removeCachedToken();
}
}
async signIn() {
let options = {
method: 'GET',
url: "https://www.kozbs.com/demo/wx/home/sign?userId=",
headers: {},
try {
const status = await this.request("home/signDay", {
data: { userId: this.userId },
});
if (status?.data?.isSign) {
$.log(`🌸账号[${this.index}] 今日已签到`);
return;
}
};
let { data: result } = await this.request(options);
if (result?.errno == '0') {
//打印签到结果
$.log(`🌸账号[${this.index}]` + `签到成功🎉`);
} else {
$.log(`🌸账号[${this.index}] 签到-失败:${result.errmsg}❌`)
}
}
async getPoints() {
let options = {
method: 'GET',
url: "https://www.kozbs.com/demo/wx/user/getUserIntegral?userId=",
headers: {},
};
let { data: result } = await this.request(options);
if (result?.errno == '0') {
//打印签到结果
$.log(`🌸账号[${this.index}]` + `当前积分` + `${result.data.integer}🎉`);
} else {
$.log(`🌸账号[${this.index}] 获取积分-失败:${result.errmsg}❌`)
await this.request("home/sign", {
data: { userId: this.userId },
});
$.log(`🌸账号[${this.index}] 签到成功🎉`);
} catch (e) {
const message = String(e.message || e);
if (/已签到|已签|重复/.test(message)) {
$.log(`🌸账号[${this.index}] 今日已签到`);
return;
}
$.log(`🌸账号[${this.index}] 签到失败: ${message}❌`);
if (isTokenError(message)) this.removeCachedToken();
}
}
}
!(async () => {
await getNotice()
await getNotice();
$.checkEnv(ckName);
for (let user of $.userList) {
for (const user of $.userList) {
await new Task(user).run();
}
})()
@@ -114,19 +257,16 @@ class Task {
.finally(() => $.done());
async function getNotice() {
try {
let options = {
url: `https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json`,
headers: {
"User-Agent": defaultUserAgent,
},
timeout:3000
}
let {
data: res
} = await axios.request(options);
$.log(res)
return res
} catch (e) {}
try {
const options = {
url: "https://ghproxy.net/https://raw.githubusercontent.com/smallfawn/Note/refs/heads/main/Notice.json",
headers: {
"User-Agent": defaultUserAgent,
},
timeout: 3000,
};
const { data: res } = await axios.request(options);
$.log(res);
return res;
} catch (e) {}
}