From 19d7d64034ced2d7fe0a25c360379e5ab52a6564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Rodr=C3=ADguez?= Date: Wed, 7 Dec 2016 14:10:30 +0100 Subject: [PATCH] Progress on Dota lobbies Now the bot is able to create lobbies and start with force-lobby-start --- config.js | 2 +- lib/commands/admin/force-lobby-start.js | 14 ++ lib/commands/admin/get-lobby.js | 23 +++ lib/commands/general/add-inhouse.js | 35 ++++- lib/commands/general/confirm.js | 65 +++++--- lib/commands/general/resend-invite.js | 36 +++++ lib/index.js | 55 ++++++- lib/modules/dbhandler/core.js | 72 ++++++++- lib/modules/dbhandler/index.js | 22 +++ lib/modules/dotahandler/index.js | 194 ++++++++++++++++++++++++ lib/modules/dotahandler/package.json | 11 ++ lib/modules/summaryhandler/index.js | 101 +++++++++--- lib/structures/ScheduledEvent.js | 24 +++ 13 files changed, 600 insertions(+), 54 deletions(-) create mode 100644 lib/commands/admin/force-lobby-start.js create mode 100644 lib/commands/admin/get-lobby.js create mode 100644 lib/commands/general/resend-invite.js create mode 100644 lib/modules/dotahandler/index.js create mode 100644 lib/modules/dotahandler/package.json diff --git a/config.js b/config.js index 3bf1631..4d8699f 100644 --- a/config.js +++ b/config.js @@ -68,7 +68,7 @@ module.exports = { // --server flag to the add-inhouse command. // Go to that command's file (Or type -schedulebot add-ihouse --help) // to see possible values. - defaultServer: "Europe" + defaultServer: "Luxembourg" } }; diff --git a/lib/commands/admin/force-lobby-start.js b/lib/commands/admin/force-lobby-start.js new file mode 100644 index 0000000..06a37f6 --- /dev/null +++ b/lib/commands/admin/force-lobby-start.js @@ -0,0 +1,14 @@ +"use strict"; + +const Clapp = require('../../modules/clapp-discord/index'); + +module.exports = new Clapp.Command({ + name: "force-lobby-start", + desc: "Forces the current lobby to start, even if there aren't enough players.", + fn: (argv, context) => { + return new Promise((fulfill, reject) => { + context.dotaHandler.forceStart().catch(reject); + fulfill("Forced current lobby start"); + }); + } +}); \ No newline at end of file diff --git a/lib/commands/admin/get-lobby.js b/lib/commands/admin/get-lobby.js new file mode 100644 index 0000000..c722f6d --- /dev/null +++ b/lib/commands/admin/get-lobby.js @@ -0,0 +1,23 @@ +"use strict"; + +const Clapp = require('../../modules/clapp-discord/index'); + +module.exports = new Clapp.Command({ + name: "get-lobby", + desc: "Gets the current lobby name and password sent to you on a DM", + fn: (argv, context) => { + return new Promise((fulfill, reject) => { + let lobby = context.dotaHandler.currentLobbyName; + let pass = context.dotaHandler.currentLobbyPassword; + + context.msg.author.sendMessage( + "Hello! Here's the information you requested:\n\n" + + + "- **Current lobby name**: `" + lobby + "`\n" + + "- **Current lobby password**: `" + pass + "`" + ).then(() => { + fulfill("The information you requested was sent to you in a DM."); + }).catch(reject); + }); + } +}); \ No newline at end of file diff --git a/lib/commands/general/add-inhouse.js b/lib/commands/general/add-inhouse.js index fff5e5f..60957d7 100644 --- a/lib/commands/general/add-inhouse.js +++ b/lib/commands/general/add-inhouse.js @@ -2,7 +2,7 @@ const Clapp = require('../../modules/clapp-discord/index') , cfg = require('../../../config') - , db = require('../../modules/dbhandler').events; + , db = require('../../modules/dbhandler'); module.exports = new Clapp.Command({ name: "add-inhouse", @@ -13,15 +13,38 @@ module.exports = new Clapp.Command({ "\nWhen the event time comes, every attendant will be invited to the event.", fn: (argv, context) => { return new Promise((fulfill, reject) => { - db.get(argv.args.id).then(event => { + db.events.get(argv.args.id).then(event => { if (event !== null) { let inhouseProps = {}; inhouseProps.gameMode = argv.flags.gamemode.toLowerCase().replace(" ", ""); inhouseProps.server = argv.flags.server.toLowerCase().replace(" ", ""); - db.addInhouse(event, inhouseProps).then(() => { - fulfill("The inhouse has been added to the event `#" + argv.args.id + "`"); + db.events.addInhouse(event, inhouseProps).then(() => { + + // Kick every user that hasn't linked their Steam from the event + db.confirms.getByEvent(event).then(confirms => { + let people = confirms.map(e => { return e.user }); + + for (let i = 0; i < people.length; i++) { + db.users.getByDiscord(people[i]).then(user => { + if (user === null || user.steam_id === null) { + db.confirms.deleteByUserAndEvent( + people[i], event.id + ).then(() => { + context.summaryHandler.updateSummary(event) + .catch(reject); + }).catch(reject); + } + }).catch(reject); + } + }).catch(reject); + context.summaryHandler.updateSummary(event).catch(reject); + + fulfill("The inhouse has been added to the event `#" + + argv.args.id + "`\n" + + "If there were any people who confirmed their attendance, but didn't" + + " have their Steam account linked, they have been removed."); }).catch(reject); } else { fulfill("The event `#" + argv.args.id + "` doesn't exist."); @@ -61,7 +84,7 @@ module.exports = new Clapp.Command({ desc: "The inhouse server. Possible values are:\n" + "- US West\n" + "- US East\n" + - "- Europe\n" + + "- Luxembourg\n" + "- Australia\n" + "- Stockholm\n\n" + "" + @@ -78,7 +101,7 @@ module.exports = new Clapp.Command({ switch (value) { case "uswest": case "useast": - case "europe": + case "luxembourg": case "australia": case "stockholm": return true; diff --git a/lib/commands/general/confirm.js b/lib/commands/general/confirm.js index 15cdc01..15b2d4e 100644 --- a/lib/commands/general/confirm.js +++ b/lib/commands/general/confirm.js @@ -13,31 +13,62 @@ module.exports = new Clapp.Command({ "`yes` or `no`"); return; } - db.events.get(argv.args.id).then(event => { + let isSteamLinkedPromise = new Promise((fulfill, reject) => { + db.users.getByDiscord(context.msg.author.id).then(user => { + fulfill(user !== null && user.steam_id !== null); + }); + }); + let getEventPromise = db.events.get(argv.args.id); + + Promise.all([isSteamLinkedPromise, getEventPromise]).then(values => { + let isSteamLinked = values[0]; + let event = values[1]; + if (event !== null) { - db.confirms.getByEvent(event).then(confirms => { - let attendanceConfirms = confirms !== null ? confirms.filter(el => { - return el.attends; - }) : []; - - if (attendanceConfirms.length < event.limit) { - db.confirms.add( - event, - context.msg.author, - argv.args.attendance === "yes" - ).then(() => { - cb("Your attendance status was updated."); - context.summaryHandler.updateSummary(event) - .catch(console.error); - }).catch(reject); + let getInhousePropsPromise = db.events.getInhouse(event); + let getConfirmsPromise = db.confirms.getByEvent(event); + + Promise.all([getInhousePropsPromise, getConfirmsPromise]).then(values2 => { + let inhouseProps = values2[0]; + let confirms = values2[1]; + + if (!(inhouseProps !== null && !isSteamLinked)) { + let attendanceConfirms = confirms !== null ? confirms.filter(el => { + return el.attends; + }) : []; + + if (attendanceConfirms.length < event.limit) { + db.confirms.add( + event, + context.msg.author, + argv.args.attendance === "yes" + ).then(() => { + // TODO change to fulfill in master as well + fulfill("Your attendance status was updated."); + context.summaryHandler.updateSummary(event) + .catch(console.error); + }).catch(reject); + } else { + fulfill("Sorry, the event is full."); + } } else { - fulfill("Sorry, the event is full."); + fulfill("Error: this event is an inhouse, but you haven't linked" + + " your Steam account.\n" + + "Use the `link-steam` command to link it, then try to confirm" + + " again."); } }).catch(reject); + + db.confirms.getByEvent(event).then(confirms => { + + }).catch(reject); } else { fulfill("Event #`" + argv.args.id + "` does not exist"); } }).catch(reject); + db.events.get(argv.args.id).then(event => { + + }).catch(reject); }); }, args: [ diff --git a/lib/commands/general/resend-invite.js b/lib/commands/general/resend-invite.js new file mode 100644 index 0000000..8eb7fb6 --- /dev/null +++ b/lib/commands/general/resend-invite.js @@ -0,0 +1,36 @@ +"use strict"; + +const Clapp = require('../../modules/clapp-discord/index') + , cfg = require('../../../config') + , db = require('../../modules/dbhandler'); + +module.exports = new Clapp.Command({ + name: "resend-invite", + desc: "Resends an invite to the current lobby. You need to have confirmed attendance for" + + " this to work.", + fn: (argv, context) => { + return new Promise((fulfill, reject) => { + context.dotaHandler.currentLobbyEvent.getConfirms().then(people => { + let confirmed = false; + + for (let i = 0; i < people.confirmed.length; i++) { + let discordID = people.confirmed[i]; + + if (context.msg.author.id === discordID) { + confirmed = true; + } + } + + if (confirmed) { + context.dotaHandler.invite(context.msg.author.id).then(() => { + fulfill("The invite has been resent. Accept it inside Dota 2."); + }).catch(reject); + } else { + fulfill("Error: you haven't confirmed attendance to the event `#" + + context.dotaHandler.currentLobbyEvent.id + "`.\n" + + "You need to do so before requesting to be invited to the lobby"); + } + }).catch(reject); + }); + } +}); \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index cd83eb9..8055afb 100644 --- a/lib/index.js +++ b/lib/index.js @@ -6,16 +6,20 @@ const fs = require('fs') , SummaryHandler = require('./modules/summaryhandler') , db = require('./modules/dbhandler') , cfg = require('../config.js') + , moment = require('moment') , pkg = require('../package.json') , Discord = require('discord.js') + , Dota2 = require('dota2') + , DotaHandler = require('./modules/dotahandler') , Steam = require('steam') , steamVerf = require('steam-verificator') , bot = new Discord.Client(); -let masterChannel, summaryHandler, botAdmins, blacklist = [], verificator, +let masterChannel, summaryHandler, botAdmins, blacklist = [], verificator, dotaHandler, steamClient = new Steam.SteamClient(), steamUser = new Steam.SteamUser(steamClient), - steamFriends = new Steam.SteamFriends(steamClient); + steamFriends = new Steam.SteamFriends(steamClient), + dotaClient = new Dota2.Dota2Client(steamClient, false, false); let generalApp = new Clapp.App({ name: cfg.name, @@ -79,7 +83,8 @@ bot.on('message', msg => { summaryHandler: summaryHandler, steam: { verificator: verificator - } + }, + dotaHandler: dotaHandler }); } else { msg.reply('\n' + "Sorry, you are blacklisted and can't use any commands.") @@ -94,7 +99,8 @@ bot.on('message', msg => { msg: msg, summaryHandler: summaryHandler, botAdmins: botAdmins, - blacklist: blacklist + blacklist: blacklist, + dotaHandler: dotaHandler }); } else { msg.reply('\n' + "Yo, this is top secret! You need to be a bot admin to access" + @@ -130,7 +136,7 @@ steamUser.on('updateMachineAuth', function(sentry, callback) { }); // Startup tasks -console.log("Loading ScheduleBot..."); +console.log("[INFO] Loading ScheduleBot... Please wait"); let startupPromises = []; @@ -258,7 +264,14 @@ startupPromises.push( steamFriends: steamFriends }); - fulfill(); + dotaClient.on("ready", () => { + console.log("[DOTA] Running!"); + dotaHandler = new DotaHandler(dotaClient); + + fulfill(); + }); + + dotaClient.launch(); } else { let err = new Error("[STEAM] Login failed"); err.steamResponse = response; @@ -282,10 +295,35 @@ Promise.all(startupPromises).then(values => { // Execute the update function now and every update_interval milliseconds (function update(){ // Update all active events' summaries - db.events.getAllActive().then( + db.events.getAll().then( events => { for (let i = 0; i < events.length; i++) { summaryHandler.updateSummary(events[i]).catch(console.error); + + if (events[i].time.diff(moment()) < 0) { + let getInhousePromise = db.events.getInhouse(events[i]); + let getLobbyEndedPromise = events[i].getLobbyEnded(); + + Promise.all([ + getInhousePromise, + getLobbyEndedPromise + ]).then(values => { + let inhouseProps = values[0]; + let lobbyEnded = values[1]; + + if ( + inhouseProps !== null && + dotaClient.Lobby === null && + !lobbyEnded + ) { + // If the event has an inhouse, is already happening, the + // dota client is not currently in a lobby, and this event's + // lobby was never created then create it. + inhouseProps.event = events[i]; + dotaHandler.createLobby(inhouseProps).catch(console.error); + } + }).catch(console.error); + } } } ).catch(console.error); @@ -294,6 +332,7 @@ Promise.all(startupPromises).then(values => { })(); console.log("[DISCORD] Running!"); - }); + console.log("[INFO] ScheduleBot finished loading.") + }).catch(console.error); }).catch(console.error); diff --git a/lib/modules/dbhandler/core.js b/lib/modules/dbhandler/core.js index 55838b1..c26b939 100644 --- a/lib/modules/dbhandler/core.js +++ b/lib/modules/dbhandler/core.js @@ -30,6 +30,17 @@ const events = { }); }, + /** + * Returns every active row in the events table, understanding by active every future event. + * + * @return {Promise} + */ + getAll: function() { + return new Promise((fulfill, reject) => { + db.select().from("events").then(fulfill).catch(reject); + }); + }, + /** * Returns every active row in the events table, understanding by active every future event. * @@ -72,7 +83,38 @@ const events = { db("events").select("waiting").where({ id: event.id }).then(rows => { - fulfill(rows[0].waiting || null); + fulfill(rows[0] ? rows[0].waiting : null); + }).catch(reject); + }); + }, + + /** + * Gets the "lobby ended" property of a specific event. + * @param {ScheduledEvent} event + * @return {Promise} + */ + getLobbyEnded: function(event) { + return new Promise((fulfill, reject) => { + db("events").select("lobby_ended").where({ + id: event.id + }).then(rows => { + fulfill(rows[0] ? rows[0].lobby_ended : null); + }).catch(reject); + }); + }, + + /** + * Gets the inhouse properties for the specified event. + * @param {ScheduledEvent} event + * @return {Promise} Resolves with the inhouse properties or null if no inhouse was + * added. + */ + getInhouse: function(event) { + return new Promise((fulfill, reject) => { + db("events").select("inhouse").where({ + id: event.id + }).then(rows => { + fulfill(rows[0].inhouse || null); }).catch(reject); }); }, @@ -153,6 +195,23 @@ const events = { }); }, + /** + * Updates the lobby_ended property of an event + * + * @param {ScheduledEvent} event + * @param {boolean} lobbyEnded + * @return {Promise} + */ + updateLobbyEnded: function(event, lobbyEnded) { + return new Promise((fulfill, reject) => { + db("events").update({ + lobby_ended: lobbyEnded + }).where({ + id: event.id + }).then(fulfill).catch(reject); + }); + }, + /** * Deletes a single event. * @@ -273,7 +332,16 @@ const confirms = { return new Promise((fulfill, reject) => { db("confirms").del().where({ event: eventId - }).then(fulfill, reject); + }).then(fulfill).catch(reject); + }); + }, + + deleteByUserAndEvent: function (userId, eventId) { + return new Promise((fulfill, reject) => { + db("confirms").del().where({ + event: eventId, + user: userId + }).then(fulfill).catch(reject); }); } }; diff --git a/lib/modules/dbhandler/index.js b/lib/modules/dbhandler/index.js index b815941..b05a131 100644 --- a/lib/modules/dbhandler/index.js +++ b/lib/modules/dbhandler/index.js @@ -49,6 +49,25 @@ module.exports = { }); }, + /** + * Returns every row in the events table + * + * @return {Promise} + */ + getAll: function() { + return new Promise((fulfill, reject) => { + core.events.getAll().then(rows => { + let scheduledEvents = []; + for (let i = 0; i < rows.length; i++) { + scheduledEvents.push(new ScheduledEvent( + rows[i].id, rows[i].name, rows[i].time, rows[i].limit + )); + } + fulfill(scheduledEvents) + }).catch(reject); + }); + }, + /** * Returns every active row in the events table, understanding by active every future event. * @@ -73,9 +92,12 @@ module.exports = { }, getWaiting: core.events.getWaiting, + getLobbyEnded: core.events.getLobbyEnded, + getInhouse: core.events.getInhouse, add: core.events.add, addInhouse: core.events.addInhouse, updateWaiting: core.events.updateWaiting, + updateLobbyEnded: core.events.updateLobbyEnded, deleteEvent: core.events.deleteEvent }, diff --git a/lib/modules/dotahandler/index.js b/lib/modules/dotahandler/index.js new file mode 100644 index 0000000..be6dcf7 --- /dev/null +++ b/lib/modules/dotahandler/index.js @@ -0,0 +1,194 @@ +const db = require("../dbhandler") + , Dota2 = require("dota2"); + +//Dota2.schema.DOTAChatChannelType_t.DOTAChannelType_Lobby + +class DotaHandler { + + constructor(dotaClient) { + this.client = dotaClient; + + this.client.on("practiceLobbyUpdate", lobby => { + this.currentLobbyChatChannel = "Lobby_" + lobby.lobby_id; + + this.sendMessageToLobby(DotaHandler.generateStatusMessage(lobby)); + }); + } + + createLobby(inhouseProps) { + return new Promise((fulfill, reject) => { + this.client.leavePracticeLobby(); + + this.currentLobbyEvent = inhouseProps.event; + this.currentLobbyName = inhouseProps.event.name; + this.currentLobbyPassword = DotaHandler.generatePassword(); + + let server; + + switch (inhouseProps.server) { + case "uswest": + server = Dota2.ServerRegion.USWEST; + break; + case "useast": + server = Dota2.ServerRegion.USEAST; + break; + case "luxembourg": + server = Dota2.ServerRegion.EUROPE; + break; + case "australia": + server = Dota2.ServerRegion.AUSTRALIA; + break; + case "stockholm": + server = Dota2.ServerRegion.STOCKHOLM; + break; + } + + let gamemode; + + switch (inhouseProps.gameMode) { + case "captainsmode": + gamemode = Dota2.schema.DOTA_GameMode.DOTA_GAMEMODE_CM; + break; + case "allpick": + gamemode = Dota2.schema.DOTA_GameMode.DOTA_GAMEMODE_AP; + break; + } + + this.client.createPracticeLobby( + this.currentLobbyPassword, + { + "game_name": this.currentLobbyName, + "server_region": server, + "game_mode": gamemode, + "game_version": Dota2.schema.DOTAGameVersion.GAME_VERSION_STABLE, + "series_type": Dota2.SeriesType.NONE, + "cm_pick": Dota2.schema.DOTA_CM_PICK.DOTA_CM_RANDOM, + "allow_cheats": false, + "fill_with_bots": false, + "allow_spectating": true, + "pass_key": this.currentLobbyPassword, + "radiant_series_wins": 0, + "dire_series_wins": 0, + "allchat": false, + "dota_tv_delay": Dota2.schema.LobbyDotaTVDelay.LobbyDotaTV_120 + }, + err => { + if (!err) { + console.log("[DOTA] Created lobby " + this.currentLobbyName); + + // For some reason the bot automatically joins the first slot. Kick him. + this.client.practiceLobbyKickFromTeam(this.client.AccountID, err => { + if (err) { + reject(new Error("Couldn't kick the bot from the game slot.")); + } + }); + + this.inviteAll(); + fulfill(); + } else { + reject(new Error("[DOTA] Error creating lobby - Error code: " + err)); + } + } + ); + }); + } + + sendMessageToLobby(message) { + this.client.joinChat( + this.currentLobbyChatChannel, + Dota2.schema.DOTAChatChannelType_t.DOTAChannelType_Lobby + ); + + this.client.sendMessage( + /*channel*/ this.currentLobbyChatChannel, + /*message*/ message, + /*channel_type*/ Dota2.schema.DOTAChatChannelType_t.DOTAChannelType_Lobby + ); + } + + /** + * Invites an user to the current lobby based on their Discord ID + * + * @param {string} discordID + * @return {Promise} + */ + invite(discordID) { + return new Promise((fulfill, reject) => { + db.users.getByDiscord(discordID).then(user => { + this.client.inviteToLobby(user.steam_id); + console.log("[DOTA] Sent an invite to user with Discord ID " + discordID + " and " + + "Steam ID " + user.steam_id + " to lobby " + this.currentLobbyName); + fulfill(); + }).catch(reject); + }); + } + + /** + * Sends an invite to every user who has confirmed attendance to the current lobby's event. + * @return {Promise} + */ + inviteAll() { + return new Promise((fulfill, reject) => { + this.currentLobbyEvent.getConfirms().then(people => { + let pendingInvites = []; + + for (let i = 0; i < people.confirmed.length; i++) { + let discordID = people.confirmed[i]; + + pendingInvites.push(this.invite(discordID)); + } + + Promise.all(pendingInvites).then(fulfill).catch(reject); + }).catch(reject); + }); + } + + // TODO automatically start when 10 players + forceStart() { + return new Promise((fulfill, reject) => { + this.sendMessageToLobby("Game start was forced"); + + let remainingSeconds = 10; + let self = this; + + (function tick() { + if (remainingSeconds > 0) { + self.sendMessageToLobby("Starting in " + remainingSeconds + " seconds."); + setTimeout(tick, 1000); + remainingSeconds--; + } else { + self.client.launchPracticeLobby(); + self.currentLobbyEvent.setLobbyEnded().then(fulfill).catch(reject); + } + })(); + }); + } + + static generateStatusMessage(lobby) { + let people = lobby.members.filter(e => { + return e.slot !== 0 && e.slot !== null + }).length; + return "Hello! The game will autostart when 10 people join. (We need " + (10 - people) + + " more). To force a start, tell an admin to run the command force-lobby-start in" + + " Discord."; + } + + static generatePassword() { + let code = ""; + + // Omitted characters that can look like others + let possibleChars = ["B", "D", "E", "F", "G", "H", "C", "J", "K", "L", "M", "N", "P", "Q", + "R", "S", "T", "W", "X", "Y","Z", "2", "3", "5", "6", "7", "8", "9"]; + + for (let i = 0; i < 20; i++) { + code += possibleChars[ + Math.floor(Math.random() * possibleChars.length) + ]; + } + + return code; + } + +} + +module.exports = DotaHandler; \ No newline at end of file diff --git a/lib/modules/dotahandler/package.json b/lib/modules/dotahandler/package.json new file mode 100644 index 0000000..22e6aec --- /dev/null +++ b/lib/modules/dotahandler/package.json @@ -0,0 +1,11 @@ +{ + "name": "dotahandler", + "version": "1.0.0", + "description": "A module that handles Dota lobbies", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "Apache-2.0" +} diff --git a/lib/modules/summaryhandler/index.js b/lib/modules/summaryhandler/index.js index 779ce58..b4d3968 100644 --- a/lib/modules/summaryhandler/index.js +++ b/lib/modules/summaryhandler/index.js @@ -18,9 +18,19 @@ class SummaryHandler { */ static generateSummary(event) { return new Promise((fulfill, reject) => { - event.getConfirms().then(people => { - var summary = ""; - var status = event.getStatus(); + let getConfirmsPromise = event.getConfirms(); + let getInhousePropsPromise = event.getInhouseProperties(); + let getLobbyEndedPromise = event.getLobbyEnded(); + + Promise.all([ + getConfirmsPromise, getInhousePropsPromise, getLobbyEndedPromise + ]).then(values => { + let people = values[0]; + let inhouseProps = values[1]; + let lobbyEnded = values[2]; + + let summary = ""; + let status = event.getStatus(); summary += "Summary for **" + event.name + "** (`#" + event.id + "`):\n\n" @@ -28,24 +38,75 @@ class SummaryHandler { + event.time.format("dddd, MMMM Do YYYY, HH:mm") + " (" + event.time._z.name + ")`.\n"; - switch (status) { - case "pending": - summary += "That's " + event.time.fromNow() + ".\n\n"; - break; + if (inhouseProps === null) { + switch (status) { + case "pending": + summary += "That's " + event.time.fromNow() + ".\n\n"; + break; + + case "happening": + summary += "The event is happening right now! Hurry up!\n\n"; + break; + + case "expired": + summary += "The event has expired. Stay tuned for new events!\n\n"; + break; + } + } else { + switch (inhouseProps.gameMode) { + case "captainsmode": + inhouseProps.gameMode = "Captains Mode"; + break; + case "allpick": + inhouseProps.gameMode = "All Pick"; + break; + } + + switch (inhouseProps.server) { + case "uswest": + inhouseProps.server = "US West"; + break; + case "useast": + inhouseProps.server = "US East"; + break; + case "luxembourg": + inhouseProps.server = "Luxembourg"; + break; + case "australia": + inhouseProps.server = "Australia"; + break; + case "stockholm": + inhouseProps.server = "Stockholm"; + break; + } + + switch (status) { + case "pending": + summary += "That's " + event.time.fromNow() + ".\n\n"; + break; + + case "happening": + case "expired": + if (!lobbyEnded) { + summary += "The lobby is up! If you haven't got an invite, run the" + + " command `resend-invite`\n\n"; + } else { + summary += "The lobby for this event is closed\n\n"; + } + + break; + } - case "happening": - summary += "The event is happening right now! Hurry up!\n\n"; - break; + summary += "**Lobby details**\n\n" + - case "expired": - summary += "The event has expired. Stay tuned for new events!\n\n"; - break; + "- Game mode: *" + inhouseProps.gameMode + "*\n" + + "- Server: *" + inhouseProps.server + "*\n\n" } summary += "**Will attend** (" + people.confirmed.length + "/" + event.limit + "):\n\n"; if (people.confirmed.length > 0) { - for (var i = 0; i < people.confirmed.length; i++) { + for (let i = 0; i < people.confirmed.length; i++) { summary += "- <@" + people.confirmed[i] + ">\n"; } } else { @@ -54,7 +115,7 @@ class SummaryHandler { summary += "\n**Will not attend**:\n\n"; if (people.rejected.length > 0) { - for (i = 0; i < people.rejected.length; i++) { + for (let i = 0; i < people.rejected.length; i++) { summary += "- <@" + people.rejected[i] + ">\n"; } } else { @@ -64,7 +125,7 @@ class SummaryHandler { if (people.waiting.length > 0) { summary += "\n**Waiting to confirm**:\n\n"; - for (i = 0; i < people.waiting.length; i++) { + for (let i = 0; i < people.waiting.length; i++) { summary += "- <@" + people.waiting[i] + ">\n"; } } @@ -106,12 +167,12 @@ class SummaryHandler { } else { // The summary message already exists. Update it. - var getMsgPromise = this.masterChannel.fetchMessage(msgId); - var getSummaryPromise = SummaryHandler.generateSummary(event); + let getMsgPromise = this.masterChannel.fetchMessage(msgId); + let getSummaryPromise = SummaryHandler.generateSummary(event); Promise.all([getMsgPromise, getSummaryPromise]).then(values => { - var message = values[0]; - var summary = values[1]; + let message = values[0]; + let summary = values[1]; message.edit(summary).then(msg => { if (!msg.pinned) { diff --git a/lib/structures/ScheduledEvent.js b/lib/structures/ScheduledEvent.js index f6227d0..b32ebe3 100644 --- a/lib/structures/ScheduledEvent.js +++ b/lib/structures/ScheduledEvent.js @@ -55,6 +55,15 @@ class ScheduledEvent { } } + /** + * Determines whether or not the lobby for this event has ended. + * + * @return {Promise.} + */ + getLobbyEnded() { + return db.events.getLobbyEnded(this); + } + /** * @param {string} msgId * @return {Promise} Resolves on success, or rejects with the error. @@ -67,6 +76,17 @@ class ScheduledEvent { }); } + /** + * Declares a event as "lobby ended". No lobby will be created again for that event. + * + * @return {Promise} + */ + setLobbyEnded() { + return new Promise((fulfill, reject) => { + db.events.updateLobbyEnded(this, true).then(fulfill).catch(reject); + }); + } + /** * Gets every confirm for the event. * @returns {Promise} Resolves on success with the people object, or rejects @@ -106,6 +126,10 @@ class ScheduledEvent { }); } + getInhouseProperties() { + return db.events.getInhouse(this); + } + /** * Deletes this event and every confirm asociated with it from the database. *