feat: add per-account socks5 proxy

This commit is contained in:
2026-06-07 13:50:03 +08:00
parent c7f74b50eb
commit 7c580d3234
2 changed files with 496 additions and 1 deletions
+83 -1
View File
@@ -2,6 +2,14 @@ const axios = require('axios');
const fs = require('fs');
const path = require('path');
const vm = require('vm');
const { AsyncLocalStorage } = require('async_hooks');
let SocksProxyAgent = null;
try {
({ SocksProxyAgent } = require('socks-proxy-agent'));
} catch (e) {
// 未配置代理时不需要安装;配置 SOCKS5 代理时会给出明确提示。
}
// ============================================
// 大象新闻积分脚本 - Token缓存版
@@ -23,6 +31,12 @@ const vm = require('vm');
// export dxxwhd="账号1&密码1@账号2&密码2" # 多账号用@分隔
// export dxxwhd="账号1&密码1
// 账号2&密码2" # 多账号也可用换行分隔
// export dxxwhd="账号&密码&支付宝账号&姓名&socks5://127.0.0.1:7890" # 可选账号级 SOCKS5 代理
//
// 账号字段:账号&密码&支付宝账号&姓名&socks5代理
// - 支付宝账号/姓名/代理均可选;如果只想配置代理但不配置支付宝,可写:账号&密码&&&socks5://host:port
// - 代理支持 socks5:// / socks5h://,可带认证:socks5h://user:pass@host:port
// - 该账号配置代理后,登录、积分、文章、微剧/兑吧等所有 axios 请求均走该代理;未配置则使用本地网络
//
// 脚本配置(在脚本中修改):
// ENABLE_NOTIFY = true # 开启通知(默认false,需要青龙面板环境)
@@ -58,6 +72,70 @@ const AXIOS_COMMON_OPTS = {
maxContentLength: Infinity
};
// ========== 账号级 SOCKS5 代理 ==========
const accountContext = new AsyncLocalStorage();
const socksAgentCache = new Map();
const axiosRequestRaw = axios.request.bind(axios);
function normalizeSocksProxy(proxyUrl) {
const raw = String(proxyUrl || '').trim();
if (!raw) return '';
if (/^socks5h?:\/\//i.test(raw)) return raw;
// 兼容只填 host:port 的写法,默认按 socks5:// 处理。
if (/^[^\s:/]+:\d+$/i.test(raw)) return `socks5://${raw}`;
throw new Error(`SOCKS5代理格式不正确: ${raw}`);
}
function maskProxyUrl(proxyUrl) {
if (!proxyUrl) return '未配置';
try {
const u = new URL(proxyUrl);
if (u.username || u.password) {
u.username = '***';
u.password = '***';
}
return u.toString();
} catch (_) {
return String(proxyUrl).replace(/:\/\/([^:@/]+):([^@/]+)@/, '://***:***@');
}
}
function getSocksAgent(proxyUrl) {
const normalized = normalizeSocksProxy(proxyUrl);
if (!normalized) return null;
if (!SocksProxyAgent) {
throw new Error('已配置SOCKS5代理,但缺少依赖 socks-proxy-agent,请先执行: npm install');
}
if (!socksAgentCache.has(normalized)) {
socksAgentCache.set(normalized, new SocksProxyAgent(normalized));
}
return socksAgentCache.get(normalized);
}
function applyCurrentAccountProxy(config = {}) {
const ctx = accountContext.getStore();
const proxyUrl = ctx && ctx.socksProxy;
if (!proxyUrl) return config;
const agent = getSocksAgent(proxyUrl);
return {
...config,
proxy: false,
httpAgent: config.httpAgent || agent,
httpsAgent: config.httpsAgent || agent
};
}
axios.request = function patchedAxiosRequest(config) {
return axiosRequestRaw(applyCurrentAccountProxy(config || {}));
};
axios.interceptors.request.use(config => applyCurrentAccountProxy(config || {}));
function runWithAccountProxy(socksProxy, fn) {
const normalized = normalizeSocksProxy(socksProxy);
return accountContext.run({ socksProxy: normalized }, fn);
}
function addNotifyStr(str, is_log = true) {
if (is_log) console.log(str);
msg += `${str}\n`;
@@ -1193,12 +1271,15 @@ async function doWeijuSignTask(token, alipay = '', realname = '') {
async function executeAccount(accountInfo, index) {
const username = accountInfo[0];
const password = accountInfo[1];
// 账号格式:账号&密码&支付宝账号&姓名(后项可选;缺则不抽奖、不提现
// 账号格式:账号&密码&支付宝账号&姓名&socks5代理(后项可选;代理配置后该账号所有请求均走代理
let alipay = (accountInfo[2] || '').trim();
let realname = (accountInfo[3] || '').trim();
const socksProxy = normalizeSocksProxy(accountInfo.slice(4).join('&'));
addNotifyStr(`\n==== 开始【第 ${index + 1} 个账号: ${username}】====`);
addNotifyStr(`🌐 SOCKS5代理: ${socksProxy ? maskProxyUrl(socksProxy) : '未配置,使用本地网络'}`);
return runWithAccountProxy(socksProxy, async () => {
// 使用新的token获取方法(优先缓存,失效则登录),同时把 alipay/realname 写入缓存
const token = await getValidToken(username, password, { alipay, realname });
if (!token) {
@@ -1337,6 +1418,7 @@ async function executeAccount(accountInfo, index) {
if (earnedScore > 0) {
addNotifyStr(`🎉 本次获得积分: +${earnedScore}`);
}
});
}
// ========== 主程序 ==========