Накидал базовое api

This commit is contained in:
Dhaverd 2025-12-30 15:00:52 +08:00
parent 6be4db0e72
commit cf2a49d92f
9 changed files with 184 additions and 12 deletions

View File

@ -24,11 +24,12 @@
"@nestjs/config": "^4.0.2",
"@nestjs/core": "^11.0.1",
"@nestjs/platform-express": "^11.0.1",
"@nestjs/typeorm": "^11.0.0",
"@nestjs/sequelize": "^11.0.1",
"mysql2": "^3.16.0",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"typeorm": "^0.3.28"
"sequelize": "^6.37.7",
"sequelize-typescript": "^2.1.6"
},
"devDependencies": {
"@eslint/eslintrc": "^3.2.0",
@ -39,6 +40,7 @@
"@types/express": "^5.0.0",
"@types/jest": "^30.0.0",
"@types/node": "^22.10.7",
"@types/sequelize": "^4.28.20",
"@types/supertest": "^6.0.2",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",

View File

@ -1,9 +1,9 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DataSource } from 'typeorm';
import { BlacklistModule } from './modules/blacklist/blacklist.module';
import { SequelizeModule } from '@nestjs/sequelize';
@Module({
imports: [
@ -11,23 +11,21 @@ import { DataSource } from 'typeorm';
envFilePath: ['.env.local', '.env'],
isGlobal: true,
}),
TypeOrmModule.forRoot({
type: 'mysql',
SequelizeModule.forRoot({
dialect: 'mysql',
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
entities: [],
synchronize: true,
autoLoadModels: true,
synchronize: false,
}),
BlacklistModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
constructor(
private dataSource: DataSource,
private configService: ConfigService,
) {}
constructor(private configService: ConfigService) {}
}

View File

@ -0,0 +1,44 @@
import { BadRequestException, Body, Controller, Get, Post, Query } from '@nestjs/common';
import { BlacklistService } from './blacklist.service';
import { BlacklistItemList } from './types/blacklistItemList';
import { BlacklistReport } from './models/blacklistReport.model';
import * as blacklistReport from './dto/blacklistReport';
@Controller('api/v1/blacklist')
export class BlacklistController {
constructor(private readonly blacklistService: BlacklistService) {
}
@Get('/health_check')
getHello(): string {
return this.blacklistService.getHealthCheck();
}
@Get('/all')
async getAllReports(): Promise<BlacklistItemList> {
return this.blacklistService.getAllRecords();
}
@Get('/by_link')
async getReportsByLink(
@Query('link') link: string,
): Promise<BlacklistItemList> {
return this.blacklistService.getRecordsByLink(link);
}
@Post('/create')
async createReport(
@Body()
blacklistReportDto: blacklistReport.BlacklistReportDto,
): Promise<BlacklistReport> {
if (!blacklistReportDto.steam_link) {
throw new BadRequestException('Steam link is missing', {
cause: new Error(),
description: 'Property steam_link is required',
});
}
return await this.blacklistService.createBlacklistRecord(
blacklistReportDto,
);
}
}

View File

@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { BlacklistController } from './blacklist.controller';
import { BlacklistService } from './blacklist.service';
import { BlacklistReport } from './models/blacklistReport.model';
import { SequelizeModule } from '@nestjs/sequelize';
@Module({
controllers: [BlacklistController],
providers: [BlacklistService],
imports: [SequelizeModule.forFeature([BlacklistReport])],
})
export class BlacklistModule {}

View File

@ -0,0 +1,68 @@
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { BlacklistReport } from './models/blacklistReport.model';
import { BlacklistItem } from './types/blacklistItem';
import { BlacklistItemList } from './types/blacklistItemList';
import { BlacklistReportDto } from './dto/blacklistReport';
@Injectable()
export class BlacklistService {
constructor(
@InjectModel(BlacklistReport)
private blacklistReportModel: typeof BlacklistReport,
) {}
getHealthCheck(): string {
return 'OK';
}
async getAllRecords(): Promise<BlacklistItemList> {
const allRecords = await this.blacklistReportModel.findAll({ raw: true });
return this.groupRecordsByLink(allRecords);
}
async getRecordsByLink(link: string): Promise<BlacklistItemList> {
const allRecords: BlacklistReport[] =
await this.blacklistReportModel.findAll({
raw: true,
where: { steam_link: link },
});
return this.groupRecordsByLink(allRecords);
}
groupRecordsByLink(records: BlacklistReport[]): BlacklistItemList {
const result: BlacklistItemList = {};
for (const record of records) {
if (result[record.steam_link]) {
const item: BlacklistItem = result[record.steam_link];
item.comments.push(record.comment);
item.toxic += Number(record.toxic);
item.cheater += Number(record.cheater);
item.afk += Number(record.afk);
item.useless += Number(record.useless);
item.griefer += Number(record.griefer);
result[record.steam_link] = item;
} else {
const item: BlacklistItem = {
link: record.steam_link,
comments: [],
toxic: Number(record.toxic),
cheater: Number(record.cheater),
afk: Number(record.afk),
useless: Number(record.useless),
griefer: Number(record.griefer),
};
item.comments.push(record.comment);
result[record.steam_link] = item;
}
}
return result;
}
async createBlacklistRecord(
blackListReportDto: BlacklistReportDto,
): Promise<BlacklistReport> {
const report = BlacklistReport.build(blackListReportDto);
return await report.save();
}
}

View File

@ -0,0 +1,9 @@
export type BlacklistReportDto = {
steam_link: string;
comment: string;
toxic: boolean;
cheater: boolean;
afk: boolean;
useless: boolean;
griefer: boolean;
};

View File

@ -0,0 +1,25 @@
import { Column, Model, Table } from 'sequelize-typescript';
@Table
export class BlacklistReport extends Model {
@Column
steam_link: string;
@Column
comment: string;
@Column({ defaultValue: false })
toxic: boolean;
@Column({ defaultValue: false })
cheater: boolean;
@Column({ defaultValue: false })
afk: boolean;
@Column({ defaultValue: false })
useless: boolean;
@Column({ defaultValue: false })
griefer: boolean;
}

View File

@ -0,0 +1,9 @@
export type BlacklistItem = {
link: string;
comments: Array<string>;
toxic: number;
cheater: number;
afk: number;
useless: number;
griefer: number;
};

View File

@ -0,0 +1,5 @@
import { BlacklistItem } from './blacklistItem';
export type BlacklistItemList = {
[index: string]: BlacklistItem;
};