2025年8月21日星期四

九号出行任务脚本

1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/W9mv4W若失效,可用地址

1.购买服务器

阿里云:

服务器购买地址

https://t.aliyun.com/U/W9mv4W

若失效,可用地址

https://www.aliyun.com/minisite/goods?source=5176.29345612&userCode=49hts92d

腾讯云:

https://curl.qcloud.com/wJpWmSfU

若失效,可用地址

https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=ad201ee2ef3b771157f72ee5464b1fea&from=console

华为云

https://activity.huaweicloud.com/cps.html?fromacct=64b5cf7cc11b4840bb4ed2ea0b2f4468&utm_source=V1g3MDY4NTY=&utm_medium=cps&utm_campaign=201905

2.部署教程

2024年最新青龙面板跑脚本教程(一)持续更新中

3.代码如下

import axios from "axios";import moment from "moment";import dotenv from "dotenv";import { fileURLToPath } from "url";import { dirname } from "path";
// 初始化环境变量和路径const __dirname = dirname(fileURLToPath(import.meta.url));dotenv.config({ path`${__dirname}/.env` });
class NineBot {    constructor(deviceId, authorization, name = "九号出行") {        if (!deviceId || !authorization) {            throw new Error("缺少必要的参数: deviceId 或 authorization");        }
        this.msg = [];        this.name = name; // 账号名称(支持自定义)        this.deviceId = deviceId;        this.headers = {            Accept"application/json, text/plain, */*",            Authorization: authorization,            "Accept-Encoding""gzip, deflate, br",            "Accept-Language""zh-CN,zh-Hans;q=0.9",            "Content-Type""application/json",            Host"cn-cbu-gateway.ninebot.com",            Origin"https://h5-bj.ninebot.com",            from_platform_1"1",            language"zh",            "User-Agent""Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Segway v6 C 609033420",            Referer"https://h5-bj.ninebot.com/",        };
        // API端点        this.endpoints = {            sign"https://cn-cbu-gateway.ninebot.com/portal/api/user-sign/v2/sign",            status"https://cn-cbu-gateway.ninebot.com/portal/api/user-sign/v2/status"        };
        // 请求配置        this.requestConfig = {            timeout10000,            retry3,            retryDelay2000        };    }
    // 带重试机制的请求方法    async makeRequest(method, url, data = null) {        let attempts = 0;        const maxAttempts = this.requestConfig.retry;
        while (attempts < maxAttempts) {            try {                console.log(`[${this.name}] 尝试 ${attempts + 1}/${maxAttempts}${method} ${url}`);                const response = await axios({                    method,                    url,                    data,                    headersthis.headers,                    timeoutthis.requestConfig.timeout                });
                console.log(`[${this.name}] 请求成功: ${url}`);                return response.data;            } catch (error) {                attempts++;                console.error(`[${this.name}] 请求失败 (${attempts}/${maxAttempts}):`, error.message);                if (attempts === maxAttempts) {                    throw error;                }                await new Promise(resolve => setTimeout(resolve, this.requestConfig.retryDelay));            }        }    }
    // 执行签到    async sign() {        try {            console.log(`[${this.name}] 开始签到...`);            const responseData = await this.makeRequest(                "post",                this.endpoints.sign,                { deviceIdthis.deviceId }            );
            if (responseData.code === 0) {                console.log(`[${this.name}] 签到成功`);                return true;            } else {                const errorMsg = responseData.msg || "未知错误";                this.msg.push({ name"签到结果"value`签到失败: ${errorMsg}` });                console.error(`[${this.name}] 签到失败:`, errorMsg);                return false;            }        } catch (error) {            this.handleError("签到", error);            return false;        }    }
    // 验证登录状态并获取签到信息    async valid() {        try {            console.log(`[${this.name}] 验证登录状态并获取签到信息...`);            const timestamp = moment().valueOf();            const responseData = await this.makeRequest(                "get",                `${this.endpoints.status}?t=${timestamp}`            );
            if (responseData.code === 0) {                console.log(`[${this.name}] 验证成功,获取到签到信息`);                return [responseData.data""];            }            const errorMsg = responseData.msg || "验证失败";            console.error(`[${this.name}] 验证失败:`, errorMsg);            return [false, errorMsg];        } catch (error) {            const errorMsg = `登录验证异常: ${this.getErrorMessage(error)}`;            console.error(`[${this.name}${errorMsg}`);            return [false, errorMsg];        }    }
    // 错误处理    handleError(action, error) {        const errorMessage = this.getErrorMessage(error);        console.error(`[${this.name}${action}错误:`, errorMessage);        this.msg.push(            { name`${action}结果`value`${action}失败` },            { name"错误详情"value: errorMessage }        );    }
    // 提取错误信息    getErrorMessage(error) {        return error.response            ? `状态码: ${error.response.status}, 信息: ${error.response.data?.msg || error.message}`            : error.message;    }
    // 获取日志信息    get logs() {        return this.msg.map((one) => `${one.name}${one.value}`).join("\n");    }
    // 运行签到流程    async run() {        try {            console.log(`[${this.name}] 开始执行签到任务...`);            // 首次获取签到状态            let [validData, errInfo] = await this.valid();
            if (validData) {                const completed = validData.currentSignStatus === 1;                // 记录初始状态                this.msg.push({                    name"连续签到天数",                    value`${validData.consecutiveDays || 0}天`,                });                this.msg.push({                    name"今日签到状态",                    value: completed ? "已签到🎉" : "未签到❌",                });
                if (!completed) {                    // 执行签到                    const signSuccess = await this.sign();                    if (signSuccess) {                        // 签到成功后重新获取最新状态                        console.log(`[${this.name}] 签到成功,获取最新签到数据...`);                        const [newValidData] = await this.valid();                        if (newValidData) {                            // 更新连续签到天数为最新值                            this.msg = this.msg.map(item =>                                item.name === "连续签到天数"                                    ? { name"连续签到天数"value`${newValidData.consecutiveDays || 0}天` }                                    : item                            );                            // 更新今日签到状态                            this.msg = this.msg.map(item =>                                item.name === "今日签到状态"                                    ? { name"今日签到状态"value"已签到🎉" }                                    : item                            );                            this.msg.push({ name"签到结果"value"签到成功🎉🎉" });                        } else {                            this.msg.push({ name"签到结果"value"签到成功,但获取最新状态失败" });                        }                    }                } else {                    console.log(`[${this.name}] 今日已签到,无需重复签到`);                }            } else {                this.msg.push({ name"验证结果"value: errInfo });            }        } catch (error) {            this.msg.push({ name"执行结果"value`执行异常: ${error.message}` });            console.error(`[${this.name}] 执行异常:`, error);        } finally {            console.log(`[${this.name}] 任务执行完成`);        }    }}
// 发送Bark通知(支持完整参数配置)async function sendBarkNotification(title, message) {    // 从环境变量获取Bark配置    const barkUrl = process.env.BARK_URL || "https://api.day.app";    const barkKey = process.env.BARK_KEY;
    // 没有Bark密钥则不发送    if (!barkKey) {        console.log("未配置BARK_KEY,跳过Bark通知");        return false;    }
    try {        // 构建基础URL        let url = `${barkUrl}/${barkKey}/${encodeURIComponent(title)}/${encodeURIComponent(message)}`;
        // 收集所有可选参数        const params = [];
        // 通知分组        if (process.env.BARK_GROUP) {            params.push(`group=${encodeURIComponent(process.env.BARK_GROUP)}`);        }
        // 通知图标        if (process.env.BARK_ICON) {            params.push(`icon=${encodeURIComponent(process.env.BARK_ICON)}`);        }
        // 通知铃声        if (process.env.BARK_SOUND) {            params.push(`sound=${encodeURIComponent(process.env.BARK_SOUND)}`);        }
        // 点击跳转URL        if (process.env.BARK_URL_JUMP) {            params.push(`url=${encodeURIComponent(process.env.BARK_URL_JUMP)}`);        }
        // 可复制文本        if (process.env.BARK_COPY) {            // 提取连续天数用于替换变量            const dayMatch = message.match(/连续签到天数: (\d+)天/);            const day = dayMatch ? dayMatch[1] : "未知";            const copyText = process.env.BARK_COPY.replace('%day%', day);            params.push(`copy=${encodeURIComponent(copyText)}`);        }
        // 自动复制        if (process.env.BARK_AUTO_COPY === '1') {            params.push(`autoCopy=1`);        }
        // 添加参数到URL        if (params.length > 0) {            url += `?${params.join('&')}`;        }
        console.log(`发送Bark通知: ${url}`);
        // 发送请求        const response = await axios.get(url, { timeout5000 });
        if (response.data.code === 200) {            console.log("Bark通知发送成功");            return true;        } else {            console.error("Bark通知发送失败:", response.data);            return false;        }    } catch (error) {        console.error("发送Bark通知异常:", error.message);        return false;    }}
// 初始化并执行签到async function init() {    // 处理多账号配置    let accounts = [];    if (process.env.NINEBOT_ACCOUNTS) {        try {            accounts = JSON.parse(process.env.NINEBOT_ACCOUNTS);            // 为每个账号添加默认名称(如果未配置)            accounts = accounts.map((acc, index) => ({                name: acc.name || `账号${index + 1}`// 默认为"账号1"、"账号2"                deviceId: acc.deviceId,                authorization: acc.authorization            }));        } catch (e) {            console.error("NINEBOT_ACCOUNTS 格式错误:", e.message);            return;        }    }    // 处理单账号配置    else if (process.env.NINEBOT_DEVICE_ID && process.env.NINEBOT_AUTHORIZATION) {        accounts.push({            name: process.env.NINEBOT_NAME || "默认账号"// 支持单账号设置名称            deviceId: process.env.NINEBOT_DEVICE_ID,            authorization: process.env.NINEBOT_AUTHORIZATION        });    } else {        console.error("未配置任何账号信息");        return;    }
    // 执行所有账号的签到并收集结果    const allResults = [];    for (const account of accounts) {        console.log(`\n===== 开始处理账号: ${account.name} =====`);        try {            const bot = new NineBot(account.deviceId, account.authorization, account.name);            await bot.run();            allResults.push({                name: account.name,                success: bot.logs.includes("签到成功") || bot.logs.includes("已签到"),                logs: bot.logs            });        } catch (e) {            allResults.push({                name: account.name,                successfalse,                logs`初始化失败: ${e.message}`            });        }    }
    // 生成汇总通知内容    const title = "九号出行签到结果";    let message = allResults.map(acc => {        const status = acc.success ? "✅" : "❌";        return `${status} ${acc.name}\n${acc.logs.replace(/\n/g, "\n  ")}`;    }).join("\n\n");
    // 发送Bark通知    await sendBarkNotification(title, message);}
// 启动执行init();
解析

该脚本为九号出行(Ninebot)签到脚本,主要作用:

  • 使用抓到的 authorization(九号出行 H5/App 接口鉴权)对设备ID执行每日签到。

  • 先查询今日签到状态,未签到再调用签到接口;成功后二次查询以回填"连续签到天数/今日状态"。

  • 支持多账号(环境变量 JSON 列表)与单账号两种配置方式。

  • 结果可通过 Bark 推送(可设置分组、图标、声音、点击跳转、自动复制等)。

主要方法

初始化与配置

  • 构造函数 constructor(deviceId, authorization, name)
    校验必要参数;设置统一请求头(含 Authorization、UA 等)、接口地址(sign/status)、超时与重试策略;name 用于日志/区分账号。

  • 环境变量

    • 多账号:NINEBOT_ACCOUNTS(JSON 数组,元素含 name?deviceIdauthorization

    • 单账号:NINEBOT_DEVICE_IDNINEBOT_AUTHORIZATIONNINEBOT_NAME?

    • Bark:BARK_KEY(必填否则不发)、BARK_URL?BARK_GROUP?BARK_ICON?BARK_SOUND?BARK_URL_JUMP?BARK_COPY?(支持占位 %day%)、BARK_AUTO_COPY=1?

请求与错误处理

  • makeRequest(method, url, data)
    统一的 Axios 请求封装,带重试(默认 3 次、间隔 2s)与超时(10s)。

  • handleError(action, error) / getErrorMessage(error)
    规范化错误信息并记录到 this.msg

业务逻辑

  • valid()
    GET /user-sign/v2/status 查询当前签到状态与连续天数。返回 [data, ""] 或 [false, 错误信息]

  • sign()
    POST /user-sign/v2/sign 执行签到(入参含 deviceId)。成功返回 true,否则记录失败原因。

  • run()(单账号完整流程)

    1. 调 valid() 取今日状态与连续天数并记录到 msg

    2. 若未签到则调 sign();成功后再次 valid() 以刷新连续天数与"今日状态";

    3. 整个过程中的关键信息累积到 this.msg

  • logs getter
    将累积消息格式化为多行文本,便于汇总/通知。

通知与入口

  • sendBarkNotification(title, message)
    读取 Bark 配置,按可选参数拼 URL 并发送通知;支持分组、图标、声音、跳转、复制文本/自动复制

  • init()(脚本入口)
    解析账号配置 → 为每个账号实例化 NineBot 并执行 run() → 汇总各账号结果(成功/失败+日志) → 统一调用 Bark 推送。



注意

本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。


历史脚本txt文件获取>>
服务器搭建,人工服务咨询>>


没有评论:

发表评论

做temu拼多多跨境电商亏大了?

在网络上稍微搜索一下,看上去做temu跨境电商的都在亏钱,有的亏损几十万,甚至有的上百万,骂声一大片,似乎很恐 在网络上稍微搜索一下,看上去做temu跨境电商的都在亏钱,有的亏损几十万,甚至有的上百万,骂声一大片,似乎很恐怖的样子。 我相信类似的信息影响了很多人,想做temu...