feat(xuequ): 添加携趣白名单切换脚本

- 新增 switch.js 脚本,用于自动切换携趣代理的白名单IP
- 支持多账户和多IP配置,通过环境变量 XQ_ACCOUNTS 和 XQ_WHITELIST 设置
- 实现获取当前白名单、删除所有白名单、选择剩余次数最多的账户并添加新白名单的功能
- 集成定时任务,可通过 cron 表达式设置执行时间
- 添加详细的日志输出和错误处理机制
This commit is contained in:
2025-11-02 17:16:09 +08:00
commit 625a6ea2f9
7 changed files with 1873 additions and 0 deletions

96
.gitignore vendored Normal file
View File

@@ -0,0 +1,96 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node_modules
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
.env.local
.env.production
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
.claude/

60
README.md Normal file
View File

@@ -0,0 +1,60 @@
# 青龙面板脚本库
这是一个专为青龙面板设计的脚本库,包含各种自动化脚本和工具。
## 简介
青龙面板是一个支持 Python3、JavaScript、Shell、Typescript 的定时任务管理平台。本仓库提供了一系列实用的脚本,帮助用户更好地使用青龙面板进行自动化任务管理。
## 功能特性
- 📦 丰富的脚本库
- 🔧 易于配置和使用
- 📝 详细的文档说明
- 🚀 持续更新维护
## 安装使用
### 环境要求
- Node.js >= 14.0.0
- 青龙面板 >= 2.10.0
### 快速开始
1. 克隆仓库
```bash
git clone https://github.com/your-username/ql-scripts.git
cd ql-scripts
```
2. 安装依赖
```bash
npm install
```
3. 配置环境变量
```bash
cp .env.local .env
# 编辑 .env 文件,填入必要的配置信息
```
## 脚本说明
### 使用方法
每个脚本都有详细的使用说明,请查看对应的文档或脚本内的注释。
## 注意事项
- 请确保脚本符合青龙面板的规范
- 使用前请仔细阅读脚本说明
- 定期更新脚本以获得最新功能
## 免责声明
本项目仅供学习交流使用,请勿用于非法用途。使用本项目所产生的一切后果由使用者自行承担。
---
⭐ 如果这个项目对你有帮助,请给个 Star 支持一下!

8
common.js Normal file

File diff suppressed because one or more lines are too long

157
package-lock.json generated Normal file
View File

@@ -0,0 +1,157 @@
{
"name": "ql-scripts",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ql-scripts",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"node-fetch": "^2.7.0"
},
"devDependencies": {
"env-cmd": "^11.0.0"
}
},
"node_modules/@commander-js/extra-typings": {
"version": "13.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/@commander-js/extra-typings/-/extra-typings-13.1.0.tgz",
"integrity": "sha512-q5P52BYb1hwVWE6dtID7VvuJWrlfbCv4klj7BjUUOqMz4jbSZD4C9fJ9lRjL2jnBGTg+gDDlaXN51rkWcLk4fg==",
"dev": true,
"peerDependencies": {
"commander": "~13.1.0"
}
},
"node_modules/commander": {
"version": "13.1.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/commander/-/commander-13.1.0.tgz",
"integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==",
"dev": true,
"engines": {
"node": ">=18"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://mirrors.cloud.tencent.com/npm/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/env-cmd": {
"version": "11.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/env-cmd/-/env-cmd-11.0.0.tgz",
"integrity": "sha512-gnG7H1PlwPqsGhFJNTv68lsDGyQdK+U9DwLVitcj1+wGq7LeOBgUzZd2puZ710bHcH9NfNeGWe2sbw7pdvAqDw==",
"dev": true,
"dependencies": {
"@commander-js/extra-typings": "^13.1.0",
"commander": "^13.1.0",
"cross-spawn": "^7.0.6"
},
"bin": {
"env-cmd": "bin/env-cmd.js"
},
"engines": {
"node": ">=20.10.0"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://mirrors.cloud.tencent.com/npm/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://mirrors.cloud.tencent.com/npm/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://mirrors.cloud.tencent.com/npm/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://mirrors.cloud.tencent.com/npm/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
}
}
}

33
package.json Normal file
View File

@@ -0,0 +1,33 @@
{
"name": "ql-scripts",
"version": "1.0.0",
"description": "青龙面板脚本库 - 自动化任务脚本集合",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "npx env-cmd -f .env.local node ./xuequ/switch.js",
"test": "jest",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write ."
},
"keywords": [
"青龙面板",
"qinglong",
"scripts",
"automation",
"cron",
"task"
],
"author": "@ZhuHJay",
"license": "MIT",
"volta": {
"node": "18.20.4"
},
"dependencies": {
"node-fetch": "^2.7.0"
},
"devDependencies": {
"env-cmd": "^11.0.0"
}
}

1437
sendNotify.js Normal file

File diff suppressed because one or more lines are too long

82
xuequ/switch.js Normal file
View File

@@ -0,0 +1,82 @@
/**
* cron: 0 12 * * *
*
* 携趣白名单切换(多个携趣多个IP多个IP选中一个合适的携趣进行切换)
*/
const { Env } = require('../common');
const $ = new Env('携趣小助手-白名单切换');
const fetch = require('node-fetch');
/** 环境变量
* XQ_ACCOUNTS: uid1;ukey1@备注 -》 多个则使用 & 分隔
* XQ_WHITELIST: ip1 -》 多个则使用 & 分隔
*/
const accounts = process.env['XQ_ACCOUNTS'];
const whitelist = process.env['XQ_WHITELIST'];
const apiTpl = {
// 查看当前哪些 IP 在白名单中
get: info => `http://op.xiequ.cn/IpWhiteList.aspx?uid=${info.uid}&ukey=${info.ukey}&act=get`,
add: (info, ip) => `http://op.xiequ.cn/IpWhiteList.aspx?uid=${info.uid}&ukey=${info.ukey}&act=add&ip=${ip}`,
delOne: (info, ip) => `http://op.xiequ.cn/IpWhiteList.aspx?uid=${info.uid}&ukey=${info.ukey}&act=del&ip=${ip}`,
delAll: info => `http://op.xiequ.cn/IpWhiteList.aspx?uid=${info.uid}&ukey=${info.ukey}&act=del&ip=all`,
// 获取 API 使用情况
apiUse: info => `http://op.xiequ.cn/ApiUser.aspx?act=suitdt&uid=${info.uid}&ukey=${info.ukey}`
}
!(async () => {
if (!accounts || !whitelist) {
$.log('请填写环境变量 XQ_ACCOUNTS & XQ_WHITELIST');
return;
}
let tmp = [];
let accs = accounts.split('&');
let ips = whitelist.split('&');
// 解析参数 & 获取信息
for (let content of accs) {
let [acc, comment] = content.split('@');
let [uid, ukey] = acc.split(';');
if (!uid || !ukey) {
$.log('请填写正确的环境变量 XQ_ACCOUNTS');
return;
}
let info = { uid: uid.trim(), ukey: ukey.trim(), comment: comment || `[uid:${uid}]` };
let item = {
info: info,
res: await (await fetch(apiTpl.get(info))).text(),
count: await (async function () {
let { data } = await (await fetch(apiTpl.apiUse(info))).json();
return +data[0].num - +data[0].use;
}())
};
tmp.push(item)
$.log(`[INFO] ${item.info.comment} 剩余数: ${item.count}`);
}
// 删除所有白名单
$.log('\n--- 删除白名单 --- \n');
for (let tmpElement of tmp) {
if (tmpElement?.res) {
await fetch(apiTpl.delAll(tmpElement.info));
$.log(`删除 name: ${tmpElement.info.comment} 下的所有白名单 -> `, tmpElement.res);
}
}
await $.wait(520);
// 选中一个数量最多的 API
let change = tmp.sort((a, b) => b.count - a.count)[0];
$.log('\n--- 切换白名单 --- \n');
if (change) {
for (const ip of ips) {
await fetch(apiTpl.add(change.info, ip));
$.log(`添加 name: ${change.info.comment} 白名单`);
}
}
})()
.catch((e) => {
$.logErr(e);
})
.finally(() => {
$.done();
});