mirror of
https://github.com/hex-ci/smzdm_script.git
synced 2026-10-28 19:25:04 +08:00
feat(smzdm): 🚀 优化风控对抗逻辑并完善签到/任务流程
* **风控对抗增强**:
* 更新 `APP_VERSION` 至 `11.1.98`。
* 引入 `device_id` 确定性派生机制,通过 `userId` 结合 `DEVICE_SALT` 生成固定的设备串,解决跨运行设备不一致问题。
* 优化 `sk` (设备签名) 生成逻辑,支持基于派生设备串自动计算。
* 增加 `Cookie` 完整性检查,自动检测并提示缺失 `device_id`、`device_rid`、`z_dr` 等关键字段。
* **签到流程优化**:
* 引入 `getCheckinCard` 接口,先渲染签到卡片以获取最新的连签状态,确保奖励判断准确。
* 移除硬编码的 `IS_INSTALL_ZHANGDAMA` 参数。
* **任务处理优化**:
* 增加 `getCaptchaType` 逻辑,在领取任务失败时识别验证码类型(滑块/图形),并友好提示用户手动操作。
* 完善 `getArticleDetail` 接口,支持传递 `hashcode` 以匹配 APP 端跳转逻辑。
* **文档更新**:
* 更新 `README.md`,详细说明 `SMZDM_SK` 的使用逻辑、设备字段缺失的影响以及如何正确抓包。
This commit is contained in:
@@ -47,7 +47,7 @@ ql repo https://github.com/hex-ci/smzdm_script.git "smzdm_" "" "env.js|bot.js|se
|
||||
|
||||
建议使用 Android 手机抓包(iOS 也可以)域名为 `user-api.smzdm.com` 的任意链接,把**所有** Cookie 取出来放到青龙面板的 `SMZDM_COOKIE` 环境变量中,多用户请添加多个同名环境变量或者用 `&` 符号分隔。
|
||||
|
||||
如果手机实在抓不到,也可以用浏览器的 Cookie,但是强烈建议使用手机端的 Cookie。
|
||||
如果手机实在抓不到,也可以用浏览器的 Cookie,但是强烈建议使用手机端的 Cookie。脚本会自动检查 `device_id`、`device_rid`、`z_dr` 等设备字段,缺失时在日志里提示,缺字段的 Cookie 更容易被风控。
|
||||
|
||||
#### 抓包教程
|
||||
|
||||
@@ -64,7 +64,7 @@ ql repo https://github.com/hex-ci/smzdm_script.git "smzdm_" "" "env.js|bot.js|se
|
||||
环境变量请使用环境变量列表直接添加,不要使用 `export xxx=""` 这种方式添加环境变量。
|
||||
|
||||
* `SMZDM_COOKIE`: 抓包抓到的 Cookie 内容,需要所有 Cookie 内容,多用户可以用 `&` 分隔,或者使用多个同名环境变量。
|
||||
* `SMZDM_SK`: 这个值是可选值,会自动计算,如果你一定想用自己的,可以抓取,是从安卓 App 的 `https://user-api.smzdm.com/checkin` 请求参数中抓包抓到的,多用户可以用 `&` 分隔,或者使用多个同名环境变量,顺序要保持与 `SMZDM_COOKIE` 多用户顺序一致。
|
||||
* `SMZDM_SK`: 签到请求里的设备签名,从安卓 App 的 `https://user-api.smzdm.com/checkin` 请求参数中抓包得到,多用户可以用 `&` 分隔,或者使用多个同名环境变量,顺序要保持与 `SMZDM_COOKIE` 多用户顺序一致。不填时脚本会按账号派生一个固定的设备串来生成 sk(跨运行不变,但与真机的设备串不同);填了之后会解密校验它是否属于对应的 Cookie,不属于会在日志里提示(通常是多账号顺序错位)。无论哪种情况,脚本都会把 Cookie 的 `device_rid`/`device_s` 对齐成 md5(实际使用的设备串)——同机抓的 Cookie 这两个值本来就相等,不会变;不一致时说明 Cookie 和 sk 可能不是同一台设备,日志会提示。
|
||||
* `SMZDM_USER_AGENT_APP`: 这个值是可选值,是指 APP 的 User-Agent,从 APP 的 API 请求头中抓包得到,建议抓取 Android 的 User-Agent,不填使用脚本默认值。
|
||||
* `SMZDM_USER_AGENT_WEB`: 这个值是可选值,是指 APP 中访问网页的 User-Agent,一般在 APP 内的转盘网页中抓包得到,建议抓取 Android 的 User-Agent,不填使用脚本默认值。
|
||||
* `SMZDM_COMMENT`: 如果要完成评论文章的任务请设置这个环境变量,环境变量的内容是评论的文案,文案要大于 10 个汉字,建议用比较个性化的文案,脚本发布评论后会删除这条评论,但是为防止删除失败的情况,请尽量用好一点的文案,防止被判定为恶意灌水。可以写多条文案(用换行或 `|` 分隔,每条都要大于 10 个汉字),脚本每次随机选一条,避免每天发同样的内容。
|
||||
|
||||
45
bot.js
45
bot.js
@@ -3,8 +3,8 @@ const got = require('got');
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
const APP_VERSION = '11.1.95';
|
||||
const APP_VERSION_REV = '1195';
|
||||
const APP_VERSION = '11.1.98';
|
||||
const APP_VERSION_REV = '1198';
|
||||
|
||||
const DEFAULT_USER_AGENT_APP = `smzdm_android_V${APP_VERSION} rv:${APP_VERSION_REV} (Redmi Note 3;Android10.0;zh)smzdmapp`;
|
||||
const DEFAULT_USER_AGENT_WEB = `Mozilla/5.0 (Linux; Android 10.0; Redmi Build/Redmi Note 3; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/95.0.4638.74 Mobile Safari/537.36 smzdm_android_V${APP_VERSION} rv:${APP_VERSION_REV} (Redmi;Android10.0;zh) jsbv_1.0.0 webv_2.0 smzdmapp`;
|
||||
@@ -192,6 +192,41 @@ const removeCookie = (cookie, name) => {
|
||||
return cookie.replace(re, '$1');
|
||||
};
|
||||
|
||||
const hasCookie = (cookie, name) => new RegExp(`(^|;)\\s*${name}=`, 'i').test(cookie);
|
||||
|
||||
// 值为空也是 APP 的合法字段,已存在就不要覆盖
|
||||
const addCookieIfAbsent = (cookie, name, value = '') => {
|
||||
if (hasCookie(cookie, name)) {
|
||||
return cookie;
|
||||
}
|
||||
|
||||
return `${cookie.replace(/;?\s*$/, ';')} ${name}=${value};`;
|
||||
};
|
||||
|
||||
// APP 会用本地设备信息重建整条 Cookie,缺字段的请求一眼可辨
|
||||
const REQUIRED_COOKIE_FIELDS = [
|
||||
'sess',
|
||||
'smzdm_id',
|
||||
'device_id',
|
||||
'device_rid',
|
||||
'z_dr'
|
||||
];
|
||||
|
||||
const warnedCookieFields = new Set();
|
||||
|
||||
const checkCookie = (cookie) => {
|
||||
const missing = REQUIRED_COOKIE_FIELDS.filter(name => !hasCookie(cookie, name));
|
||||
const key = missing.join(',');
|
||||
|
||||
if (missing.length < 1 || warnedCookieFields.has(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
warnedCookieFields.add(key);
|
||||
|
||||
console.log(`Cookie 缺少 APP 会发送的字段: ${missing.join('、')},建议重新从 APP 抓取完整 Cookie`);
|
||||
};
|
||||
|
||||
const getEnvCookies = () => {
|
||||
let cookies = [];
|
||||
|
||||
@@ -253,15 +288,17 @@ class SmzdmBot {
|
||||
this.androidCookie = setCookie(this.androidCookie, 'device_smzdm', 'android');
|
||||
this.androidCookie = setCookie(this.androidCookie, 'f', 'android');
|
||||
this.androidCookie = setCookie(this.androidCookie, 'basic_v', '0');
|
||||
this.androidCookie = addCookieIfAbsent(this.androidCookie, 'device_type');
|
||||
|
||||
[
|
||||
'smzdm_version',
|
||||
'device_smzdm_version',
|
||||
'device_type',
|
||||
'device_name'
|
||||
].forEach(name => {
|
||||
this.androidCookie = removeCookie(this.androidCookie, name);
|
||||
});
|
||||
|
||||
checkCookie(this.androidCookie);
|
||||
}
|
||||
|
||||
getHeaders() {
|
||||
@@ -274,8 +311,6 @@ class SmzdmBot {
|
||||
}
|
||||
|
||||
return {
|
||||
Accept: '*/*',
|
||||
'Accept-Language': 'zh-Hans-CN;q=1',
|
||||
'Accept-Encoding': 'gzip',
|
||||
'request_key': requestKey(),
|
||||
'User-Agent': userAgent,
|
||||
|
||||
@@ -191,6 +191,11 @@ class SmzdmTaskBot extends SmzdmBot {
|
||||
return article.article_hash_id || article.article_id;
|
||||
}
|
||||
|
||||
// 打开文章时 APP 会把任务 redirect 里的 hashcode 一起带上
|
||||
getRedirectHashcode(task) {
|
||||
return (task.task_redirect_url && task.task_redirect_url.hashcode) || '';
|
||||
}
|
||||
|
||||
// 随机取一条评论文案,多条时用换行或 | 分隔
|
||||
getCommentContent() {
|
||||
const words = String(process.env.SMZDM_COMMENT || '')
|
||||
@@ -438,7 +443,7 @@ class SmzdmTaskBot extends SmzdmBot {
|
||||
articleId = task.task_redirect_url.link_val;
|
||||
|
||||
// 获取文章信息
|
||||
const articleDetail = await this.getArticleDetail(articleId);
|
||||
const articleDetail = await this.getArticleDetail(articleId, this.getRedirectHashcode(task));
|
||||
|
||||
if (articleDetail === false) {
|
||||
return {
|
||||
@@ -803,7 +808,7 @@ class SmzdmTaskBot extends SmzdmBot {
|
||||
await this.getHaojiaDetail(article.article_id);
|
||||
}
|
||||
else {
|
||||
await this.getArticleDetail(article.article_id);
|
||||
await this.getArticleDetail(article.article_id, this.getRedirectHashcode(task));
|
||||
}
|
||||
|
||||
await wait(8, 20);
|
||||
@@ -868,7 +873,7 @@ class SmzdmTaskBot extends SmzdmBot {
|
||||
await this.getHaojiaDetail(article.article_id);
|
||||
}
|
||||
else {
|
||||
await this.getArticleDetail(article.article_id);
|
||||
await this.getArticleDetail(article.article_id, this.getRedirectHashcode(task));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1337,15 +1342,12 @@ class SmzdmTaskBot extends SmzdmBot {
|
||||
}
|
||||
|
||||
// 获取文章详情
|
||||
async getArticleDetail(id) {
|
||||
async getArticleDetail(id, hashcode = '') {
|
||||
const { isSuccess, data, response } = await requestApi(`https://article-api.smzdm.com/article_detail/${id}`, {
|
||||
headers: this.getHeaders(),
|
||||
data: {
|
||||
comment_flow: '',
|
||||
lastest_update_time: '',
|
||||
uhome: 0,
|
||||
imgmode: 0,
|
||||
article_channel_id: 0
|
||||
hashcode,
|
||||
h5hash: ''
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
218
smzdm_checkin.js
218
smzdm_checkin.js
@@ -5,6 +5,7 @@ smzdm 签到脚本
|
||||
cron: 10 8 * * *
|
||||
*/
|
||||
|
||||
const crypto = require('crypto');
|
||||
const Env = require('./env');
|
||||
const {
|
||||
SmzdmBot,
|
||||
@@ -13,8 +14,7 @@ const {
|
||||
getEnvCookies,
|
||||
wait,
|
||||
waitHuman,
|
||||
CREATE_CENTER_VIEW,
|
||||
IS_INSTALL_ZHANGDAMA
|
||||
CREATE_CENTER_VIEW
|
||||
} = require('./bot');
|
||||
const notify = require('./sendNotify');
|
||||
const CryptoJS = require('crypto-js');
|
||||
@@ -31,6 +31,9 @@ class SmzdmCheckinBot extends SmzdmBot {
|
||||
}
|
||||
|
||||
async run() {
|
||||
// 客户端先渲染签到卡片,用户点签到后才发 /checkin
|
||||
await this.getCheckinCard();
|
||||
|
||||
const { msg: msg1 } = await this.checkin();
|
||||
|
||||
const { msg: msg2 } = await this.allReward();
|
||||
@@ -46,7 +49,7 @@ class SmzdmCheckinBot extends SmzdmBot {
|
||||
headers: this.getHeaders(),
|
||||
data: {
|
||||
touchstone_event: '',
|
||||
sk: this.sk || '1',
|
||||
sk: this.sk,
|
||||
token: this.token,
|
||||
captcha: ''
|
||||
}
|
||||
@@ -127,7 +130,8 @@ class SmzdmCheckinBot extends SmzdmBot {
|
||||
}
|
||||
|
||||
async extraReward() {
|
||||
const isContinue = await this.isContinueCheckin();
|
||||
// 连签奖励状态以签到后的卡片为准,所以这里重新拉一次
|
||||
const isContinue = this.isContinueCheckin(await this.getCheckinCard());
|
||||
|
||||
if (!isContinue) {
|
||||
const msg = '今天没有额外奖励';
|
||||
@@ -167,26 +171,31 @@ class SmzdmCheckinBot extends SmzdmBot {
|
||||
}
|
||||
}
|
||||
|
||||
async isContinueCheckin() {
|
||||
// 签到卡片,APP 进签到页时先渲染它
|
||||
async getCheckinCard() {
|
||||
const { isSuccess, data, response } = await requestApi('https://user-api.smzdm.com/checkin/show_view_v2', {
|
||||
method: 'post',
|
||||
headers: this.getHeaders(),
|
||||
data: {
|
||||
is_install_zhangdama: IS_INSTALL_ZHANGDAMA
|
||||
}
|
||||
headers: this.getHeaders()
|
||||
});
|
||||
|
||||
if (isSuccess) {
|
||||
// 连续签到的卡片,直接按有没有 checkin_continue 来找
|
||||
const result = data.data.rows.find(item => item.cell_data && item.cell_data.checkin_continue);
|
||||
|
||||
return !!(result && result.cell_data.checkin_continue.continue_checkin_reward_show);
|
||||
return data.data;
|
||||
}
|
||||
else {
|
||||
$.log(`查询是否有额外奖励失败!${response}`);
|
||||
|
||||
$.log(`查询签到卡片失败!${response}`);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 连续签到的卡片,直接按有没有 checkin_continue 来找
|
||||
isContinueCheckin(card) {
|
||||
if (!card || !card.rows) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = card.rows.find(item => item.cell_data && item.cell_data.checkin_continue);
|
||||
|
||||
return !!(result && result.cell_data.checkin_continue.continue_checkin_reward_show);
|
||||
}
|
||||
|
||||
async getVipInfo() {
|
||||
@@ -210,27 +219,44 @@ class SmzdmCheckinBot extends SmzdmBot {
|
||||
}
|
||||
}
|
||||
|
||||
function random32() {
|
||||
const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
const SK_KEY = 'geZm53XAspb02exN';
|
||||
const warned = new Set();
|
||||
|
||||
function warnOnce(key, message) {
|
||||
if (warned.has(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
warned.add(key);
|
||||
|
||||
$.log(message);
|
||||
}
|
||||
|
||||
function getUserId(cookie) {
|
||||
const match = cookie.match(/smzdm_id=([^;]*)/);
|
||||
|
||||
return match ? match[1] : '';
|
||||
}
|
||||
|
||||
const DEVICE_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
// 盐值一旦定下就不能改,改了等于所有账号换设备
|
||||
const DEVICE_SALT = 'smzdm_script_device_v1';
|
||||
|
||||
// APP 的设备串是 62 字符集 32 位随机串,这里按账号确定性派生,保证跨运行固定不变
|
||||
function makeDeviceId(userId) {
|
||||
const digest = crypto.createHash('sha256').update(`${DEVICE_SALT}:${userId}`).digest();
|
||||
let result = '';
|
||||
|
||||
for (let i = 0; i < 32; i++) {
|
||||
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
result += DEVICE_ALPHABET.charAt(digest[i] % DEVICE_ALPHABET.length);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function getSk(cookie) {
|
||||
const matchUserId = cookie.match(/smzdm_id=([^;]*)/);
|
||||
|
||||
if (!matchUserId) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const userId = matchUserId[1];
|
||||
const deviceId = getDeviceId(cookie);
|
||||
const key = CryptoJS.enc.Utf8.parse('geZm53XAspb02exN');
|
||||
function makeSk(userId, deviceId) {
|
||||
const key = CryptoJS.enc.Utf8.parse(SK_KEY);
|
||||
const cipherText = CryptoJS.DES.encrypt(userId + deviceId, key, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
@@ -239,14 +265,81 @@ function getSk(cookie) {
|
||||
return cipherText.toString();
|
||||
}
|
||||
|
||||
function getDeviceId(cookie) {
|
||||
const matchDeviceId = cookie.match(/device_id=([^;]*)/);
|
||||
|
||||
if (matchDeviceId) {
|
||||
return matchDeviceId[1];
|
||||
// sk 是 DES(userId + 设备 id) 的 Base64,可逆;返回设备段,不属于这个账号就返回空串
|
||||
function decodeSkDevice(sk, userId) {
|
||||
if (!userId) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return random32();
|
||||
try {
|
||||
const plain = CryptoJS.DES.decrypt(
|
||||
{ ciphertext: CryptoJS.enc.Base64.parse(sk) },
|
||||
CryptoJS.enc.Utf8.parse(SK_KEY),
|
||||
{
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
}
|
||||
).toString(CryptoJS.enc.Utf8);
|
||||
|
||||
return plain.indexOf(userId) === 0 ? plain.slice(userId.length) : '';
|
||||
}
|
||||
catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// cookie 缺 smzdm_id 时,/vip 的 data.base.user_smzdm_id 还能拿到(APP 也用它回写 sp,sk 的 userId 正是来自这里)
|
||||
async function fetchUserId(cookie) {
|
||||
const bot = new SmzdmBot(cookie);
|
||||
const { isSuccess, data } = await requestApi('https://user-api.smzdm.com/vip', {
|
||||
method: 'post',
|
||||
headers: bot.getHeaders(),
|
||||
data: {
|
||||
token: bot.token,
|
||||
create_center_view: CREATE_CENTER_VIEW
|
||||
}
|
||||
});
|
||||
// smzdm_id 在响应信封顶层(每个响应都有),base.user_smzdm_id 作为兜底
|
||||
const userId = isSuccess
|
||||
? (data.smzdm_id || (data.data && data.data.base ? data.data.base.user_smzdm_id : ''))
|
||||
: '';
|
||||
|
||||
return userId && userId != '0' ? String(userId) : '';
|
||||
}
|
||||
|
||||
const md5 = (str) => crypto.createHash('md5').update(str).digest('hex');
|
||||
|
||||
function getCookieValue(cookie, name) {
|
||||
const match = cookie.match(new RegExp(`(?:^|;)\\s*${name}=([^;]*)`, 'i'));
|
||||
|
||||
return match ? match[1] : '';
|
||||
}
|
||||
|
||||
// 覆盖或补上 cookie 字段,值为空也要能覆盖
|
||||
function upsertCookie(cookie, name, value) {
|
||||
const re = new RegExp(`(^|;)\\s*${name}=[^;]*;?`, 'i');
|
||||
|
||||
if (re.test(cookie)) {
|
||||
return cookie.replace(re, `$1${name}=${value};`);
|
||||
}
|
||||
|
||||
return `${cookie.replace(/;?\s*$/, ';')} ${name}=${value};`;
|
||||
}
|
||||
|
||||
// APP 的 device_rid/device_s 就是 md5(设备串),把 cookie 对齐到 sk 实际用的设备段
|
||||
function alignDeviceCookie(cookie, deviceId) {
|
||||
const hash = md5(deviceId);
|
||||
let result = cookie;
|
||||
|
||||
if (getCookieValue(result, 'device_rid') !== hash) {
|
||||
result = upsertCookie(result, 'device_rid', hash);
|
||||
}
|
||||
|
||||
if (getCookieValue(result, 'device_s') !== hash) {
|
||||
result = upsertCookie(result, 'device_s', hash);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
!(async () => {
|
||||
@@ -275,15 +368,64 @@ function getDeviceId(cookie) {
|
||||
let notifyContent = '';
|
||||
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
const cookie = cookies[i];
|
||||
let cookie = cookies[i];
|
||||
|
||||
if (!cookie) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let sk = sks[i];
|
||||
if (!sk) {
|
||||
sk = getSk(cookie)
|
||||
let userId = getUserId(cookie);
|
||||
let sk = (sks[i] || '').trim();
|
||||
let deviceId = '';
|
||||
|
||||
if (!userId) {
|
||||
// 少数 Cookie 只有 sess 没 smzdm_id,用 /vip 把它补回来,避免退化成 sk=1
|
||||
userId = await fetchUserId(cookie);
|
||||
|
||||
if (userId) {
|
||||
warnOnce('vip-id', 'Cookie 里没有 smzdm_id,已从 /vip 接口取到');
|
||||
}
|
||||
}
|
||||
|
||||
if (sk) {
|
||||
// 用配置的真 sk,并把 cookie 对齐到它自己的设备段(同机抓的两个值本来就相等)
|
||||
deviceId = decodeSkDevice(sk, userId);
|
||||
|
||||
if (!deviceId) {
|
||||
$.log(`🟡第 ${i + 1} 个 SMZDM_SK 解不出设备段(不是有效的 sk 或不属于这个账号),签到很可能失败,请检查多账号顺序`);
|
||||
}
|
||||
}
|
||||
else if (userId) {
|
||||
// 没有真值就按账号派生一个固定设备串,sk 和 cookie 用同一个
|
||||
deviceId = makeDeviceId(userId);
|
||||
sk = makeSk(userId, deviceId);
|
||||
|
||||
warnOnce(
|
||||
'auto',
|
||||
'未配置 SMZDM_SK,改用按账号派生的固定设备串生成 sk;如需与真机完全一致,请在 APP 的签到请求里抓 sk 填入 SMZDM_SK'
|
||||
);
|
||||
}
|
||||
else {
|
||||
// cookie 和 /vip 都拿不到 userId,sk 拼不出来;发 1 是最后一档,至少保持参数存在
|
||||
sk = '1';
|
||||
|
||||
warnOnce(
|
||||
'empty',
|
||||
'Cookie 里没有 smzdm_id,/vip 也没取到,只能发 sk=1;这种 Cookie 很可能被判定异常,建议重新从 APP 抓包'
|
||||
);
|
||||
}
|
||||
|
||||
if (deviceId) {
|
||||
const aligned = alignDeviceCookie(cookie, deviceId);
|
||||
|
||||
if (aligned !== cookie) {
|
||||
warnOnce(
|
||||
'align',
|
||||
'cookie 的 device_rid/device_s 与 sk 的设备段不一致,已按 sk 对齐(cookie 和 sk 可能不是同一台设备)'
|
||||
);
|
||||
}
|
||||
|
||||
cookie = aligned;
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
|
||||
@@ -12,6 +12,7 @@ const {
|
||||
getEnvCookies,
|
||||
wait,
|
||||
waitHuman,
|
||||
CREATE_CENTER_VIEW,
|
||||
IS_INSTALL_ZHANGDAMA
|
||||
} = require('./bot');
|
||||
const notify = require('./sendNotify');
|
||||
@@ -135,11 +136,14 @@ class SmzdmNormalTaskBot extends SmzdmTaskBot {
|
||||
|
||||
if (robotToken === false) {
|
||||
return {
|
||||
isSuccess,
|
||||
isSuccess: false,
|
||||
msg: '领取任务奖励失败!'
|
||||
};
|
||||
}
|
||||
|
||||
// 客户端初始化验证码组件时就会查一次,用来说明被要求的是哪种验证码
|
||||
const captchaType = await this.getCaptchaType();
|
||||
|
||||
const { isSuccess, data, response } = await requestApi('https://user-api.smzdm.com/task/activity_task_receive', {
|
||||
method: 'post',
|
||||
headers: this.getHeaders(),
|
||||
@@ -163,14 +167,45 @@ class SmzdmNormalTaskBot extends SmzdmTaskBot {
|
||||
msg
|
||||
};
|
||||
}
|
||||
else {
|
||||
$.log(`领取任务奖励失败!${response}`);
|
||||
|
||||
// 110202 = 服务端要求人机验证,空验证码一定过不了
|
||||
if (data.error_code == '110202') {
|
||||
const type = captchaType === 'geetest' ? '滑块' : '图形';
|
||||
|
||||
$.log(`🟡[${taskId}] 领取需要${type}验证码,脚本无法通过,请到 APP 内手动领取`);
|
||||
|
||||
return {
|
||||
isSuccess,
|
||||
msg: '领取任务奖励失败!'
|
||||
isSuccess: false,
|
||||
msg: '需要验证码'
|
||||
};
|
||||
}
|
||||
|
||||
$.log(`领取任务奖励失败!${response}`);
|
||||
|
||||
return {
|
||||
isSuccess,
|
||||
msg: '领取任务奖励失败!'
|
||||
};
|
||||
}
|
||||
|
||||
// 验证码类型:geetest 走滑块,其余走图形
|
||||
async getCaptchaType() {
|
||||
const { isSuccess, data, response } = await requestApi('https://user-api.smzdm.com/getcaptcha/switch', {
|
||||
method: 'post',
|
||||
headers: this.getHeaders(),
|
||||
data: {
|
||||
token: this.token,
|
||||
create_center_view: CREATE_CENTER_VIEW
|
||||
}
|
||||
});
|
||||
|
||||
if (isSuccess && data.data) {
|
||||
return data.data.type || '';
|
||||
}
|
||||
|
||||
$.log(`获取验证码配置失败!${response}`);
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user