添加部分服务

This commit is contained in:
Jerry 2025-08-24 22:47:47 +08:00
parent 120bf912f1
commit ccda3ec271
12 changed files with 151 additions and 17 deletions

View File

@ -24,7 +24,7 @@
"@nestjs/platform-ws": "^11.1.6",
"@nestjs/swagger": "^11.2.0",
"@nestjs/websockets": "^11.1.6",
"axios": "^1.10.0",
"axios": "1.11.0",
"ioredis": "^5.6.1",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",

16
pnpm-lock.yaml generated
View File

@ -10,7 +10,7 @@ importers:
dependencies:
'@nestjs/axios':
specifier: ^4.0.1
version: 4.0.1(@nestjs/common@11.1.5(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.10.0)(rxjs@7.8.2)
version: 4.0.1(@nestjs/common@11.1.5(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.11.0)(rxjs@7.8.2)
'@nestjs/common':
specifier: ^11.0.1
version: 11.1.5(reflect-metadata@0.2.2)(rxjs@7.8.2)
@ -36,8 +36,8 @@ importers:
specifier: ^11.1.6
version: 11.1.6(@nestjs/common@11.1.5(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.5)(@nestjs/platform-socket.io@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2)
axios:
specifier: ^1.10.0
version: 1.10.0
specifier: 1.11.0
version: 1.11.0
ioredis:
specifier: ^5.6.1
version: 5.6.1
@ -1437,8 +1437,8 @@ packages:
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
axios@1.10.0:
resolution: {integrity: sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==}
axios@1.11.0:
resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==}
b4a@1.6.7:
resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==}
@ -4432,10 +4432,10 @@ snapshots:
'@napi-rs/nice-win32-x64-msvc': 1.0.4
optional: true
'@nestjs/axios@4.0.1(@nestjs/common@11.1.5(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.10.0)(rxjs@7.8.2)':
'@nestjs/axios@4.0.1(@nestjs/common@11.1.5(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.11.0)(rxjs@7.8.2)':
dependencies:
'@nestjs/common': 11.1.5(reflect-metadata@0.2.2)(rxjs@7.8.2)
axios: 1.10.0
axios: 1.11.0
rxjs: 7.8.2
'@nestjs/cli@11.0.7(@swc/cli@0.6.0(@swc/core@1.13.1)(chokidar@4.0.3))(@swc/core@1.13.1)(@types/node@22.16.5)':
@ -5191,7 +5191,7 @@ snapshots:
asynckit@0.4.0: {}
axios@1.10.0:
axios@1.11.0:
dependencies:
follow-redirects: 1.15.9
form-data: 4.0.4

View File

@ -22,7 +22,7 @@ export class ResponseInterceptor<T>
map((data) => ({
success: true,
data,
message: '操作成功',
message: '欢迎使用晶灵核心 | Welcome to use crystelf-core',
})),
);
}

View File

@ -19,7 +19,7 @@ export class AppConfigService implements OnModuleInit {
* @param key
* @param defaultValue
*/
get<T = string>(key: string, defaultValue?: T): T | undefined {
public get<T = string>(key: string, defaultValue?: T): T | undefined {
const value = this.nestConfigService.get<T>(key);
if (value === undefined || value === null) {
if (defaultValue !== undefined) {

View File

@ -2,7 +2,6 @@ import { Inject, Injectable, Logger } from '@nestjs/common';
import * as path from 'path';
import * as fs from 'fs';
import { PathService } from '../path/path.service';
import { AutoUpdateModule } from '../auto-update/auto-update.module';
import { AutoUpdateService } from '../auto-update/auto-update.service';
import * as process from 'node:process';

View File

@ -1,7 +1,9 @@
import { Module } from '@nestjs/common';
import { ToolsService } from './tools.service';
import { AppConfigModule } from '../../config/config.module';
@Module({
imports: [AppConfigModule],
providers: [ToolsService],
exports: [ToolsService],
})

View File

@ -1,10 +1,19 @@
import { Injectable, Logger } from '@nestjs/common';
import {
Inject,
Injectable,
Logger,
UnauthorizedException,
} from '@nestjs/common';
import { RetryOptions } from './retry-options.interface';
import { AppConfigService } from '../../config/config.service';
@Injectable()
export class ToolsService {
private readonly logger = new Logger(ToolsService.name);
constructor(
@Inject(AppConfigService)
private readonly config: AppConfigService,
) {}
/**
*
* @param operation
@ -48,4 +57,26 @@ export class ToolsService {
getRandomDelay(min: number, max: number): number {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
/**
* token
* @param token token
*/
checkToken(token: string): boolean {
const expected = this.config.get<string>('TOKEN');
if (!expected) {
this.logger.error('环境变量 TOKEN 未配置,无法进行验证!');
throw new UnauthorizedException('系统配置错误,缺少 TOKEN');
}
return token === expected;
}
/**
* token
* @param token token
*/
tokenCheckFailed(token: string): never {
this.logger.warn(`有个小可爱使用了错误的 token: ${JSON.stringify(token)}`);
throw new UnauthorizedException('token 验证失败..');
}
}

View File

@ -1,11 +1,10 @@
import { Injectable, Logger } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { AuthenticatedSocket } from '../../../types/ws/ws.interface';
import { IMessageHandler } from '../../../types/ws/ws.handlers.interface';
@Injectable()
export class PongHandler implements IMessageHandler {
type = 'pong';
private readonly logger = new Logger(PongHandler.name);
async handle(socket: AuthenticatedSocket, msg: any) {
//this.logger.debug(`收到 pong 消息: ${JSON.stringify(msg)}`);

View File

@ -3,7 +3,6 @@ import { WsTools } from './ws.tools';
import { WsClientManager } from './ws-client.manager';
import { IMessageHandler } from '../../types/ws/ws.handlers.interface';
import { AuthenticatedSocket } from '../../types/ws/ws.interface';
import { TestHandler } from './handlers/test.handler';
@Injectable()
export class WsMessageHandler {

View File

@ -0,0 +1,58 @@
import {
Controller,
Post,
Body,
UnauthorizedException,
Inject,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBody } from '@nestjs/swagger';
import { SystemWebService } from './system.service';
import { ToolsService } from '../../core/tools/tools.service';
class TokenDto {
token: string;
}
@ApiTags('System')
@Controller('system')
export class SystemController {
constructor(
@Inject(SystemWebService)
private readonly systemService: SystemWebService,
@Inject(ToolsService)
private readonly toolService: ToolsService,
) {}
/**
*
*/
@Post('restart')
@ApiOperation({
summary: '系统重启',
description: '传入正确的 token 后,核心将执行重启。',
})
@ApiBody({ type: TokenDto })
async systemRestart(@Body() body: TokenDto): Promise<string> {
if (!this.toolService.checkToken(body.token)) {
throw new UnauthorizedException('Token 无效');
}
await this.systemService.systemRestart();
return '核心正在重启..';
}
/**
*
*/
@Post('getRestartTime')
@ApiOperation({
summary: '获取重启所需时间',
description: '传入正确的 token返回上次核心重启的耗时',
})
@ApiBody({ type: TokenDto })
async getRestartTime(@Body() body: TokenDto): Promise<string> {
if (!this.toolService.checkToken(body.token)) {
throw new UnauthorizedException('Token 无效');
}
return await this.systemService.getRestartTime();
}
}

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { SystemController } from './system.controller';
import { SystemWebService } from './system.service';
import { ToolsModule } from '../../core/tools/tools.module';
import { PathModule } from '../../core/path/path.module';
@Module({
imports: [ToolsModule, SystemModule, PathModule],
controllers: [SystemController],
providers: [SystemWebService],
})
export class SystemModule {}

View File

@ -0,0 +1,34 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import fs from 'fs/promises';
import path from 'path';
import { PathService } from '../../core/path/path.service';
import { SystemService } from 'src/core/system/system.service';
@Injectable()
export class SystemWebService {
private readonly logger = new Logger(SystemWebService.name);
@Inject(SystemService)
private readonly system: SystemService;
@Inject(PathService)
private readonly pathService: PathService;
/**
*
*/
async systemRestart(): Promise<void> {
this.logger.debug(`有个小可爱正在请求重启核心..`);
await this.system.restart();
}
/**
*
*/
async getRestartTime(): Promise<string> {
this.logger.debug(`有个小可爱想知道核心重启花了多久..`);
const restartTimePath = path.join(
this.pathService.get('temp'),
'restart_time',
);
return await fs.readFile(restartTimePath, 'utf8');
}
}