From caf1d7e550425a0ab23b117caed8e6fdd750e693 Mon Sep 17 00:00:00 2001 From: zhiyu1998 <542716863@qq.com> Date: Fri, 22 Nov 2024 20:20:14 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8feat:=20=E4=BF=AE=E5=A4=8D=E9=83=A8?= =?UTF-8?q?=E5=88=86=E7=94=B5=E8=84=91=E6=97=A0=E6=B3=95=E7=9C=8B=E5=88=B0?= =?UTF-8?q?=20Bot=20=E7=8A=B6=E6=80=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/webUI.js | 56 ++++++++++++++++++++++++++ constants/constant.js | 4 +- package.json | 1 + server/app/page.jsx | 11 ++++- server/app/r/api/bot/route.js | 12 ++++++ server/app/r/api/napcat/[pid]/route.js | 10 ----- server/app/r/page.js | 12 ------ server/components/header.jsx | 16 +++++--- server/components/home/bot-item.jsx | 30 +++++++------- server/components/home/bot-network.jsx | 2 +- server/components/home/system.jsx | 2 +- server/constants/{system.js => api.js} | 2 + server/constants/napcat.js | 11 ----- server/utils/axiosInstance.js | 50 ----------------------- server/utils/napact.js | 17 -------- server/utils/redis.js | 17 ++++++++ start-nextjs.js | 18 +++++---- utils/redis-util.js | 48 ---------------------- utils/yunzai-util.js | 29 ++++++++++++- 19 files changed, 164 insertions(+), 184 deletions(-) create mode 100644 apps/webUI.js create mode 100644 server/app/r/api/bot/route.js delete mode 100644 server/app/r/api/napcat/[pid]/route.js delete mode 100644 server/app/r/page.js rename server/constants/{system.js => api.js} (73%) delete mode 100644 server/constants/napcat.js delete mode 100644 server/utils/axiosInstance.js delete mode 100644 server/utils/napact.js create mode 100644 server/utils/redis.js diff --git a/apps/webUI.js b/apps/webUI.js new file mode 100644 index 0000000..06c23d7 --- /dev/null +++ b/apps/webUI.js @@ -0,0 +1,56 @@ +import { REDIS_YUNZAI_WEBUI } from "../constants/constant.js"; +import config from "../model/config.js"; +import { redisSetKey } from "../utils/redis-util.js"; +import { getBotLoginInfo, getBotStatus, getBotVersionInfo } from "../utils/yunzai-util.js"; + +export class WebUI extends plugin { + constructor() { + super({ + name: "R插件 WebUI 开关", + dsc: "R插件 WebUI 开关", + event: "message", + priority: 4000, + rule: [ + { + reg: "^#(r|R)wss$", + fnc: "rWebSwitch", + permission: "master", + }, + { + reg: "^#(r|R)ws$", + fnc: "rWebStatus", + permission: "master", + } + ] + }); + // 配置文件 + this.toolsConfig = config.getConfig("tools"); + // 加载WebUI开关 + this.isOpenWebUI = this.toolsConfig.isOpenWebUI; + } + + async rWebSwitch(e) { + config.updateField("tools", "isOpenWebUI", !this.isOpenWebUI); + const realIsOpenWebUI = config.getConfig("tools").isOpenWebUI; + if (realIsOpenWebUI) { + Promise.all([getBotStatus(e), getBotVersionInfo(e), getBotLoginInfo(e)]).then(values => { + const status = values[0].data; + const versionInfo = values[1].data; + const loginInfo = values[2].data; + redisSetKey(REDIS_YUNZAI_WEBUI, { + ...status, + ...versionInfo, + ...loginInfo + }) + }) + } + // 这里有点延迟,需要写反 + e.reply(`R插件 WebUI:${ realIsOpenWebUI ? "开启\n🚀 请重启以启动 WebUI" : "关闭" }`); + return true; + } + + async rWebStatus(e) { + e.reply(`R插件 WebUI:${ this.toolsConfig.isOpenWebUI ? "开启" : "关闭" }`); + return true; + } +} diff --git a/constants/constant.js b/constants/constant.js index 0becdb5..930046f 100644 --- a/constants/constant.js +++ b/constants/constant.js @@ -93,10 +93,10 @@ export const REDIS_YUNZAI_CLOUDSONGLIST = "Yz:rconsole:tools:cloudsonglist"; export const REDIS_YUNZAI_WHITELIST = "Yz:rconsole:tools:whitelist"; /** - * 番剧列表缓存 + * WEBUI需要数据的缓存 * @type {string} */ -export const REDIS_YUNZAI_ANIMELIST = "Yz:rconsole:tools:anime"; +export const REDIS_YUNZAI_WEBUI = "Yz:rconsole:tools:webui"; export const TWITTER_BEARER_TOKEN = ""; diff --git a/package.json b/package.json index a30c81a..f62f624 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "axios": "^1.3.4", "chart.js": "^4.4.6", "form-data": "^4.0.1", + "ioredis": "^5.4.1", "js-yaml": "^4.1.0", "next": "^14.2.16", "node-id3": "^0.2.6", diff --git a/server/app/page.jsx b/server/app/page.jsx index 4e3a190..63aed4c 100644 --- a/server/app/page.jsx +++ b/server/app/page.jsx @@ -1,3 +1,12 @@ +import Header from "../components/header.jsx"; +import Sidebar from "../components/sidebar.jsx"; +import { DrawerProvider } from "../contexts/drawer-context.js"; + export default function Page() { - return

进入控制面板

+ return ( + +
+ + + ) } diff --git a/server/app/r/api/bot/route.js b/server/app/r/api/bot/route.js new file mode 100644 index 0000000..9066032 --- /dev/null +++ b/server/app/r/api/bot/route.js @@ -0,0 +1,12 @@ +import { REDIS_YUNZAI_WEBUI } from "../../../../../constants/constant.js"; +import { redis } from "../../../../utils/redis.js"; + + +export async function GET(req, res) { + const botInfo = JSON.parse(await redis.get(REDIS_YUNZAI_WEBUI)); + + return new Response(JSON.stringify(botInfo), { + status: 200, + headers: { 'Content-Type': 'application/json' }, + }); +} diff --git a/server/app/r/api/napcat/[pid]/route.js b/server/app/r/api/napcat/[pid]/route.js deleted file mode 100644 index 0fd7fc0..0000000 --- a/server/app/r/api/napcat/[pid]/route.js +++ /dev/null @@ -1,10 +0,0 @@ -import axiosInstance from "../../../../../utils/axiosInstance.js"; - -export async function GET(request, { params }) { - const { pid } = params; - const napcatResp = await axiosInstance.get(`/${ pid }`); - return new Response(JSON.stringify(napcatResp), { - status: 200, - headers: { 'Content-Type': 'application/json' }, - }); -} diff --git a/server/app/r/page.js b/server/app/r/page.js deleted file mode 100644 index 3bc2d81..0000000 --- a/server/app/r/page.js +++ /dev/null @@ -1,12 +0,0 @@ -import Sidebar from "../../components/sidebar.jsx"; -import Header from "../../components/header.jsx"; -import { DrawerProvider } from "../../contexts/drawer-context.js"; - -export default function Page() { - return ( - -
- - - ) -} diff --git a/server/components/header.jsx b/server/components/header.jsx index 1ede9ec..8f2c03e 100644 --- a/server/components/header.jsx +++ b/server/components/header.jsx @@ -1,17 +1,21 @@ "use client" import { useState, useEffect } from 'react'; +import { BOT_INFO_URL } from "../constants/api.js"; import { useDrawer } from "../contexts/drawer-context.js"; -import { getUserInfo } from "../utils/napact.js"; import ThemeToggle from "./ThemeToggle.jsx"; export default function Header () { const { toggleDrawer } = useDrawer(); - const [user, setUser] = useState({ user_id: null, nickname: '' }); + const [user, setUser] = useState(null); useEffect(() => { - getUserInfo().then(setUser); + fetch(BOT_INFO_URL) + .then(response => { + return response.json(); + }) + .then(data => setUser(data)) }, []); return ( @@ -49,12 +53,12 @@ export default function Header () {
头像 + src={`http://q1.qlogo.cn/g?b=qq&nk=${user?.user_id}&s=100`}/>
-
{user.nickname || "未获取"}
-
{user.user_id || "NaN"}
+
{user?.nickname || "未获取"}
+
{user?.user_id || "NaN"}
diff --git a/server/components/home/bot-item.jsx b/server/components/home/bot-item.jsx index 67557ee..50a4298 100644 --- a/server/components/home/bot-item.jsx +++ b/server/components/home/bot-item.jsx @@ -1,18 +1,16 @@ -import { getStatus, getUserInfo, getVersionInfo } from "../../utils/napact.js"; import React, { useEffect, useState } from "react"; +import { BOT_INFO_URL } from "../../constants/api.js"; export function BotItem() { - const [user, setUser] = useState({ user_id: null, nickname: '' }); - - const [status, setStatus] = useState({ online: false, good: false, stat: {} }); - - const [versionInfo, setVersionInfo] = useState({ app_name: "", app_version: "", protocol_version: "" }); + const [user, setUser] = useState(null); useEffect(() => { - getUserInfo().then(setUser); - getStatus().then(setStatus); - getVersionInfo().then(setVersionInfo); + fetch(BOT_INFO_URL) + .then(response => { + return response.json(); + }) + .then(data => setUser(data)) }, []); return ( @@ -20,22 +18,22 @@ export function BotItem() {

🐔状态

-
+
- +
-
昵称:{ user.nickname || "未获取" }
-
QQ号:{ user.user_id || "NaN" }
+
昵称:{ user?.nickname || "未获取" }
+
QQ号:{ user?.user_id || "NaN" }
协议信息:
-
{ versionInfo.app_name }
-
{ versionInfo.app_version }
-
{ versionInfo.protocol_version }
+
{ user?.app_name }
+
{ user?.app_version }
+
{ user?.protocol_version }
diff --git a/server/components/home/bot-network.jsx b/server/components/home/bot-network.jsx index abc3feb..65b7fe9 100644 --- a/server/components/home/bot-network.jsx +++ b/server/components/home/bot-network.jsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from "react"; -import { NETWORK_BASE_URL } from "../../constants/system.js"; +import { NETWORK_BASE_URL } from "../../constants/api.js"; // 测试链接配置 const TESTING_LINKS = [ diff --git a/server/components/home/system.jsx b/server/components/home/system.jsx index b0be871..0754bbb 100644 --- a/server/components/home/system.jsx +++ b/server/components/home/system.jsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import { CircularProgressbar, buildStyles } from 'react-circular-progressbar'; import 'react-circular-progressbar/dist/styles.css'; -import { SYSTEM_BASE_URL } from "../../constants/system.js"; +import { SYSTEM_BASE_URL } from "../../constants/api.js"; export default function System() { const [systemInfo, setSystemInfo] = useState(null); diff --git a/server/constants/system.js b/server/constants/api.js similarity index 73% rename from server/constants/system.js rename to server/constants/api.js index 648c8b1..c9d2595 100644 --- a/server/constants/system.js +++ b/server/constants/api.js @@ -3,3 +3,5 @@ const BASE_URL = "/r/api"; export const SYSTEM_BASE_URL = `${BASE_URL}/system`; export const NETWORK_BASE_URL = `${BASE_URL}/network?url=`; + +export const BOT_INFO_URL = `${ BASE_URL }/bot`; diff --git a/server/constants/napcat.js b/server/constants/napcat.js deleted file mode 100644 index 3cd8565..0000000 --- a/server/constants/napcat.js +++ /dev/null @@ -1,11 +0,0 @@ -export const NAPCAT_BASE_URL = "/r/api/napcat"; - -/** - * 获取登录号信息 - * @type {string} - */ -export const NAPCAT_GET_LOGIN_INFO = `${NAPCAT_BASE_URL}/get_login_info`; - -export const NAPCAT_GET_STATUS = `${ NAPCAT_BASE_URL }/get_status`; - -export const NAPCAT_GET_VERSION_INFO = `${ NAPCAT_BASE_URL }/get_version_info`; diff --git a/server/utils/axiosInstance.js b/server/utils/axiosInstance.js deleted file mode 100644 index e446da2..0000000 --- a/server/utils/axiosInstance.js +++ /dev/null @@ -1,50 +0,0 @@ -import axios from 'axios'; - -// 创建 Axios 实例 -const axiosInstance = axios.create({ - baseURL: 'http://192.168.31.230:2537', // 基础请求地址 - timeout: 5000, // 设置请求超时时间,可根据需要调整 - headers: { - 'Content-Type': 'application/json', - }, -}); - -// 请求拦截器 -axiosInstance.interceptors.request.use( - (config) => { - // 这里可以添加请求前的处理逻辑,例如添加 token - // const token = localStorage.getItem('token'); - // if (token) { - // config.headers.Authorization = `Bearer ${token}`; - // } - return config; - }, - (error) => { - // 请求错误处理 - return Promise.reject(error); - } -); - -// 响应拦截器 -axiosInstance.interceptors.response.use( - (response) => { - // 响应成功处理 - return response.data; - }, - (error) => { - // 响应错误处理 - if (error.response) { - // 服务器返回的错误 - console.error('Error:', error.response.status, error.response.data); - } else if (error.request) { - // 请求未收到服务器响应 - console.error('No response received:', error.request); - } else { - // 设置请求时发生的错误 - console.error('Request setup error:', error.message); - } - return Promise.reject(error); - } -); - -export default axiosInstance; diff --git a/server/utils/napact.js b/server/utils/napact.js deleted file mode 100644 index 7f3735d..0000000 --- a/server/utils/napact.js +++ /dev/null @@ -1,17 +0,0 @@ -import { NAPCAT_GET_LOGIN_INFO, NAPCAT_GET_STATUS, NAPCAT_GET_VERSION_INFO } from "../constants/napcat.js"; - -export async function getUserInfo() { - const userInfo = await fetch(NAPCAT_GET_LOGIN_INFO).then(resp => resp.json()); - const { user_id, nickname } = userInfo.data; - return { user_id, nickname } -} - -export async function getStatus() { - const status = await fetch(NAPCAT_GET_STATUS).then(resp => resp.json()); - return status.data; -} - -export async function getVersionInfo() { - const versionInfo = await fetch(NAPCAT_GET_VERSION_INFO).then(resp => resp.json()); - return versionInfo.data; -} diff --git a/server/utils/redis.js b/server/utils/redis.js new file mode 100644 index 0000000..3744815 --- /dev/null +++ b/server/utils/redis.js @@ -0,0 +1,17 @@ +import fs from "fs"; +import Redis from "ioredis"; +import yaml from "js-yaml"; +import path from "path"; + +const configPath = path.join(process.cwd(), "../../../", "config", 'config', 'redis.yaml'); + +const yamlContent = await fs.promises.readFile(configPath, 'utf8'); +const config = yaml.load(yamlContent); + +export const redis = new Redis({ + port: config.port, + host: config.host, + username: config.username, + password: config.password, + db: config.db, +}) diff --git a/start-nextjs.js b/start-nextjs.js index d2d5543..222c859 100644 --- a/start-nextjs.js +++ b/start-nextjs.js @@ -1,8 +1,10 @@ import { spawn } from 'child_process'; +import child_process from "node:child_process"; +import { getBotLoginInfo, getBotStatus, getBotVersionInfo } from "./utils/yunzai-util.js"; logger.info(`[R插件][Next.js监测], 父进程 PID: ${process.pid}`); -let childProcess = null; +let nextjsProcess = null; // 构建应用程序 export const buildNextJs = () => { @@ -10,7 +12,7 @@ export const buildNextJs = () => { return new Promise((resolve, reject) => { const buildProcess = spawn('pnpm', ['run', 'build'], { cwd: './plugins/rconsole-plugin/server', - stdio: 'inherit', + stdio: 'ignore', shell: true, }); @@ -32,24 +34,24 @@ export const startNextJs = (mode = 'start') => { logger.info(logger.yellow(`[R插件][Next.js监测],启动 Next.js ${mode} 进程...`)); - childProcess = spawn('pnpm', ['run', script], { + nextjsProcess = spawn('pnpm', ['run', script], { cwd: './plugins/rconsole-plugin', // 指定工作目录 - stdio: 'inherit', // 继承父进程的标准输入输出 + stdio: ['ignore', 'ignore', 'ignore', 'ipc'], // 继承父进程的标准输入输出 shell: true, }); // 子进程异常退出时捕获信号 - childProcess.on('close', (code) => { + nextjsProcess.on('close', (code) => { logger.error(`[R插件][Next.js监测],Next.js 进程发生异常 ${code}`); - childProcess = null; + nextjsProcess = null; }); }; // 捕获父进程退出信号 const cleanup = () => { logger.info(logger.yellow('[R插件][Next.js监测] 父进程退出,终止子进程...')); - if (childProcess) { - childProcess.kill(); // 终止子进程 + if (nextjsProcess) { + nextjsProcess.kill(); // 终止子进程 } process.exit(); }; diff --git a/utils/redis-util.js b/utils/redis-util.js index cd1ddf4..1d15eea 100644 --- a/utils/redis-util.js +++ b/utils/redis-util.js @@ -86,51 +86,3 @@ export async function redisExistAndUpdateObject(key, updateKey, updateObj) { await redisSetKey(key, objs); } } - -/** - * 删除某个key - * @param key - * @returns {Promise} - * @example - * const result = await redisDeleteKey('myKey'); - * console.log(result); // 1 if key was deleted, 0 if key did not exist - */ -export async function redisDeleteKey(key) { - return redis.del(key); -} - -/** - * 获取所有的key - * @returns {Promise>} - * @example - * const keys = await redisGetAllKeys(); - * console.log(keys); // ['key1', 'key2', ...] - */ -export async function redisGetAllKeys() { - return redis.keys('*'); -} - -/** - * 设置某个key的过期时间 - * @param key - * @param seconds - * @returns {Promise} - * @example - * const result = await redisExpireKey('myKey', 3600); - * console.log(result); // true if timeout was set, false if key does not exist - */ -export async function redisExpireKey(key, seconds) { - return redis.expire(key, seconds); -} - -/** - * 获取某个key的剩余生存时间 - * @param key - * @returns {Promise} - * @example - * const ttl = await redisTTLKey('myKey'); - * console.log(ttl); // time to live in seconds, -1 if key does not have timeout, -2 if key does not exist - */ -export async function redisTTLKey(key) { - return redis.ttl(key); -} \ No newline at end of file diff --git a/utils/yunzai-util.js b/utils/yunzai-util.js index f0799ea..fa343c1 100644 --- a/utils/yunzai-util.js +++ b/utils/yunzai-util.js @@ -124,4 +124,31 @@ export async function getReplyMsg(e) { "message_id" : msgId }) return msg.data -} \ No newline at end of file +} + +/** + * 获取机器人信息 + * @param e + * @returns {Promise<*>} + */ +export async function getBotLoginInfo(e) { + return await e.bot.sendApi("get_login_info"); +} + +/** + * 获取运行状态 + * @param e + * @returns {Promise<*>} + */ +export async function getBotStatus(e) { + return await e.bot.sendApi("get_status"); +} + +/** + * 获取版本信息 + * @param e + * @returns {Promise<*>} + */ +export async function getBotVersionInfo(e) { + return await e.bot.sendApi("get_version_info"); +}