Skip to content

Commit

Permalink
Version 1.5.0
Browse files Browse the repository at this point in the history
Merge pull request #27 from Kalissaac/master
  • Loading branch information
Kalissaac authored Mar 19, 2021
2 parents 0db3fce + 24d076f commit 9d876c8
Show file tree
Hide file tree
Showing 8 changed files with 580 additions and 585 deletions.
1,010 changes: 472 additions & 538 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@
},
"homepage": "https://github.com/SchwaIndustries/ScrimBot#readme",
"dependencies": {
"chrono-node": "^2.2.3",
"chrono-node": "^2.2.4",
"discord.js": "^12.5.1",
"dotenv": "^8.2.0",
"firebase-admin": "^9.5.0",
"moment": "^2.29.1",
"moment-timezone": "^0.5.33"
},
"devDependencies": {
"heroku": "^7.50.0",
"heroku": "^7.51.0",
"nodemon": "^2.0.7",
"standard": "^15.0.1"
"standard": "^16.0.3"
},
"engines": {
"node": "14.x"
"node": "12.x"
}
}
1 change: 1 addition & 0 deletions src/commands/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports = exports = {
${process.env.PREFIX}match score <match id> <team a score>-<team b score>: Report final match score (only for match creator)
${process.env.PREFIX}match edit <match id> <date, map, minRank, maxRank, teamPlayerCount, spectators, mode> <edited value>: Edit match information (only for match creator)
${process.env.PREFIX}match info <match id>: Retrieves match information
${process.env.PREFIX}match refresh <match id>: Refreshes a broken match embed
**__USER COMMANDS__**
${process.env.PREFIX}user info <mention or user id>: Retrieves user information
Expand Down
84 changes: 76 additions & 8 deletions src/commands/match.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const CONSTANTS = require('../constants')
const moment = require('moment-timezone')
const admin = require('firebase-admin')
const chrono = require('chrono-node')

module.exports = exports = {
name: 'match',
Expand All @@ -18,6 +19,7 @@ module.exports = exports = {
case 'cancel': cancel(message, GLOBALS); break
case 'info': info(message, GLOBALS); break
case 'edit': edit(message, GLOBALS); break
case 'refresh': refresh(message, GLOBALS); break
}
}
}
Expand Down Expand Up @@ -404,19 +406,14 @@ const edit = async (message, GLOBALS) => {

switch (editedProperty) {
case 'date': {
const dateString = editedValue.split(' ')
if (dateString.length === 2) {
const actualDate = moment().tz(process.env.TIME_ZONE).format('YYYY-MM-DD')
dateString.push(actualDate)
}

const date = moment.tz(dateString.join(' '), 'h:mm a YYYY-MM-DD', process.env.TIME_ZONE).toDate()
if (isNaN(date)) return message.reply('please give a valid date!').then(msg => msg.delete({ timeout: 5000 }))
const date = chrono.parseDate(`${editedValue} ${moment.tz.zone(process.env.TIME_ZONE).abbr(Date.now())}`)
if (!date) return message.reply('please give a valid date!').then(msg => msg.delete({ timeout: 5000 }))
matchInformation.date = date

matchEmbed.setTimestamp(matchInformation.date)
break
}

case 'minRank': {
if (editedValue.toLowerCase() === 'any') {
matchInformation.rankMinimum = 0
Expand All @@ -428,6 +425,7 @@ const edit = async (message, GLOBALS) => {
matchEmbed.fields[4].value = CONSTANTS.capitalizeFirstLetter(CONSTANTS.RANKS_REVERSED[matchInformation.rankMinimum])
break
}

case 'maxRank': {
if (editedValue.toLowerCase() === 'any') {
matchInformation.rankMaximum = 99
Expand All @@ -441,6 +439,7 @@ const edit = async (message, GLOBALS) => {
matchEmbed.fields[5].value = CONSTANTS.capitalizeFirstLetter(CONSTANTS.RANKS_REVERSED[matchInformation.rankMaximum])
break
}

case 'teamPlayerCount': {
if (!Number(editedValue) || Number(editedValue) > 5) {
return message.reply('please give a valid number!').then(msg => msg.delete({ timeout: 5000 }))
Expand All @@ -450,10 +449,12 @@ const edit = async (message, GLOBALS) => {
break
}
}

case 'spectators':
matchInformation.spectators = (CONSTANTS.AFFIRMATIVE_WORDS.includes(editedValue.toLowerCase())) ? [] : false
matchEmbed.fields[8].value = matchInformation.spectators instanceof Array ? 'None' : 'Not allowed'
break

case 'map': {
if (editedValue.toLowerCase() === 'any') {
matchInformation.map = CONSTANTS.MAPS[Math.floor(Math.random() * Math.floor(CONSTANTS.MAPS.length))]
Expand All @@ -466,6 +467,7 @@ const edit = async (message, GLOBALS) => {
matchEmbed.setThumbnail(CONSTANTS.MAPS_THUMBNAILS[matchInformation.map])
break
}

case 'mode': {
if (CONSTANTS.GAME_MODES.includes(editedValue.toLowerCase())) {
matchInformation.mode = editedValue.toLowerCase()
Expand All @@ -475,6 +477,7 @@ const edit = async (message, GLOBALS) => {
}
break
}

default:
return message.reply('Property `' + editedProperty + '` not found! Please try again using a valid property (date, map, minRank, maxRank, teamPlayerCount, spectators, mode).')
}
Expand All @@ -483,3 +486,68 @@ const edit = async (message, GLOBALS) => {
message.reply(`${editedProperty} successfully changed to ${editedValue} for match ${matchID}!`)
botMessage.edit(matchEmbed)
}

/**
* @param {import('discord.js').Message} message
* @param {import('../index.js').GLOBALS} GLOBALS
*/
const refresh = async (message, GLOBALS) => {
const matchID = message.content.split(' ')[2]

if (!matchID) return message.reply('Match not found! Ensure correct match ID is submitted.')
const matchInformationRef = GLOBALS.db.collection('matches').doc(matchID)
let matchInformation = await matchInformationRef.get()
if (!matchInformation.exists) return message.reply('Match not found! Ensure correct match ID is submitted.')
matchInformation = matchInformation.data()
const botMessageChannel = await GLOBALS.client.channels.fetch(matchInformation.message.channel)
const botMessage = await botMessageChannel.messages.fetch(matchID)

const matchCreator = await GLOBALS.client.users.fetch(matchInformation.creator)

const matchEmbed = new GLOBALS.Embed()
.setTitle('Match Information')
.setDescription('React with 🇦 to join the A team, react with 🇧 to join the B team' + (matchInformation.spectators instanceof Array ? ', and react with 🇸 to be a spectator.' : '.'))
.setThumbnail(CONSTANTS.MAPS_THUMBNAILS[matchInformation.map])
.setTimestamp(matchInformation.date.toDate())
.setAuthor(matchCreator.tag, matchCreator.avatarURL())
.addField('Status', CONSTANTS.capitalizeFirstLetter(matchInformation.status), true)
.addField('Game Mode', CONSTANTS.capitalizeFirstLetter(matchInformation.mode), true)
.addField('Map', CONSTANTS.capitalizeFirstLetter(matchInformation.map), true)
.addField('Max Team Count', matchInformation.maxTeamCount + ' players per team', true)
.addField('Minimum Rank', CONSTANTS.capitalizeFirstLetter(CONSTANTS.RANKS_REVERSED[matchInformation.rankMinimum]), true)
.addField('Maximum Rank', CONSTANTS.capitalizeFirstLetter(CONSTANTS.RANKS_REVERSED[matchInformation.rankMaximum]), true)
.addField('Team A', 'None', true)
.addField('Team B', 'None', true)
.addField('Spectators', matchInformation.spectators instanceof Array ? 'None' : 'Not allowed', true)
.setFooter('match id: ' + matchID)
matchEmbed.fields[6].value = ''
for (const playerRef of matchInformation.players.a) {
let playerDoc = await playerRef.get()
playerDoc = playerDoc.data()
matchEmbed.fields[6].value += `\n• ${playerDoc.valorantUsername}`
}
if (matchEmbed.fields[6].value === '') matchEmbed.fields[6].value = 'None'

matchEmbed.fields[7].value = ''
for (const playerRef of matchInformation.players.b) {
let playerDoc = await playerRef.get()
playerDoc = playerDoc.data()
matchEmbed.fields[7].value += `\n• ${playerDoc.valorantUsername}`
}
if (matchEmbed.fields[7].value === '') matchEmbed.fields[7].value = 'None'

if (matchInformation.spectators instanceof Array) {
matchEmbed.fields[8].value = ''
for (const playerRef of matchInformation.spectators) {
let playerDoc = await playerRef.get()
playerDoc = playerDoc.data()
matchEmbed.fields[8].value += `\n• ${playerDoc.valorantUsername}`
}
if (matchEmbed.fields[8].value === '') matchEmbed.fields[8].value = 'None'
}

if (matchInformation.status === 'completed') {
matchEmbed.addField('Final Score', `${matchInformation.score[0]}-${matchInformation.score[1]}`)
}
botMessage.edit(matchEmbed)
}
4 changes: 4 additions & 0 deletions src/commands/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ const edit = async (message, GLOBALS) => {
if (editedValue.match(/\S{3,16}#\S{3,5}/)) userInformation.valorantUsername = editedValue
else return message.reply('Please give a valid username!').then(msg => msg.delete({ timeout: 5000 }))
break

case 'rank':
if (!CONSTANTS.RANKS[editedValue.toUpperCase()]) {
return message.reply('Please give a valid rank!').then(msg => msg.delete({ timeout: 5000 }))
Expand All @@ -122,14 +123,17 @@ const edit = async (message, GLOBALS) => {
updateUserRankRoles(message.author, userInformation.valorantRank, GLOBALS)
break
}

case 'notifications':
userInformation.notifications = CONSTANTS.AFFIRMATIVE_WORDS.includes(editedValue.toLowerCase())
if (userInformation.notifications) updateUserRoles(message.author, 'notificationRole', true, GLOBALS)
else updateUserRoles(message.author, 'notificationRole', false, GLOBALS)
break

default:
return message.reply('Requested property not found!')
}

userInformationRef.update(userInformation)
message.reply(`${editedProperty} successfully changed to ${editedValue}!`)
}
24 changes: 13 additions & 11 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,25 +68,27 @@ module.exports = exports = {

GAME_MODES: ['standard', 'spike rush', 'deathmatch'],

AFFIRMATIVE_WORDS: ['yes', 'yeah', 'sure', 'true', '1', 'one', 'si', 'yea', 'ok', 'okay', 'mhm', 'k', 'yah', 'on', 'why not', 'alright', 'aight', 'affirmative'],
AFFIRMATIVE_WORDS: ['yes', 'yeah', 'yea', 'ye', 'yah', 'sure', 'true', '1', 'one', 'on', 'si', 'ok', 'okay', 'k', 'mhm', 'why not', 'alright', 'aight', 'affirmative', 'yeet'],

MAX_TEAM_COUNT: 5, // maximum amount of players allowed on one team

userRegistrationSteps: [
['1. Valorant Username', 'What is your FULL Valorant username? (including tag, e.g. `Username#NA1`)'],
['2. Valorant Rank', 'What rank are you in Valorant? If you don\'t have a rank, go with "Iron 1"'],
['2. Valorant Rank', 'What rank are you in Valorant? If you don\'t have a rank, go with "Iron 1".'],
['3. Notifications', 'Do you want to be notified when matches are created? Respond "yes" if you would like to opt-in.']
],

matchCreationSteps: [
['1. Date & Time', 'When will the match be? If no date is specified the current day is assumed. You can also specify a time zone such as `CST` or `EDT`, defaults to Pacific. Ex: "Today at 4 AM", "8/24/1932 4:00 AM JST", "8:00 PM in 4 years"'],
['2. Rank Minimum', 'What is the **MINIMUM** rank you are allowing into your tournament? If any, type "any"'],
['3. Rank Maximum', 'What is the **MAXIMUM** rank you are allowing into your tournament? If any, type "any"'],
['4. Player Count', 'How many players should be on each team? Max 5.'],
['5. Spectators', 'Are spectators allowed?'],
['6. Map', 'Which map would you like to play on? Options are "Split", "Bind", "Haven", "Ascent", and "Icebox". If any, type "any"'],
['7. Game Mode', 'What game mode would you like? Options are "standard", "spike rush", and "deathmatch".']
],
get matchCreationSteps () {
return [
['1. Date & Time', 'When will the match be? If no date is specified the current day is assumed. You can also specify a time zone such as `CST` or `EDT`, defaults to Pacific time. Ex: "Today at 10 AM", "12:30 PM on Saturday", "03/14/2021 at 6:28 PM EST"'],
['2. Rank Minimum', 'What is the **MINIMUM** rank you are allowing into your tournament? If any, type "any".'],
['3. Rank Maximum', 'What is the **MAXIMUM** rank you are allowing into your tournament? If any, type "any".'],
['4. Player Count', `How many players should be on each team? Max ${this.MAX_TEAM_COUNT}.`],
['5. Spectators', 'Are spectators allowed?'],
['6. Map', `Which map would you like to play on? Options are "${this.MAPS.map(m => this.capitalizeFirstLetter(m)).join('", "')}". If any, type "any".`],
['7. Game Mode', `What game mode would you like? Options are "${this.GAME_MODES.map(m => this.capitalizeFirstLetter(m)).join('", "')}".`]
]
},

capitalizeFirstLetter: string => {
string = string.toLowerCase()
Expand Down
6 changes: 6 additions & 0 deletions src/services/matchCreation.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const handleMatchCreation = async (matchRecord, userMessage, GLOBALS) => {
matchRecord.creationInformation.date = date
break
}

case 1: {
if (content === 'any') {
matchRecord.creationInformation.rankMinimum = 0
Expand All @@ -43,6 +44,7 @@ const handleMatchCreation = async (matchRecord, userMessage, GLOBALS) => {
break
}
}

case 2: {
if (content === 'any') {
matchRecord.creationInformation.rankMaximum = 99
Expand All @@ -56,6 +58,7 @@ const handleMatchCreation = async (matchRecord, userMessage, GLOBALS) => {
break
}
}

case 3: {
if (!Number(content)) {
return userMessage.reply('please give a valid number!').then(msg => msg.delete({ timeout: 5000 }))
Expand All @@ -66,9 +69,11 @@ const handleMatchCreation = async (matchRecord, userMessage, GLOBALS) => {
break
}
}

case 4:
matchRecord.creationInformation.spectators = (CONSTANTS.AFFIRMATIVE_WORDS.includes(content)) ? [] : false
break

case 5: {
if (content === 'any') {
matchRecord.creationInformation.map = CONSTANTS.MAPS[Math.floor(Math.random() * Math.floor(CONSTANTS.MAPS.length))]
Expand All @@ -80,6 +85,7 @@ const handleMatchCreation = async (matchRecord, userMessage, GLOBALS) => {
return userMessage.reply('please give a valid map!').then(msg => msg.delete({ timeout: 5000 }))
}
}

case 6: {
if (CONSTANTS.GAME_MODES.includes(content)) {
matchRecord.creationInformation.mode = CONSTANTS.GAME_MODES.find(e => e === content) || content
Expand Down
28 changes: 4 additions & 24 deletions src/services/matchReactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,30 +52,10 @@ const _addPlayerToMatch = async (reaction, user, GLOBALS, matchInformation) => {
}
playerInformation = playerInformation.data()

if (matchInformation.players.a.find(e => e.id === playerInformationRef.id)) {
if (!reaction.message.guild.me.hasPermission('MANAGE_MESSAGES')) {
reaction.message.channel.send(`${user}, you have already joined a team! Please remove that reaction before joining a new one.`).then(msg => msg.delete({ timeout: 5000 }))
reaction.users.remove(user.id)
return
} else {
matchInformation = await _removePlayerFromMatch(await reaction.message.reactions.cache.get('🇦'), user, GLOBALS, matchInformation)
}
} else if (matchInformation.players.b.find(e => e.id === playerInformationRef.id)) {
if (!reaction.message.guild.me.hasPermission('MANAGE_MESSAGES')) {
reaction.message.channel.send(`${user}, you have already joined a team! Please remove that reaction before joining a new one.`).then(msg => msg.delete({ timeout: 5000 }))
reaction.users.remove(user.id)
return
} else {
matchInformation = await _removePlayerFromMatch(await reaction.message.reactions.cache.get('🇧'), user, GLOBALS, matchInformation)
}
} else if (matchInformation.spectators && matchInformation.spectators.find(e => e.id === playerInformationRef.id)) {
if (!reaction.message.guild.me.hasPermission('MANAGE_MESSAGES')) {
reaction.message.channel.send(`${user}, you have already joined a team! Please remove that reaction before joining a new one.`).then(msg => msg.delete({ timeout: 5000 }))
reaction.users.remove(user.id)
return
} else {
matchInformation = await _removePlayerFromMatch(await reaction.message.reactions.cache.get('🇸'), user, GLOBALS, matchInformation)
}
if (matchInformation.players.a.find(e => e.id === playerInformationRef.id) || matchInformation.players.b.find(e => e.id === playerInformationRef.id) || (matchInformation.spectators && matchInformation.spectators.find(e => e.id === playerInformationRef.id))) {
reaction.message.channel.send(`${user}, you have already joined a team! Please remove that reaction before joining a new one.`).then(msg => msg.delete({ timeout: 5000 }))
reaction.users.remove(user.id)
return
}

const messageEmbed = reaction.message.embeds[0]
Expand Down

0 comments on commit 9d876c8

Please sign in to comment.