Reformat code

This commit is contained in:
2021-01-12 14:15:33 +01:00
parent c514337fea
commit e3951d4793
14 changed files with 169 additions and 116 deletions

View File

@@ -1,3 +1,3 @@
export interface Predicate<T, O> {
process(input: T): O;
}
process(input: T): O;
}

View File

@@ -1,13 +1,13 @@
export class Sort {
public static descending = (a: number, b: number) => {
if (a < b) {
return 1;
}
if (a > b) {
return -1;
}
return 0;
public static descending = (a: number, b: number) => {
if (a < b) {
return 1;
}
}
if (a > b) {
return -1;
}
return 0;
};
}

View File

@@ -1,11 +1,10 @@
export class TimeUtil {
public static humanize = (seconds: number) => {
const d = Math.floor(seconds / (3600 * 24));
const h = Math.floor(seconds % (3600 * 24) / 3600);
const m = Math.floor(seconds % 3600 / 60);
const s = Math.floor(seconds % 60);
return `${d}d ${h}h ${m}m ${s}s`;
}
}
public static humanize = (seconds: number) => {
const d = Math.floor(seconds / (3600 * 24));
const h = Math.floor((seconds % (3600 * 24)) / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
return `${d}d ${h}h ${m}m ${s}s`;
};
}

View File

@@ -1,9 +1,17 @@
import { Controller, Get, HostParam, HttpException, HttpStatus, Param, Req } from '@nestjs/common';
import {
Controller,
Get,
HostParam,
HttpException,
HttpStatus,
Param,
Req,
} from '@nestjs/common';
import { AppService } from './app.service';
import { DatabaseService } from './database/database.service';
import logger from './logger/Logger';
import { TableEntry } from "./models/TableEntry";
import { SinusBotService } from "./services/sinusbot.service";
import { TableEntry } from './models/TableEntry';
import { SinusBotService } from './services/sinusbot.service';
import { UserStatsResponse } from './models/aliases';
@Controller()
@@ -11,7 +19,7 @@ export class AppController {
constructor(
private readonly appService: AppService,
private readonly sinusBotService: SinusBotService,
private readonly databaseService: DatabaseService
private readonly databaseService: DatabaseService,
) {}
@Get()
@@ -26,13 +34,16 @@ export class AppController {
@Get('/stats/season/:id')
async getStats(@Param('id') id: string): Promise<UserStatsResponse> {
return this.databaseService.fetchStats(id)
.then(value => { return value; })
return this.databaseService
.fetchStats(id)
.then(value => {
return value;
})
.catch(err => {
logger.error(`Error occured when fetching stats.`, err);
throw new HttpException(
'Error when fetching stats. Contact administrator or try again later!',
HttpStatus.INTERNAL_SERVER_ERROR
HttpStatus.INTERNAL_SERVER_ERROR,
);
});
}

View File

@@ -10,7 +10,13 @@ import { TimeTrackerPredicate } from './database/timetracking.predicate';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService, SinusBotService, DatabaseService, PrismaService, TimeTrackerPredicate],
providers: [
AppService,
SinusBotService,
DatabaseService,
PrismaService,
TimeTrackerPredicate,
],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer): any {

View File

@@ -1,6 +1,10 @@
import { Injectable } from '@nestjs/common';
import { TimeTrackerPredicate } from './timetracking.predicate';
import { SeasonInfo, TimeTrackerStats, UserStatsResponse } from '../models/aliases';
import {
SeasonInfo,
TimeTrackerStats,
UserStatsResponse,
} from '../models/aliases';
import { PrismaService } from '../prisma/prisma.service';
@Injectable()
@@ -16,8 +20,7 @@ export class DatabaseService {
constructor(
private readonly prismaClient: PrismaService,
private readonly timetrackerPredicate: TimeTrackerPredicate,
) {
}
) {}
public fetchSeasonInfos = async (seasonId: string): Promise<SeasonInfo> => {
let seasons;

View File

@@ -1,23 +1,26 @@
import { ranks, seasons, timetracker, user } from "@prisma/client";
import { Predicate } from "src/api/predicate";
import { Sort } from "src/api/sort";
import { TimeUtil } from "src/api/timeutil";
import { TableEntry } from "src/models/TableEntry";
import { ranks, seasons, timetracker, user } from '@prisma/client';
import { Predicate } from 'src/api/predicate';
import { Sort } from 'src/api/sort';
import { TimeUtil } from 'src/api/timeutil';
import { TableEntry } from 'src/models/TableEntry';
import { Injectable } from '@nestjs/common';
type UserStats = timetracker & { user: user, ranks: ranks; };
type UserStats = timetracker & { user: user; ranks: ranks };
export class TimeTrackerPredicate implements Predicate<UserStats[], TableEntry[]> {
process(input: UserStats[]): TableEntry[] {
return input.filter((userStats: UserStats) => userStats.time != null)
.map((userStats: UserStats) => {
return {
name: userStats.user.name,
rawTime: userStats.time,
onlineTime: TimeUtil.humanize(userStats.time),
rank: userStats.ranks.rank_name
}
})
.sort((lhs, rhs) => Sort.descending(lhs.rawTime, rhs.rawTime));
}
}
@Injectable()
export class TimeTrackerPredicate
implements Predicate<UserStats[], TableEntry[]> {
process(input: UserStats[]): TableEntry[] {
return input
.filter((userStats: UserStats) => userStats.time != null)
.map((userStats: UserStats) => {
return {
name: userStats.user.name,
rawTime: userStats.time,
onlineTime: TimeUtil.humanize(userStats.time),
rank: userStats.ranks.rank_name,
};
})
.sort((lhs, rhs) => Sort.descending(lhs.rawTime, rhs.rawTime));
}
}

View File

@@ -13,7 +13,7 @@ export class LoggerMiddleware implements NestMiddleware {
const contentLength = response.get('content-length');
logger.info(
`${method} ${url} ${statusCode} ${contentLength} - ${userAgent} ${ip}`
`${method} ${url} ${statusCode} ${contentLength} - ${userAgent} ${ip}`,
);
});

View File

@@ -1,11 +1,11 @@
import * as winston from 'winston';
const transports = {
console: new winston.transports.Console()
console: new winston.transports.Console(),
};
const logger = winston.createLogger({
transports: [transports.console]
})
transports: [transports.console],
});
export default logger;

View File

@@ -4,7 +4,7 @@ interface RequestError extends Error {
}
interface RequestErrorConstructor extends ErrorConstructor {
new(message?: string): RequestError;
new (message?: string): RequestError;
(message?: string): RequestError;
readonly prototype: RequestError;
}

View File

@@ -1,4 +1,5 @@
export interface TableEntry {
name: string;
onlineTime: string;
name: string;
rank: string;
onlineTime: string;
}

View File

@@ -1,6 +1,6 @@
import { ranks, seasons, timetracker, user } from '@prisma/client';
import { TableEntry } from './TableEntry';
export type TimeTrackerStats = timetracker & { user: user; ranks: ranks; }
export type SeasonInfo = seasons & { maxSeasonId: number }
export type UserStatsResponse = SeasonInfo & TableEntry[]
export type TimeTrackerStats = timetracker & { user: user; ranks: ranks };
export type SeasonInfo = seasons & { maxSeasonId: number };
export type UserStatsResponse = SeasonInfo & TableEntry[];

View File

@@ -11,4 +11,4 @@ export class PrismaService extends PrismaClient
async onModuleDestroy() {
await this.$disconnect();
}
}
}

View File

@@ -1,22 +1,22 @@
import { TableEntry } from "../models/TableEntry";
import { TunakillUser } from "../models/TunakillUser";
import {HttpException, HttpStatus, Injectable} from "@nestjs/common";
import {TunakillLogin} from "../models/TunakillLogin";
import { TableEntry } from '../models/TableEntry';
import { TunakillUser } from '../models/TunakillUser';
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { TunakillLogin } from '../models/TunakillLogin';
import fetch from 'node-fetch';
import logger from "../logger/Logger";
import logger from '../logger/Logger';
@Injectable()
export class SinusBotService {
private host = process.env.HOST
private host = process.env.HOST;
private credentials = {
username: process.env.SINUSBOT_USER,
password: process.env.SINUSBOT_PASSWORD
}
password: process.env.SINUSBOT_PASSWORD,
};
private botInfo = {
id: undefined,
instanceId: process.env.SINUSBOT_INSTANCEID
}
instanceId: process.env.SINUSBOT_INSTANCEID,
};
private botIdURL = `${this.host}/api/v1/botId`;
private tunaKillURL = `${this.host}/api/v1/bot/i/${this.botInfo.instanceId}/event/tunakill_rank_all_user`;
@@ -34,23 +34,30 @@ export class SinusBotService {
// if (this.bearer == null) {
logger.info(`Hey! I'm trying to get my Bearer token!`);
await this.login()
.then(token => this.bearer = token)
.then(token => (this.bearer = token))
.then(() => {
logger.debug(
`Seems like I have my Bearer token!
Looks like it's ${this.bearer == null ? 'undefined' : 'not undefined'}`
Looks like it's ${
this.bearer == null ? 'undefined' : 'not undefined'
}`,
);
});
// }
logger.info(`I try to fetch user data now! The URL is called ${this.tunaKillURL}`);
logger.info(
`I try to fetch user data now! The URL is called ${this.tunaKillURL}`,
);
return await fetch(this.tunaKillURL, this.requestConfig(null, this.bearer))
.then(res => this.checkStatus(res))
.then(res => res.json())
.then(data => this.consumeTunakillResponse(data))
.catch(error => {
logger.error(`I couldn't fetch user data.`, error);
throw this.createHttpException(HttpStatus.INTERNAL_SERVER_ERROR, error.message);
throw this.createHttpException(
HttpStatus.INTERNAL_SERVER_ERROR,
error.message,
);
});
}
@@ -61,12 +68,15 @@ export class SinusBotService {
if (this.botInfo.id == null) {
logger.debug(`I have to fetch a bot ID before I can continue!`);
await this.fetchDefaultBotId()
.then(defaultBotId => this.botInfo.id = defaultBotId)
.then(defaultBotId => (this.botInfo.id = defaultBotId))
.catch(error => {
logger.warn(`I couldn't retrieve SinusBot bot information. Login is likely to fail!`, error);
logger.warn(
`I couldn't retrieve SinusBot bot information. Login is likely to fail!`,
error,
);
throw this.createHttpException(
HttpStatus.NOT_FOUND,
`Could not fetch enough bot information for further requests.`
`Could not fetch enough bot information for further requests.`,
);
});
logger.info(`The bot ID now is ${this.botInfo.id}`);
@@ -75,20 +85,23 @@ export class SinusBotService {
const body: TunakillLogin = {
username: this.credentials.username,
password: this.credentials.password,
botId: this.botInfo.id
}
botId: this.botInfo.id,
};
logger.info(`Logging in for Bearer token!`)
logger.info(`Logging in for Bearer token!`);
return await fetch(this.loginURL, this.requestConfig(JSON.stringify(body)))
.then(res => this.checkStatus(res))
.then(res => res.json())
.then(data => data.token)
.catch(error => {
logger.error(`Oh oh! Something went wrong while fetching Bearer token.`, error);
logger.error(
`Oh oh! Something went wrong while fetching Bearer token.`,
error,
);
throw this.createHttpException(
HttpStatus.UNAUTHORIZED,
`Fetching Bearer token for Sinusbot failed.
Please refresh page or try again later!`
Please refresh page or try again later!`,
);
});
}
@@ -110,39 +123,56 @@ export class SinusBotService {
throw Error('Response from SinusBot does not have any data to parse.');
}
return response
// TODO: Remove hardcoded username filter for bots.
.filter((user: TunakillUser) => user.name !== "Server Query Admin" && user.name !== "DJ Inshalla")
return (
response
// TODO: Remove hardcoded username filter for bots.
.filter(
(user: TunakillUser) =>
user.name !== 'Server Query Admin' && user.name !== 'DJ Inshalla',
)
.filter((user: TunakillUser) => user.time != null)
.map((user: TunakillUser) => {
return {
name: user.name,
rawTime: user.time,
onlineTime: this.humanizeTime(user.time)
};
})
.sort((a: any, b: any) => this.sortByDescendingTime(a.rawTime, b.rawTime));
.filter((user: TunakillUser) => user.time != null)
.map((user: TunakillUser) => {
return {
name: user.name,
rawTime: user.time,
onlineTime: this.humanizeTime(user.time),
};
})
.sort((a: any, b: any) =>
this.sortByDescendingTime(a.rawTime, b.rawTime),
)
);
}
private requestConfig = (body?: string, bearerToken?: string, requestType: string = 'POST'): RequestInit => {
private requestConfig = (
body?: string,
bearerToken?: string,
requestType: string = 'POST',
): RequestInit => {
return {
method: requestType,
body: body,
headers: {
'Accept': '*/*',
Accept: '*/*',
'Content-Type': 'application/json',
'User-Agent': 'HumeniusTSRankingBackend/0.0.2',
'Authorization': `Bearer ${bearerToken}`
}
Authorization: `Bearer ${bearerToken}`,
},
};
}
};
private createHttpException = (statusCode: HttpStatus, message?: string): HttpException => {
return new HttpException({
status: statusCode,
error: message
}, statusCode);
}
private createHttpException = (
statusCode: HttpStatus,
message?: string,
): HttpException => {
return new HttpException(
{
status: statusCode,
error: message,
},
statusCode,
);
};
private checkStatus = response => {
if (!response.ok) {
@@ -151,7 +181,7 @@ export class SinusBotService {
throw err;
}
return response;
}
};
private sortByDescendingTime = (a: number, b: number) => {
if (a < b) {
@@ -163,16 +193,16 @@ export class SinusBotService {
}
return 0;
}
};
private humanizeTime = (seconds: number) => {
const d = Math.floor(seconds / (3600 * 24));
const h = Math.floor(seconds % (3600 * 24) / 3600);
const m = Math.floor(seconds % 3600 / 60);
const h = Math.floor((seconds % (3600 * 24)) / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
return `${d}d ${h}h ${m}m ${s}s`;
}
};
private static logResponse(res: any) {
logger.debug(res);