vertex是挺好用的,但是规则不用js的话功能实在是有限。尤其是rss规则和删种规则,选种规则可设置的项目实在是太少了,严重不符合需求(分享的第三项是选种规则,目前已经基本符合我的轻度刷流需求了,得益于保种体积设置项,甚至可以用15G硬盘的小盘鸡刷而不爆硬盘。),下面分享几个有意思的规则。
1.删种规则(可配置,修改config部分),效果:根据种子的流行程度动态删除种子,只删除没什么人下载的种子,留着上传量大的种子。具体规则:超过七天才可能删除符合规则的种子,删种按分享率删除,每在3的基础上多0.1分享率就多留一天。
(maindata, torrent) => {
const config = {
deleteHours: 7 * 24 *3600, // 超时才删种的时间
ratioThreshold: 3, // 基础分享率一阈值(上传量 / 种子大小)
enableLogging: false, // 是否启用日志记录
};
const moment = require('moment'); // 确保 moment 模块可用
const now = moment().unix();
// 辅助函数:向 /vertex/log22/log.txt 中追加日志信息
function logFailure(message) {
if (!config.enableLogging) return; // 如果未启用日志记录,直接返回
const fs = require('fs');
const path = require('path');
const logFilePath = '/vertex/log22/log.txt';
const logDir = path.dirname(logFilePath);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
const logMessage = `${new Date().toISOString()} - ${message}\n`;
fs.appendFileSync(logFilePath, logMessage);
}
// 计算下载时间和分享率
const downloadTime = now - torrent.addedTime;
const downloadTime2 = downloadTime - config.deleteHours;
const extraDays = Math.max(0, Math.floor(downloadTime2 / 86400)); // 每天86400秒
// 动态调整分享率上限
const ratioLimit = config.ratioThreshold + extraDays * 0.1;
// 检查种子是否完成下载
if (now - torrent.completedTime < config.deleteHours ) {
return false; // 不删除种子
}
if (torrent.completedTime > 0 && torrent.ratio < ratioLimit && torrent.uploadSpeed < 10* 1024) {
return true; // 删除种子
}
return false; // 不删除种子
};
2.删种规则(可配置config部分),效果:适应馒头标盒机制,对于小流量的机器不当冤大头额外上传不计入上传流量的部分。同时又不暂停,可以获取魔力。规则:不实际删除种子,超过分享率后设置限速100k,两天后解除限速(适用于馒头盒子机制:新种标盒,两天盒子规则消失,盒子规则限制时间内只计算3倍种子大小上传量,标盒过期后取消限制)
// 参数:
// maindata:qBittorrent 的全局数据
// torrent:当前种子的信息
(maindata, torrent) => {
// 统一配置对象(所有时间单位均为小时)
const config = {
pauseThresholdHours: 72, // 当种子添加时间小于72小时(3天)且分享率大于阈值时触发暂停
resumeThresholdHours: 72, // 当种子添加时间大于72小时时用于恢复(这里与暂停阈值相同)
ratioThreshold: 3, // 分享率一阈值(上传量 / 种子大小 > 3时触发操作)
enableLogging: false, // 是否启用日志记录
downloaderId: 'e88e88dd', // 下载器ID,指定适用的下载器ID
speedLimit: 100 * 1024, // 限速值(单位:KB/s)
};
// 辅助函数:向 /vertex/log22/log.txt 中追加日志信息
function logFailure(message) {
if (!config.enableLogging) return; // 如果未启用日志记录,直接返回
const fs = require('fs');
const path = require('path');
const logFilePath = '/vertex/log22/log.txt';
const logDir = path.dirname(logFilePath);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
const logMessage = `${new Date().toISOString()} - ${message}\n`;
fs.appendFileSync(logFilePath, logMessage);
}
// 获取下载器ID和下载器对象
const downloaderId = config.downloaderId;
const client = global.runningClient[downloaderId];
if (!client) {
logFailure(`未找到下载器 ${downloaderId}`);
return false;
}
const moment = require('moment'); // 确保 moment 模块可用
const now = moment().unix();
// 计算种子添加后的持续时间(单位:秒)
const ageSeconds = now - torrent.addedTime;
// 根据配置中的小时数转换为秒数
const thresholdSeconds = config.pauseThresholdHours * 3600;
const thresholdSeconds2 = config.resumeThresholdHours * 3600;
// 计算“分享率一”:上传量 / 种子大小
const shareRatio1 = torrent.size > 0 ? torrent.uploaded / torrent.size : 0;
// 如果种子添加时间小于阈值(72小时)且分享率大于阈值,则限速种子
if (ageSeconds < thresholdSeconds && shareRatio1 > config.ratioThreshold) {
client.setSpeedLimit(torrent.hash, 'upload', config.speedLimit)
.then(() => {
logFailure(`限速种子成功: ${torrent.name}`);
})
.catch(err => {
logFailure(`限速种子 ${torrent.name} 失败: ${err}`);
});
}
// 如果种子当前已限速且添加时间大于阈值,则取消限速
if (ageSeconds > thresholdSeconds2) {
client.setSpeedLimit(torrent.hash, 'upload', 0) // 设置为0表示取消限速
.then(() => {
logFailure(`取消限速成功: ${torrent.name}`);
})
.catch(err => {
logFailure(`取消限速 ${torrent.name} 失败: ${err}`);
});
}
// 始终返回 false,不会执行删种操作
return false;
};
3.rss规则(可以配置config),效果:可以根据更多规则选择要刷的种子,对于小盘鸡友好,完全不会超过设置的保种体积,同时计算体积带矫正,和性能缓解,2分钟前算过体积就不重新计算了,不会每个种子都算一遍全盘种子大小。可以限制下载数量,种子大小,文件名等,可以自定义开启关闭功能进行组合。15G小盘鸡也能刷了,添加种子前计算下载器中种子的大小,这个不是vertex自带的剩余空间大小,那个实际因为没下完种子可能会超过空间导致占满空间,当然可用提前分配缓解,但是还是不符合需求,这个可以直接实现完全不会超过设置空间。可以说是非常人性化了。注意要设置相应下载器的id。
(torrent) => {
// 配置部分:这些部分可以自定义
const config = {
downloaderId: 'e88e88dd', // 下载器ID,指定适用的下载器ID
enableLogging: false, // 是否启用日志记录
enableSeedingVolumeLimit: true, // 是否启用保种体积限制
seedingVolumeLimit: 50 * 1024 * 1024 * 1024, // 保种体积限制(单位:字节),例如14GB
enableTaskCountLimit: true, // 是否启用下载器任务数量限制
taskCountLimit: 200, // 下载器任务数量限制,设置最大任务数
enableSizeLimit: true, // 是否启用种子大小限制
sizeLimitRange: [1 * 1024 * 1024 * 1024, 10 * 1024 * 1024 * 1024], // 种子大小范围(单位:字节)
enableFileNameMatchLimit: false, // 是否启用文件名匹配限制
fileNameRegex: /sample|test/i // 文件名正则匹配,支持正则表达式
};
const fs = require('fs');
const path = require('path');
// 获取本地时间字符串
function getLocalTimeString() {
return new Date().toLocaleString('zh-CN', { hour12: false });
}
// 辅助函数:向 /vertex/log22/log.txt 中追加日志信息
function logFailure(message) {
if (!config.enableLogging) return; // 如果未启用日志记录,直接返回
const logFilePath = '/vertex/log22/log.txt';
const logDir = path.dirname(logFilePath);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
const now = getLocalTimeString();
fs.appendFileSync(logFilePath, `[${now}] ${message}\n`);
}
// 获取下载器ID和下载器对象
const downloaderId = config.downloaderId; // 当前下载器ID
const client = global.runningClient[downloaderId];
if (!client) {
logFailure(`未找到下载器 ${downloaderId}`);
return false;
}
// 2. 保种体积限制:先检查 /vertex/${downloaderId}/size.txt 中存储的时间和累计体积
if (config.enableSeedingVolumeLimit) {
const sizeFilePath = `/vertex/${downloaderId}/size.txt`;
const sizeDir = path.dirname(sizeFilePath);
if (!fs.existsSync(sizeDir)) {
fs.mkdirSync(sizeDir, { recursive: true });
}
let currentCumulative = 0; // 当前累计体积(字节)
let fileTimestamp = 0; // 文件中记录的时间(秒)
const now = Math.floor(Date.now() / 1000); // 当前时间,单位:秒
// 尝试读取文件,如果存在则解析内容(格式:timestamp,cumulativeSize)
if (fs.existsSync(sizeFilePath)) {
try {
const data = fs.readFileSync(sizeFilePath, 'utf8').trim();
if (data) {
const parts = data.split(',');
if (parts.length === 2) {
fileTimestamp = Number(parts[0]);
currentCumulative = Number(parts[1]);
}
}
} catch (err) {
logFailure(`读取 size.txt 失败: ${err}`);
}
} else {
// 如果文件不存在,则计算累计体积并创建文件
client.maindata.torrents.forEach(t => {
currentCumulative += Number(t.size || 0);
});
fileTimestamp = now;
try {
fs.writeFileSync(sizeFilePath, `${fileTimestamp},${currentCumulative}`);
} catch (err) {
logFailure(`写入 size.txt 失败: ${err}`);
}
}
// 如果下载器中没有任务,则重置累计体积为 0
if (!client.maindata.torrents || client.maindata.torrents.length === 0) {
currentCumulative = 0;
fileTimestamp = now;
try {
fs.writeFileSync(sizeFilePath, `${fileTimestamp},${currentCumulative}`);
} catch (err) {
logFailure(`重置 size.txt 失败: ${err}`);
}
}
// 如果文件中的时间超过2分钟,则重新计算累计体积
else if (now - fileTimestamp > 120) {
currentCumulative = 0;
client.maindata.torrents.forEach(t => {
currentCumulative += Number(t.size || 0);
});
fileTimestamp = now;
try {
fs.writeFileSync(sizeFilePath, `${fileTimestamp},${currentCumulative}`);
} catch (err) {
logFailure(`更新 size.txt 失败: ${err}`);
}
}
// 确保 torrent.size 为数值
const torrentSize = Number(torrent.size);
// 将累计体积加上当前种子的大小,与保种体积限制比较
if ((currentCumulative + torrentSize) >= config.seedingVolumeLimit) {
logFailure(`保种体积限制不通过:累计体积 ${currentCumulative} + 当前种子 ${torrentSize} 超过限制 ${config.seedingVolumeLimit}`);
return false;
}
}
// 3. 下载器任务数量限制:检查下载器当前任务数量
if (config.enableTaskCountLimit) {
if (client.maindata.torrents.length >= config.taskCountLimit) {
logFailure(`任务数量限制不通过:当前任务数量 ${client.maindata.torrents.length} 超过限制 ${config.taskCountLimit}`);
return false;
}
}
// 4. 种子大小限制:检查种子的大小是否在规定范围内
if (config.enableSizeLimit) {
const size = Number(torrent.size);
if (size < config.sizeLimitRange[0] || size > config.sizeLimitRange[1]) {
logFailure(`种子大小限制不通过:种子大小 ${size} 不在范围 ${config.sizeLimitRange[0]} - ${config.sizeLimitRange[1]}`);
return false;
}
}
// 5. 文件名匹配限制:检查文件名是否符合正则匹配
if (config.enableFileNameMatchLimit) {
const fileName = torrent.name;
if (!fileName.match(config.fileNameRegex)) {
logFailure(`文件名匹配限制不通过:种子名称 "${fileName}" 未匹配正则 ${config.fileNameRegex}`);
return false;
}
}
// 如果所有条件都满足,则表示添加该种子。
// 在返回 true 前,如果启用了保种体积限制,则更新 /vertex/${downloaderId}/size.txt
if (config.enableSeedingVolumeLimit) {
const sizeFilePath = `/vertex/${downloaderId}/size.txt`;
let cumulative = 0;
let fileTimestamp = 0;
if (fs.existsSync(sizeFilePath)) {
try {
const data = fs.readFileSync(sizeFilePath, 'utf8').trim();
if (data) {
const parts = data.split(',');
if (parts.length === 2) {
fileTimestamp = Number(parts[0]);
cumulative = Number(parts[1]);
}
}
} catch (err) {
logFailure(`读取 size.txt 更新部分失败: ${err}`);
}
}
cumulative += Number(torrent.size);
try {
fs.writeFileSync(sizeFilePath, `${fileTimestamp},${cumulative}`);
} catch (err) {
logFailure(`更新 size.txt 失败: ${err}`);
}
}
return true;
};
赞一个,🍗奉上
bd
帮顶帮顶
nc 1o鸡准备开刷
ky弄一个rss规则实现选取做种人数在1和5之前的种子吗?
经常刷到一些还没有开始做种的种子进来
@rainbow #3
黑盒
这个牛
我不刷大站,TLF不限盒
赞一个
谢谢分享,还在准备阶段

想问下,pttime的rss一直配置不上,是怎么回事