diff --git a/dist/api.js b/dist/api.js index a9be464..dc635cb 100644 --- a/dist/api.js +++ b/dist/api.js @@ -38,9 +38,11 @@ const https_1 = __importDefault(require("https")); //while names cant have spaces, the name slot in ogtitle could be shown as "No Player Name" which has spaces const uniteApiRegex = { //$1 = name, $2 = id - ogtitle: /Unite API - ([\w\d ]+) \((.*)\)/, + ogtitle: /unite api - ([\w\d ]+) \((.*)\)/i, //$1 = level, $2 = rank, $3 = elo, $4 = battles, $5 = wins, $6 = win rate - ogdescription: /Pokémon Unite : Lv.(\d+) (\w+) \((\d+)\)\n Battles : (\d+)\n Wins : (\d+)\n Win Rate : (\d+)%/, + ogdescription: /pokémon unite : lv\.(\d+) (\w+) \((\d+)\)\n battles : (\d+)\n Wins : (\d+)\n win rate : (\d+)%/i, + //for non-masters (no elo) + //ogdescription: /pokémon unite : lv\.(\d+) (\w+): class (\d+) *\n battles : (\d+) *\n wins : (\d+) *\n win rate : (\d+)%/i, }; /* og:title @@ -152,12 +154,12 @@ exports.getPlayer = getPlayer; function getPlayerInteraction(interaction) { return __awaiter(this, void 0, void 0, function* () { let username = interaction.options.getString('username', true); - interaction.deferReply(); + yield interaction.deferReply(); let data = yield getPlayer(username); if (data === null) - yield interaction.reply('Unable to find user'); + yield interaction.editReply('Unable to find user'); else - yield interaction.reply('```\n' + JSON.stringify(data, null, 2) + '\n```'); + yield interaction.editReply('```\n' + JSON.stringify(data, null, 2) + '\n```'); }); } exports.getPlayerInteraction = getPlayerInteraction; diff --git a/dist/discord.js b/dist/discord.js index 03cb6d0..f86ad58 100644 --- a/dist/discord.js +++ b/dist/discord.js @@ -15,7 +15,7 @@ const v9_1 = require("discord-api-types/v9"); const commands = [ { name: 'queue', - description: 'creates a queue', + description: 'create a queue', options: [ { type: 4, @@ -27,24 +27,28 @@ const commands = [ }, { name: 'join', - description: 'joins the active queue' + description: 'join the active queue' + }, + { + name: 'leave', + description: 'leave the active queue' }, { name: 'ready', - description: 'readys the queue and displays team info' + description: 'ready the queue and display team info' }, { name: 'queueinfo', - description: 'gets info of the current queue' + description: 'get info of the current queue' }, { name: 'elo', - description: 'displays your elo information', + description: 'display elo information', options: [ { type: 3, name: 'username', - description: 'your in game name', + description: 'in game name', required: true } ] diff --git a/dist/index.js b/dist/index.js index 2dc5c99..9cab9ec 100644 --- a/dist/index.js +++ b/dist/index.js @@ -52,8 +52,10 @@ CLIENT.on('interactionCreate', (interaction) => __awaiter(void 0, void 0, void 0 yield (0, queue_1.createQueue)(interaction); else if (interaction.commandName === 'join') yield (0, queue_1.joinQueue)(interaction); - //else if (interaction.commandName === 'ready') - // await readyQueue(interaction); + else if (interaction.commandName === 'leave') + yield (0, queue_1.leaveQueue)(interaction); + else if (interaction.commandName === 'ready') + yield (0, queue_1.readyQueue)(interaction); else if (interaction.commandName === 'queueinfo') yield (0, queue_1.queueInfo)(interaction); else if (interaction.commandName === 'elo') diff --git a/dist/queue.js b/dist/queue.js index dac7532..111d706 100644 --- a/dist/queue.js +++ b/dist/queue.js @@ -9,8 +9,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.queueInfo = exports.joinQueue = exports.createQueue = void 0; +exports.queueInfo = exports.readyQueue = exports.leaveQueue = exports.joinQueue = exports.createQueue = void 0; const discord_js_1 = require("discord.js"); +const util_1 = require("./util"); //maps ChannelID to QueueInfo const QUEUE = new Map(); function createQueue(interaction) { @@ -23,15 +24,18 @@ function createQueue(interaction) { } let channelId = interaction.channelId; if (QUEUE.has(channelId)) { - yield interaction.reply('There is already an active queue in this channel, type `/join` to join'); + yield interaction.reply('There is already an active queue in this channel, type `/join` to join'); //and you are already in it return; } + let teamsize = interaction.options.getInteger('teamsize', true); QUEUE.set(channelId, { - players: [], + players: [ + member + ], initiator: member, - teamsize: interaction.options.getInteger('teamsize', true) + teamsize: teamsize }); - yield interaction.reply('Queue has been created, type `/join` to join'); + yield interaction.reply(`Queue for teams of ${teamsize} has been created, and you have joined`); }); } exports.createQueue = createQueue; @@ -49,12 +53,79 @@ function joinQueue(interaction) { yield interaction.reply('There is not an active queue in this channel, type `/queue` to create one'); return; } + if (info.players.map(m => m.id).includes(member.id)) { + yield interaction.reply('You are already in the active queue'); + return; + } + console.log(JSON.stringify(member.id)); + console.log(JSON.stringify(info.players.map(m => m.id))); info.players.push(member); QUEUE.set(channelId, info); yield interaction.reply('Joined the queue'); }); } exports.joinQueue = joinQueue; +function leaveQueue(interaction) { + return __awaiter(this, void 0, void 0, function* () { + console.log('COMMAND leaveQueue'); + let member = interaction.member; + if (!(member instanceof discord_js_1.GuildMember)) { + yield interaction.reply('Unable to retrieve guild member information, please try again'); + return; + } + let channelId = interaction.channelId; + let info = QUEUE.get(channelId); + if (!info) { + yield interaction.reply('There is not an active queue in this channel, type `/queue` to create one'); + return; + } + if (!info.players.map(m => m.id).includes(member.id)) { + yield interaction.reply('You aren\'t in the active queue'); + return; + } + info.players.splice(info.players.indexOf(member), 1); + QUEUE.set(channelId, info); + yield interaction.reply('Left the queue'); + }); +} +exports.leaveQueue = leaveQueue; +function readyQueue(interaction) { + return __awaiter(this, void 0, void 0, function* () { + console.log('COMMAND readyQueue'); + let member = interaction.member; + if (!(member instanceof discord_js_1.GuildMember)) { + yield interaction.reply('Unable to retrieve guild member information, please try again'); + return; + } + let channelId = interaction.channelId; + let info = QUEUE.get(channelId); + if (!info) { + yield interaction.reply('There is no active queue in this channel, type `/queue` to create one'); //and you are already in it + return; + } + let { initiator } = info; + if (member.id !== initiator.id) { + yield interaction.reply('Only the queue initiator can ready the queue'); + return; + } + QUEUE.delete(channelId); + if (info.players.filter(m => m.id !== initiator.id).length === 0) { + yield interaction.reply('Nobody signed up for the queue, the queue has been reset'); + return; + } + let playerlist = (0, util_1.shuffle)(info.players), teams = []; + for (let i = 0; i < playerlist.length; i += info.teamsize) + teams.push(playerlist.slice(i, i + info.teamsize)); + let teamsStr = []; + teams.forEach((team, i) => { + let str = [`Team ${i + 1}`]; + team.forEach(m => str.push(` ${m.user.tag}`)); + teamsStr.push(str.join('\n')); + }); + yield interaction.reply('```\n' + teamsStr.join('\n\n') + '\n```'); + }); +} +exports.readyQueue = readyQueue; function queueInfo(interaction) { return __awaiter(this, void 0, void 0, function* () { console.log('COMMAND queueInfo'); diff --git a/dist/util.js b/dist/util.js new file mode 100644 index 0000000..9ccfa56 --- /dev/null +++ b/dist/util.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.shuffle = void 0; +/** + * shuffles an array + * https://stackoverflow.com/a/2450976/2856416 + * @param array an array + * @returns an array but shuffled + */ +function shuffle(array) { + let currentIndex = array.length, randomIndex; + // While there remain elements to shuffle... + while (currentIndex != 0) { + // Pick a remaining element... + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex--; + // And swap it with the current element. + [array[currentIndex], array[randomIndex]] = [ + array[randomIndex], array[currentIndex] + ]; + } + return array; +} +exports.shuffle = shuffle; diff --git a/src/api.ts b/src/api.ts index 058fc8d..56020ab 100644 --- a/src/api.ts +++ b/src/api.ts @@ -7,9 +7,11 @@ import http from 'https'; //while names cant have spaces, the name slot in ogtitle could be shown as "No Player Name" which has spaces const uniteApiRegex = { //$1 = name, $2 = id - ogtitle: /Unite API - ([\w\d ]+) \((.*)\)/, + ogtitle: /unite api - ([\w\d ]+) \((.*)\)/i, //$1 = level, $2 = rank, $3 = elo, $4 = battles, $5 = wins, $6 = win rate - ogdescription: /Pokémon Unite : Lv.(\d+) (\w+) \((\d+)\)\n Battles : (\d+)\n Wins : (\d+)\n Win Rate : (\d+)%/, + ogdescription: /pokémon unite : lv\.(\d+) (\w+) \((\d+)\)\n battles : (\d+)\n Wins : (\d+)\n win rate : (\d+)%/i, + //for non-masters (no elo) + //ogdescription: /pokémon unite : lv\.(\d+) (\w+): class (\d+) *\n battles : (\d+) *\n wins : (\d+) *\n win rate : (\d+)%/i, } type uniteApiData = { @@ -151,13 +153,13 @@ export async function getPlayer(name: string): Promise { export async function getPlayerInteraction(interaction: CommandInteraction): Promise { let username = interaction.options.getString('username', true); - interaction.deferReply(); + await interaction.deferReply(); let data = await getPlayer(username); if (data === null) - await interaction.reply('Unable to find user'); + await interaction.editReply('Unable to find user'); else - await interaction.reply('```\n'+JSON.stringify(data, null, 2)+'\n```'); + await interaction.editReply('```\n'+JSON.stringify(data, null, 2)+'\n```'); } //await getPlayer('IanWhysp') \ No newline at end of file diff --git a/src/discord.ts b/src/discord.ts index 287d5cc..4112671 100644 --- a/src/discord.ts +++ b/src/discord.ts @@ -4,7 +4,7 @@ import { Routes } from 'discord-api-types/v9'; const commands = [ { name: 'queue', - description: 'creates a queue', + description: 'create a queue', options: [ { type: 4, //INTEGER @@ -16,24 +16,28 @@ const commands = [ }, { name: 'join', - description: 'joins the active queue' + description: 'join the active queue' + }, + { + name: 'leave', + description: 'leave the active queue' }, { name: 'ready', - description: 'readys the queue and displays team info' + description: 'ready the queue and display team info' }, { name: 'queueinfo', - description: 'gets info of the current queue' + description: 'get info of the current queue' }, { name: 'elo', - description: 'displays your elo information', + description: 'display elo information', options: [ { type: 3, //STRING name: 'username', - description: 'your in game name', + description: 'in game name', required: true } ] diff --git a/src/index.ts b/src/index.ts index dca9970..8d4ceaf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import { Client, Intents } from 'discord.js'; import * as fs from 'fs'; import { getPlayerInteraction } from './api'; import { registerCommands } from './discord'; -import { createQueue, joinQueue, queueInfo } from './queue'; +import { createQueue, joinQueue, leaveQueue, queueInfo, readyQueue } from './queue'; const CLIENT = new Client({ intents: [Intents.FLAGS.GUILDS] }); console.log(new Date().toISOString()+'\n\n'); @@ -28,8 +28,10 @@ CLIENT.on('interactionCreate', async interaction => { await createQueue(interaction); else if (interaction.commandName === 'join') await joinQueue(interaction); - //else if (interaction.commandName === 'ready') - // await readyQueue(interaction); + else if (interaction.commandName === 'leave') + await leaveQueue(interaction); + else if (interaction.commandName === 'ready') + await readyQueue(interaction); else if (interaction.commandName === 'queueinfo') await queueInfo(interaction); else if (interaction.commandName === 'elo') diff --git a/src/queue.ts b/src/queue.ts index a9b5781..a279e6f 100644 --- a/src/queue.ts +++ b/src/queue.ts @@ -1,4 +1,5 @@ import { CommandInteraction, GuildMember } from "discord.js"; +import { shuffle } from "./util"; type queueInfo = { players: GuildMember[], @@ -23,17 +24,21 @@ export async function createQueue(interaction: CommandInteraction) { let channelId = interaction.channelId; if (QUEUE.has(channelId)) { - await interaction.reply('There is already an active queue in this channel, type `/join` to join'); + await interaction.reply('There is already an active queue in this channel, type `/join` to join'); //and you are already in it return; } + let teamsize = interaction.options.getInteger('teamsize', true); + QUEUE.set(channelId, { - players: [], + players: [ + member + ], initiator: member, - teamsize: interaction.options.getInteger('teamsize', true) + teamsize: teamsize }); - await interaction.reply('Queue has been created, type `/join` to join'); + await interaction.reply(`Queue for teams of ${teamsize} has been created, and you have joined`); } @@ -57,6 +62,14 @@ export async function joinQueue(interaction: CommandInteraction) { return; } + if (info.players.map(m=>m.id).includes(member.id)) { + await interaction.reply('You are already in the active queue'); + return; + } + + console.log(JSON.stringify(member.id)) + console.log(JSON.stringify(info.players.map(m=>m.id))) + info.players.push(member); QUEUE.set(channelId, info); @@ -65,6 +78,93 @@ export async function joinQueue(interaction: CommandInteraction) { } +export async function leaveQueue(interaction: CommandInteraction) { + + console.log('COMMAND leaveQueue') + + let member = interaction.member; + + if (!(member instanceof GuildMember)) { + await interaction.reply('Unable to retrieve guild member information, please try again'); + return; + } + + let channelId = interaction.channelId; + + let info = QUEUE.get(channelId); + + if (!info) { + await interaction.reply('There is not an active queue in this channel, type `/queue` to create one'); + return; + } + + if (!info.players.map(m=>m.id).includes(member.id)) { + await interaction.reply('You aren\'t in the active queue'); + return; + } + + info.players.splice(info.players.indexOf(member), 1); + + QUEUE.set(channelId, info); + + await interaction.reply('Left the queue'); + +} + +export async function readyQueue(interaction: CommandInteraction) { + + console.log('COMMAND readyQueue'); + + let member = interaction.member; + + if (!(member instanceof GuildMember)) { + await interaction.reply('Unable to retrieve guild member information, please try again'); + return; + } + + let channelId = interaction.channelId; + + let info = QUEUE.get(channelId); + + if (!info) { + await interaction.reply('There is no active queue in this channel, type `/queue` to create one'); //and you are already in it + return; + } + + let {initiator} = info; + + if (member.id !== initiator.id) { + await interaction.reply('Only the queue initiator can ready the queue'); + return; + } + + QUEUE.delete(channelId); + + if (info.players.filter(m => m.id !== initiator.id).length === 0) { + await interaction.reply('Nobody signed up for the queue, the queue has been reset'); + return; + } + + let playerlist: GuildMember[] = shuffle(info.players), + teams: GuildMember[][] = []; + + for (let i = 0; i < playerlist.length; i+= info.teamsize) + teams.push(playerlist.slice(i, i+info.teamsize)); + + let teamsStr: string[] = []; + + teams.forEach((team, i) => { + let str = [`Team ${i+1}`]; + + team.forEach(m => str.push(` ${m.user.tag}`)); + + teamsStr.push(str.join('\n')); + }); + + await interaction.reply('```\n'+teamsStr.join('\n\n')+'\n```'); + +} + export async function queueInfo(interaction: CommandInteraction) { console.log('COMMAND queueInfo') @@ -81,6 +181,6 @@ export async function queueInfo(interaction: CommandInteraction) { players: ${info.players.map(p => p.user.tag).join('\n ')} initiator: ${info.initiator.user.tag} teamsize: ${info.teamsize} -`+'```') +`+'```'); } \ No newline at end of file diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 0000000..b31d19f --- /dev/null +++ b/src/util.ts @@ -0,0 +1,24 @@ + +/** + * shuffles an array + * https://stackoverflow.com/a/2450976/2856416 + * @param array an array + * @returns an array but shuffled + */ +export function shuffle(array: any[]) { + let currentIndex = array.length, randomIndex; + + // While there remain elements to shuffle... + while (currentIndex != 0) { + + // Pick a remaining element... + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex--; + + // And swap it with the current element. + [array[currentIndex], array[randomIndex]] = [ + array[randomIndex], array[currentIndex]]; + } + + return array; +}