diff --git a/package.json b/package.json index 99f066d..851aab1 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/app.module.ts b/src/app.module.ts index 8b0b7ef..3f4bd98 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -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) {} } diff --git a/src/modules/blacklist/blacklist.controller.ts b/src/modules/blacklist/blacklist.controller.ts new file mode 100644 index 0000000..93fd38f --- /dev/null +++ b/src/modules/blacklist/blacklist.controller.ts @@ -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 { + return this.blacklistService.getAllRecords(); + } + + @Get('/by_link') + async getReportsByLink( + @Query('link') link: string, + ): Promise { + return this.blacklistService.getRecordsByLink(link); + } + + @Post('/create') + async createReport( + @Body() + blacklistReportDto: blacklistReport.BlacklistReportDto, + ): Promise { + 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, + ); + } +} diff --git a/src/modules/blacklist/blacklist.module.ts b/src/modules/blacklist/blacklist.module.ts new file mode 100644 index 0000000..2c8a6c0 --- /dev/null +++ b/src/modules/blacklist/blacklist.module.ts @@ -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 {} diff --git a/src/modules/blacklist/blacklist.service.ts b/src/modules/blacklist/blacklist.service.ts new file mode 100644 index 0000000..88cbbdf --- /dev/null +++ b/src/modules/blacklist/blacklist.service.ts @@ -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 { + const allRecords = await this.blacklistReportModel.findAll({ raw: true }); + return this.groupRecordsByLink(allRecords); + } + + async getRecordsByLink(link: string): Promise { + 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 { + const report = BlacklistReport.build(blackListReportDto); + return await report.save(); + } +} diff --git a/src/modules/blacklist/dto/blacklistReport.ts b/src/modules/blacklist/dto/blacklistReport.ts new file mode 100644 index 0000000..a8bf526 --- /dev/null +++ b/src/modules/blacklist/dto/blacklistReport.ts @@ -0,0 +1,9 @@ +export type BlacklistReportDto = { + steam_link: string; + comment: string; + toxic: boolean; + cheater: boolean; + afk: boolean; + useless: boolean; + griefer: boolean; +}; diff --git a/src/modules/blacklist/models/blacklistReport.model.ts b/src/modules/blacklist/models/blacklistReport.model.ts new file mode 100644 index 0000000..3a12fea --- /dev/null +++ b/src/modules/blacklist/models/blacklistReport.model.ts @@ -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; +} diff --git a/src/modules/blacklist/types/blacklistItem.ts b/src/modules/blacklist/types/blacklistItem.ts new file mode 100644 index 0000000..4cab007 --- /dev/null +++ b/src/modules/blacklist/types/blacklistItem.ts @@ -0,0 +1,9 @@ +export type BlacklistItem = { + link: string; + comments: Array; + toxic: number; + cheater: number; + afk: number; + useless: number; + griefer: number; +}; diff --git a/src/modules/blacklist/types/blacklistItemList.ts b/src/modules/blacklist/types/blacklistItemList.ts new file mode 100644 index 0000000..76e9c70 --- /dev/null +++ b/src/modules/blacklist/types/blacklistItemList.ts @@ -0,0 +1,5 @@ +import { BlacklistItem } from './blacklistItem'; + +export type BlacklistItemList = { + [index: string]: BlacklistItem; +};