mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 16:19:18 +00:00
🦄 reactor: 令牌桶
深度清洁
This commit is contained in:
parent
6db22d4ffa
commit
824a01f7c8
@ -10,15 +10,8 @@ import { CAT_LIMIT, COMMON_USER_AGENT } from "../constants/constant.js";
|
|||||||
import config from "../model/index.js";
|
import config from "../model/index.js";
|
||||||
// 书库
|
// 书库
|
||||||
import { getYiBook, getZBook, getZHelper } from "../utils/books.js";
|
import { getYiBook, getZBook, getZHelper } from "../utils/books.js";
|
||||||
// 工具类
|
|
||||||
import TokenBucket from '../utils/token-bucket.js'
|
|
||||||
|
|
||||||
export class query extends plugin {
|
export class query extends plugin {
|
||||||
/**
|
|
||||||
* 令牌桶 拿来限流
|
|
||||||
* @type {TokenBucket}
|
|
||||||
*/
|
|
||||||
static #tokenBucket = new TokenBucket(1, 1, 60);
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
@ -320,20 +313,6 @@ export class query extends plugin {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 限制用户调用(默认1分钟1次)
|
|
||||||
* @param e
|
|
||||||
* @param func
|
|
||||||
* @return {Promise<void>}
|
|
||||||
*/
|
|
||||||
async limitUserUse(e, func) {
|
|
||||||
if (query.#tokenBucket.consume(e.user_id, 1)) {
|
|
||||||
await func();
|
|
||||||
} else {
|
|
||||||
e.reply(`🙅${ e.nickname }你已经被限流,请稍后再试!`, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除标签
|
// 删除标签
|
||||||
removeTag(title) {
|
removeTag(title) {
|
||||||
const titleRex = /<[^>]+>/g;
|
const titleRex = /<[^>]+>/g;
|
||||||
|
@ -52,7 +52,6 @@ import * as aBogus from "../utils/a-bogus.cjs";
|
|||||||
import { getBodianAudio, getBodianMusicInfo, getBodianMv } from "../utils/bodian.js";
|
import { getBodianAudio, getBodianMusicInfo, getBodianMv } from "../utils/bodian.js";
|
||||||
import { av2BV } from "../utils/bilibili-bv-av-convert.js";
|
import { av2BV } from "../utils/bilibili-bv-av-convert.js";
|
||||||
import querystring from "querystring";
|
import querystring from "querystring";
|
||||||
import TokenBucket from "../utils/token-bucket.js";
|
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
import { getWbi } from "../utils/biliWbi.js";
|
import { getWbi } from "../utils/biliWbi.js";
|
||||||
import {
|
import {
|
||||||
@ -94,11 +93,6 @@ export class tools extends plugin {
|
|||||||
static Constants = {
|
static Constants = {
|
||||||
existsTransKey: Object.keys(transMap).join("|"),
|
existsTransKey: Object.keys(transMap).join("|"),
|
||||||
};
|
};
|
||||||
/**
|
|
||||||
* 构造令牌桶,防止解析致使服务器宕机(默认限制5s调用一次)
|
|
||||||
* @type {TokenBucket}
|
|
||||||
*/
|
|
||||||
static #tokenBucket = new TokenBucket(1, 1, 5);
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
@ -463,16 +457,8 @@ export class tools extends plugin {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// B 站解析
|
||||||
// bilibi解析
|
|
||||||
async bili(e) {
|
async bili(e) {
|
||||||
// 限制用户密集使用的 AOP
|
|
||||||
await this.limitUserUse(e, () => {
|
|
||||||
this.biliCore(e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async biliCore(e) {
|
|
||||||
const urlRex = /(?:https?:\/\/)?www\.bilibili\.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
const urlRex = /(?:https?:\/\/)?www\.bilibili\.com\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
||||||
const bShortRex = /(http:|https:)\/\/b23.tv\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
const bShortRex = /(http:|https:)\/\/b23.tv\/[A-Za-z\d._?%&+\-=\/#]*/g;
|
||||||
let url = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim().replaceAll("\\", "");
|
let url = e.msg === undefined ? e.message.shift().data.replaceAll("\\", "") : e.msg.trim().replaceAll("\\", "");
|
||||||
@ -659,13 +645,15 @@ export class tools extends plugin {
|
|||||||
// 下载哔哩哔哩音乐
|
// 下载哔哩哔哩音乐
|
||||||
async biliMusic(e, url) {
|
async biliMusic(e, url) {
|
||||||
const videoId = /video\/[^\?\/ ]+/.exec(url)[0].split("/")[1];
|
const videoId = /video\/[^\?\/ ]+/.exec(url)[0].split("/")[1];
|
||||||
getBiliAudio(videoId, "").then(async audioUrl => {
|
this.queue.add(() => {
|
||||||
const path = this.getCurDownloadPath(e);
|
getBiliAudio(videoId, "").then(async audioUrl => {
|
||||||
const biliMusicPath = await m4sToMp3(audioUrl, path)
|
const path = this.getCurDownloadPath(e);
|
||||||
// 发送语音
|
const biliMusicPath = await m4sToMp3(audioUrl, path)
|
||||||
e.reply(segment.record(biliMusicPath));
|
// 发送语音
|
||||||
// 上传群文件
|
e.reply(segment.record(biliMusicPath));
|
||||||
await this.uploadGroupFile(e, biliMusicPath);
|
// 上传群文件
|
||||||
|
await this.uploadGroupFile(e, biliMusicPath);
|
||||||
|
})
|
||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -2002,20 +1990,6 @@ export class tools extends plugin {
|
|||||||
return JSON.parse((await redis.get(REDIS_YUNZAI_LAGRANGE))).driver;
|
return JSON.parse((await redis.get(REDIS_YUNZAI_LAGRANGE))).driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 限制用户调用
|
|
||||||
* @param e
|
|
||||||
* @param func
|
|
||||||
* @return {Promise<void>}
|
|
||||||
*/
|
|
||||||
async limitUserUse(e, func) {
|
|
||||||
if (tools.#tokenBucket.consume(e.user_id, 1)) {
|
|
||||||
await func();
|
|
||||||
} else {
|
|
||||||
logger.warn(`解析被限制使用`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送转上传视频
|
* 发送转上传视频
|
||||||
* @param e 交互事件
|
* @param e 交互事件
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
export default class TokenBucket {
|
|
||||||
constructor(rate, capacity, interval = 1, isMinute = false) {
|
|
||||||
this.interval = interval; // 生成令牌的时间间隔
|
|
||||||
this.rate = isMinute ? rate / 60 : rate; // 修改为每分钟生成的令牌数量
|
|
||||||
this.capacity = capacity; // 令牌容量
|
|
||||||
this.tokens = capacity; // 令牌容量
|
|
||||||
this.tokens = new Map(); // 使用 Map 存储每个用户的令牌桶
|
|
||||||
this.lastTime = new Date().getTime(); // 上次使用时间
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 核心算法
|
|
||||||
* @param tokens
|
|
||||||
* @param capacity
|
|
||||||
* @param rate
|
|
||||||
* @param lastTime
|
|
||||||
* @param interval
|
|
||||||
* @param isMinute
|
|
||||||
* @return {{lastTime: number, tokens: number}}
|
|
||||||
*/
|
|
||||||
this.updateTokens = (tokens, capacity, rate, lastTime, interval) => {
|
|
||||||
// 计算从上次请求到现在经过的时间
|
|
||||||
const now = new Date().getTime();
|
|
||||||
const elapsed = now - lastTime;
|
|
||||||
// 根据时间计算出新生成的令牌数量
|
|
||||||
const addedTokens = elapsed * (rate / interval / 1000); // 修改为每分钟生成的令牌数量
|
|
||||||
tokens = Math.min(tokens + addedTokens, capacity);
|
|
||||||
lastTime = now;
|
|
||||||
return { tokens, lastTime };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消耗令牌-一个桶
|
|
||||||
* @param count
|
|
||||||
* @return {boolean}
|
|
||||||
*/
|
|
||||||
consumeSingle(count = 1) {
|
|
||||||
const { tokens, lastTime } = this.updateTokens(this.tokens, this.capacity, this.rate, this.lastTime, this.interval);
|
|
||||||
// 更新令牌桶中的令牌数量
|
|
||||||
this.tokens = tokens;
|
|
||||||
|
|
||||||
// 判断请求是否能够被处理(即令牌桶中是否有足够的令牌)
|
|
||||||
if (count <= this.tokens) {
|
|
||||||
this.tokens -= count;
|
|
||||||
return true; // 返回 true 表示请求被处理
|
|
||||||
} else {
|
|
||||||
return false; // 返回 false 表示请求被限流
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消耗令牌
|
|
||||||
* @param id 用户id
|
|
||||||
* @param count 请求次数
|
|
||||||
* @return {boolean}
|
|
||||||
*/
|
|
||||||
consume(id, count = 1) {
|
|
||||||
const { tokens: userTokens, lastTime: userLastTime } = this.tokens.get(id) || { tokens: this.capacity, lastTime: new Date().getTime() };
|
|
||||||
const { tokens, lastTime } = this.updateTokens(userTokens, this.capacity, this.rate, userLastTime, this.interval);
|
|
||||||
// 更新令牌桶中的令牌数量
|
|
||||||
this.tokens.set(id, { tokens, lastTime });
|
|
||||||
|
|
||||||
// 判断请求是否能够被处理(即令牌桶中是否有足够的令牌)
|
|
||||||
if (count <= tokens) {
|
|
||||||
this.tokens.set(id, { tokens: tokens - count, lastTime });
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置令牌
|
|
||||||
* @param newCapacity
|
|
||||||
*/
|
|
||||||
resetCapacity(newCapacity) {
|
|
||||||
if (newCapacity >= this.tokens) {
|
|
||||||
this.capacity = newCapacity;
|
|
||||||
this.tokens = newCapacity;
|
|
||||||
} else {
|
|
||||||
throw new Error('分配少于当前的容量!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user