diff --git a/core/log-parser/index.js b/core/log-parser/index.js index 2a91ebbc0..4ea61f303 100644 --- a/core/log-parser/index.js +++ b/core/log-parser/index.js @@ -8,6 +8,8 @@ import Logger from '../logger.js'; import TailLogReader from './log-readers/tail.js'; import FTPLogReader from './log-readers/ftp.js'; +const addedLines = []; + export default class LogParser extends EventEmitter { constructor(filename = 'filename.log', options = {}) { super(); @@ -46,24 +48,28 @@ export default class LogParser extends EventEmitter { async processLine(line) { Logger.verbose('LogParser', 4, `Matching on line: ${line}`); - for (const rule of this.getRules()) { + let i = this.getRules().length; + while (i--) { + const rule = this.getRules()[i]; const match = line.match(rule.regex); if (!match) continue; - + addedLines.push({ rule, match }); + } + this.linesPerMinute += 1; + this.onLine(addedLines); + addedLines.length = 0; + } + + onLine(addedLine) { + for(const ad of addedLine) { + const { rule, match } = ad; Logger.verbose('LogParser', 3, `Matched on line: ${match[0]}`); - match[1] = moment.utc(match[1], 'YYYY.MM.DD-hh.mm.ss:SSS').toDate(); match[2] = parseInt(match[2]); - rule.onMatch(match, this); - - this.matchingLinesPerMinute++; - this.matchingLatency += Date.now() - match[1]; - - break; - } - - this.linesPerMinute++; + this.matchingLinesPerMinute += 1; + this.matchingLatency += Number(Date.now()) - match[1]; + }; } // manage cleanup disconnected players, session data. @@ -100,7 +106,7 @@ export default class LogParser extends EventEmitter { } lines per minute | Matching lines per minute: ${ this.matchingLinesPerMinute } matching lines per minute | Average matching latency: ${ - this.matchingLatency / this.matchingLinesPerMinute + Number.isNaN(this.matchingLatency / this.matchingLinesPerMinute) ? 0 : this.matchingLatency / this.matchingLinesPerMinute }ms` ); this.linesPerMinute = 0; diff --git a/squad-server/factory.js b/squad-server/factory.js index a8865a5a9..0e6b3fb1f 100644 --- a/squad-server/factory.js +++ b/squad-server/factory.js @@ -2,7 +2,7 @@ import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; -import Discord from 'discord.js'; +import { Client, GatewayIntentBits } from 'discord.js'; import sequelize from 'sequelize'; import AwnAPI from './utils/awn-api.js'; @@ -103,7 +103,13 @@ export default class SquadServerFactory { Logger.verbose('SquadServerFactory', 1, `Starting ${type} connector ${connectorName}...`); if (type === 'discord') { - const connector = new Discord.Client(); + const connector = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.MessageContent, + ], + }); await connector.login(connectorConfig); return connector; } diff --git a/squad-server/package.json b/squad-server/package.json index c7d8104c2..577260aa7 100644 --- a/squad-server/package.json +++ b/squad-server/package.json @@ -6,7 +6,7 @@ "axios": "^0.21.1", "core": "1.0.0", "didyoumean": "^1.2.1", - "discord.js": "^12.3.1", + "discord.js": "^14.11.0", "gamedig": "^2.0.20", "graphql": "^15.4.0", "graphql-request": "^3.4.0", diff --git a/squad-server/plugins/cbl-info.js b/squad-server/plugins/cbl-info.js index 1818ef951..5ec5f72e3 100644 --- a/squad-server/plugins/cbl-info.js +++ b/squad-server/plugins/cbl-info.js @@ -52,6 +52,10 @@ export default class CBLInfo extends DiscordBasePlugin { async onPlayerConnected(info) { try { + const steamID = this.isValid(info, ''); + if(!steamID) { + return; + }; const data = await request( 'https://communitybanlist.com/graphql', gql` @@ -85,13 +89,13 @@ export default class CBLInfo extends DiscordBasePlugin { } } `, - { id: info.player.steamID } + { id: steamID } ); if (!data.steamUser) { this.verbose( 2, - `Player ${info.player.name} (Steam ID: ${info.player.steamID}) is not listed in the Community Ban List.` + `Player ${info.player.name} (Steam ID: ${steamID}) is not listed in the Community Ban List.` ); return; } @@ -99,59 +103,51 @@ export default class CBLInfo extends DiscordBasePlugin { if (data.steamUser.reputationPoints < this.options.threshold) { this.verbose( 2, - `Player ${info.player.name} (Steam ID: ${info.player.steamID}) has a reputation below the threshold.` + `Player ${info.player.name} (Steam ID: ${steamID}) has a reputation below the threshold.` ); return; } - - await this.sendDiscordMessage({ - embed: { - title: `${info.player.name} is a potentially harmful player!`, - author: { - name: 'Community Ban List', - url: 'https://communitybanlist.com/', - icon_url: 'https://communitybanlist.com/static/media/cbl-logo.caf6584e.png' - }, - thumbnail: { - url: data.steamUser.avatarFull - }, - description: `[${info.player.name}](https://communitybanlist.com/search/${info.player.steamID}) has ${data.steamUser.reputationPoints} reputation points on the Community Ban List and is therefore a potentially harmful player.`, - fields: [ - { - name: 'Reputation Points', - value: `${data.steamUser.reputationPoints} (${ - data.steamUser.reputationPointsMonthChange || 0 - } from this month)`, - inline: true - }, - { - name: 'Risk Rating', - value: `${data.steamUser.riskRating} / 10`, - inline: true - }, - { - name: 'Reputation Rank', - value: `#${data.steamUser.reputationRank}`, - inline: true - }, - { - name: 'Active Bans', - value: `${data.steamUser.activeBans.edges.length}`, - inline: true - }, - { - name: 'Expired Bans', - value: `${data.steamUser.expiredBans.edges.length}`, - inline: true - } - ], - color: '#ffc40b', - timestamp: info.time.toISOString(), - footer: { - text: 'Powered by SquadJS and the Community Ban List' - } + const embed = this.buildEmbed() + .setColor('#ffc40b') + .setTitle(`${info.player.name} is a potentially harmful player!`) + .setAuthor({ + name: 'Community Ban List', + iconURL: 'https://communitybanlist.com/static/media/cbl-logo.caf6584e.png', + url: 'https://communitybanlist.com/' + }) + .setDescription(`[${info.player.name}](https://communitybanlist.com/search/${steamID}) has ${data.steamUser.reputationPoints} reputation points on the Community Ban List and is therefore a potentially harmful player.`) + .setThumbnail(data.steamUser.avatarFull) + .addFields( + { + name: 'Reputation Points', + value: `${data.steamUser.reputationPoints} (${ + data.steamUser.reputationPointsMonthChange || 0 + } from this month)`, + inline: true + }, + { + name: 'Risk Rating', + value: `${data.steamUser.riskRating} / 10`, + inline: true + }, + { + name: 'Reputation Rank', + value: `#${data.steamUser.reputationRank}`, + inline: true + }, + { + name: 'Active Bans', + value: `${data.steamUser.activeBans.edges.length}`, + inline: true + }, + { + name: 'Expired Bans', + value: `${data.steamUser.expiredBans.edges.length}`, + inline: true } - }); + ) + .setFooter({ text: 'Powered by SquadJS and the Community Ban List', iconURL: null }); + await this.sendDiscordMessage({ embeds: [embed] }); } catch (err) { this.verbose( 1, diff --git a/squad-server/plugins/discord-admin-broadcast.js b/squad-server/plugins/discord-admin-broadcast.js index 050f58758..c1dc3e11a 100644 --- a/squad-server/plugins/discord-admin-broadcast.js +++ b/squad-server/plugins/discord-admin-broadcast.js @@ -44,18 +44,10 @@ export default class DiscordAdminBroadcast extends DiscordBasePlugin { } async onAdminBroadcast(info) { - await this.sendDiscordMessage({ - embed: { - title: 'Admin Broadcast', - color: this.options.color, - fields: [ - { - name: 'Message', - value: `${info.message}` - } - ], - timestamp: info.time.toISOString() - } + const embed = this.buildEmbed(this.options.color, info.time, 'Admin Broadcast').addFields({ + name: 'Message', + value: `${info.message}` }); + await this.sendDiscordMessage(this.objEmbed(embed)); } } diff --git a/squad-server/plugins/discord-admin-cam-logs.js b/squad-server/plugins/discord-admin-cam-logs.js index 8cbbaac2c..65615ceda 100644 --- a/squad-server/plugins/discord-admin-cam-logs.js +++ b/squad-server/plugins/discord-admin-cam-logs.js @@ -46,50 +46,38 @@ export default class DiscordAdminCamLogs extends DiscordBasePlugin { } async onEntry(info) { - await this.sendDiscordMessage({ - embed: { - title: `Admin Entered Admin Camera`, - color: this.options.color, - fields: [ - { - name: "Admin's Name", - value: info.player.name, - inline: true - }, - { - name: "Admin's SteamID", - value: `[${info.player.steamID}](https://steamcommunity.com/profiles/${info.player.steamID})`, - inline: true - } - ], - timestamp: info.time.toISOString() + const embed = this.buildEmbed(this.options.color, info.time, 'Admin Entered Admin Camera').addFields( + { + name: "Admin's Name", + value: info.player.name, + inline: true + }, + { + name: "Admin's SteamID", + value: `[${info.player.steamID}](https://steamcommunity.com/profiles/${info.player.steamID})`, + inline: true } - }); + ); + await this.sendDiscordMessage(this.objEmbed(embed)); } async onExit(info) { - await this.sendDiscordMessage({ - embed: { - title: `Admin Left Admin Camera`, - color: this.options.color, - fields: [ - { - name: "Admin's Name", - value: info.player.name, - inline: true - }, - { - name: "Admin's SteamID", - value: `[${info.player.steamID}](https://steamcommunity.com/profiles/${info.player.steamID})`, - inline: true - }, - { - name: 'Time in Admin Camera', - value: `${Math.round(info.duration / 60000)} mins` - } - ], - timestamp: info.time.toISOString() + const embed = this.buildEmbed(this.options.color, info.time, 'Admin Left Admin Camera').addFields( + { + name: "Admin's Name", + value: info.player.name, + inline: true + }, + { + name: "Admin's SteamID", + value: `[${info.player.steamID}](https://steamcommunity.com/profiles/${info.player.steamID})`, + inline: true + }, + { + name: 'Time in Admin Camera', + value: `${Math.round(info.duration / 60000)} mins` } - }); + ); + await this.sendDiscordMessage(this.objEmbed(embed)); } } diff --git a/squad-server/plugins/discord-admin-request.js b/squad-server/plugins/discord-admin-request.js index f904c2127..13fd68c04 100644 --- a/squad-server/plugins/discord-admin-request.js +++ b/squad-server/plugins/discord-admin-request.js @@ -108,37 +108,32 @@ export default class DiscordAdminRequest extends DiscordBasePlugin { await this.server.rcon.warn(player.steamID, `[${info.player.name}] - ${info.message}`); } - const message = { - embed: { - title: `${info.player.name} has requested admin support!`, - color: this.options.color, - fields: [ - { - name: 'Player', - value: info.player.name, - inline: true - }, - { - name: 'SteamID', - value: `[${info.player.steamID}](https://steamcommunity.com/profiles/${info.player.steamID})`, - inline: true - }, - { - name: 'Team & Squad', - value: `Team: ${info.player.teamID}, Squad: ${info.player.squadID || 'Unassigned'}` - }, - { - name: 'Message', - value: info.message - }, - { - name: 'Admins Online', - value: amountAdmins - } - ], - timestamp: info.time.toISOString() + const message = { }; + const embed = this.buildEmbed(this.options.color, info.time, `${info.player.name} has requested admin support!`).addFields( + { + name: 'Player', + value: info.player.name, + inline: true + }, + { + name: 'SteamID', + value: `[${info.player.steamID}](https://steamcommunity.com/profiles/${info.player.steamID})`, + inline: true + }, + { + name: 'Team & Squad', + value: `Team: ${info.player.teamID}, Squad: ${info.player.squadID || 'Unassigned'}` + }, + { + name: 'Message', + value: info.message + }, + { + name: 'Admins Online', + value: amountAdmins } - }; + ); + Object.assign(message, this.objEmbed(embed)); if (this.options.pingGroups.length > 0 && Date.now() - this.options.pingDelay > this.lastPing) { message.content = this.options.pingGroups.map((groupID) => `<@&${groupID}>`).join(' '); diff --git a/squad-server/plugins/discord-base-message-updater.js b/squad-server/plugins/discord-base-message-updater.js index 66376a62d..9532a5e9a 100644 --- a/squad-server/plugins/discord-base-message-updater.js +++ b/squad-server/plugins/discord-base-message-updater.js @@ -51,11 +51,11 @@ export default class DiscordBaseMessageUpdater extends BasePlugin { } async mount() { - this.options.discordClient.on('message', this.onDiscordMessage); + this.options.discordClient.on('messageCreate', this.onDiscordMessage); } async unmount() { - this.options.discordClient.removeEventListener('message', this.onDiscordMessage); + this.options.discordClient.removeEventListener('messageCreate', this.onDiscordMessage); } async generateMessage() { diff --git a/squad-server/plugins/discord-base-plugin.js b/squad-server/plugins/discord-base-plugin.js index 26557ed9e..1a121a480 100644 --- a/squad-server/plugins/discord-base-plugin.js +++ b/squad-server/plugins/discord-base-plugin.js @@ -1,6 +1,6 @@ import BasePlugin from './base-plugin.js'; - import { COPYRIGHT_MESSAGE } from '../utils/constants.js'; +import { EmbedBuilder } from 'discord.js'; export default class DiscordBasePlugin extends BasePlugin { static get optionsSpecification() { @@ -27,15 +27,193 @@ export default class DiscordBasePlugin extends BasePlugin { } } + /** + * Object is Null + * @param {Object} obj - Object + * @returns {boolean} Returns booleantrue or false + */ + isNull(obj) { + return Object.is(obj, null) || Object.is(obj, undefined); + } + + /** + * Object is Blank + * @param {(Object|Object[]|string)} obj - Array, Set, Object or String + * @returns {boolean} Returns boolean true or false + */ + isBlank(obj) { + return ( + (typeof obj === 'string' && Object.is(obj.trim(), '')) || + (obj instanceof Set && Object.is(obj.size, 0)) || + (Array.isArray(obj) && Object.is(obj.length, 0)) || + (obj instanceof Object && + typeof obj.entries !== 'function' && + Object.is(Object.keys(obj).length, 0)) + ); + } + + /** + * Object is Empty + * @param {(Object|Object[]|string)} obj - Array, object or string + * @returns {boolean} Returns boolean true or false + */ + isEmpty(obj) { + return this.isNull(obj) || this.isBlank(obj); + } + + isObj(obj) { + return obj instanceof Object && typeof obj.entries !== 'function' || typeof obj === 'object'; + } + + /** + * Has valid info + * @param {Object} info - Root information + * @param {string} template - template to use + * + * Templates: + * - steamID + * - squadID + * - squadName + * - TeamID + * - teamName + * @returns {boolean} Returns boolean true or false + */ + isValid(info, template) { + const check = this.validate(info, template); + if(Object.is(check, `<${template}>`)) { + return false; + }; + return check; + } + + /** + * Embed Builder + * @param {Number|string} color - Color of embed message + * @param {Date|string} time - Timestamp of embed message + * @param {string} title - Title of embed message + * @param {string} author - Author of embed message + * @returns {class} embed - EmbedBuilder() + */ + buildEmbed(color, time, title, author) { + const embed = new EmbedBuilder(); + if(!this.isEmpty(author)) { + if(isObj(author)) { + embed.setAuthor(author); + } else { + embed.setAuthor({ + name: author, + iconURL: null, + url: null + }); + } + }; + if(!this.isEmpty(color)) { + if(typeof color === 'string') { + embed.setColor(this.options.chatColors[color]) + } else { + embed.setColor(color) + }; + }; + if(this.isNull(time)) { + embed.setTimestamp(new Date()); + } else if(typeof time === 'string') { + embed.setTimestamp(new Date(time)); + } else { + embed.setTimestamp(time); + }; + if(!this.isEmpty(title)) { + embed.setTitle(title) + }; + return embed; + } + + /** + * Embed to Object + * @param {class|object} embed - EmbedBuilder() class + * @returns {object} Embed Object + */ + objEmbed(embed) { + if(Array.isArray(embed)) { + return { + embeds: embed + }; + }; + if(embed instanceof Set) { + return { + embeds: [...embed] + }; + }; + return { + embeds: [embed] + }; + } + + validator(obj, locate) { + let result = null; + for(const key in obj) { + if(key === locate) { + result = obj[key]; + break; + } else if(obj[key] instanceof Object) { + result = this.validator(obj[key], locate); + }; + }; + return result; + } + + validate(info, template) { + if (!this.isObj(info)) { + return 'Undefined'; + }; + const formatted = template.replace(/(<[\w\d]+>)/g, (_match, root) => { + const mfind = (txt) => { + const reg = new RegExp(txt, 'g'); + const txtMatch = root.match(/[\w\d]+/g)[0].match(reg) || []; + return !!txtMatch.length; + }; + const mFormat = (key, alt) => { + const extras = alt ?? key; + return this.isNull(key) ? root : extras; + }; + let response = null; + if(mfind('steamID')) { + response = mFormat(this.validator(info, 'steamID')) + } else if(mfind('squadID')) { + response = mFormat(this.validator(info, 'squadID')) + } else if(mfind('squadName')) { + response = mFormat(this.validator(info, 'squadName')) + } else if(mfind('name')) { + response = mFormat(this.validator(info, 'name')) + } else if(mfind('TeamID')) { + response = mFormat(this.validator(info, 'teamID')) + } else if(mfind('teamName')) { + response = mFormat(this.validator(info, 'teamName')) + } else { + response = root; + } + return response; + }); + return formatted; + } + async sendDiscordMessage(message) { + if (this.isEmpty(message)) { + this.verbose(1, 'Could not send Discord Message. Message is empty.'); + return; + } if (!this.channel) { this.verbose(1, `Could not send Discord Message. Channel not initialized.`); return; } - - if (typeof message === 'object' && 'embed' in message) - message.embed.footer = message.embed.footer || { text: COPYRIGHT_MESSAGE }; + if (typeof message === 'object' && 'embeds' in message) { + for(const e of message.embeds) { + e.setFooter({ + text: COPYRIGHT_MESSAGE, + iconURL: null + }); + }; + } await this.channel.send(message); } -} +} \ No newline at end of file diff --git a/squad-server/plugins/discord-chat.js b/squad-server/plugins/discord-chat.js index 4d22d2210..24d6f8621 100644 --- a/squad-server/plugins/discord-chat.js +++ b/squad-server/plugins/discord-chat.js @@ -53,33 +53,26 @@ export default class DiscordChat extends DiscordBasePlugin { async onChatMessage(info) { if (this.options.ignoreChats.includes(info.chat)) return; - - await this.sendDiscordMessage({ - embed: { - title: info.chat, - color: this.options.chatColors[info.chat] || this.options.color, - fields: [ - { - name: 'Player', - value: info.player.name, - inline: true - }, - { - name: 'SteamID', - value: `[${info.player.steamID}](https://steamcommunity.com/profiles/${info.steamID})`, - inline: true - }, - { - name: 'Team & Squad', - value: `Team: ${info.player.teamID}, Squad: ${info.player.squadID || 'Unassigned'}` - }, - { - name: 'Message', - value: `${info.message}` - } - ], - timestamp: info.time.toISOString() + const embed = this.buildEmbed(this.options.chatColors[info.chat] || this.options.color, info.time, info.chat).addFields( + { + name: 'Player', + value: info.player.name, + inline: true + }, + { + name: 'SteamID', + value: `[${info.player.steamID}](https://steamcommunity.com/profiles/${info.steamID})`, + inline: true + }, + { + name: 'Team & Squad', + value: `Team: ${info.player.teamID}, Squad: ${info.player.squadID || 'Unassigned'}` + }, + { + name: 'Message', + value: `${info.message}` } - }); + ); + await this.sendDiscordMessage(this.objEmbed(embed)); } } diff --git a/squad-server/plugins/discord-fob-hab-explosion-damage.js b/squad-server/plugins/discord-fob-hab-explosion-damage.js index 182e355b3..51afe9b8f 100644 --- a/squad-server/plugins/discord-fob-hab-explosion-damage.js +++ b/squad-server/plugins/discord-fob-hab-explosion-damage.js @@ -48,7 +48,7 @@ export default class DiscordFOBHABExplosionDamage extends DiscordBasePlugin { if (!info.weapon.match(/_Deployable_/i)) return; if (!info.player) return; - const fields = [ + const embed = this.buildEmbed(this.options.color, info.time, `FOB/HAB Explosion Damage: ${info.player.name}`).addFields( { name: "Player's Name", value: info.player.name, @@ -67,15 +67,7 @@ export default class DiscordFOBHABExplosionDamage extends DiscordBasePlugin { name: 'Weapon', value: info.weapon } - ]; - - await this.sendDiscordMessage({ - embed: { - title: `FOB/HAB Explosion Damage: ${info.player.name}`, - color: this.options.color, - fields: fields, - timestamp: info.time.toISOString() - } - }); + ); + await this.sendDiscordMessage(this.objEmbed(embed)); } } diff --git a/squad-server/plugins/discord-killfeed.js b/squad-server/plugins/discord-killfeed.js index 752e8104e..3f2a8cb1d 100644 --- a/squad-server/plugins/discord-killfeed.js +++ b/squad-server/plugins/discord-killfeed.js @@ -86,13 +86,10 @@ export default class DiscordKillFeed extends DiscordBasePlugin { value: `[Attacker's Bans](https://communitybanlist.com/search/${info.attacker.steamID})` }); - await this.sendDiscordMessage({ - embed: { - title: `KillFeed: ${info.attacker.name}`, - color: this.options.color, - fields: fields, - timestamp: info.time.toISOString() - } - }); + const embed = this.buildEmbed(this.options.color, info.time, `KillFeed: ${info.attacker.name}`); + for(const f of fields) { + embed.addFields(f) + } + await this.sendDiscordMessage(this.objEmbed(embed)); } } diff --git a/squad-server/plugins/discord-placeholder.js b/squad-server/plugins/discord-placeholder.js index 495f7c531..d6ba19345 100644 --- a/squad-server/plugins/discord-placeholder.js +++ b/squad-server/plugins/discord-placeholder.js @@ -42,11 +42,11 @@ export default class DiscordPlaceholder extends BasePlugin { } async mount() { - this.options.discordClient.on('message', this.onMessage); + this.options.discordClient.on('messageCreate', this.onMessage); } async unmount() { - this.options.discordClient.removeEventListener('message', this.onMessage); + this.options.discordClient.removeEventListener('messageCreate', this.onMessage); } async onMessage(message) { diff --git a/squad-server/plugins/discord-rcon.js b/squad-server/plugins/discord-rcon.js index 5f42e68e3..1efee9f6d 100644 --- a/squad-server/plugins/discord-rcon.js +++ b/squad-server/plugins/discord-rcon.js @@ -54,11 +54,11 @@ export default class DiscordRcon extends BasePlugin { } async mount() { - this.options.discordClient.on('message', this.onMessage); + this.options.discordClient.on('messageCreate', this.onMessage); } async unmount() { - this.options.discordClient.removeEventListener('message', this.onMessage); + this.options.discordClient.removeEventListener('messageCreate', this.onMessage); } async onMessage(message) { diff --git a/squad-server/plugins/discord-round-winner.js b/squad-server/plugins/discord-round-winner.js index 151534064..62e993f8c 100644 --- a/squad-server/plugins/discord-round-winner.js +++ b/squad-server/plugins/discord-round-winner.js @@ -41,18 +41,12 @@ export default class DiscordRoundWinner extends DiscordBasePlugin { } async onNewGame(info) { - await this.sendDiscordMessage({ - embed: { - title: 'Round Winner', - color: this.options.color, - fields: [ - { - name: 'Message', - value: `${info.winner} won on ${this.server.layerHistory[1].layer.name}.` - } - ], - timestamp: info.time.toISOString() + const embed = this.buildEmbed(this.options.color, info.time, 'Round Winner').addFields( + { + name: 'Message', + value: `${info.winner} won on ${this.server.layerHistory[1].layer.name}.` } - }); + ); + await this.sendDiscordMessage(this.objEmbed(embed)); } } diff --git a/squad-server/plugins/discord-roundended.js b/squad-server/plugins/discord-roundended.js index f9757b167..2d63430a2 100644 --- a/squad-server/plugins/discord-roundended.js +++ b/squad-server/plugins/discord-roundended.js @@ -41,39 +41,27 @@ export default class DiscordRoundEnded extends DiscordBasePlugin { } async onRoundEnd(info) { + const embed = this.buildEmbed(this.options.color, info.time); if (!info.winner || !info.loser) { - await this.sendDiscordMessage({ - embed: { - title: 'Round Ended', - description: 'This match Ended in a Draw', - color: this.options.color, - timestamp: info.time.toISOString() - } - }); + embed.setTitle('Round Ended').setDescription('This match Ended in a Draw'); + await this.sendDiscordMessage(this.objEmbed(embed)); return; } - await this.sendDiscordMessage({ - embed: { - title: 'Round Ended', - description: `${info.winner.layer} - ${info.winner.level}`, - color: this.options.color, - fields: [ - { - name: `Team ${info.winner.team} Won`, - value: `${info.winner.subfaction}\n ${info.winner.faction}\n won with ${info.winner.tickets} tickets.` - }, - { - name: `Team ${info.loser.team} Lost`, - value: `${info.loser.subfaction}\n ${info.loser.faction}\n lost with ${info.loser.tickets} tickets.` - }, - { - name: 'Ticket Difference', - value: `${info.winner.tickets - info.loser.tickets}.` - } - ], - timestamp: info.time.toISOString() + embed.setTitle('Round Ended').setDescription(`${info.winner.layer} - ${info.winner.level}`).addFields( + { + name: `Team ${info.winner.team} Won`, + value: `${info.winner.subfaction}\n ${info.winner.faction}\n won with ${info.winner.tickets} tickets.` + }, + { + name: `Team ${info.loser.team} Lost`, + value: `${info.loser.subfaction}\n ${info.loser.faction}\n lost with ${info.loser.tickets} tickets.` + }, + { + name: 'Ticket Difference', + value: `${info.winner.tickets - info.loser.tickets}.` } - }); + ); + await this.sendDiscordMessage(this.objEmbed(embed)); } } diff --git a/squad-server/plugins/discord-server-status.js b/squad-server/plugins/discord-server-status.js index 180c6f693..418ca8738 100644 --- a/squad-server/plugins/discord-server-status.js +++ b/squad-server/plugins/discord-server-status.js @@ -1,4 +1,4 @@ -import Discord from 'discord.js'; +import { ActivityType, EmbedBuilder } from 'discord.js'; import tinygradient from 'tinygradient'; import { COPYRIGHT_MESSAGE } from '../utils/constants.js'; @@ -55,11 +55,6 @@ export default class DiscordServerStatus extends DiscordBaseMessageUpdater { } async generateMessage() { - const embed = new Discord.MessageEmbed(); - - // Set embed title. - embed.setTitle(this.server.serverName); - // Set player embed field. let players = ''; @@ -70,37 +65,43 @@ export default class DiscordServerStatus extends DiscordBaseMessageUpdater { players += ` / ${this.server.publicSlots}`; if (this.server.reserveSlots > 0) players += ` (+${this.server.reserveSlots})`; - embed.addField('Players', players); - - // Set layer embed fields. - embed.addField( - 'Current Layer', - `\`\`\`${this.server.currentLayer?.name || 'Unknown'}\`\`\``, - true - ); - embed.addField( - 'Next Layer', - `\`\`\`${ - this.server.nextLayer?.name || (this.server.nextLayerToBeVoted ? 'To be voted' : 'Unknown') - }\`\`\``, - true - ); - + const embed = new EmbedBuilder() + // Set embed title. + .setTitle(this.server.serverName) + .addFields( + { + name: 'Players', + value: players + }, + // Set layer embed fields. + { + name: 'Current Layer', + value: `\`\`\`${this.server.currentLayer?.name || 'Unknown'}\`\`\``, + inline: true + }, + { + name: 'Next Layer', + value: `\`\`\`${ + this.server.nextLayer?.name || (this.server.nextLayerToBeVoted ? 'To be voted' : 'Unknown') + }\`\`\``, + inline: true + }, + ) // Set layer image. - embed.setImage( + .setImage( this.server.currentLayer ? `https://squad-data.nyc3.cdn.digitaloceanspaces.com/main/${this.server.currentLayer.layerid}.jpg` : undefined - ); - + ) // Set timestamp. - embed.setTimestamp(new Date()); - + .setTimestamp(new Date()) // Set footer. - embed.setFooter(COPYRIGHT_MESSAGE); - + .setFooter({ + text: COPYRIGHT_MESSAGE, + iconURL: null + }) // Set gradient embed color. - embed.setColor( + .setColor( parseInt( tinygradient([ { color: '#ff0000', pos: 0 }, @@ -113,17 +114,24 @@ export default class DiscordServerStatus extends DiscordBaseMessageUpdater { ) ); - return embed; + return { + embeds: [embed] + }; } async updateStatus() { if (!this.options.setBotStatus) return; - await this.options.discordClient.user.setActivity( - `(${this.server.a2sPlayerCount}/${this.server.publicSlots}) ${ - this.server.currentLayer?.name || 'Unknown' - }`, - { type: 'WATCHING' } - ); + await this.options.discordClient.user.setPresence({ + activities: [ + { + name: `(${this.server.a2sPlayerCount}/${this.server.publicSlots}) ${ + this.server.currentLayer?.name || 'Unknown' + }`, + type: ActivityType.Watching + } + ], + status: 'online' + }); } } diff --git a/squad-server/plugins/discord-squad-created.js b/squad-server/plugins/discord-squad-created.js index 1fe83830d..52e0fcba1 100644 --- a/squad-server/plugins/discord-squad-created.js +++ b/squad-server/plugins/discord-squad-created.js @@ -47,29 +47,23 @@ export default class DiscordSquadCreated extends DiscordBasePlugin { async onSquadCreated(info) { if (this.options.useEmbed) { - await this.sendDiscordMessage({ - embed: { - title: `Squad Created`, - color: this.options.color, - fields: [ - { - name: 'Player', - value: info.player.name, - inline: true - }, - { - name: 'Team', - value: info.teamName, - inline: true - }, - { - name: 'Squad Number & Squad Name', - value: `${info.player.squadID} : ${info.squadName}` - } - ], - timestamp: info.time.toISOString() + const embed = this.buildEmbed(this.options.color, info.time, 'Squad Created').addFields( + { + name: 'Player', + value: info.player.name, + inline: true + }, + { + name: 'Team', + value: info.teamName, + inline: true + }, + { + name: 'Squad Number & Squad Name', + value: `${info.player.squadID} : ${info.squadName}` } - }); + ); + await this.sendDiscordMessage(this.objEmbed(embed)); } else { await this.sendDiscordMessage( ` \`\`\`Player: ${info.player.name}\n created Squad ${info.player.squadID} : ${info.squadName}\n on ${info.teamName}\`\`\` ` diff --git a/squad-server/plugins/discord-subsystem-restarter.js b/squad-server/plugins/discord-subsystem-restarter.js index e718e7575..e6adb48b5 100644 --- a/squad-server/plugins/discord-subsystem-restarter.js +++ b/squad-server/plugins/discord-subsystem-restarter.js @@ -40,11 +40,11 @@ export default class DiscordSubsystemRestarter extends BasePlugin { } async mount() { - this.options.discordClient.on('message', this.onMessage); + this.options.discordClient.on('messageCreate', this.onMessage); } async unmount() { - this.options.discordClient.removeEventListener('message', this.onMessage); + this.options.discordClient.removeEventListener('messageCreate', this.onMessage); } async onMessage(message) { diff --git a/squad-server/plugins/discord-teamkill.js b/squad-server/plugins/discord-teamkill.js index b7e20ed55..1898bedf6 100644 --- a/squad-server/plugins/discord-teamkill.js +++ b/squad-server/plugins/discord-teamkill.js @@ -83,14 +83,10 @@ export default class DiscordTeamkill extends DiscordBasePlugin { name: 'Community Ban List', value: `[Attacker's Bans](https://communitybanlist.com/search/${info.attacker.steamID})` }); - - await this.sendDiscordMessage({ - embed: { - title: `Teamkill: ${info.attacker.name}`, - color: this.options.color, - fields: fields, - timestamp: info.time.toISOString() - } - }); + const embed = this.buildEmbed(this.options.color, info.time, `Teamkill: ${info.attacker.name}`); + for(const f of fields) { + embed.addFields(f) + } + await this.sendDiscordMessage(this.objEmbed(embed)); } }