diff --git a/src/adapter/commands/ranking.ts b/src/adapter/commands/ranking.ts new file mode 100644 index 0000000..33b96df --- /dev/null +++ b/src/adapter/commands/ranking.ts @@ -0,0 +1,42 @@ +import { Reply, ReplyType } from '../../usecase/types/reply'; +import { playerController } from '../queries/player'; + +export const commandRanking = async (args: string[]): Promise => { + if (args.length !== 2) { + return { + type: ReplyType.Error, + errorText: `Invalid Arguments: maxRange`, + }; + } + const maxRange = parseInt(args[1]); + if (isNaN(maxRange)) { + return { + type: ReplyType.Error, + errorText: `Error: maxRange is not a number`, + }; + } + if (maxRange < 1 || maxRange > 10) { + return { + type: ReplyType.Error, + errorText: `Error: maxRange must be between 1 and 10`, + }; + } + try { + const players = await playerController.readRanking(maxRange); + let replyText = ''; + players.forEach((player, index) => { + replyText += `${index + 1}. ${ + player.discordId ? player.discordId : player.playerName + }: ${player.currentRate}pt\n`; + }); + return { + type: ReplyType.Text, + contentText: replyText, + }; + } catch (error) { + return { + type: ReplyType.Error, + errorText: `${error}`, + }; + } +}; diff --git a/src/adapter/queries/player.ts b/src/adapter/queries/player.ts index 228f2a5..28e1e80 100644 --- a/src/adapter/queries/player.ts +++ b/src/adapter/queries/player.ts @@ -49,6 +49,20 @@ export class PlayerController implements IController { return parsePlayerList(result); } + async readRanking(maxCount: number): Promise { + const result = await this.pool + .query(`SELECT * FROM players ORDER BY current_rate DESC LIMIT $1`, [ + maxCount.toString(), + ]) + .catch((error) => { + throw error; + }); + if (result.length === 0) { + throw new Error(`Player Not Found`); + } + return parsePlayerList(result); + } + async readByDiscordOrName(id: string): Promise { const result = await this.pool .query(`SELECT * FROM players WHERE discord_id = $1`, [id]) diff --git a/src/infrastructure/discord.ts b/src/infrastructure/discord.ts index 6db32b4..0c0deb4 100644 --- a/src/infrastructure/discord.ts +++ b/src/infrastructure/discord.ts @@ -1,6 +1,7 @@ import { Client, GatewayIntentBits, Message, Partials } from 'discord.js'; import { commandLink } from '../adapter/commands/link'; import { commandPing } from '../adapter/commands/ping'; +import { commandRanking } from '../adapter/commands/ranking'; import { commandRate } from '../adapter/commands/rate'; import { commandRegister } from '../adapter/commands/register'; import { config } from '../config/config'; @@ -88,6 +89,15 @@ export const runDiscordBot = () => { message.reply(replyText); break; } + // ranking + case commands.ranking.name: { + if (!checkPermission(message, line, commands.ping.requirePermission)) + break; + const reply = await commandRanking(commandText); + const replyText = generateReply(reply, line); + message.reply(replyText); + break; + } // register case commands.register.name: { if ( diff --git a/src/usecase/types/commands.ts b/src/usecase/types/commands.ts index 27db5fe..af78911 100644 --- a/src/usecase/types/commands.ts +++ b/src/usecase/types/commands.ts @@ -6,6 +6,7 @@ export interface Command { export const enum CommandList { ping = 'ping', rate = 'rate', + ranking = 'ranking', register = 'register', link = 'link', } @@ -19,6 +20,10 @@ export const commands: Record = { name: 'rate', requirePermission: false, }, + ranking: { + name: 'ranking', + requirePermission: false, + }, register: { name: 'register', requirePermission: true,