diff --git a/README.md b/README.md
index 67c3000..c9f98b6 100644
--- a/README.md
+++ b/README.md
@@ -102,7 +102,10 @@ sudo apt-get install ffmpeg
| 春日野穹OvO | 25 |
| MiX | 30 |
| AO | 26 |
-| Chino | 30 |
+| Chino | 80 |
+| 辰 | 50 |
+| 非酋 | 1杯瑞幸 |
+| 白洲梓 | 1杯瑞幸 |
diff --git a/apps/webUI.js b/apps/webUI.js
deleted file mode 100644
index c3467c1..0000000
--- a/apps/webUI.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import { REDIS_YUNZAI_WEBUI } from "../constants/constant.js";
-import config from "../model/config.js";
-import { constructPublicIPsMsg } from "../utils/network.js";
-import { redisSetKey } from "../utils/redis-util.js";
-import { buildNextJs } from "../utils/start-nextjs.js";
-import { getBotLoginInfo, getBotStatus, getBotVersionInfo, sendPrivateMsg } 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 initData(e, realIsOpenWebUI) {
- 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
- });
- });
- }
- }
-
- async rWebSwitch(e) {
- config.updateField("tools", "isOpenWebUI", !this.isOpenWebUI);
- const realIsOpenWebUI = config.getConfig("tools").isOpenWebUI;
- if (realIsOpenWebUI) {
- // 初始化数据
- await this.initData(e, realIsOpenWebUI);
- e.reply(`R插件可视化面板:正在构建中,请稍等...`);
- // 动态编译生产环境
- await buildNextJs();
- await sendPrivateMsg(e, constructPublicIPsMsg());
- }
- e.reply(`R插件可视化面板:${ realIsOpenWebUI ? "✅已开启" : "❌已关闭" },重启后生效`);
- return true;
- }
-
- async rWebStatus(e) {
- e.reply(`R插件可视化面板:\n状态:${ this.toolsConfig.isOpenWebUI ? "✅开启" : "❌关闭" }\n地址:******:4016`);
- return true;
- }
-}
diff --git a/config/tools.yaml b/config/tools.yaml
index 96ed8ee..b86c1f6 100644
--- a/config/tools.yaml
+++ b/config/tools.yaml
@@ -1,4 +1,3 @@
-isOpenWebUI: false # 是否开启webui
defaultPath: './data/rcmp4/' # 保存视频的位置
videoSizeLimit: 70 # 视频大小限制(单位MB),超过大小则转换成群文件上传
proxyAddr: '127.0.0.1' # 魔法地址
diff --git a/config/version.yaml b/config/version.yaml
index 0422893..562ab48 100644
--- a/config/version.yaml
+++ b/config/version.yaml
@@ -1,5 +1,5 @@
- {
- version: 1.10.0-rc1,
+ version: 1.10.0-rc2,
data:
[
新增RBS查看哔哩哔哩状态功能,
diff --git a/constants/constant.js b/constants/constant.js
index 930046f..72dbc91 100644
--- a/constants/constant.js
+++ b/constants/constant.js
@@ -92,12 +92,6 @@ 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_WEBUI = "Yz:rconsole:tools:webui";
-
export const TWITTER_BEARER_TOKEN = "";
/**
diff --git a/index.js b/index.js
index cdc5be4..8a5f3e9 100644
--- a/index.js
+++ b/index.js
@@ -1,16 +1,12 @@
import fs from "node:fs";
import path from "path";
import config from "./model/config.js";
-import { constructPublicIPsMsg } from "./utils/network.js";
-import { startNextJs } from "./utils/start-nextjs.js";
if (!global.segment) {
global.segment = (await import("oicq")).segment
}
// 加载版本号
const versionData = config.getConfig("version");
-// 加载是否使用WebUI
-const isOpenWebUI = config.getConfig("tools").isOpenWebUI;
// 加载名称
const packageJsonPath = path.join('./plugins', 'rconsole-plugin', 'package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
@@ -40,10 +36,4 @@ for (let i in files) {
apps[name] = ret[i].value[Object.keys(ret[i].value)[0]];
}
-// 检查是否启动 webui
-if (isOpenWebUI) {
- startNextJs('start');
- logger.info(constructPublicIPsMsg());
-}
-
export { apps };
diff --git a/package.json b/package.json
index 0a5a716..930fa43 100644
--- a/package.json
+++ b/package.json
@@ -2,33 +2,11 @@
"name": "rconsole-plugin",
"description": "R-Plugin",
"type": "module",
- "scripts": {
- "dev": "cd server && next dev -p 4016",
- "dev6": "cd server && HOST=:: next dev -p 4016",
- "start": "cd server && next start -p 4016",
- "start6": "cd server && HOST=:: next start -p 4016",
- "build": "cd server && next build"
- },
"dependencies": {
"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",
- "node-os-utils": "^1.3.7",
- "os-utils": "^0.0.14",
- "p-queue": "^8.0.1",
"qrcode": "^1.5.3",
- "react": "^18.3.1",
- "react-chartjs-2": "^5.2.0",
- "react-circular-progressbar": "^2.1.0",
- "react-dom": "^18.3.1",
- "systeminformation": "^5.23.5"
- },
- "devDependencies": {
- "daisyui": "^4.12.14",
- "tailwindcss": "^3.4.14"
+ "p-queue": "^8.0.1"
}
-}
+}
\ No newline at end of file
diff --git a/server/app/layout.jsx b/server/app/layout.jsx
deleted file mode 100644
index e8acbcc..0000000
--- a/server/app/layout.jsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import "../styles/global.css";
-
-export default function RootLayout({ children }) {
- return (
-
-
{children}
-
- )
-}
diff --git a/server/app/page.jsx b/server/app/page.jsx
deleted file mode 100644
index 63aed4c..0000000
--- a/server/app/page.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import Header from "../components/header.jsx";
-import Sidebar from "../components/sidebar.jsx";
-import { DrawerProvider } from "../contexts/drawer-context.js";
-
-export default function Page() {
- return (
-
-
-
-
- )
-}
diff --git a/server/app/r/api/bot/route.js b/server/app/r/api/bot/route.js
deleted file mode 100644
index 35d92dc..0000000
--- a/server/app/r/api/bot/route.js
+++ /dev/null
@@ -1,11 +0,0 @@
-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/commit/route.js b/server/app/r/api/commit/route.js
deleted file mode 100644
index 4860c3e..0000000
--- a/server/app/r/api/commit/route.js
+++ /dev/null
@@ -1,30 +0,0 @@
-async function getLatestCommit(platform = "github") {
- // 构建 API URL
- const baseUrl =
- platform === "github"
- ? `https://api.github.com/repos/zhiyu1998/rconsole-plugin/commits`
- : `https://gitee.com/api/v5/repos/kyrzy0416/rconsole-plugin/commits`;
-
- try {
- const response = await fetch(baseUrl);
- if (!response.ok) throw new Error("获取提交信息失败");
-
- const commits = await response.json();
- const latestCommit = commits[0]; // 最新提交
- const { sha, commit, html_url } = latestCommit;
-
- return { sha, author: commit.author.name, message: commit.message, url: html_url };
- } catch (error) {
- console.error("无法获取最新的提交:", error.message);
- return null;
- }
-}
-
-export async function GET(req, res) {
- const latestCommit = await getLatestCommit();
-
- return new Response(JSON.stringify(latestCommit), {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
-}
diff --git a/server/app/r/api/config/route.js b/server/app/r/api/config/route.js
deleted file mode 100644
index 2e6f69e..0000000
--- a/server/app/r/api/config/route.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import fs from 'fs';
-import yaml from 'js-yaml';
-import path from 'path';
-
-const configPath = path.join(process.cwd(), "../", 'config', 'tools.yaml');
-
-export async function GET(req, res) {
- try {
- const yamlContent = await fs.promises.readFile(configPath, 'utf8');
- const config = yaml.load(yamlContent);
- return new Response(JSON.stringify(config), {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
- } catch (error) {
- console.error('读取配置文件失败:', error);
- return new Response(JSON.stringify({ error: '读取配置文件失败' }), {
- status: 500,
- headers: { 'Content-Type': 'application/json' },
- });
- }
-}
-
-export async function POST(req, res) {
- try {
- const updates = await req.json();
-
- const yamlContent = await fs.promises.readFile(configPath, 'utf8');
- const currentConfig = yaml.load(yamlContent);
-
- // 只更新指定的字段
- const newConfig = { ...currentConfig, ...updates };
-
- // 转换回YAML并保存
- const newYamlContent = yaml.dump(newConfig, {
- indent: 2,
- lineWidth: -1,
- quotingType: '"'
- });
- await fs.promises.writeFile(configPath, newYamlContent, 'utf8');
- return new Response(JSON.stringify({ success: true }), {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
- } catch (error) {
- console.error('更新配置文件失败:', error);
- return new Response(JSON.stringify({ error: '更新配置文件失败' }), {
- status: 500,
- headers: { 'Content-Type': 'application/json' },
- });
- }
-}
diff --git a/server/app/r/api/network/route.js b/server/app/r/api/network/route.js
deleted file mode 100644
index ba2c6af..0000000
--- a/server/app/r/api/network/route.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import axios from "axios";
-
-export async function GET(request) {
- const url = new URL(request.url); // 获取请求的 URL
- const targetUrl = url.searchParams.get("url"); // 从查询参数中获取目标 URL
- const start = Date.now(); // 记录请求开始时间
-
- try {
- await axios.get(targetUrl);
- // 计算结束时间减去开始时间
- return new Response(JSON.stringify({
- time: Date.now() - start
- }), {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
- } catch (error) {
- return new Response(JSON.stringify({
- time: 0
- }), {
- status: 500,
- headers: { 'Content-Type': 'application/json' },
- })
- }
-}
diff --git a/server/app/r/api/network2/route.js b/server/app/r/api/network2/route.js
deleted file mode 100644
index c8ef821..0000000
--- a/server/app/r/api/network2/route.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import { unstable_noStore as noStore } from 'next/cache';
-import { promises as fs } from 'fs';
-import os from 'os';
-import si from 'systeminformation';
-
-let lastBytesReceived = 0;
-let lastBytesSent = 0;
-let lastTimestamp = Date.now();
-
-async function getLinuxStats() {
- const data = await fs.readFile('/proc/net/dev', 'utf8');
- const lines = data.trim().split('\n');
-
- let bytesReceived = 0;
- let bytesSent = 0;
-
- for (let i = 2; i < lines.length; i++) {
- const line = lines[i].trim();
- const parts = line.split(/\s+/);
-
- if (parts[0].startsWith('lo:')) continue;
-
- bytesReceived += parseInt(parts[1], 10);
- bytesSent += parseInt(parts[9], 10);
- }
-
- return { bytesReceived, bytesSent };
-}
-
-async function getWindowsStats() {
- const networkStats = await si.networkStats();
- let bytesReceived = 0;
- let bytesSent = 0;
-
- for (const stat of networkStats) {
- bytesReceived += stat.rx_bytes || 0;
- bytesSent += stat.tx_bytes || 0;
- }
-
- return { bytesReceived, bytesSent };
-}
-
-async function getNetworkStats() {
- try {
- const platform = os.platform();
- let bytesReceived = 0;
- let bytesSent = 0;
-
- if (platform === 'linux') {
- const stats = await getLinuxStats();
- bytesReceived = stats.bytesReceived;
- bytesSent = stats.bytesSent;
- } else {
- const stats = await getWindowsStats();
- bytesReceived = stats.bytesReceived;
- bytesSent = stats.bytesSent;
- }
-
- const now = Date.now();
- const timeDiff = (now - lastTimestamp) / 1000;
-
- const downloadSpeed = Math.max(0, (bytesReceived - lastBytesReceived) / timeDiff);
- const uploadSpeed = Math.max(0, (bytesSent - lastBytesSent) / timeDiff);
-
- lastBytesReceived = bytesReceived;
- lastBytesSent = bytesSent;
- lastTimestamp = now;
-
- return {
- downloadSpeed: (downloadSpeed / 1024).toFixed(2),
- uploadSpeed: (uploadSpeed / 1024).toFixed(2),
- totalReceived: (bytesReceived / (1024 * 1024 * 1024)).toFixed(2),
- totalSent: (bytesSent / (1024 * 1024 * 1024)).toFixed(2),
- timestamp: now
- };
- } catch (error) {
- console.error('获取网络统计信息失败:', error);
- return {
- downloadSpeed: "0",
- uploadSpeed: "0",
- totalReceived: "0",
- totalSent: "0",
- timestamp: Date.now()
- };
- }
-}
-
-export async function GET() {
- // 这个不允许删除,否则无法做到实时获取
- noStore();
- try {
- const stats = await getNetworkStats();
- return new Response(JSON.stringify(stats), {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
- } catch (error) {
- return new Response(JSON.stringify({ error: error.message }), {
- status: 500,
- headers: { 'Content-Type': 'application/json' },
- });
- }
-}
diff --git a/server/app/r/api/resolveControl/route.js b/server/app/r/api/resolveControl/route.js
deleted file mode 100644
index 200e6d9..0000000
--- a/server/app/r/api/resolveControl/route.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import { REDIS_RESOLVE_CONTROLLER } from "../../../../constants/redis.js";
-import { GLOBAL_RESOLE_CONTROLLER } from "../../../../constants/resolve.js";
-import { redis } from "../../../../utils/redis.js";
-
-export async function GET(req, res) {
- let resolveList = await redis.get(REDIS_RESOLVE_CONTROLLER);
- if (resolveList == null) {
- // Redis中不存在就初始化进去
- await redis.set(REDIS_RESOLVE_CONTROLLER, JSON.stringify(GLOBAL_RESOLE_CONTROLLER));
- return new Response(JSON.stringify(GLOBAL_RESOLE_CONTROLLER), {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
- }
-
- return new Response(resolveList, {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
-}
-
-export async function POST(req) {
- try {
- const data = await req.json();
- const { selectedTags } = data;
-
- // 获取所有可能的标签
- const allTags = GLOBAL_RESOLE_CONTROLLER.map(item => item.label);
-
- // 更新控制器状态
- const updatedController = GLOBAL_RESOLE_CONTROLLER.map(item => ({
- ...item,
- value: selectedTags.includes(item.label) ? 1 : 0
- }));
-
- // 保存到Redis
- await redis.set(REDIS_RESOLVE_CONTROLLER, JSON.stringify(updatedController));
-
- return new Response(JSON.stringify({ success: true }), {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
- } catch (error) {
- return new Response(JSON.stringify({ success: false, error: error.message }), {
- status: 500,
- headers: { 'Content-Type': 'application/json' },
- });
- }
-}
diff --git a/server/app/r/api/system/route.js b/server/app/r/api/system/route.js
deleted file mode 100644
index 10b627d..0000000
--- a/server/app/r/api/system/route.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import { unstable_noStore as noStore } from 'next/cache';
-import si from 'systeminformation';
-import os from 'os';
-
-export async function GET(request, { params }) {
- // 这个不允许删除,否则无法做到实时获取
- noStore();
- try {
- // 获取CPU信息
- const cpuInfo = await si.cpu();
- const cpuUsage = await si.currentLoad();
- const totalCpuCores = cpuInfo.cores;
- const cpuCoresUsed = ((cpuUsage.currentLoad / 100) * totalCpuCores).toFixed(1); // 使用的核心数
-
- // 获取内存信息
- const totalMemory = (os.totalmem() / (1024 ** 3)).toFixed(2); // 转换为 GB
- const freeMemory = (os.freemem() / (1024 ** 3)).toFixed(2); // 转换为 GB
- const usedMemory = (totalMemory - freeMemory).toFixed(2);
- const memoryUsagePercent = ((usedMemory / totalMemory) * 100).toFixed(2);
-
- // 获取磁盘信息
- const diskInfo = await si.fsSize();
- const totalDisk = (diskInfo[0].size / (1024 ** 3)).toFixed(2); // 转换为 GB
- const usedDisk = (diskInfo[0].used / (1024 ** 3)).toFixed(2); // 转换为 GB
- const diskUsagePercent = ((usedDisk / totalDisk) * 100).toFixed(2);
-
- // 获取网络信息
- const networkInterfaces = os.networkInterfaces();
- const ipAddress = Object.values(networkInterfaces)
- .flat()
- .filter(detail => detail.family === 'IPv4' && !detail.internal)[0].address;
-
- // 获取系统信息
- const hostname = os.hostname();
- const uptime = os.uptime();
- const osInfo = await si.osInfo();
-
- return new Response(JSON.stringify({
- cpuUsage: cpuUsage.currentLoad.toFixed(2),
- cpuUsageDetail: `${cpuUsage.currentLoad.toFixed(2)}%`,
- totalCpuCores,
- cpuCoresUsed,
- memoryUsage: memoryUsagePercent,
- usedMemory: `${usedMemory} GB`,
- totalMemory: `${totalMemory} GB`,
- diskUsage: diskUsagePercent,
- usedDisk: `${usedDisk} GB`,
- totalDisk: `${totalDisk} GB`,
- loadAverage: cpuUsage.avgLoad.toFixed(2),
- ipAddress,
- hostname,
- uptime: `${Math.floor(uptime / 60 / 60)} hours`,
- distro: osInfo.distro,
- kernelVersion: osInfo.kernel,
- arch: os.arch(),
- }), {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
- } catch (error) {
- return new Response(JSON.stringify({ error: error.message }), { status: 500 });
- }
-}
diff --git a/server/app/r/api/update/route.js b/server/app/r/api/update/route.js
deleted file mode 100644
index db50ca8..0000000
--- a/server/app/r/api/update/route.js
+++ /dev/null
@@ -1,241 +0,0 @@
-import { exec } from 'child_process';
-import { promisify } from 'util';
-import fs from 'fs/promises';
-import path from 'path';
-import { REDIS_UPDATE_PATH, REDIS_UPDATE_STATUS } from "../../../../constants/redis.js";
-import { redis } from "../../../../utils/redis.js";
-
-const execAsync = promisify(exec);
-
-// Git错误处理函数
-function handleGitError(error, stderr) {
- if (error.message.includes('RPC failed')) {
- return '网络连接失败,请检查网络后重试';
- }
- if (error.message.includes('early EOF')) {
- return '数据传输中断,请重试';
- }
- if (error.message.includes('fetch-pack: invalid index-pack output')) {
- return '数据包错误,请重试';
- }
- if (error.message.includes('Timed out')) {
- return '连接超时,请检查网络后重试';
- }
- if (error.message.includes('Could not resolveControl host')) {
- return '无法解析主机地址,请检查网络';
- }
- if (error.message.includes('Permission denied')) {
- return '权限被拒绝,请检查git权限配置';
- }
- if (error.message.includes('be overwritten by merge')) {
- return '存在冲突,请使用强制更新';
- }
-
- // 如果是其他错误,返回具体错误信息
- return stderr || error.message || '未知错误';
-}
-
-async function ensureDirectory(dir) {
- try {
- await fs.access(dir);
- } catch {
- await fs.mkdir(dir, { recursive: true });
- }
-}
-
-async function copyConfig(src, dest) {
- try {
- await ensureDirectory(path.dirname(dest));
- await fs.cp(src, dest, { recursive: true });
- console.log(`成功复制配置文件从 ${src} 到 ${dest}`);
- return true;
- } catch (error) {
- console.error(`复制配置文件失败: ${error.message}`);
- return false;
- }
-}
-
-// 清理更新状态和临时文件
-async function cleanupUpdate(tempDir) {
- try {
- // 清理临时文件
- await fs.rm(tempDir, { recursive: true, force: true });
- // 清理Redis中的更新状态
- await redis.del(REDIS_UPDATE_STATUS);
- await redis.del(REDIS_UPDATE_PATH);
- console.log('清理完成');
- } catch (error) {
- console.error('清理失败:', error);
- }
-}
-
-export async function GET(req) {
- try {
- const { searchParams } = new URL(req.url);
- const isCheck = searchParams.get('check') === 'true';
- const isRestore = searchParams.get('restore') === 'true';
- const isForce = searchParams.get('force') === 'true';
-
- // 如果是检查请求
- if (isCheck) {
- const updateStatus = await redis.get(REDIS_UPDATE_STATUS);
- return new Response(JSON.stringify({
- needsRestore: updateStatus === 'restoring'
- }), {
- headers: { 'Content-Type': 'application/json' },
- });
- }
-
- // 如果是恢复请求
- if (isRestore) {
- const updateStatus = await redis.get(REDIS_UPDATE_STATUS);
- const paths = JSON.parse(await redis.get(REDIS_UPDATE_PATH) || '{}');
-
- if (updateStatus === 'restoring' && paths.tempDir && paths.configDir) {
- try {
- await copyConfig(paths.tempDir, paths.configDir);
- await cleanupUpdate(paths.tempDir);
- return new Response(JSON.stringify({
- success: true,
- message: '配置恢复完成'
- }), {
- headers: { 'Content-Type': 'application/json' },
- });
- } catch (error) {
- return new Response(JSON.stringify({
- success: false,
- message: '配置恢复失败:' + error.message
- }), {
- headers: { 'Content-Type': 'application/json' },
- });
- }
- }
-
- return new Response(JSON.stringify({
- success: true,
- message: '无需恢复'
- }), {
- headers: { 'Content-Type': 'application/json' },
- });
- }
-
- const projectRoot = path.join(process.cwd(), '..');
- const tempDir = path.join(projectRoot, 'temp', 'update-tmp');
- const configDir = path.join(projectRoot, 'config');
-
- // 检查是否有未完成的更新
- const updateStatus = await redis.get(REDIS_UPDATE_STATUS);
- if (updateStatus === 'restoring') {
- // 如果有未完成的更新,尝试恢复
- const paths = JSON.parse(await redis.get(REDIS_UPDATE_PATH) || '{}');
- if (paths.tempDir && paths.configDir) {
- try {
- await copyConfig(paths.tempDir, paths.configDir);
- console.log('恢复了之前未完成的配置文件更新');
- } finally {
- await cleanupUpdate(paths.tempDir);
- }
- }
- }
-
- console.log('开始新的更新流程');
-
- // 保存路径信息到Redis
- await redis.set(REDIS_UPDATE_PATH, JSON.stringify({
- tempDir,
- configDir
- }));
- await redis.set(REDIS_UPDATE_STATUS, 'started');
-
- // 确保临时目录存在
- await ensureDirectory(tempDir);
-
- // 备份配置文件
- let configBackedUp = false;
- try {
- await fs.access(configDir);
- await copyConfig(configDir, tempDir);
- configBackedUp = true;
- console.log('配置文件备份成功');
- await redis.set(REDIS_UPDATE_STATUS, 'backed_up');
- } catch (error) {
- console.log('无配置文件需要备份或备份失败:', error.message);
- }
-
- try {
- // 执行git操作
- if (isForce) {
- console.log('执行强制更新...');
- await execAsync(`git -C "${projectRoot}" checkout .`);
- }
-
- // 标记状态为需要恢复
- await redis.set(REDIS_UPDATE_STATUS, 'restoring');
-
- console.log('执行git pull...');
- const { stdout } = await execAsync(`git -C "${projectRoot}" pull --no-rebase`);
-
- // 恢复配置文件
- if (configBackedUp) {
- console.log('开始恢复配置文件...');
- await copyConfig(tempDir, configDir);
- }
-
- // 清理所有临时文件和状态
- await cleanupUpdate(tempDir);
-
- if (stdout.includes('Already up to date') || stdout.includes('已经是最新')) {
- return new Response(JSON.stringify({
- success: true,
- message: '已经是最新版本'
- }), {
- headers: { 'Content-Type': 'application/json' },
- });
- }
-
- return new Response(JSON.stringify({
- success: true,
- message: '更新成功'
- }), {
- headers: { 'Content-Type': 'application/json' },
- });
-
- } catch (error) {
- // 如果git操作失败,也尝试恢复配置文件
- if (configBackedUp) {
- try {
- await copyConfig(tempDir, configDir);
- console.log('git操作失败,但配置文件已恢复');
- } catch (restoreError) {
- console.error('恢复配置文件失败:', restoreError.message);
- }
- }
-
- await cleanupUpdate(tempDir);
-
- const errorMessage = handleGitError(error, error.stderr);
- return new Response(JSON.stringify({
- success: false,
- message: errorMessage
- }), {
- headers: { 'Content-Type': 'application/json' },
- });
- }
-
- } catch (error) {
- console.error('更新过程出错:', error);
-
- // 确保清理所有临时状态
- const paths = JSON.parse(await redis.get(REDIS_UPDATE_PATH) || '{}');
- if (paths.tempDir) {
- await cleanupUpdate(paths.tempDir);
- }
-
- return new Response(JSON.stringify({
- success: false,
- message: '更新过程出错:' + (error.message || '未知错误')
- }), {
- headers: { 'Content-Type': 'application/json' },
- });
- }
-}
diff --git a/server/app/r/api/version/route.js b/server/app/r/api/version/route.js
deleted file mode 100644
index de810b7..0000000
--- a/server/app/r/api/version/route.js
+++ /dev/null
@@ -1,43 +0,0 @@
-async function getLatestTag() {
- // GitHub 和 Gitee 的 API URL
- const githubUrl = `https://api.github.com/repos/zhiyu1998/rconsole-plugin/tags`;
- const giteeUrl = `https://gitee.com/api/v5/repos/kyrzy0416/rconsole-plugin/tags`;
-
- // 定义 fetch 请求
- const fetchGitHub = fetch(githubUrl).then(async (response) => {
- if (!response.ok) throw new Error("GitHub请求失败");
- const data = await response.json();
- return { source: "GitHub", tag: data };
- });
-
- const fetchGitee = fetch(giteeUrl).then(async (response) => {
- if (!response.ok) throw new Error("Gitee请求失败");
- const data = await response.json();
- return { source: "Gitee", tag: data };
- });
-
- // 使用 Promise.race 竞速
- try {
- return await Promise.race([fetchGitHub, fetchGitee]);
- } catch (error) {
- console.error("无法获取最新的标签:", error.message);
- return null;
- }
-}
-
-export async function GET(req, res) {
- const tags = await getLatestTag();
- console.log(tags);
-
- let latestTag;
- if (tags.source === "Gitee") {
- latestTag = tags.tag[tags.length - 1];
- }
- latestTag = tags.tag[0];
- console.log(latestTag);
-
- return new Response(JSON.stringify(latestTag), {
- status: 200,
- headers: { 'Content-Type': 'application/json' },
- });
-}
diff --git a/server/components/TagSelector.jsx b/server/components/TagSelector.jsx
deleted file mode 100644
index cd22a68..0000000
--- a/server/components/TagSelector.jsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import React, { useState, useEffect } from "react";
-
-const TagSelector = ({ options = [], initialTags = [], onChange }) => {
- const [selectedTags, setSelectedTags] = useState(initialTags);
-
- useEffect(() => {
- setSelectedTags(initialTags);
- }, [initialTags]);
-
- const addTag = (tag) => {
- if (!selectedTags.includes(tag)) {
- const updatedTags = [...selectedTags, tag];
- setSelectedTags(updatedTags);
- if (onChange) onChange(updatedTags);
- }
- };
-
- const removeTag = (tag) => {
- const updatedTags = selectedTags.filter((t) => t !== tag);
- setSelectedTags(updatedTags);
- if (onChange) onChange(updatedTags);
- };
-
- return (
-
-
- {selectedTags.length > 0 ? (
- selectedTags.map((tag, index) => (
- removeTag(tag)}
- >
- {tag}
-
- ))
- ) : (
- 暂无标签,请选择一个选项。
- )}
-
-
-
-
- );
-};
-
-export default TagSelector;
diff --git a/server/components/ThemeToggle.jsx b/server/components/ThemeToggle.jsx
deleted file mode 100644
index 67ba3a8..0000000
--- a/server/components/ThemeToggle.jsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import React, { useState } from 'react';
-
-function ThemeToggle() {
- // 用于保存主题状态,默认为“light”主题
- const [isDarkTheme, setIsDarkTheme] = useState(false);
-
- // 切换主题时的处理函数
- const handleThemeChange = () => {
- setIsDarkTheme(!isDarkTheme);
- };
-
- return (
-
- );
-}
-
-export default ThemeToggle;
diff --git a/server/components/common/ConfigItem.jsx b/server/components/common/ConfigItem.jsx
deleted file mode 100644
index 33b36bf..0000000
--- a/server/components/common/ConfigItem.jsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import React from 'react';
-
-export const ConfigToggle = ({ label, checked, onChange }) => (
-
-
-
-);
-
-export const ConfigInput = ({ label, value, onChange, type = "text", placeholder = "" }) => (
-
-
- onChange(type === "number" ? parseInt(e.target.value) : e.target.value)}
- placeholder={placeholder}
- className="input input-bordered"
- />
-
-);
-
-export const ConfigSelect = ({ label, value, onChange, options }) => (
-
-
-
-
-);
\ No newline at end of file
diff --git a/server/components/content.jsx b/server/components/content.jsx
deleted file mode 100644
index 135534a..0000000
--- a/server/components/content.jsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { SIDEBAR_ITEMS } from "../constants/sidebar.js";
-
-export function Content({ activeItem }) {
- // 查找当前激活项
- const currentItem = SIDEBAR_ITEMS.find(item => item.name === activeItem);
-
- // 如果没找到则返回总控制台
- return (
-
- {currentItem?.component || SIDEBAR_ITEMS[0].component}
-
- );
-}
diff --git a/server/components/contents/bili.jsx b/server/components/contents/bili.jsx
deleted file mode 100644
index 44627de..0000000
--- a/server/components/contents/bili.jsx
+++ /dev/null
@@ -1,156 +0,0 @@
-import { useState, useEffect } from 'react';
-import { BILI_CDN_SELECT_LIST, BILI_DOWNLOAD_METHOD, BILI_RESOLUTION_LIST } from "../../../constants/constant.js";
-import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
-import Toast from "../toast.jsx";
-import { ConfigToggle, ConfigInput, ConfigSelect } from '../common/ConfigItem';
-
-// 定义配置项
-const BILI_CONFIG = {
- toggles: [
- { key: 'biliDisplayCover', label: '显示封面' },
- { key: 'biliDisplayInfo', label: '显示视频信息' },
- { key: 'biliDisplayIntro', label: '显示简介' },
- { key: 'biliDisplayOnline', label: '显示在线人数' },
- { key: 'biliDisplaySummary', label: '显示总结' },
- { key: 'biliUseBBDown', label: '使用BBDown' },
- ],
- inputs: [
- { key: 'biliSessData', label: 'SESSDATA', type: 'text', placeholder: '请输入Bilibili SESSDATA' },
- { key: 'biliDuration', label: '视频时长限制(秒)', type: 'number' },
- { key: 'biliIntroLenLimit', label: '简介长度限制', type: 'number' },
- ],
- selects: [
- { key: 'biliCDN', label: 'CDN选择', options: BILI_CDN_SELECT_LIST },
- { key: 'biliDownloadMethod', label: '下载方式', options: BILI_DOWNLOAD_METHOD },
- { key: 'biliResolution', label: '视频画质', options: BILI_RESOLUTION_LIST },
- ]
-};
-
-// 默认配置
-const DEFAULT_CONFIG = {
- biliSessData: '',
- biliDuration: 480,
- biliIntroLenLimit: 50,
- biliDisplayCover: true,
- biliDisplayInfo: true,
- biliDisplayIntro: true,
- biliDisplayOnline: true,
- biliDisplaySummary: false,
- biliUseBBDown: false,
- biliCDN: 0,
- biliDownloadMethod: 0,
- biliResolution: 5
-};
-
-export default function Bili() {
- const [config, setConfig] = useState(DEFAULT_CONFIG);
- const [loading, setLoading] = useState(false);
-
- useEffect(() => {
- const loadConfig = async () => {
- const yamlConfig = await readYamlConfig();
- if (yamlConfig) {
- const newConfig = {};
- Object.keys(DEFAULT_CONFIG).forEach(key => {
- newConfig[key] = yamlConfig[key] ?? DEFAULT_CONFIG[key];
- });
- setConfig(newConfig);
- }
- };
- loadConfig();
- }, []);
-
- const handleSave = async () => {
- setLoading(true);
- try {
- const success = await updateYamlConfig(config);
- if (success) {
- document.getElementById('toast-success').classList.remove('hidden');
- setTimeout(() => {
- document.getElementById('toast-success').classList.add('hidden');
- }, 3000);
- }
- } catch (error) {
- console.error('保存配置失败:', error);
- } finally {
- setLoading(false);
- }
- };
-
- const handleConfigChange = (key, value) => {
- setConfig(prev => ({ ...prev, [key]: value }));
- };
-
- return (
-
-
-
-
-
Bilibili 配置
-
-
-
-
基础配置
-
- {/* 输入框配置 */}
-
- {BILI_CONFIG.inputs.map(item => (
- handleConfigChange(item.key, value)}
- placeholder={item.placeholder}
- />
- ))}
-
-
- {/* 开关配置 */}
-
- {BILI_CONFIG.toggles.map(item => (
- handleConfigChange(item.key, value)}
- />
- ))}
-
-
- {/* 选择框配置 */}
-
- {BILI_CONFIG.selects.map(item => (
- handleConfigChange(item.key, value)}
- options={item.options}
- />
- ))}
-
-
-
-
- {/* 操作按钮 */}
-
-
-
-
-
-
- );
-}
diff --git a/server/components/contents/generic.jsx b/server/components/contents/generic.jsx
deleted file mode 100644
index 53d2746..0000000
--- a/server/components/contents/generic.jsx
+++ /dev/null
@@ -1,359 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
-import { ConfigInput, ConfigSelect, ConfigToggle } from '../common/ConfigItem';
-import TagSelector from "../TagSelector.jsx";
-import Toast from "../toast.jsx";
-
-// 定义配置项
-const GENERIC_CONFIG = {
- basicInputs: [
- {
- key: 'defaultPath',
- label: '视频保存路径',
- type: 'text',
- placeholder: '请输入视频保存路径...',
- defaultValue: './data/rcmp4/'
- },
- {
- key: 'videoSizeLimit',
- label: '视频大小限制(MB)',
- type: 'number',
- hint: '超过限制转为群文件',
- defaultValue: 70
- }
- ],
- proxyInputs: [
- {
- key: 'proxyAddr',
- label: '魔法地址',
- type: 'text',
- placeholder: '请输入代理地址...',
- defaultValue: '127.0.0.1'
- },
- {
- key: 'proxyPort',
- label: '魔法端口',
- type: 'text',
- placeholder: '请输入代理端口...',
- defaultValue: '7890'
- }
- ],
- streamInputs: [
- {
- key: 'identifyPrefix',
- label: '识别前缀',
- type: 'text',
- placeholder: '请输入识别前缀...',
- defaultValue: ''
- },
- {
- key: 'streamDuration',
- label: '视频最大时长(秒)',
- type: 'number',
- defaultValue: 10
- }
- ],
- concurrencyInputs: [
- {
- key: 'queueConcurrency',
- label: '队列并发数',
- type: 'number',
- hint: '仅影响B站下载',
- defaultValue: 1
- },
- {
- key: 'videoDownloadConcurrency',
- label: '视频下载并发数',
- type: 'number',
- defaultValue: 1
- }
- ],
- textareas: [
- {
- key: 'deeplApiUrls',
- label: 'DeepL API地址',
- placeholder: '请输入DeepL API地址,多个地址用逗号分隔...',
- defaultValue: ''
- }
- ],
- toggles: [
- {
- key: 'streamCompatibility',
- label: '兼容模式',
- hint: 'NCQQ不用开启,其他ICQQ、LLO需要开启',
- defaultValue: false
- }
- ],
- otherInputs: [
- {
- key: 'xiaohongshuCookie',
- label: '小红书Cookie',
- type: 'text',
- placeholder: '请输入小红书的Cookie...',
- defaultValue: ''
- },
- {
- key: 'autoclearTrashtime',
- label: '自动清理时间',
- type: 'text',
- placeholder: '请输入Cron表达式...',
- hint: 'Cron表达式',
- defaultValue: '0 0 8 * * ?'
- }
- ],
- aiInputs: [
- {
- key: 'aiBaseURL',
- label: 'AI接口地址',
- type: 'text',
- placeholder: '请输入AI接口地址...',
- defaultValue: '',
- hint: '用于识图的接口,kimi默认接口为:https://api.moonshot.cn,其他服务商自己填写'
- },
- {
- key: 'aiApiKey',
- label: 'API Key',
- type: 'text',
- placeholder: '请输入API Key...',
- defaultValue: '',
- hint: '用于识图的api key,kimi接口申请:https://platform.moonshot.cn/console/api-keys'
- }
- ],
- aiSelects: [
- {
- key: 'aiModel',
- label: 'AI模型',
- options: [
- { value: 'moonshot-v1-8k', label: 'Moonshot V1 8K' },
- { value: 'moonshot-v1-32k', label: 'Moonshot V1 32K' },
- { value: 'moonshot-v1-128k', label: 'Moonshot V1 128K' },
- // 可以根据需要添加更多模型选项
- ],
- defaultValue: 'moonshot-v1-8k',
- hint: '模型,使用kimi不用填写,其他要填写'
- }
- ]
-};
-
-// 生成默认配置
-const DEFAULT_CONFIG = Object.values(GENERIC_CONFIG).reduce((acc, group) => {
- group.forEach(item => {
- acc[item.key] = item.defaultValue;
- });
- return acc;
-}, {});
-
-export default function Generic() {
- const [config, setConfig] = useState(DEFAULT_CONFIG);
- const [loading, setLoading] = useState(false);
- const [resolveOptions, setResolveOptions] = useState([]);
- const [selectedResolveTags, setSelectedResolveTags] = useState([]);
-
- useEffect(() => {
- const loadConfig = async () => {
- const yamlConfig = await readYamlConfig();
- if (yamlConfig) {
- const newConfig = {};
- Object.keys(DEFAULT_CONFIG).forEach(key => {
- newConfig[key] = yamlConfig[key] ?? DEFAULT_CONFIG[key];
- });
- setConfig(newConfig);
- }
- };
- loadConfig();
- }, []);
-
- useEffect(() => {
- // 获取解析控制器配置
- const fetchResolveControl = async () => {
- try {
- const response = await fetch('/r/api/resolveControl');
- const data = await response.json();
- const enabledTags = data
- .filter(item => item.value === 1)
- .map(item => item.label);
- setSelectedResolveTags(enabledTags);
- setResolveOptions(data.map(item => item.label));
- } catch (error) {
- console.error('获取解析控制器配置失败:', error);
- }
- };
-
- fetchResolveControl();
- }, []);
-
- const handleSave = async () => {
- setLoading(true);
- try {
- const success = await updateYamlConfig(config);
- if (success) {
- document.getElementById('generic-toast-success').classList.remove('hidden');
- setTimeout(() => {
- document.getElementById('generic-toast-success').classList.add('hidden');
- }, 3000);
- }
- } catch (error) {
- console.error('保存配置失败:', error);
- } finally {
- setLoading(false);
- }
- };
-
- const handleConfigChange = (key, value) => {
- setConfig(prev => ({ ...prev, [key]: value }));
- };
-
- const handleResolveTagsChange = async (tags) => {
- try {
- const response = await fetch('/r/api/resolveControl', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ selectedTags: tags }),
- });
-
- if (response.ok) {
- setSelectedResolveTags(tags);
- }
- } catch (error) {
- console.error('更新解析控制器配置失败:', error);
- }
- };
-
- // 渲染输入框组
- const renderInputGroup = (inputs, title) => (
-
- {inputs.map(item => (
-
- handleConfigChange(item.key, value)}
- placeholder={item.placeholder}
- />
- {item.hint && (
-
- {item.hint}
-
- )}
-
- ))}
-
- );
-
- return (
-
-
-
-
-
通用配置
-
-
-
-
基础配置
-
- {/* 基础配置 */}
- {renderInputGroup(GENERIC_CONFIG.basicInputs)}
-
- {/* 解析控制 */}
-
全局解析控制
-
-
- {/* 代理配置 */}
-
代理设置
- {renderInputGroup(GENERIC_CONFIG.proxyInputs)}
-
- {/* 流媒体配置 */}
-
流媒体设置
- {renderInputGroup(GENERIC_CONFIG.streamInputs)}
-
- {/* 并发配置 */}
-
并发设置
- {renderInputGroup(GENERIC_CONFIG.concurrencyInputs)}
-
- {/* DeepL API配置 */}
-
API设置
- {GENERIC_CONFIG.textareas.map(item => (
-
-
-
- ))}
-
- {/* 开关配置 */}
- {GENERIC_CONFIG.toggles.map(item => (
-
- handleConfigChange(item.key, value)}
- />
- {item.hint && (
-
- {item.hint}
-
- )}
-
- ))}
-
- {/* 其他配置 */}
-
其他设置
- {renderInputGroup(GENERIC_CONFIG.otherInputs)}
-
- {/* AI配置 */}
-
AI设置
- {renderInputGroup(GENERIC_CONFIG.aiInputs)}
-
- {GENERIC_CONFIG.aiSelects.map(item => (
-
- handleConfigChange(item.key, value)}
- options={item.options}
- />
- {item.hint && (
-
- {item.hint}
-
- )}
-
- ))}
-
-
-
-
- {/* 保存按钮 */}
-
-
-
-
-
-
- );
-}
diff --git a/server/components/contents/home.jsx b/server/components/contents/home.jsx
deleted file mode 100644
index 6d68f90..0000000
--- a/server/components/contents/home.jsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react';
-import BotInfo from "../home/bot-info.jsx";
-import Network from "../home/network.jsx";
-import System from "../home/system.jsx";
-
-export default function Home({ }) {
- return (
-
-
-
-
-
- );
-}
diff --git a/server/components/contents/ncm.jsx b/server/components/contents/ncm.jsx
deleted file mode 100644
index 1f2aefa..0000000
--- a/server/components/contents/ncm.jsx
+++ /dev/null
@@ -1,194 +0,0 @@
-import { useState, useEffect } from 'react';
-import { NETEASECLOUD_QUALITY_LIST } from "../../../constants/constant.js";
-import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
-import Toast from "../toast.jsx";
-import { ConfigToggle, ConfigInput, ConfigSelect } from '../common/ConfigItem';
-
-// 定义配置项
-const NCM_CONFIG = {
- textareas: [
- {
- key: 'neteaseCookie',
- label: 'Cookie',
- placeholder: '请输入网易云Cookie...'
- }
- ],
- inputs: [
- {
- key: 'neteaseCloudAPIServer',
- label: '自建API服务器地址',
- type: 'text',
- placeholder: '请输入API服务器地址...'
- },
- {
- key: 'neteaseUserId',
- label: '用户ID',
- type: 'text',
- placeholder: '网易云用户ID',
- hint: '不要手动更改!'
- },
- {
- key: 'songRequestMaxList',
- label: '点歌最大列表数',
- type: 'number'
- }
- ],
- toggles: [
- { key: 'useLocalNeteaseAPI', label: '使用自建API' },
- { key: 'useNeteaseSongRequest', label: '开启点歌功能' },
- { key: 'isSendVocal', label: '发送群语音' }
- ],
- selects: [
- {
- key: 'neteaseCloudAudioQuality',
- label: '音频质量',
- options: NETEASECLOUD_QUALITY_LIST
- }
- ]
-};
-
-// 默认配置
-const DEFAULT_CONFIG = {
- useLocalNeteaseAPI: false,
- useNeteaseSongRequest: false,
- isSendVocal: true,
- songRequestMaxList: 10,
- neteaseCookie: '',
- neteaseCloudAPIServer: '',
- neteaseCloudAudioQuality: 'exhigh',
- neteaseUserId: ''
-};
-
-export default function Ncm() {
- const [config, setConfig] = useState(DEFAULT_CONFIG);
- const [loading, setLoading] = useState(false);
-
- useEffect(() => {
- const loadConfig = async () => {
- const yamlConfig = await readYamlConfig();
- if (yamlConfig) {
- const newConfig = {};
- Object.keys(DEFAULT_CONFIG).forEach(key => {
- newConfig[key] = yamlConfig[key] ?? DEFAULT_CONFIG[key];
- });
- setConfig(newConfig);
- }
- };
- loadConfig();
- }, []);
-
- const handleSave = async () => {
- setLoading(true);
- try {
- const success = await updateYamlConfig(config);
- if (success) {
- document.getElementById('ncm-toast-success').classList.remove('hidden');
- setTimeout(() => {
- document.getElementById('ncm-toast-success').classList.add('hidden');
- }, 3000);
- }
- } catch (error) {
- console.error('保存配置失败:', error);
- } finally {
- setLoading(false);
- }
- };
-
- const handleConfigChange = (key, value) => {
- setConfig(prev => ({ ...prev, [key]: value }));
- };
-
- return (
-
-
-
-
-
网易云音乐配置
-
-
-
-
基础配置
-
- {/* 文本域配置 */}
- {NCM_CONFIG.textareas.map(item => (
-
-
-
- ))}
-
- {/* 输入框配置 */}
-
- {NCM_CONFIG.inputs.map(item => (
-
- handleConfigChange(item.key, value)}
- placeholder={item.placeholder}
- />
- {item.hint && (
-
- {item.hint}
-
- )}
-
- ))}
-
-
- {/* 开关配置 */}
-
- {NCM_CONFIG.toggles.map(item => (
- handleConfigChange(item.key, value)}
- />
- ))}
-
-
- {/* 选择框配置 */}
-
- {NCM_CONFIG.selects.map(item => (
- handleConfigChange(item.key, value)}
- options={item.options}
- />
- ))}
-
-
-
-
- {/* 保存按钮 */}
-
-
-
-
-
-
- );
-}
diff --git a/server/components/contents/tiktok.jsx b/server/components/contents/tiktok.jsx
deleted file mode 100644
index 5fec894..0000000
--- a/server/components/contents/tiktok.jsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import { useState, useEffect } from 'react';
-import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
-import Toast from "../toast.jsx";
-import { ConfigToggle } from '../common/ConfigItem';
-
-// 定义配置项
-const TIKTOK_CONFIG = {
- textareas: [
- {
- key: 'douyinCookie',
- label: 'Cookie',
- placeholder: '请输入抖音Cookie...',
- hint: '格式:odin_tt=xxx;passport_fe_beating_status=xxx;...'
- }
- ],
- toggles: [
- {
- key: 'douyinCompression',
- label: '视频压缩',
- hint: '开启后使用压缩格式,加速视频发送'
- },
- {
- key: 'douyinComments',
- label: '显示评论',
- hint: '是否显示视频评论'
- }
- ]
-};
-
-// 默认配置
-const DEFAULT_CONFIG = {
- douyinCookie: '',
- douyinCompression: true,
- douyinComments: false
-};
-
-export default function Tiktok() {
- const [config, setConfig] = useState(DEFAULT_CONFIG);
- const [loading, setLoading] = useState(false);
-
- useEffect(() => {
- const loadConfig = async () => {
- const yamlConfig = await readYamlConfig();
- if (yamlConfig) {
- const newConfig = {};
- Object.keys(DEFAULT_CONFIG).forEach(key => {
- newConfig[key] = yamlConfig[key] ?? DEFAULT_CONFIG[key];
- });
- setConfig(newConfig);
- }
- };
- loadConfig();
- }, []);
-
- const handleSave = async () => {
- setLoading(true);
- try {
- const success = await updateYamlConfig(config);
- if (success) {
- document.getElementById('tiktok-toast-success').classList.remove('hidden');
- setTimeout(() => {
- document.getElementById('tiktok-toast-success').classList.add('hidden');
- }, 3000);
- }
- } catch (error) {
- console.error('保存配置失败:', error);
- } finally {
- setLoading(false);
- }
- };
-
- const handleConfigChange = (key, value) => {
- setConfig(prev => ({ ...prev, [key]: value }));
- };
-
- return (
-
-
-
-
-
抖音配置
-
-
-
-
基础配置
-
- {/* Cookie配置 */}
- {TIKTOK_CONFIG.textareas.map(item => (
-
-
-
- ))}
-
- {/* 开关配置 */}
-
- {TIKTOK_CONFIG.toggles.map(item => (
-
- handleConfigChange(item.key, value)}
- />
- {item.hint && (
-
- {item.hint}
-
- )}
-
- ))}
-
-
-
-
- {/* 保存按钮 */}
-
-
-
-
-
-
- );
-}
diff --git a/server/components/contents/weekly.jsx b/server/components/contents/weekly.jsx
deleted file mode 100644
index c3767d5..0000000
--- a/server/components/contents/weekly.jsx
+++ /dev/null
@@ -1,11 +0,0 @@
-export default function Weekly() {
- return (
-
-
-
- )
-}
diff --git a/server/components/contents/youtube.jsx b/server/components/contents/youtube.jsx
deleted file mode 100644
index a66e124..0000000
--- a/server/components/contents/youtube.jsx
+++ /dev/null
@@ -1,126 +0,0 @@
-import { useState, useEffect } from 'react';
-import { YOUTUBE_GRAPHICS_LIST } from "../../../constants/constant.js";
-import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
-import Toast from "../toast.jsx";
-import { ConfigInput, ConfigSelect } from '../common/ConfigItem';
-
-// 定义配置项
-const YOUTUBE_CONFIG = {
- inputs: [
- { key: 'youtubeCookiePath', label: 'Cookie文件路径', type: 'text', placeholder: '请输入Cookie.txt文件路径...' },
- { key: 'youtubeClipTime', label: '最大截取时长(秒)', type: 'number', hint: '建议不超过5分钟' },
- { key: 'youtubeDuration', label: '视频时长限制(秒)', type: 'number', hint: '建议不超过30分钟' }
- ],
- selects: [
- { key: 'youtubeGraphicsOptions', label: '下载画质', options: YOUTUBE_GRAPHICS_LIST, hint: '0为原画' }
- ]
-};
-
-// 默认配置
-const DEFAULT_CONFIG = {
- youtubeGraphicsOptions: 720,
- youtubeClipTime: 0,
- youtubeDuration: 480,
- youtubeCookiePath: ''
-};
-
-export default function Youtube() {
- const [config, setConfig] = useState(DEFAULT_CONFIG);
- const [loading, setLoading] = useState(false);
-
- useEffect(() => {
- const loadConfig = async () => {
- const yamlConfig = await readYamlConfig();
- if (yamlConfig) {
- const newConfig = {};
- Object.keys(DEFAULT_CONFIG).forEach(key => {
- newConfig[key] = yamlConfig[key] ?? DEFAULT_CONFIG[key];
- });
- setConfig(newConfig);
- }
- };
- loadConfig();
- }, []);
-
- const handleSave = async () => {
- setLoading(true);
- try {
- const success = await updateYamlConfig(config);
- if (success) {
- document.getElementById('youtube-toast-success').classList.remove('hidden');
- setTimeout(() => {
- document.getElementById('youtube-toast-success').classList.add('hidden');
- }, 3000);
- }
- } catch (error) {
- console.error('保存配置失败:', error);
- } finally {
- setLoading(false);
- }
- };
-
- const handleConfigChange = (key, value) => {
- setConfig(prev => ({ ...prev, [key]: value }));
- };
-
- return (
-
-
-
-
-
YouTube 配置
-
-
-
-
基础配置
-
- {/* 输入框配置 */}
-
- {YOUTUBE_CONFIG.inputs.map(item => (
- handleConfigChange(item.key, value)}
- placeholder={item.placeholder}
- />
- ))}
-
-
- {/* 选择框配置 */}
-
- {YOUTUBE_CONFIG.selects.map(item => (
- handleConfigChange(item.key, value)}
- options={item.options}
- />
- ))}
-
-
-
-
- {/* 保存按钮 */}
-
-
-
-
-
-
- );
-}
diff --git a/server/components/header.jsx b/server/components/header.jsx
deleted file mode 100644
index 8f2c03e..0000000
--- a/server/components/header.jsx
+++ /dev/null
@@ -1,67 +0,0 @@
-"use client"
-import { useState, useEffect } from 'react';
-import { BOT_INFO_URL } from "../constants/api.js";
-import { useDrawer } from "../contexts/drawer-context.js";
-import ThemeToggle from "./ThemeToggle.jsx";
-
-export default function Header () {
-
- const { toggleDrawer } = useDrawer();
-
- const [user, setUser] = useState(null);
-
- useEffect(() => {
- fetch(BOT_INFO_URL)
- .then(response => {
- return response.json();
- })
- .then(data => setUser(data))
- }, []);
-
- return (
-
-
-
-
-
-
-
-
-
-

-
-
-
-
{user?.nickname || "未获取"}
-
{user?.user_id || "NaN"}
-
-
-
-
- )
-};
diff --git a/server/components/home/bot-config.jsx b/server/components/home/bot-config.jsx
deleted file mode 100644
index f40e6c9..0000000
--- a/server/components/home/bot-config.jsx
+++ /dev/null
@@ -1,106 +0,0 @@
-import { useEffect, useState } from "react";
-import { GIT_COMMIT_URL, GIT_VERSION_URL } from "../../constants/api.js";
-
-export function BotConfig() {
- const [version, setVersion] = useState("v0.0.0");
- const [commit, setCommit] = useState(null);
- const [updating, setUpdating] = useState(false);
- const [updateMessage, setUpdateMessage] = useState("");
-
- useEffect(() => {
- fetch(GIT_VERSION_URL).then(response => response.json()).then(data => setVersion(data.name));
- fetch(GIT_COMMIT_URL).then(response => response.json()).then(data => setCommit(data));
-
- const checkUpdateStatus = async () => {
- try {
- const response = await fetch('/r/api/update?check=true');
- const data = await response.json();
- if (data.needsRestore) {
- setUpdateMessage("检测到未完成的更新,正在恢复配置...");
- const restoreResponse = await fetch('/r/api/update?restore=true');
- const restoreData = await restoreResponse.json();
- setUpdateMessage(restoreData.message);
- }
- } catch (error) {
- console.error('检查更新状态失败:', error);
- }
- };
-
- checkUpdateStatus();
- }, []);
-
- const handleUpdate = async (isForce = false) => {
- try {
- setUpdating(true);
- setUpdateMessage("正在更新中...");
-
- const response = await fetch(`/r/api/update?force=${isForce}`);
- const data = await response.json();
-
- if (data.success) {
- setUpdateMessage(data.message);
- fetch(GIT_VERSION_URL).then(response => response.json()).then(data => setVersion(data.name));
- fetch(GIT_COMMIT_URL).then(response => response.json()).then(data => setCommit(data));
- } else {
- setUpdateMessage(`更新失败:${data.message}`);
- }
- } catch (error) {
- setUpdateMessage(`更新出错:${error.message}`);
- } finally {
- setUpdating(false);
- }
- };
-
- return (
-
-
-
🔥更新看板
-
-
-
-
最新版本
-
当前最新版本为:{version}
-
-
-
-
-
-
更新操作
-
选择更新方式进行更新
- {updateMessage && (
-
- {updateMessage}
-
- )}
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/server/components/home/bot-info.jsx b/server/components/home/bot-info.jsx
deleted file mode 100644
index ded27b8..0000000
--- a/server/components/home/bot-info.jsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { BotConfig } from "./bot-config.jsx";
-import { BotItem } from "./bot-item.jsx";
-import { BotNetwork } from "./bot-network.jsx";
-
-export default function BotInfo() {
-
- return (
-
-
- {/* 机器人信息卡片 */ }
-
-
-
-
-
- )
-}
diff --git a/server/components/home/bot-item.jsx b/server/components/home/bot-item.jsx
deleted file mode 100644
index cb55d9b..0000000
--- a/server/components/home/bot-item.jsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import React, { useEffect, useState } from "react";
-import { BOT_INFO_URL } from "../../constants/api.js";
-
-export function BotItem() {
-
- const [user, setUser] = useState(null);
- const [isLoading, setIsLoading] = useState(false);
-
- const fetchBotInfo = async () => {
- setIsLoading(true);
- try {
- const response = await fetch(BOT_INFO_URL);
- const data = await response.json();
- setUser(data);
- } catch (error) {
- console.error("获取机器人信息失败:", error);
- } finally {
- setIsLoading(false);
- }
- };
-
- useEffect(() => {
- fetchBotInfo();
- }, []);
-
- return (
-
-
-
🐔状态
-
-
-
-

-
-
-
-
-
昵称:{user?.nickname || "未获取"}
-
QQ号:{user?.user_id || "NaN"}
-
-
-
协议信息:
-
-
{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
deleted file mode 100644
index 5d07ae0..0000000
--- a/server/components/home/bot-network.jsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import React, { useEffect, useState } from "react";
-import { NETWORK_BASE_URL } from "../../constants/api.js";
-
-// 测试链接配置
-const TESTING_LINKS = [
- {
- name: "bilibili",
- url: "https://bilibili.com/",
- icon: (
-
- )
- },
- {
- name: "Github",
- url: "https://github.com/",
- icon: (
-
- )
- },
- {
- name: "YouTube",
- url: "https://youtube.com/",
- icon: (
-
- )
- },
- {
- name: "Tiktok",
- url: "https://tiktok.com/",
- icon: (
-
- )
- },
- // ... 其他链接配置类似
-];
-
-export function BotNetwork() {
- const [linksTime, setLinksTime] = useState(new Array(TESTING_LINKS.length).fill('NaN ms'));
- const [isLoading, setIsLoading] = useState(false);
-
- // 测试单个链接
- const testSingleLink = async (url, index) => {
- try {
- const response = await fetch(NETWORK_BASE_URL + url);
- const data = await response.json();
- setLinksTime(prev => {
- const newTimes = [...prev];
- newTimes[index] = `${data.time}ms`;
- return newTimes;
- });
- } catch (error) {
- console.error(`测试链接失败: ${url}`, error);
- setLinksTime(prev => {
- const newTimes = [...prev];
- newTimes[index] = '超时';
- return newTimes;
- });
- }
- };
-
- // 一键测速
- const handleTestAll = async () => {
- setIsLoading(true);
- setLinksTime(new Array(TESTING_LINKS.length).fill('测试中...'));
-
- try {
- await Promise.all(
- TESTING_LINKS.map((link, index) =>
- testSingleLink(link.url, index)
- )
- );
- } finally {
- setIsLoading(false);
- }
- };
-
- return (
-
-
-
-
🌐网速
-
-
-
- { TESTING_LINKS.map((link, index) => (
-
- { link.icon }
- { linksTime[index] }
-
- )) }
-
-
-
-
-
-
-
- );
-}
diff --git a/server/components/home/network.jsx b/server/components/home/network.jsx
deleted file mode 100644
index 4e632d6..0000000
--- a/server/components/home/network.jsx
+++ /dev/null
@@ -1,147 +0,0 @@
-import React, { useEffect, useState } from "react";
-import { Line } from "react-chartjs-2";
-import {
- Chart as ChartJS,
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- Title,
- Tooltip,
- Legend
-} from 'chart.js';
-
-ChartJS.register(
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- Title,
- Tooltip,
- Legend
-);
-
-const MAX_DATA_POINTS = 30;
-
-export default function Network() {
- const [networkData, setNetworkData] = useState({
- uploadSpeed: 0,
- downloadSpeed: 0,
- totalSent: 0,
- totalReceived: 0
- });
- const [chartData, setChartData] = useState({
- labels: [],
- datasets: [
- {
- label: '上传速度 (KB/s)',
- data: [],
- borderColor: 'rgb(75, 192, 192)',
- tension: 0.1
- },
- {
- label: '下载速度 (KB/s)',
- data: [],
- borderColor: 'rgb(255, 99, 132)',
- tension: 0.1
- }
- ]
- });
-
- useEffect(() => {
- const fetchData = async () => {
- try {
- const response = await fetch('/r/api/network2');
- const data = await response.json();
-
- setNetworkData({
- uploadSpeed: data.uploadSpeed,
- downloadSpeed: data.downloadSpeed,
- totalSent: data.totalSent,
- totalReceived: data.totalReceived
- });
-
- setChartData(prevData => {
- const newLabels = [...prevData.labels, new Date().toLocaleTimeString()];
- const newUploadData = [...prevData.datasets[0].data, data.uploadSpeed];
- const newDownloadData = [...prevData.datasets[1].data, data.downloadSpeed];
-
- // 保持最新的30个数据点
- if (newLabels.length > MAX_DATA_POINTS) {
- newLabels.shift();
- newUploadData.shift();
- newDownloadData.shift();
- }
-
- return {
- labels: newLabels,
- datasets: [
- {
- ...prevData.datasets[0],
- data: newUploadData
- },
- {
- ...prevData.datasets[1],
- data: newDownloadData
- }
- ]
- };
- });
- } catch (error) {
- console.error('获取网络数据失败:', error);
- }
- };
-
- // 每秒更新一次数据
- const interval = setInterval(fetchData, 1000);
- return () => clearInterval(interval);
- }, []);
-
- const chartOptions = {
- responsive: true,
- animation: {
- duration: 0
- },
- scales: {
- y: {
- beginAtZero: true
- }
- },
- plugins: {
- legend: {
- position: 'top'
- }
- }
- };
-
- return (
-
-
-
-
-
网络监控
-
-
-
上传: {networkData.uploadSpeed} KB/s
-
下载: {networkData.downloadSpeed} KB/s
-
-
-
总发送: {networkData.totalSent} GB
-
总接收: {networkData.totalReceived} GB
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/server/components/home/system.jsx b/server/components/home/system.jsx
deleted file mode 100644
index 0754bbb..0000000
--- a/server/components/home/system.jsx
+++ /dev/null
@@ -1,116 +0,0 @@
-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/api.js";
-
-export default function System() {
- const [systemInfo, setSystemInfo] = useState(null);
-
- useEffect(() => {
- async function fetchSystemInfo() {
- const response = await fetch(SYSTEM_BASE_URL);
- const data = await response.json();
- setSystemInfo(data);
- }
-
- const intervalId = setInterval(fetchSystemInfo, 5000); // 每隔5秒更新一次系统信息
-
- return () => clearInterval(intervalId); // 清除定时器,避免内存泄漏
- }, []);
-
- return (
-
-
- {/* 状态卡片 */ }
-
-
-
状态
-
-
-
-
-
-
CPU
-
{ systemInfo ? `( ${ systemInfo.cpuCoresUsed } / ${ systemInfo.totalCpuCores } ) 核` : "" }
-
-
-
-
-
-
内存
-
{systemInfo ? `${systemInfo.usedMemory} / ${systemInfo.totalMemory}` : ""}
-
-
-
-
-
-
磁盘使用
-
{systemInfo ? `${systemInfo.usedDisk} / ${systemInfo.totalDisk}` : ""}
-
-
-
-
-
-
- {/* 系统信息卡片 */ }
-
-
-
系统信息
-
主机名称: {systemInfo ? systemInfo.hostname : ""}
-
发行版本: {systemInfo ? systemInfo.distro : ""}
-
内核版本: {systemInfo ? systemInfo.kernelVersion : ""}
-
系统类型: {systemInfo ? systemInfo.arch : ""}
-
主机地址: {systemInfo ? systemInfo.ipAddress : ""}
-
运行时间: {systemInfo ? systemInfo.uptime : ""}
-
-
-
-
- );
-}
diff --git a/server/components/sidebar.jsx b/server/components/sidebar.jsx
deleted file mode 100644
index a1287d5..0000000
--- a/server/components/sidebar.jsx
+++ /dev/null
@@ -1,45 +0,0 @@
-"use client"
-import { useState } from "react";
-import { SIDEBAR_ITEMS } from "../constants/sidebar.js";
-import { useDrawer } from "../contexts/drawer-context.js";
-import { Content } from "./content.jsx";
-
-export default function Sidebar() {
- const { isDrawerOpen, toggleDrawer } = useDrawer();
-
- const [activeItem, setActiveItem] = useState("总控制台");
-
- // 定义当前主题状态
- const [theme, setTheme] = useState("light");
-
- // 切换主题的函数
- const toggleTheme = (newTheme) => {
- setTheme(newTheme); // 更新状态
- document.documentElement.setAttribute("data-theme", newTheme); // 更新主题属性
- };
-
- return (
-
- );
-}
diff --git a/server/components/toast.jsx b/server/components/toast.jsx
deleted file mode 100644
index 512fb87..0000000
--- a/server/components/toast.jsx
+++ /dev/null
@@ -1,9 +0,0 @@
-export default function Toast({ id }) {
- return (
-
- );
-};
diff --git a/server/constants/api.js b/server/constants/api.js
deleted file mode 100644
index be7f14a..0000000
--- a/server/constants/api.js
+++ /dev/null
@@ -1,11 +0,0 @@
-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`;
-
-export const GIT_VERSION_URL = `${ BASE_URL }/version`;
-
-export const GIT_COMMIT_URL = `${ BASE_URL }/commit`;
diff --git a/server/constants/redis.js b/server/constants/redis.js
deleted file mode 100644
index f0177ba..0000000
--- a/server/constants/redis.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export const REDIS_UPDATE_STATUS = "Yz:rconsole:update:status"
-
-export const REDIS_UPDATE_PATH = "Yz:rconsole:update:paths"
-
-export const REDIS_RESOLVE_CONTROLLER = "Yz:rconsole:resolve:controller"
diff --git a/server/constants/resolve.js b/server/constants/resolve.js
deleted file mode 100644
index 726a2a9..0000000
--- a/server/constants/resolve.js
+++ /dev/null
@@ -1,78 +0,0 @@
-export const GLOBAL_RESOLE_CONTROLLER = [
- {
- label: "哔哩哔哩",
- value: 1
- },
- {
- label: "抖音",
- value: 1
- },
- {
- label: "TikTok",
- value: 1
- },
- {
- label: "YouTube",
- value: 1
- },
- {
- label: "Acfun",
- value: 1
- },
- {
- label: "小红书",
- value: 1
- },
- {
- label: "波点",
- value: 1
- },
- {
- label: "网易云音乐",
- value: 1
- },
- {
- label: "通用(包含快手等)",
- value: 1
- },
- {
- label: "Twitter",
- value: 1
- },
- {
- label: "米游社",
- value: 1
- },
- {
- label: "微博",
- value: 1
- },
- {
- label: "微视",
- value: 1
- },
- {
- label: "zuiyou",
- value: 1
- },
- {
- label: "AM+Spotify",
- value: 1
- },
- {
- label: "扣扣音乐",
- value: 1
- },
- {
- label: "汽水音乐",
- value: 1
- },
- {
- label: "小飞机",
- value: 1
- },
- {
- label: "贴吧",
- value: 1
- }
-]
diff --git a/server/constants/sidebar.js b/server/constants/sidebar.js
deleted file mode 100644
index 57bf14b..0000000
--- a/server/constants/sidebar.js
+++ /dev/null
@@ -1,130 +0,0 @@
-import Bili from "../components/contents/bili.jsx";
-import Generic from "../components/contents/generic.jsx";
-import Home from "../components/contents/home.jsx";
-import Ncm from "../components/contents/ncm.jsx";
-import Tiktok from "../components/contents/tiktok.jsx";
-import Weekly from "../components/contents/weekly.jsx";
-import Youtube from "../components/contents/youtube.jsx";
-
-export const SIDEBAR_ITEMS = [
- {
- name: "总控制台",
- icon: ,
- theme: "light",
- component:
- },
- {
- name: "通用及杂项",
- icon: ,
- theme: "cupcake",
- component:
- },
- {
- name: "哔哩哔哩控制台",
- icon: ,
- theme: "valentine",
- component:
- },
- {
- name: "抖音控制台",
- icon: ,
- theme: "dark",
- component:
- },
- {
- name: "油管控制台",
- icon: ,
- theme: "dracula",
- component:
- },
- {
- name: "网易云控制台",
- icon: ,
- theme: "lofi",
- component:
- },
- {
- name: "周刊预览",
- icon: ,
- theme: "retro",
- component:
- }
-];
diff --git a/server/contexts/drawer-context.js b/server/contexts/drawer-context.js
deleted file mode 100644
index ced0fed..0000000
--- a/server/contexts/drawer-context.js
+++ /dev/null
@@ -1,22 +0,0 @@
-"use client"
-import { createContext, useContext, useState } from 'react';
-
-const DrawerContext = createContext();
-
-export const DrawerProvider = ({ children }) => {
- const [isDrawerOpen, setIsDrawerOpen] = useState(false);
-
- const toggleDrawer = () => {
- setIsDrawerOpen(prev => !prev);
- };
-
- return (
-
- {children}
-
- );
-};
-
-export const useDrawer = () => useContext(DrawerContext);
-
-
diff --git a/server/next.config.js b/server/next.config.js
deleted file mode 100644
index 2333c75..0000000
--- a/server/next.config.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export default {
- eslint: {
- ignoreDuringBuilds: true, // 构建时忽略 ESLint 错误
- },
-};
diff --git a/server/postcss.config.js b/server/postcss.config.js
deleted file mode 100644
index 28c1b6d..0000000
--- a/server/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// postcss.config.js
-export default {
- plugins: {
- tailwindcss: {},
- },
-};
diff --git a/server/styles/global.css b/server/styles/global.css
deleted file mode 100644
index 1f09233..0000000
--- a/server/styles/global.css
+++ /dev/null
@@ -1,41 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-/** 代码字体 */
-@font-face {
- font-family: "FZB";
- src: url("../../resources/font/FZB.ttf");
-}
-
-* {
- margin: 0;
- font-family: "FZB", serif;
- box-sizing: border-box;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
-}
-
-/* 自定义滚动条 */
-::-webkit-scrollbar {
- width: 8px;
- /* 滚动条宽度 */
-}
-
-::-webkit-scrollbar-track {
- background: #f1f1f1;
- /* 滚动条轨道背景色 */
-}
-
-::-webkit-scrollbar-thumb {
- background: #888;
- /* 滚动条滑块颜色 */
- border-radius: 4px;
- /* 滑块圆角 */
-}
-
-::-webkit-scrollbar-thumb:hover {
- background: #555;
- /* 滑块悬停时的颜色 */
-}
diff --git a/server/tailwind.config.js b/server/tailwind.config.js
deleted file mode 100644
index 34e338e..0000000
--- a/server/tailwind.config.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import daisyui from "daisyui"
-
-/** @type {import('tailwindcss').Config} */
-const config = {
- content: [
- "./app/**/*.{html,js,jsx}",
- "./components/**/*.{html,js,jsx}",
- "./pages/**/*.{html,js,jsx}",
- "./styles/**/*.{html,js,jsx}"
- ],
- theme: {
- extend: {},
- },
- darkMode: "class",
- plugins: [
- daisyui,
- ],
- daisyui: {
- themes: ["light", "dark", "valentine", "retro", "lofi", "dracula", "aqua", "cupcake"],
- },
-};
-
-export default config;
diff --git a/server/utils/redis.js b/server/utils/redis.js
deleted file mode 100644
index 3744815..0000000
--- a/server/utils/redis.js
+++ /dev/null
@@ -1,17 +0,0 @@
-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/server/utils/yamlHelper.js b/server/utils/yamlHelper.js
deleted file mode 100644
index c9abffe..0000000
--- a/server/utils/yamlHelper.js
+++ /dev/null
@@ -1,29 +0,0 @@
-export const readYamlConfig = async () => {
- try {
- const response = await fetch('/r/api/config');
- if (!response.ok) throw new Error('获取配置失败');
- return await response.json();
- } catch (error) {
- console.error('读取配置文件失败:', error);
- return null;
- }
-};
-
-export const updateYamlConfig = async (updates) => {
- try {
- const response = await fetch('/r/api/config', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(updates)
- });
-
- if (!response.ok) throw new Error('更新配置失败');
- const result = await response.json();
- return result.success;
- } catch (error) {
- console.error('更新配置文件失败:', error);
- return false;
- }
-};
\ No newline at end of file
diff --git a/utils/network.js b/utils/network.js
deleted file mode 100644
index d47defe..0000000
--- a/utils/network.js
+++ /dev/null
@@ -1,109 +0,0 @@
-import os from 'os';
-
-/**
- * 判断是否是公网地址
- * @param ip
- * @returns {boolean}
- */
-function isPublicIP(ip) {
- if (ip.includes(':')) {
- // IPv6 检测
- if (ip.startsWith('fe80') || ip.startsWith('fc00')) {
- return false; // 本地链路或私有 IPv6
- }
- return true; // 其他 IPv6 认为是公网
- } else {
- // IPv4 检测
- const parts = ip.split('.').map(Number);
- if (
- (parts[0] === 10) || // 10.0.0.0/8
- (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) || // 172.16.0.0/12
- (parts[0] === 192 && parts[1] === 168) // 192.168.0.0/16
- ) {
- return false; // 私有 IPv4
- }
- return true; // 其他 IPv4 认为是公网
- }
-}
-
-/**
- * 判断是否有公网 IPv6
- * @returns {boolean}
- */
-export function hasIPv6Only() {
- const interfaces = os.networkInterfaces();
- let hasPublicIPv4 = false;
- let hasPublicIPv6 = false;
-
- for (const iface of Object.values(interfaces)) {
- for (const config of iface) {
- if (!config.internal && isPublicIP(config.address)) {
- if (config.family === 'IPv4') {
- hasPublicIPv4 = true;
- }
- if (config.family === 'IPv6') {
- hasPublicIPv6 = true;
- }
- }
- }
- }
-
- if (hasPublicIPv6 && !hasPublicIPv4) {
- logger.info('[R插件][公网检测]服务器仅拥有一个公网IPv6地址');
- return true;
- } else if (hasPublicIPv4 && hasPublicIPv6) {
- logger.info('[R插件][公网检测]服务器同时拥有公共IPv4和IPv6地址');
- return false;
- } else if (hasPublicIPv4) {
- logger.info('[R插件][公网检测]服务器仅拥有一个公网IPv4地址');
- return false;
- } else {
- logger.info('[R插件][公网检测]服务器未配置公网IP地址');
- return false;
- }
-}
-
-/**
- * 获取所有公网IP地址
- * @returns {*[]}
- */
-export function getPublicIPs() {
- const interfaces = os.networkInterfaces();
- const publicIPs = [];
-
- for (const [name, iface] of Object.entries(interfaces)) {
- for (const config of iface) {
- if (!config.internal && isPublicIP(config.address)) {
- publicIPs.push({
- interface: name,
- address: config.address,
- family: config.family,
- });
- }
- }
- }
-
- return publicIPs;
-}
-
-/**
- * 构造内网、公网消息
- * @returns {`R插件可视化面板内网地址:${string}:4016`}
- */
-export function constructPublicIPsMsg() {
- const networkInterfaces = os.networkInterfaces();
- const ipAddress = Object.values(networkInterfaces)
- .flat()
- .filter(detail => detail.family === 'IPv4' && !detail.internal)[0].address;
- const publicIPs = getPublicIPs();
- let publicIPsStr = '';
- // 如果有公网地址
- if (publicIPs.length > 0) {
- publicIPsStr = `\n公网地址:${ getPublicIPs().map(item => {
- logger.info('[R插件][公网检测]公网IP地址', item.address);
- return `${ item.address }:4016\n`;
- }) }`;
- }
- publicIPsStr = `R插件可视化面板内网地址:${ ipAddress }:4016${ publicIPsStr }`;
- return publicIPsStr;
-}
diff --git a/utils/start-nextjs.js b/utils/start-nextjs.js
deleted file mode 100644
index 9bd37fb..0000000
--- a/utils/start-nextjs.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import { spawn } from 'child_process';
-import { hasIPv6Only } from "./network.js";
-
-logger.mark(`[R插件][WebUI], 父进程 PID: ${process.pid}`);
-
-let nextjsProcess = null;
-
-// 构建应用程序
-export const buildNextJs = () => {
- logger.info(logger.yellow('[R插件][WebUI],正在构建 Next.js 应用...'));
- return new Promise((resolve, reject) => {
- const buildProcess = spawn('pnpm', ['run', 'build'], {
- cwd: './plugins/rconsole-plugin/server',
- stdio: 'ignore',
- shell: true,
- });
-
- buildProcess.on('close', (code) => {
- if (code === 0) {
- logger.info(logger.yellow('[R插件][Next.js监测],构建完成。'));
- resolve();
- } else {
- logger.error(`[R插件][WebUI监测],构建失败,退出码:${code}`);
- reject(new Error('Build failed'));
- }
- });
- });
-};
-
-// 启动子进程运行 Next.js
-export const startNextJs = (mode = 'start') => {
- let script = mode === 'start' ? 'start' : 'dev';
-
- logger.info(logger.yellow(`[R插件][WebUI监测],启动 WebUI ${mode} 进程...`));
-
- // 判断是不是只有ipv6地址
- if (hasIPv6Only()) {
- script = 'start6';
- }
-
- nextjsProcess = spawn('pnpm', ['run', script], {
- cwd: './plugins/rconsole-plugin', // 指定工作目录
- stdio: 'ignore',
- shell: true,
- });
-
- // 子进程异常退出时捕获信号
- nextjsProcess.on('close', (code) => {
- logger.error(`[R插件][WebUI监测],WebUI 进程发生异常 ${code}`);
- nextjsProcess = null;
- });
-
- nextjsProcess.on('error', (err) => {
- logger.error(`[R插件][WebUI监测] 子进程错误: ${err.message}`);
- });
-};
-
-// 捕获父进程退出信号
-export const cleanup = () => {
- logger.info(logger.yellow('[R插件][WebUI监测] 父进程退出,终止子进程...'));
- if (nextjsProcess) {
- // 终止子进程
- nextjsProcess.kill();
- nextjsProcess = null;
- }
- process.exit();
-};
-
-// 绑定父进程的退出信号
-process.on('SIGINT', cleanup); // Ctrl+C 信号
-process.on('SIGTERM', cleanup); // kill 命令信号
-process.on('exit', cleanup); // 正常退出