Merge pull request #24 from SowinskiBraeden/refactor/migrate-player-stats

Refactor/migrate player stats
This commit is contained in:
SowinskiBraeden authored and GitHub committed 2023-10-29 18:25:04 -07:00
commit aa35d2d2cd
27 files changed
+442 -509

No files matched your search

+4 -3
View File
@@ -7,8 +7,9 @@ dev-*.js
# Logs
logs/*
npm-debug.log
#env
# env
.env
.DS_Store
# Admin Script backups
admin/backup/*
+70
View File
@@ -0,0 +1,70 @@
require('dotenv').config({ path: '../.env' });
const fs = require('fs');
const MongoClient = require('mongodb').MongoClient;
const guildId = process.env.GuildID;
const URI = process.env.mongoURI;
const dbo = process.env.dbo;
const NitradoServerID = process.env.SERVER_ID;
const client = new MongoClient(URI);
/*
!WARNING!
THIS SCRIPT IS MEANT ONLY FOR BOT ADMINISTRATORS WHO ARE RUNNING THE BOT + DATABASE
This script will migrate all playerstats from the guildSettings document in the "guilds" collection,
to their own collection as their own documents in the new "players" collection.
Only run this once you have bot version ^12.0.0 or higher.
*/
async function migrate() {
const package = await JSON.parse(fs.readFileSync('../package.json'));
const version = package.version.split('.').map(v => parseInt(v));
// Ensure version is 12.0.4 or higher.
if (version[0] < 12, version[2] < 4) throw new Error('Bot version does not meet requirements: v^12.0.4');
try {
// Get the database and collection on which to run the operation
const database = client.db(dbo);
const players = database.collection("players");
const guilds = database.collection("guilds");
// Get current guild settings + player stats
let guild = await guilds.findOne({"server.serverID": guildId});
// Create backup dir
const dir = __dirname + '/backup';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
// Ensure new required values are inserted into player stat.
guild.server.playerstats.map(stat => stat.nitradoServerID = NitradoServerID);
guild.server.playerstats.map(stat => stat.bountiesLength = stat.bounties.length);
// write JSON to file
fs.writeFileSync(`${dir}/player_stats_backup.json`, JSON.stringify(guild.server.playerstats, null, 2));
console.log(`A backup of playerstats was successfully created in ./backup/player_stats_backup.json in case of a fatal error.`);
// Move player stats to new collection.
const result = await players.insertMany(guild.server.playerstats, { ordered: true });
console.log(`${result.insertedCount} documents were inserted to "players" collections.`);
// Removes player stats from guild settings.
delete guild.server.playerstats;
// Update guild settings with removed player stats.
await guilds.updateOne({"server.serverID": guildId}, {$set: guild});
} catch (err) {
throw new Error(`An error occured while attempting to migrate player stats: ${err}`)
} finally {
await client.close();
console.log(`Successfully migrated player stats into the "players" collection.`);
}
}
migrate()
+14 -64
View File
@@ -2,7 +2,8 @@ const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, StringSelect
const CommandOptions = require('../util/CommandOptionTypes').CommandOptionTypes;
const bitfieldCalculator = require('discord-bitfield-calculator');
const { Armbands } = require('../database/armbands.js');
const { createUser, addUser } = require('../database/user')
const { createUser, addUser } = require('../database/user');
const { UpdatePlayer } = require('../database/player');
module.exports = {
name: "admin",
@@ -134,19 +135,8 @@ module.exports = {
if (args[0].name == 'gamertag-link') {
if (!client.exists(GuildDB.playerstats)) {
GuildDB.playerstats = [{}];
client.dbo.collection("guilds").updateOne({ "server.serverID": GuildDB.serverID }, {
$set: {
"server.playerstats": []
}
}, (err, res) => {
if (err) return client.sendInternalError(interaction, err);
});
}
let playerStat = GuildDB.playerstats.find(stat => stat.gamertag == args[0].options[1].value );
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** This gamertag \` ${args[0].options[1].value} \` cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least \` 5 minutes \`.`)] });
let playerStat = await client.dbo.collection("players").findOne({"gamertag": args[0].options[1].value});
if (!client.exists(playerStat)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** This gamertag \` ${args[0].options[1].value} \` cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least \` 5 minutes \`.`)] });
if (client.exists(playerStat.discordID)) {
const warnGTOverwrite = new EmbedBuilder()
@@ -170,14 +160,7 @@ module.exports = {
playerStat.discordID = args[0].options[0].value;
let playerStatIndex = GuildDB.playerstats.indexOf(playerStat);
GuildDB.playerstats[playerStatIndex] = playerStat;
client.dbo.collection("guilds").updateOne({ 'server.serverID': GuildDB.serverID }, {
$set: {
'server.playerstats': GuildDB.playerstats,
}
})
await UpdatePlayer(client, playerStat, interaction);
let member = interaction.guild.members.cache.get(args[0].options[0].value);
if (client.exists(GuildDB.linkedGamertagRole)) {
@@ -198,19 +181,8 @@ module.exports = {
} else if (args[0].name == 'gamertag-unlink') {
if (!client.exists(GuildDB.playerstats)) {
GuildDB.playerstats = [{}];
client.dbo.collection("guilds").updateOne({ "server.serverID": GuildDB.serverID }, {
$set: {
"server.playerstats": []
}
}, (err, res) => {
if (err) return client.sendInternalError(interaction, err);
});
}
let playerStat = GuildDB.playerstats.find(stat => stat.discordID == args[0].options[0].value );
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** <@${args[0].options[0].value}> has no gamertag linked.`)] });
let playerStat = await client.dbo.collection("players").findOne({"discordID": args[0].options[0].value});
if (!client.exists(playerStat)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** <@${args[0].options[0].value}> has no gamertag linked.`)] });
const warnGTOverwrite = new EmbedBuilder()
.setColor(client.config.Colors.Yellow)
@@ -294,20 +266,12 @@ module.exports = {
} else if (args[0].name == 'bounty-clear') {
let playerStat = GuildDB.playerstats.find(stat => stat.gamertag == args[0].options[0].value);
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription('**Not Found** This player cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least ` 5 minutes `.')] });
let playerStatIndex = GuildDB.playerstats.indexOf(playerStat);
let playerStat = await client.dbo.collection("players").findOne({"gamertag": args[0].options[0].value});
if (!client.exists(playerStat)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription('**Not Found** This player cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least ` 5 minutes `.')] });
playerStat.bounties = [];
GuildDB.playerstats[playerStatIndex] = playerStat;
client.dbo.collection("guilds").updateOne({ "server.serverID": GuildDB.serverID }, {
$set: {
'server.playerstats': GuildDB.playerstats,
}
}, (err, res) => {
if (err) return client.sendInternalError(interaction, err);
});
await UpdatePlayer(client, playerStat, interaction);
const clearedBounty = new EmbedBuilder()
.setColor(client.config.Colors.Green)
@@ -357,18 +321,11 @@ module.exports = {
return interaction.reply({ content: 'This interaction is not for you', flags: (1 << 6) });
if (interaction.customId.split('-')[1]=='yes') {
let playerStat = GuildDB.playerstats.find(stat => stat.gamertag == interaction.customId.split('-')[2]);
let playerStat = await client.dbo.collection("players").findOne({"gamertag": interaction.customId.split('-')[2]});
playerStat.discordID = interaction.customId.split('-')[3];
let playerStatIndex = GuildDB.playerstats.indexOf(playerStat);
GuildDB.playerstats[playerStatIndex] = playerStat;
client.dbo.collection("guilds").updateOne({ 'server.serverID': GuildDB.serverID }, {
$set: {
'server.playerstats': GuildDB.playerstats,
}
});
await UpdatePlayer(client, playerStat);
let member = interaction.guild.members.cache.get(interaction.member.user.id);
if (client.exists(GuildDB.linkedGamertagRole)) {
@@ -403,18 +360,11 @@ module.exports = {
return interaction.reply({ content: 'This interaction is not for you', flags: (1 << 6) });
if (interaction.customId.split('-')[1]=='yes') {
let playerStat = GuildDB.playerstats.find(stat => stat.discordID == interaction.customId.split('-')[2]);
let playerStat = await client.dbo.collection("players").findOne({"discordID": interaction.customId.split('-')[2]});
playerStat.discordID = "";
let playerStatIndex = GuildDB.playerstats.indexOf(playerStat);
GuildDB.playerstats[playerStatIndex] = playerStat;
client.dbo.collection("guilds").updateOne({ 'server.serverID': GuildDB.serverID }, {
$set: {
'server.playerstats': GuildDB.playerstats,
}
});
await UpdatePlayer(client, playerStat, interaction);
let connectedEmbed = new EmbedBuilder()
.setColor(client.config.Colors.Default)
+2 -2
View File
@@ -471,8 +471,8 @@ module.exports = {
let alarm = GuildDB.alarms.find(alarm => alarm.name == interaction.values[0]);
let alarmIndex = GuildDB.alarms.indexOf(alarm);
let playerStat = GuildDB.playerstats.find(stat => stat.gamertag == interaction.customId.split('-')[2]);
if (playerStat == undefined) return interaction.update({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription('**Not Found** This player cannot be found, the gamertag may be incorrect or this player has not logged onto the server before.')], components: [] });
let playerStat = await client.dbo.collection("players").findOne({"gamertag": interaction.customId.split('-')[2]});
if (!client.exists(playerStat)) return interaction.update({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription('**Not Found** This player cannot be found, the gamertag may be incorrect or this player has not logged onto the server before.')], components: [] });
let add = interaction.customId.split('-')[1] == 'add';
+13 -24
View File
@@ -1,6 +1,7 @@
const { EmbedBuilder } = require('discord.js');
const CommandOptions = require('../util/CommandOptionTypes').CommandOptionTypes;
const { createUser, addUser } = require('../database/user');
const { UpdatePlayer } = require('../database/player');
module.exports = {
name: "bounty",
@@ -76,9 +77,8 @@ module.exports = {
if (args[0].name == 'set') {
let playerStat = GuildDB.playerstats.find(stat => stat.gamertag == args[0].options[0].value);
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription('**Not Found** This player cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least ` 5 minutes `.')] });
let playerStatIndex = GuildDB.playerstats.indexOf(playerStat);
let playerStat = await client.dbo.collection("players").findOne({"gamertag": args[0].options[0].value});
if (!client.exists(playerStat)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription('**Not Found** This player cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least ` 5 minutes `.')] });
if (args[0].options[1].value > banking.guilds[GuildDB.serverID].balance) {
let nsf = new EmbedBuilder()
@@ -104,16 +104,9 @@ module.exports = {
setBy: (anonymous && !anonymous.value) ? interaction.member.user.id : null,
value: args[0].options[1].value,
});
playerStat.bountiesLength++;
GuildDB.playerstats[playerStatIndex] = playerStat;
client.dbo.collection("guilds").updateOne({ "server.serverID": GuildDB.serverID }, {
$set: {
'server.playerstats': GuildDB.playerstats,
}
}, (err, res) => {
if (err) return client.sendInternalError(interaction, err);
});
await UpdatePlayer(client, playerStat, interaction);
const successEmbed = new EmbedBuilder()
.setTitle('Success')
@@ -124,9 +117,8 @@ module.exports = {
} else if (args[0].name == 'pay') {
let playerStat = GuildDB.playerstats.find(stat => stat.discordID == interaction.member.user.id);
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription('**Not Found** Your user ID could not be found, contact an Admin.')] });
let playerStatIndex = GuildDB.playerstats.indexOf(playerStat);
let playerStat = await client.dbo.collection("players").findOne({"gamertag": interaction.member.user.id});
if (!client.exists(playerStat)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription('**Not Found** Your user ID could not be found, contact an Admin.')] });
if (playerStat.bounties.length == 0) {
const noBounty = new EmbedBuilder()
@@ -156,15 +148,9 @@ module.exports = {
});
playerStat.bounties = [];
GuildDB.playerstats[playerStatIndex] = playerStat;
playerStat.bountiesLength = 0;
client.dbo.collection("guilds").updateOne({ "server.serverID": GuildDB.serverID }, {
$set: {
'server.playerstats': GuildDB.playerstats,
}
}, (err, res) => {
if (err) return client.sendInternalError(interaction, err);
});
await UpdatePlayer(client, playerStat, interaction);
const payedOff = new EmbedBuilder()
.setColor(client.config.Colors.Green)
@@ -174,7 +160,10 @@ module.exports = {
} else if (args[0].name == 'view') {
let activeBounties = GuildDB.playerstats.filter((p) => p.bounties.length > 0);
// TODO: only get players with boutnies.length greater than 0
const activeBounties = await dbo.collection("players").find({
"bountiesLength": { $gt: 0 }
});
let bountiesEmbed = new EmbedBuilder()
.setColor(client.config.Colors.Default)
+1 -1
View File
@@ -1,7 +1,7 @@
const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
const CommandOptions = require('../util/CommandOptionTypes').CommandOptionTypes;
const bitfieldCalculator = require('discord-bitfield-calculator');
const { getDefaultSettings } = require('../database/guildSettings');
const { getDefaultSettings } = require('../database/guild');
module.exports = {
name: "config",
+4 -6
View File
@@ -40,8 +40,6 @@ module.exports = {
}
if (args[0].name == 'server-connection-stats') {
let stats = GuildDB.playerstats;
let statsEmbed = new EmbedBuilder()
.setColor(client.config.Colors.Default)
.setTitle(`Server connection stats`);
@@ -49,19 +47,19 @@ module.exports = {
statsEmbed.addFields({ name: 'All time Unique connections', value: `> ${stats.length}`, inline: false });
let month3 = new Date().setMonth(new Date().getMonth() - 3);
let month3Players = stats.filter((stat) => stat.lastConnectionDate > month3);
let month3Players = await client.dbo.collection("players").find({"lastConnectDate": {$gt: month3}});
statsEmbed.addFields({ name: 'Unique connections in the last 3 months', value: `> ${month3Players.length}`, inline: false });
let month = new Date().setMonth(new Date().getMonth() - 1);
let monthlyPlayers = stats.filter((stat) => stat.lastConnectionDate > month);
let monthlyPlayers = await client.dbo.collection("players").find({"lastConnectDate": {$gt: month}});
statsEmbed.addFields({ name: 'Unique connections in the last month', value: `> ${monthlyPlayers.length}`, inline: false });
let week = new Date(new Date().getTime() - 7 * 24 * 60 * 60 * 1000)
let weeklyPlayers = stats.filter((stat) => stat.lastConnectionDate > week);
let weeklyPlayers = await client.dbo.collection("players").find({"lastConnectDate": {$gt: week}});
statsEmbed.addFields({ name: 'Unique connections in the last week', value: `> ${weeklyPlayers.length}`, inline: false });
let today = new Date(new Date().getTime() - 1 * 24 * 60 * 60 * 1000)
let dailyPlayers = stats.filter((stat) => stat.lastConnectionDate > today);
let dailyPlayers = await client.dbo.collection("players").find({"lastConnectDate": {$gt: today}});
statsEmbed.addFields({ name: 'Unique connections in the last 24 hours', value: `> ${dailyPlayers.length}`, inline: false });
return interaction.send({ embeds: [statsEmbed] });
+2 -2
View File
@@ -83,8 +83,8 @@ module.exports = {
if (args[0].name == 'player-track') {
let playerStat = GuildDB.playerstats.find(stat => stat.gamertag == args[0].options[0].value );
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** This gamertag \` ${args[0].options[0].value} \` cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least \` 5 minutes \`.`)] });
let playerStat = await client.dbo.collection("players").findOne({"gamertag": args[0].options[0].value});
if (!client.exists(playerStat)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** This gamertag \` ${args[0].options[0].value} \` cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least \` 5 minutes \`.`)] });
let event = {
type: args[0].name,
+6 -30
View File
@@ -1,5 +1,6 @@
const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
const CommandOptions = require('../util/CommandOptionTypes').CommandOptionTypes;
const { UpdatePlayer } = require('../database/player');
module.exports = {
name: "gamertag-link",
@@ -28,19 +29,8 @@ module.exports = {
*/
run: async (client, interaction, args, { GuildDB }) => {
if (!client.exists(GuildDB.playerstats)) {
GuildDB.playerstats = [{}];
client.dbo.collection("guilds").updateOne({ "server.serverID": GuildDB.serverID }, {
$set: {
"server.playerstats": []
}
}, (err, res) => {
if (err) return client.sendInternalError(interaction, err);
});
}
let playerStat = GuildDB.playerstats.find(stat => stat.gamertag == args[0].value );
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** This gamertag \` ${args[0].value} \` cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least \` 5 minutes \`.`)] });
let playerStat = await client.dbo.collection("players").findOne({"gamertag": args[0].value});
if (!client.exists(playerStat)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** This gamertag \` ${args[0].value} \` cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least \` 5 minutes \`.`)] });
if (client.exists(playerStat.discordID)) {
const warnGTOverwrite = new EmbedBuilder()
@@ -64,14 +54,7 @@ module.exports = {
playerStat.discordID = interaction.member.user.id;
let playerStatIndex = GuildDB.playerstats.indexOf(playerStat);
GuildDB.playerstats[playerStatIndex] = playerStat;
client.dbo.collection("guilds").updateOne({ 'server.serverID': GuildDB.serverID }, {
$set: {
'server.playerstats': GuildDB.playerstats,
}
});
await UpdatePlayer(client, playerStat, interaction);
let member = interaction.guild.members.cache.get(interaction.member.user.id);
if (client.exists(GuildDB.linkedGamertagRole)) {
@@ -100,18 +83,11 @@ module.exports = {
return interaction.reply({ content: 'This interaction is not for you', flags: (1 << 6) });
if (interaction.customId.split('-')[1]=='yes') {
let playerStat = GuildDB.playerstats.find(stat => stat.gamertag == interaction.customId.split('-')[2]);
let playerStat = await client.dbo.collection("players").findOne({"gamertag": interaction.customId.split('-')[2]});
playerStat.discordID = interaction.member.user.id;
let playerStatIndex = GuildDB.playerstats.indexOf(playerStat);
GuildDB.playerstats[playerStatIndex] = playerStat;
client.dbo.collection("guilds").updateOne({ 'server.serverID': GuildDB.serverID }, {
$set: {
'server.playerstats': GuildDB.playerstats,
}
});
await UpdatePlayer(client, player, interaction);
let member = interaction.guild.members.cache.get(interaction.member.user.id);
if (client.exists(GuildDB.linkedGamertagRole)) {
+4 -22
View File
@@ -20,19 +20,8 @@ module.exports = {
*/
run: async (client, interaction, args, { GuildDB }) => {
if (!client.exists(GuildDB.playerstats)) {
GuildDB.playerstats = [{}];
client.dbo.collection("guilds").updateOne({ "server.serverID": GuildDB.serverID }, {
$set: {
"server.playerstats": []
}
}, (err, res) => {
if (err) return client.sendInternalError(interaction, err);
});
}
let playerStat = GuildDB.playerstats.find(stat => stat.discordID == interaction.member.user.id);
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**No Gamertag Linked** It Appears your don't have a gamertag linked to your account.`)] });
let playerStat = await client.dbo.collection("players").findOne({"discordID": interaction.member.user.id});
if (!client.exists(playerStat)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**No Gamertag Linked** It Appears your don't have a gamertag linked to your account.`)] });
const warnGTOverwrite = new EmbedBuilder()
.setColor(client.config.Colors.Yellow)
@@ -62,18 +51,11 @@ module.exports = {
return interaction.reply({ content: 'This interaction is not for you', flags: (1 << 6) });
if (interaction.customId.split('-')[1]=='yes') {
let playerStat = GuildDB.playerstats.find(stat => stat.discordID == interaction.member.user.id);
let playerStat = await client.dbo.collection("players").findOne({"discordID": interaction.member.user.id});
playerStat.discordID = "";
let playerStatIndex = GuildDB.playerstats.indexOf(playerStat);
GuildDB.playerstats[playerStatIndex] = playerStat;
client.dbo.collection("guilds").updateOne({ 'server.serverID': GuildDB.serverID }, {
$set: {
'server.playerstats': GuildDB.playerstats,
}
});
await UpdatePlayer(client, playerStat, interaction);
let connectedEmbed = new EmbedBuilder()
.setColor(client.config.Colors.Default)
+40 -49
View File
@@ -18,17 +18,18 @@ module.exports = {
type: CommandOptions.String,
required: true,
choices: [
{ name: "money", value: "money" },
{ name: "total_time_played", value: "total_time_played" },
{ name: "longest_time_played", value: "longest_time_played" },
{ name: "kills", value: "kills" },
{ name: "killstreak", value: "killstreak" },
{ name: "best_killstreak", value: "best_killstreak" },
{ name: "deaths", value: "deaths" },
{ name: "deathstreak", value: "deathstreak" },
{ name: "worst_deathstreak", value: "worst_deathstreak" },
{ name: "longest_kill", value: "longest_kill" },
{ name: "Money", value: "money" },
{ name: "Total Time Played", value: "totalSessionTime" },
{ name: "Longest Game Session", value: "longestSessionTime" },
{ name: "Kills", value: "kills" },
{ name: "Kill Streak", value: "killStreak" },
{ name: "Best Kill Streak", value: "bestKillStreak" },
{ name: "Deaths", value: "deaths" },
{ name: "Death Streak", value: "deathStreak" },
{ name: "Worst Death Streak", value: "worstDeathStreak" },
{ name: "Longest Kill", value: "longestKill" },
{ name: "KDR", value: "KDR" },
{ name: "Server Connections", value: "connections" },
]
}, {
name: "limit",
@@ -48,50 +49,39 @@ module.exports = {
* @param {*} param3
*/
run: async (client, interaction, args, { GuildDB }) => {
let category = args[0].value;
const category = args[0].value;
const limit = args[1].value;
let leaderboard;
let leaderboard = [];
if (category == 'money') {
let users = await client.dbo.collection("users").find({}).toArray();
leaderboard = users.sort(function(a, b) {
return b.user.guilds[GuildDB.serverID].balance - a.user.guilds[GuildDB.serverID].balance;
});
leaderboard = await client.dbo.collection("users").aggregate([
{ $sort: { [`user.guilds.${GuildDB.serverID}.balance`]: -1 } }
]).toArray();
} else {
leaderboard = GuildDB.playerstats.sort(function(a, b){
if (category == 'kills') return b.kills - a.kills;
if (category == 'killstreak') return b.killStreak - a.killStreak;
if (category == 'best_killstreak') return b.bestKillStreak - a.bestKillStreak;
if (category == 'deaths') return b.deaths - a.deaths;
if (category == 'deathstreak') return b.deathStreak - a.deathSreak;
if (category == 'worst_deathstreak') return b.worstDeathStreak - a.worstDeathStreak;
if (category == 'longest_kill') return b.longestKill - a.longestKill;
if (category == 'total_time_played') return b.totalSessionTime - a.totalSessionTime;
if (category == 'longest_time_played') return b.longestSessionTime - a.longestSessionTime;
if (category == 'KDR') return b.KDR - a.KDR;
});
leaderboard = await client.dbo.collection("players").aggregate([
{ $sort: { [`${category}`]: -1 } }
]).toArray();
}
let limit = args[1].value > leaderboard.length ? leaderboard.length : args[1].value;
let leaderboardEmbed = new EmbedBuilder()
.setColor(client.config.Colors.Default);
let title = category == 'kills' ? "Total Kills Leaderboard" :
category == 'killstreak' ? "Current Killstreak Leaderboard" :
category == 'best_killstreak' ? "Best Killstreak Leaderboard" :
category == 'killStreak' ? "Current Killstreak Leaderboard" :
category == 'bestKillStreak' ? "Best Killstreak Leaderboard" :
category == 'deaths' ? "Total Deaths Leaderboard" :
category == 'deathstreak' ? "Current Deathstreak Leaderboard" :
category == 'worst_deathstreak' ? "Worst Deathstreak Leaderboard" :
category == 'longest_kill' ? "Longest Kill Leaderboard" :
category == 'deathStreak' ? "Current Deathstreak Leaderboard" :
category == 'worstDeathStreak' ? "Worst Deathstreak Leaderboard" :
category == 'longestKill' ? "Longest Kill Leaderboard" :
category == 'money' ? "Money Leaderboard" :
category == 'total_time_played' ? "Total Time Played" :
category == 'longest_time_played' ? "Longest Game Session" :
category == 'KDR' ? "Kill Death Ratio" : 'N/A Error';
category == 'totalSessionTime' ? "Total Time Played" :
category == 'longestSessionTime' ? "Longest Game Session" :
category == 'KDR' ? "Kill Death Ratio" :
category == 'connections' ? "Times Connected" : 'N/A Error';
leaderboardEmbed.setTitle(`**${title} - DayZ Reforger**`);
@@ -100,25 +90,26 @@ module.exports = {
if (leaderboard.length < limit && i == leaderboard.length) break;
let stats = category == 'kills' ? `${leaderboard[i].kills} Kill${(leaderboard[i].kills>1||leaderboard[i].kills==0)?'s':''}` :
category == 'killstreak' ? `${leaderboard[i].killStreak} Player Killstreak` :
category == 'best_killstreak' ? `${leaderboard[i].bestKillStreak} Player Killstreak` :
category == 'killStreak' ? `${leaderboard[i].killStreak} Player Killstreak` :
category == 'bestKillStreak' ? `${leaderboard[i].bestKillStreak} Player Killstreak` :
category == 'deaths' ? `${leaderboard[i].deaths} Death${leaderboard[i].deaths>1||leaderboard[i].deaths==0?'s':''}` :
category == 'deathstreak' ? `${leaderboard[i].deathStreak} Deathstreak` :
category == 'worst_deathstreak' ? `${leaderboard[i].worstDeathStreak} Deathstreak` :
category == 'longest_kill' ? `${leaderboard[i].longestKill}m` :
category == 'deathStreak' ? `${leaderboard[i].deathStreak} Deathstreak` :
category == 'worstDeathstreak' ? `${leaderboard[i].worstDeathStreak} Deathstreak` :
category == 'longestKill' ? `${leaderboard[i].longestKill}m` :
category == 'money' ? `$${(leaderboard[i].user.guilds[GuildDB.serverID].balance).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}` :
category == 'total_time_played' ? `**Total:** ${client.secondsToDhms(leaderboard[i].totalSessionTime)}\n> **Last Session:** ${client.secondsToDhms(leaderboard[i].lastSessionTime)}` :
category == 'longest_time_played' ? `**Longest Game Session:** ${client.secondsToDhms(leaderboard[i].longestSessionTime)}` :
category == 'KDR' ? `**KDR: ${leaderboard[i].KDR.toFixed(2)}**` : 'N/A Error';
category == 'totalSessionTime' ? `**Total:** ${client.secondsToDhms(leaderboard[i].totalSessionTime)}\n> **Last Session:** ${client.secondsToDhms(leaderboard[i].lastSessionTime)}` :
category == 'longestSessionTime' ? `**Longest Game Session:** ${client.secondsToDhms(leaderboard[i].longestSessionTime)}` :
category == 'KDR' ? `**KDR: ${leaderboard[i].KDR.toFixed(2)}**` :
category == 'connection' ? `**Connections: ${leaderboard[i].connections}**` : 'N/A Error';
if (category == 'money') des += `**${i+1}.** <@${leaderboard[i].user.userID}> - **${stats}**\n`
else if (category == 'total_time_played' || category == 'longest_time_played') {
else if (category == 'totalSessionTime' || category == 'longestSessionTime') {
tag = leaderboard[i].discordID != "" ? `<@${leaderboard[i].discordID}>` : leaderboard[i].gamertag;
des += `**${i+1}.** ${tag}\n> ${stats}\n\n`;
} else leaderboardEmbed.addFields({ name: `**${i+1}. ${leaderboard[i].gamertag}**`, value: `**${stats}**`, inline: true });
}
if (['money', 'total_time_played', 'longest_time_played'].includes(category)) leaderboardEmbed.setDescription(des);
if (['money', 'totalSessionTime', 'longestSessionTime'].includes(category)) leaderboardEmbed.setDescription(des);
return interaction.send({ embeds: [leaderboardEmbed] });
},
+2 -14
View File
@@ -19,20 +19,8 @@ module.exports = {
* @param {*} param3
*/
run: async (client, interaction, args, { GuildDB }) => {
if (!client.exists(GuildDB.playerstats)) {
GuildDB.playerstats = [{}];
client.dbo.collection("guilds").updateOne({ "server.serverID": GuildDB.serverID }, {
$set: {
"server.playerstats": []
}
}, (err, res) => {
if (err) return client.sendInternalError(interaction, err);
});
}
let playerStat = GuildDB.playerstats.find(stat => stat.discordID == interaction.member.user.id );
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** You haven't linked your gamertag and are unable to use this command.`)], flags: (1 << 6) });
let playerStat = await client.dbo.collection("players").findOne({"discordID": interaction.member.user.id});
if (!client.exists(playerStat)) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** You haven't linked your gamertag and are unable to use this command.`)], flags: (1 << 6) });
let newDt = await client.getDateEST(playerStat.time);
let unixTime = Math.floor(newDt.getTime()/1000);
+2 -13
View File
@@ -46,20 +46,9 @@ module.exports = {
*/
run: async (client, interaction, args, { GuildDB }) => {
if (!client.exists(GuildDB.playerstats)) {
GuildDB.playerstats = [{}];
client.dbo.collection("guilds").updateOne({ "server.serverID": GuildDB.serverID }, {
$set: {
"server.playerstats": []
}
}, (err, res) => {
if (err) return client.sendInternalError(interaction, err);
});
}
if (args[0].name == 'discord') {
let playerStat = GuildDB.playerstats.find(stat => stat.gamertag == args[0].options[0].value );
let playerStat = await client.dbo.collection("players").findOne({"gamertag": args[0].options[0].value});
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** This gamertag \` ${args[0].options[0].value} \` cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least \` 5 minutes \`.`)] });
if (client.exists(playerStat.discordID)) {
@@ -78,7 +67,7 @@ module.exports = {
} else if (args[0].name == 'gamertag') {
let playerStat = GuildDB.playerstats.find(stat => stat.discordID == args[0].options[0].value );
let playerStat = await client.dbo.collection("players").findOne({"discordID": args[0].options[0].value});
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** The user <@${args[0].options[0].value}> has not linked a gamertag.`)] });
const found = new EmbedBuilder()
+1 -1
View File
@@ -21,7 +21,7 @@ module.exports = {
*/
run: async (client, interaction, args, { GuildDB }, start) => {
let activePlayers = GuildDB.playerstats.filter(p => p.connected == true);
let activePlayers = await client.dbo.collection("players").find({"connected": true});
let des = activePlayers.length > 0 ? `` : `**No Players Online**`;
for (let i = 0; i < activePlayers.length; i++) {
+36 -42
View File
@@ -18,17 +18,18 @@ module.exports = {
type: CommandOptions.String,
required: true,
choices: [
{ name: "money", value: "money" },
{ name: "total_time_played", value: "total_time_played" },
{ name: "longest_time_played", value: "longest_time_played" },
{ name: "kills", value: "kills" },
{ name: "killstreak", value: "killstreak" },
{ name: "best_killstreak", value: "best_killstreak" },
{ name: "deaths", value: "deaths" },
{ name: "deathstreak", value: "deathstreak" },
{ name: "worst_deathstreak", value: "worst_deathstreak" },
{ name: "longest_kill", value: "longest_kill" },
{ name: "Money", value: "money" },
{ name: "Total Time Played", value: "totalSessionTime" },
{ name: "Longest Game Session", value: "longestSessionTime" },
{ name: "Kills", value: "kills" },
{ name: "Kill Streak", value: "killStreak" },
{ name: "Best Kill Streak", value: "bestKillStreak" },
{ name: "Deaths", value: "deaths" },
{ name: "Death Streak", value: "deathStreak" },
{ name: "Worst Death Streak", value: "worstDeathStreak" },
{ name: "Longest Kill", value: "longestKill" },
{ name: "KDR", value: "KDR" },
{ name: "Server Connections", value: "connections" },
]
}, {
name: "discord",
@@ -57,20 +58,19 @@ module.exports = {
let playerStat;
if (!discord && gamertag) {
playerStat = GuildDB.playerstats.find(stat => stat.gamertag == gamertag );
playerStat = await client.dbo.collection("players").findOne({"gamertag": gamertag});
if (playerStat == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** This gamertag \` ${args[0].value} \` cannot be found, the gamertag may be incorrect or this player has not logged onto the server before for at least \` 5 minutes \`.`)] });
}
let query;
let leaderboard;
let leaderboardPos;
if (category == 'money') {
let users = await client.dbo.collection("users").find({}).toArray();
leaderboard = users.sort(function(a, b) {
return b.user.guilds[GuildDB.serverID].balance - a.user.guilds[GuildDB.serverID].balance;
});
leaderboard = await client.dbo.collection("users").aggregate([
{ $sort: { [`user.guilds.${GuildDB.serverID}.balance`]: -1 } }
]).toArray();
if (discord) { // If searching by discord
query = leaderboard.find(u => u.user.userID == discord);
@@ -88,18 +88,9 @@ module.exports = {
} else {
leaderboard = GuildDB.playerstats.sort(function(a, b){
if (category == 'kills') return b.kills - a.kills;
if (category == 'killstreak') return b.killStreak - a.killStreak;
if (category == 'best_killstreak') return b.bestKillStreak - a.bestKillStreak;
if (category == 'deaths') return b.deaths - a.deaths;
if (category == 'deathstreak') return b.deathStreak - a.deathSreak;
if (category == 'worst_deathstreak') return b.worstDeathStreak - a.worstDeathStreak;
if (category == 'longest_kill') return b.longestKill - a.longestKill;
if (category == 'total_time_played') return b.totalSessionTime - a.totalSessionTime;
if (category == 'longest_time_played') return b.longestSessionTime - a.longestSessionTime;
if (category == 'KDR') return b.KDR - a.KDR;
});
leaderboard = await client.dbo.collection("players").aggregate([
{ $sort: { [`${category}`]: -1 } }
]).toArray();
if (discord) { // If searching by discord
query = leaderboard.find(s => s.discordID == discord);
@@ -113,20 +104,22 @@ module.exports = {
if (query == undefined) return interaction.send({ embeds: [new EmbedBuilder().setColor(client.config.Colors.Yellow).setDescription(`**Not Found** Unable to find any records with the gamertag or user provided.`)] });
leaderboardPos = leaderboard.indexOf(query);
}
leaderboardPos++; // add one to leaderboard pos because it is index in array and we want index zero to be num. one, index one to be num. two, etc. etc.
let title = category == 'kills' ? "Total Kills" :
category == 'killstreak' ? "Current Killstreak" :
category == 'best_killstreak' ? "Best Killstreak" :
category == 'killStreak' ? "Current Killstreak" :
category == 'bestkillStreak' ? "Best Killstreak" :
category == 'deaths' ? "Total Deaths" :
category == 'deathstreak' ? "Current Deathstreak" :
category == 'worst_deathstreak' ? "Worst Deathstreak" :
category == 'longest_kill' ? "Longest Kill" :
category == 'deathStreak' ? "Current Deathstreak" :
category == 'worstDeathStreak' ? "Worst Deathstreak" :
category == 'longestKill' ? "Longest Kill" :
category == 'money' ? "Total Money" :
category == 'total_time_played' ? "Total Time Played" :
category == 'longest_time_played' ? "Longest Game Session" :
category == 'KDR' ? "Kill Death Ratio" : 'N/A Error';
category == 'totalSessionTime' ? "Total Time Played" :
category == 'longestSessionTime' ? "Longest Game Session" :
category == 'KDR' ? "Kill Death Ratio" :
category == 'connections' ? "Times Connected" : 'N/A Error';
let statsEmbed = new EmbedBuilder()
.setColor(client.config.Colors.Default);
@@ -139,14 +132,15 @@ module.exports = {
let des = ``;
let stats = category == 'kills' ? `${query.kills} Kill${(query.kills>1||query.kills==0)?'s':''}` :
category == 'killstreak' ? `${query.killStreak} Player Killstreak` :
category == 'best_killstreak' ? `${query.bestKillStreak} Player Killstreak` :
category == 'killStreak' ? `${query.killStreak} Player Killstreak` :
category == 'bestKillStreak' ? `${query.bestKillStreak} Player Killstreak` :
category == 'deaths' ? `${query.deaths} Death${query.deaths>1||query.deaths==0?'s':''}` :
category == 'deathstreak' ? `${query.deathStreak} Deathstreak` :
category == 'worst_deathstreak' ? `${query.worstDeathStreak} Deathstreak` :
category == 'longest_kill' ? `${query.longestKill}m` :
category == 'deathStreak' ? `${query.deathStreak} Deathstreak` :
category == 'worstDeathStreak' ? `${query.worstDeathStreak} Deathstreak` :
category == 'longestKill' ? `${query.longestKill}m` :
category == 'money' ? `$${(query.user.guilds[GuildDB.serverID].balance).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}` :
category == 'KDR' ? `${query.KDR.toFixed(2)} KDR` : 'N/A Error';
category == 'KDR' ? `${query.KDR.toFixed(2)} KDR` :
category == 'connections' ? `${query.connections} connections` : 'N/A Error';
statsEmbed.addFields({ name: 'Leaderboard Position', value: `# ${leaderboardPos}`, inline: true });
+93
View File
@@ -0,0 +1,93 @@
module.exports = {
GetGuild: async (client, GuildId) => {
let guild = undefined;
if (client.databaseConnected) guild = await client.dbo.collection("guilds").findOne({"server.serverID":GuildId}).then(guild => guild);
// If guild not found, generate guild default
if (!guild) {
guild = {}
guild.server = module.exports.getDefaultSettings(GuildId);
if (client.databaseConnected) {
thiclients.dbo.collection("guilds").insertOne(guild, (err, res) => {
if (err) throw err;
});
}
}
return {
serverID: GuildId,
autoRestart: guild.server.autoRestart,
showKillfeedCoords: guild.server.showKillfeedCoords,
purchaseUAV: guild.server.purchaseUAV,
purchaseEMP: guild.server.purchaseEMP,
allowedChannels: guild.server.allowedChannels,
customChannelStatus: guild.server.allowedChannels.length > 0 ? true : false,
hasBotAdmin: guild.server.botAdminRoles.length > 0 ? true : false,
killfeedChannel: guild.server.killfeedChannel,
connectionLogsChannel: guild.server.connectionLogsChannel,
activePlayersChannel: guild.server.activePlayersChannel,
welcomeChannel: guild.server.welcomeChannel,
factionArmbands: guild.server.factionArmbands,
usedArmbands: guild.server.usedArmbands,
excludedRoles: guild.server.excludedRoles,
botAdminRoles: guild.server.botAdminRoles,
alarms: guild.server.alarms,
events: guild.server.events,
uavs: guild.server.uavs,
incomeRoles: guild.server.incomeRoles,
incomeLimiter: guild.server.incomeLimiter,
startingBalance: guild.server.startingBalance,
uavPrice: guild.server.uavPrice,
empPrice: guild.server.empPrice,
linkedGamertagRole: guild.server.linkedGamertagRole,
memberRole: guild.server.memberRole,
adminRole: guild.server.adminRole,
combatLogTimer: guild.server.combatLogTimer,
};
},
getDefaultSettings(GuildId) {
return {
serverID: GuildId,
autoRestart: 0, //
showKillfeedCoords: 0,
purchaseUAV: 1, // Allow/Disallow purchase of UAVs
purchaseEMP: 1, // Allow/Disallow purchase of EMPs
allowedChannels: [],
killfeedChannel: "",
connectionLogsChannel: "",
activePlayersChannel: "",
welcomeChannel: "",
factionArmbands: {},
usedArmbands: [],
excludedRoles: [],
botAdminRoles: [],
alarms: [],
events: [],
uavs: [],
incomeRoles: [],
incomeLimiter: 168, // # of hours in 7 days
startingBalance: 500,
uavPrice: 50000,
empPrice: 500000,
linkedGamertagRole: "",
memberRole: "",
adminRole: "",
combatLogTimer: 5, // minutes
}
}
}
-41
View File
@@ -1,41 +0,0 @@
module.exports = {
getDefaultSettings(GuildId) {
return {
serverID: GuildId,
autoRestart: 0, //
showKillfeedCoords: 0,
purchaseUAV: 1, // Allow/Disallow purchase of UAVs
purchaseEMP: 1, // Allow/Disallow purchase of EMPs
allowedChannels: [],
killfeedChannel: "",
connectionLogsChannel: "",
activePlayersChannel: "",
welcomeChannel: "",
factionArmbands: {},
usedArmbands: [],
excludedRoles: [],
botAdminRoles: [],
playerstats: [], // to be removed
alarms: [],
events: [],
uavs: [],
incomeRoles: [],
incomeLimiter: 168, // # of hours in 7 days
startingBalance: 500,
uavPrice: 50000,
empPrice: 500000,
linkedGamertagRole: "",
memberRole: "",
adminRole: "",
combatLogTimer: 5, // minutes
}
}
}
@@ -1,9 +1,19 @@
module.exports = {
getDefaultPlayerStats(gt, pID) {
UpdatePlayer: async (client, player, interaction=null) => {
return await client.dbo.collection("players").updateOne({"playerID": player.playerID}, {$set: player}, (err, _) => {
if (err) {
if (intearction == null) return client.error(err);
else return client.sendInternalError(interaction, err);
}
});
},
getDefaultPlayer(gt, pID, NSID) {
return {
gamertag: gt,
playerID: pID,
discordID: "",
nitradoServerID: NSID,
KDR: 0.00,
kills: 0,
@@ -29,6 +39,7 @@ module.exports = {
totalSessionTime: 0,
lastSessionTime: 0,
longestSessionTime: 0,
connections: 0,
bounties: [],
}
+2 -1
View File
@@ -1,8 +1,9 @@
const { EmbedBuilder } = require('discord.js');
const { GetGuild } = require('../database/guild');
module.exports = async (client, member) => {
let GuildDB = await client.GetGuild(member.guild.id);
let GuildDB = await GetGuild(client, member.guild.id);
const channel = client.GetChannel(GuildDB.welcomeChannel);
let embed = new EmbedBuilder()
+3 -1
View File
@@ -1,3 +1,5 @@
const { GetGuild } = require('../database/guild');
module.exports = async (client, interaction) => {
if (interaction.isCommand()) return;
/*
@@ -5,7 +7,7 @@ module.exports = async (client, interaction) => {
from any command
*/
let GuildDB = await client.GetGuild(interaction.guildId);
let GuildDB = await GetGuild(client, interaction.guildId);
const interactionName = interaction.customId.split("-")[0];
let interactionHandler = client.interactionHandlers.get(interactionName);
+1
View File
@@ -8,6 +8,7 @@ const { HandleActivePlayersList } = require('./util/LogsHandler');
// Log all uncaught exceptions before killing process.
process.on('uncaughtException', async (error) => {
console.trace(error);
let d = new Date();
// Asynchronously write the error message to a log file using Promises
await new Promise((resolve, reject) => {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "dayzr-bot",
"version": "11.5.3",
"version": "12.0.4",
"description": "A General Purpose Discord Bot for DayZ Nitrado Servers.",
"main": "index.js",
"nodemonConfig": {
+49 -87
View File
@@ -11,8 +11,8 @@ const { HandleKillfeed, UpdateLastDeathDate } = require('../util/KillfeedHandler
const { HandleExpiredUAVs, HandleEvents, PlaceFireplaceInAlarm } = require('../util/AlarmsHandler');
// Data structures imports
const { getDefaultPlayerStats } = require('../database/playerStatistics');
const { getDefaultSettings } = require('../database/guildSettings');
const { getDefaultPlayer, UpdatePlayer } = require('../database/player');
const { GetGuild } = require('../database/guild');
const path = require("path");
const fs = require('fs');
@@ -56,7 +56,7 @@ class DayzRBot extends Client {
this.ws.on("INTERACTION_CREATE", async (interaction) => {
const start = new Date().getTime();
if (interaction.type != 3) {
let GuildDB = await this.GetGuild(interaction.guild_id);
let GuildDB = await GetGuild(this, interaction.guild_id);
for (const [factionID, data] of Object.entries(GuildDB.factionArmbands)) {
const guild = this.guilds.cache.get(GuildDB.serverID);
@@ -134,7 +134,7 @@ class DayzRBot extends Client {
return new Date(f.getTime() + 4 * 3600000); // Add EST time offset to return timestamp in UTC
}
async readLogs(guildId) {
async readLogs(guild) {
const fileStream = fs.createReadStream('./logs/server-logs.ADM');
let logHistoryDir = path.join(__dirname, '..', 'logs', 'history-logs.ADM.json');
@@ -156,41 +156,58 @@ class DayzRBot extends Client {
let logIndex = lines.indexOf(history.lastLog);
let guild = await this.GetGuild(guildId);
if (!this.exists(guild.playerstats)) guild.playerstats = [];
let s = guild.playerstats;
if (this.playerSessions.size === 0) {
s.map(p => p.connected = false); // assume all players not connected on init only.
let players = await this.dbo.collection('players').find({"connected": true}).toArray();
players.map(p => p.connected = false); // assume all players not connected on init only.
for (let i = 0; i < players.length; i++) {
UpdatePlayer(this, players[i])
}
}
for (let i = logIndex + 1; i < lines.length; i++) {
// Handle lines to skip
if (lines[i].includes('| ####')) continue;
if (lines[i].includes("(id=Unknown") || lines[i].includes("Player \"Unknown Entity\"")) continue;
if ((i - 1) >= 0 && lines[i] == lines[i - 1]) continue; // continue if this line is a duplicate of the last line
if (lines[i].includes('connected') || lines[i].includes('pos=<')) s = await HandlePlayerLogs(this, guildId, s, lines[i], guild.combatLogTimer);
if (lines[i].includes('killed by with') || lines[i].includes('killed by LandMineTrap')) s = await HandleKillfeed(this, guildId, s, lines[i]); // Handles explosive deaths
if (!(i + 1 >= lines.length) && lines[i + 1].includes('killed by') && lines[i].includes('TransportHit')) s = await HandleKillfeed(this, guildId, s, lines[i]) // Handles vehicle deaths
if (!(i + 1 >= lines.length) && lines[i + 1].includes('killed by Player') && lines[i].includes('hit by Player')) s = await HandleKillfeed(this, guildId, s, lines[i]); // Handles regular deaths
if (lines[i].includes('killed by Player') && !lines[i - 1].includes('hit by Player')) s = await HandleKillfeed(this, guildId, s, lines[i]); // Handles deaths missing hit by log
if (lines[i].includes('killed by Zmb') || lines[i].includes('>) died.')) s = await UpdateLastDeathDate(this, s, lines[i]); // Updates users last death date for non PVP deaths.
if (lines[i].includes(') placed Fireplace')) await PlaceFireplaceInAlarm(this, guildId, lines[i]);
// Handle general logs
if (lines[i].includes('connected') || lines[i].includes('pos=<')) await HandlePlayerLogs(this, guild, lines[i], guild.combatLogTimer);
if (lines[i].includes('killed by Zmb') || lines[i].includes('>) died.')) await UpdateLastDeathDate(this, lines[i]); // Updates users last death date for non PVP deaths.
if (lines[i].includes(') placed Fireplace')) await PlaceFireplaceInAlarm(this, guild, lines[i]);
// Handle killfeed logs
if (lines[i].includes('killed by with') || lines[i].includes('killed by LandMineTrap')) await HandleKillfeed(this, guild, lines[i]); // Handles explosive deaths
if (!(i + 1 >= lines.length) && lines[i + 1].includes('killed by') && lines[i].includes('TransportHit')) await HandleKillfeed(this, guild, lines[i]); // Handles vehicle deaths
if (!(i + 1 >= lines.length) && lines[i + 1].includes('killed by Player') && lines[i].includes('hit by Player')) await HandleKillfeed(this, guild, lines[i]); // Handles regular deaths
if (lines[i].includes('killed by Player') && !lines[i - 1].includes('hit by Player')) await HandleKillfeed(this, guild, lines[i]); // Handles deaths missing hit by log
}
// Handle alarm pings
const maxEmbed = 10;
for (const [channel_id, data] of Object.entries(this.alarmPingQueue)) {
const channel = this.GetChannel(channel_id);
if (!channel) continue;
for (const [role, embeds] of Object.entries(data)) {
if (role == '-no-role-ping-') channel.send({ embeds: embeds });
else channel.send({ content: `<@&${role}>`, embeds: embeds });
if (embeds.length > maxEmbed) {
let embedArrays = [];
while (embeds.length > maxEmbed)
embedArrays.push(embeds.splice(0, maxEmbed));
for (let i = 0; i < embedArrays.length; i++) {
if (role == '-no-role-ping-') channel.send({ embeds: embedArrays[i] });
else channel.send({ content: `<@&${role}>`, embeds: embedArrays[i] });
}
} else {
if (role == '-no-role-ping-') channel.send({ embeds: embeds });
else channel.send({ content: `<@&${role}>`, embeds: embeds });
}
}
}
this.alarmPingQueue = {};
const playerTemplate = /(.*) \| Player \"(.*)\" \(id=(.*) pos=<(.*)>\)/g;
let previouslyConnected = s.filter(p => p.connected); // All players with connection log captured above and no disconnect log
let previouslyConnected = await this.dbo.collection('players').find({"connected": true}).toArray(); // All players with connection log captured above and no disconnect log
let lastDetectedTime;
for (let i = lines.length - 1; i > 0; i--) {
@@ -211,8 +228,9 @@ class DayzRBot extends Client {
if (!this.exists(info.player) || !this.exists(info.playerID)) continue; // Skip this player if the player does not exist.
lastDetectedTime = await this.getDateEST(info.time);
let playerStat = s.find(stat => stat.playerID == info.playerID);
if (playerStat == undefined) playerStat = getDefaultPlayerStats(info.player, info.playerID);
let playerStat = await this.dbo.collection("players").findOne({"playerID": info.playerID});
if (!this.exists(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID, this.config.Nitrado.ServerID);
if (!previouslyConnected.includes(playerStat) && this.exists(playerStat.lastDisconnectionDate) && playerStat.lastDisconnectionDate !== null && playerStat.lastDisconnectionDate.getTime() > lastDetectedTime.getTime()) continue; // Skip this player if the lastDisconnectionDate time is later than the player log entry.
@@ -237,22 +255,12 @@ class DayzRBot extends Client {
}
}
let playerStatIndex = s.indexOf(playerStat);
if (playerStatIndex == -1) s.push(playerStat);
else s[playerStatIndex] = playerStat;
await UpdatePlayer(this, playerStat);
}
break;
}
}
await this.dbo.collection("guilds").updateOne({ "server.serverID": guildId }, {
$set: {
"server.playerstats": s
}
}, (err, res) => {
if (err) this.sendError(this.GetChannel(guild.adminLogsChannel), err);
});
history.lastLog = lines[lines.length - 1];
// write JSON string to a file
@@ -260,8 +268,8 @@ class DayzRBot extends Client {
}
async logsUpdateTimer(c) {
if (this.processingLogs) return; // Process is already running, wait till next scheduled time.
this.processingLogs = true;
if (c.processingLogs) return; // Process is already running, wait till next scheduled time.
c.processingLogs = true;
let t = new Date();
// c.log(`...Logs Tick - ${t.getHours()}:${t.getMinutes()}:${t.getSeconds()}...`);
c.activePlayersTick++;
@@ -270,17 +278,19 @@ class DayzRBot extends Client {
const filename = settings.game_specific.log_files.sort((a, b) => a.length - b.length)[0];
const path = `${settings.game_specific.path.slice(0, -1)}${filename.split(settings.game)[1]}`;
let guild = await GetGuild(c, c.config.GuildID);
await DownloadNitradoFile(c, path, './logs/server-logs.ADM').then(async (status) => {
if (status == 1) return c.error('...Failed to Download logs...');
// c.log('...Downloaded logs...');
await c.readLogs(c.config.GuildID).then(async () => {
await c.readLogs(guild).then(async () => {
// c.log('...Analyzed logs...');
HandleExpiredUAVs(c, c.config.GuildID);
HandleEvents(c, c.config.GuildID)
if (c.activePlayersTick == 12) await HandleActivePlayersList(c, c.config.GuildID);
HandleExpiredUAVs(c, guild);
HandleEvents(c, guild)
if (c.activePlayersTick == 12) await HandleActivePlayersList(c, guild);
})
});
this.processingLogs = false;
c.processingLogs = false;
}
async connectMongo(mongoURI, dbo) {
@@ -422,54 +432,6 @@ class DayzRBot extends Client {
this.guilds.cache.forEach((guild) => RegisterGuildCommands(this, guild.id));
}
async GetGuild(GuildId) {
let guild = undefined;
if (this.databaseConnected) guild = await this.dbo.collection("guilds").findOne({"server.serverID":GuildId}).then(guild => guild);
// If guild not found, generate guild default
if (!guild) {
guild = {}
guild.server = getDefaultSettings(GuildId);
if (this.databaseConnected) {
this.dbo.collection("guilds").insertOne(guild, (err, res) => {
if (err) throw err;
});
}
}
return {
serverID: GuildId,
autoRestart: guild.server.autoRestart,
customChannelStatus: guild.server.allowedChannels.length > 0 ? true : false,
allowedChannels: guild.server.allowedChannels,
factionArmbands: guild.server.factionArmbands,
usedArmbands: guild.server.usedArmbands,
excludedRoles: guild.server.excludedRoles,
hasBotAdmin: guild.server.botAdminRoles.length > 0 ? true : false,
botAdminRoles: guild.server.botAdminRoles,
playerstats: guild.server.playerstats,
alarms: guild.server.alarms,
events: guild.server.events,
uavs: guild.server.uavs,
killfeedChannel: guild.server.killfeedChannel,
showKillfeedCoords: guild.server.showKillfeedCoords,
connectionLogsChannel: guild.server.connectionLogsChannel,
welcomeChannel: guild.server.welcomeChannel,
activePlayersChannel: guild.server.activePlayersChannel,
linkedGamertagRole: guild.server.linkedGamertagRole,
incomeRoles: guild.server.incomeRoles,
incomeLimiter: guild.server.incomeLimiter,
startingBalance: guild.server.startingBalance,
uavPrice: guild.server.uavPrice,
empPrice: guild.server.empPrice,
memberRole: guild.server.memberRole,
adminRole: guild.server.adminRole,
combatLogTimer: guild.server.combatLogTimer,
purchaseUAV: guild.server.purchaseUAV,
purchaseEMP: guild.server.purchaseEMP,
};
}
build() {
this.login(this.config.Token);
}
+3 -6
View File
@@ -4,8 +4,7 @@ const { calculateVector } = require('./vector');
module.exports = {
SendConnectionLogs: async (client, guildId, data) => {
let guild = await client.GetGuild(guildId);
SendConnectionLogs: async (client, guild, data) => {
if (!client.exists(guild.connectionLogsChannel)) return;
const channel = client.GetChannel(guild.connectionLogsChannel);
@@ -27,10 +26,8 @@ module.exports = {
if (client.exists(channel)) await channel.send({ embeds: [connectionLog] });
},
DetectCombatLog: async (client, guildId, data) => {
DetectCombatLog: async (client, guild, data) => {
if (!client.exists(data.lastDamageDate)) return;
let guild = await client.GetGuild(guildId);
if (!client.exists(guild.connectionLogsChannel)) return;
const newDt = await client.getDateEST(data.time);
@@ -43,7 +40,7 @@ module.exports = {
// If lastHitBy (attacker) died after shooting this player
// then it does not count as combat logging, (the combat ended due to death)
let attacker = guild.playerstats.find(stat => stat.gamertag = data.lastHitBy);
let attacker = await client.dbo.collection("players").findOne({"gamertag": data.lastHitBy});
if (attacker.lastDeathDate > data.lastDamageDate) return;
const channel = client.GetChannel(guild.connectionLogsChannel);
+8 -14
View File
@@ -2,6 +2,7 @@ const { BanPlayer, UnbanPlayer } = require('./NitradoAPI');
const { EmbedBuilder } = require('discord.js');
const { calculateVector } = require('./vector');
const { destinations } = require('../database/destinations');
const { GetGuild } = require('../database/guild');
// Private functions (only called locally)
@@ -20,7 +21,7 @@ const ExpireEvent = async(client, guild, e) => {
}
const HandlePlayerTrackEvent = async (client, guild, e) => {
let player = guild.playerstats.find(stat => stat.gamertag == e.gamertag );
let player = await client.dbo.collection("players").findOne({"gamertag": e.gamertag});
let newDt = await client.getDateEST(player.time);
let unixTime = Math.floor(newDt.getTime()/1000);
@@ -58,8 +59,7 @@ const HandlePlayerTrackEvent = async (client, guild, e) => {
module.exports = {
HandleAlarmsAndUAVs: async (client, guildId, data) => {
let guild = await client.GetGuild(guildId);
HandleAlarmsAndUAVs: async (client, guild, data) => {
for (let i = 0; i < guild.alarms.length; i++) {
let alarm = guild.alarms[i];
@@ -137,8 +137,7 @@ module.exports = {
}
},
HandleExpiredUAVs: async (client, guildId) => {
let guild = await client.GetGuild(guildId);
HandleExpiredUAVs: async (client, guild) => {
let uavs = guild.uavs;
let update = false;
@@ -161,7 +160,7 @@ module.exports = {
}
if (update) {
client.dbo.collection("guilds").updateOne({ "server.serverID": guildId }, {$set: { "server.uavs": uavs }}, (err, res) => {
client.dbo.collection("guilds").updateOne({ "server.serverID": guild.serverID }, {$set: { "server.uavs": uavs }}, (err, res) => {
if (err) return client.sendError(client.GetChannel(guild.adminLogsChannel), err);
});
}
@@ -169,7 +168,7 @@ module.exports = {
KillInAlarm: async (client, guildId, data) => {
let guild = await client.GetGuild(guildId);
let guild = await GetGuild(client, guildId);
for (let i = 0; i < guild.alarms.length; i++) {
let alarm = guild.alarms[i];
@@ -199,7 +198,7 @@ module.exports = {
return;
},
PlaceFireplaceInAlarm: async (client, guildId, line) => {
PlaceFireplaceInAlarm: async (client, guild, line) => {
let fireplacePlacement = /(.*) \| Player \"(.*)\" \(id=(.*) pos=<(.*)>\) placed Fireplace/g;
let data = [...line.matchAll(fireplacePlacement)][0];
@@ -212,8 +211,6 @@ module.exports = {
playerPOS: data[4].split(', ').map(v => parseFloat(v)),
};
let guild = await client.GetGuild(guildId);
for (let i = 0; i < guild.alarms.length; i++) {
let alarm = guild.alarms[i];
if (alarm.disabled || !alarm.rules.includes('ban_on_fireplace_placement')) continue;
@@ -242,10 +239,7 @@ module.exports = {
return;
},
HandleEvents: async (client, guildId) => {
let guild = await client.GetGuild(guildId);
HandleEvents: async (client, guild) => {
for (let i = 0; i < guild.events.length; i++) {
let event = guild.events[i];
if (event.type == 'player-track') HandlePlayerTrackEvent(client, guild, event);
+28 -38
View File
@@ -3,7 +3,7 @@ const { createUser, addUser } = require('../database/user');
const { KillInAlarm } = require('./AlarmsHandler');
const { destinations } = require('../database/destinations');
const { calculateVector } = require('./vector');
const { getDefaultPlayerStats } = require('../database/playerStatistics');
const { getDefaultPlayer, UpdatePlayer } = require('../database/player');
const Templates = {
Killed: 1,
@@ -42,12 +42,12 @@ const Vehicles = {
module.exports = {
// Update last death date for non PVP deaths
UpdateLastDeathDate: async (client, stats, line) => {
UpdateLastDeathDate: async (client, line) => {
let killedByZmb = /(.*) \| Player \"(.*)\" \(DEAD\) \(id=(.*) pos=<(.*)>\) killed by (.*)/g;
let diedTemplate = /(.*) \| Player \"(.*)\" \(DEAD\) \(id=(.*) pos=<(.*)>\) died\. Stats> Water: (.*) Energy: (.*) Bleed sources: (.*)/g;
let data = line.includes('>) died.') ? [...line.matchAll(diedTemplate)][0] : [...line.matchAll(killedByZmb)][0];
if (!data) return stats;
if (!data) return;
let info = {
time: data[1],
@@ -58,19 +58,16 @@ module.exports = {
const newDt = await client.getDateEST(info.time);
let victimStat = stats.find(stat => stat.playerID == info.victimID);
let victimStatIndex = stats.indexOf(victimStat);
if (victimStat == undefined) victimStat = getDefaultPlayerStats(info.victim, info.victimID);
victimStat.lastDeathDate = newDt;
if (victimStatIndex == -1) stats.push(victimStat);
else stats[victimStatIndex] = victimStat;
let victimStat = await client.dbo.collection("players").findOne({"playerID": info.playerID});
if (!client.exists(victimStat)) victimStat = getDefaultPlayer(info.player, info.playerID, client.config.Nitrado.ServerID);
return stats;
victimStat.lastDeathDate = newDt;
return await UpdatePlayer(client, victimStat);
},
HandleKillfeed: async (client, guildId, stats, line) => {
HandleKillfeed: async (client, guild, line) => {
let guild = await client.GetGuild(guildId);
const channel = client.GetChannel(guild.killfeedChannel);
let templateKilled = /(.*) \| Player \"(.*)\" \(DEAD\) \(id=(.*) pos=<(.*)>\) killed by Player \"(.*)\" \(id=(.*) pos=<(.*)>\) with (.*) from (.*) meters /g;
@@ -96,7 +93,7 @@ module.exports = {
killedBy == Templates.Vehicle ? [...line.matchAll(vehicleTemplate)][0] :
[...line.matchAll(explosionTemplate)][0];
if (!data) return stats;
if (!data) return;
// Create base data
let info = {
@@ -124,7 +121,7 @@ module.exports = {
}
else if (killedBy == Templates.Vehicle) info.causeOfDeath = data[6];
else if (killedBy == Templates.Explosion) info.causeOfDeath = data[5];
else return stats; // Unknown template;
else return; // Unknown template;
const newDt = await client.getDateEST(info.time);
const unixTime = Math.floor(newDt.getTime()/1000);
@@ -145,12 +142,9 @@ module.exports = {
const destination = lastDist > 500 ? `${destination_dir} of ${tempDest}` : `Near ${tempDest}`;
if (killedBy == Templates.LandMine || killedBy == Templates.Explosion || killedBy == Templates.Vehicle) {
let victimStat = stats.find(stat => stat.playerID == info.victimID)
let victimStatIndex = stats.indexOf(victimStat);
if (victimStat == undefined) victimStat = getDefaultPlayerStats(info.victim, info.victimID);
let victimStat = await client.dbo.collection("players").findOne({"playerID": info.victimID});
if (!client.exists(victimStat)) victimStat = getDefaultPlayer(info.victim, info.victimID, client.config.Nitrado.ServerID);
victimStat.lastDeathDate = newDt;
if (victimStatIndex == -1) stats.push(victimStat);
else stats[victimStatIndex] = victimStat;
const cod = killedBy == Templates.LandMine ? `Land Mine Trap` :
killedBy == Templates.Vehicle ? Vehicles[info.causeOfDeath] : info.causeOfDeath;
@@ -162,19 +156,17 @@ module.exports = {
.setDescription(`**Death Event** - <t:${unixTime}>\n**${info.victim}** ${killMessage} a **${cod}.**${coord}`);
if (client.exists(channel)) await channel.send({ embeds: [killEvent] });
return stats;
return await UpdatePlayer(client, victimStat);
}
KillInAlarm(client, guildId, info); // check if kill happened in a no kill zone
KillInAlarm(client, guild.serverID, info); // check if kill happened in a no kill zone
if (!client.exists(info.victim) || !client.exists(info.victimID) || !client.exists(info.killer) || !client.exists(info.killerID)) return stats;
let killerStat = stats.find(stat => stat.playerID == info.killerID)
let victimStat = stats.find(stat => stat.playerID == info.victimID)
let killerStatIndex = stats.indexOf(killerStat);
let victimStatIndex = stats.indexOf(victimStat);
if (killerStat == undefined) killerStat = getDefaultPlayerStats(info.killer, info.killerID);
if (victimStat == undefined) victimStat = getDefaultPlayerStats(info.victim, info.victimID);
let victimStat = await client.dbo.collection("players").findOne({"playerID": info.victimID});
let killerStat = await client.dbo.collection("players").findOne({"playerID": info.killerID});
if (!client.exists(victimStat)) victimStat = getDefaultPlayer(info.victim, info.victimID, client.config.Nitrado.ServerID);
if (!client.exists(killerStat)) killerStat = getDefaultPlayer(info.killer, info.killerID, client.config.Nitrado.ServerID);
killerStat.kills++;
killerStat.killStreak++;
@@ -198,23 +190,22 @@ module.exports = {
let banking = await client.dbo.collection("users").findOne({"user.userID": killerStat.discordID}).then(banking => banking);
if (!banking) {
banking = await createUser(interaction.member.user.id, guildId, guild.startingBalance, client)
banking = await createUser(interaction.member.user.id, guild.serverID, guild.startingBalance, client)
if (!client.exists(banking)) return client.sendInternalError(interaction, err);
}
banking = banking.user;
if (!client.exists(banking.guilds[guildId])) {
const success = addUser(banking.guilds, guildId, interaction.member.user.id, client, guild.startingBalance);
if (!client.exists(banking.guilds[ guild.serverID])) {
const success = addUser(banking.guilds, guild.serverID, interaction.member.user.id, client, guild.startingBalance);
if (!success) return client.sendInternalError(interaction, 'Failed to add bank');
}
const newBalance = banking.guilds[guildId].balance + totalBounty;
const newBalance = banking.guilds[ guild.serverID].balance + totalBounty;
await client.dbo.collection("users").updateOne({ "user.userID": killerStat.discordID }, {
$set: {
[`user.guilds.${guildId}.balance`]: newBalance,
[`user.guilds.${ guild.serverID}.balance`]: newBalance,
}
}, (err, res) => {
if (err) return client.sendError(client.GetChannel(guild.killfeedChannel), `Killfeed Error: Updating killer bank balance\n${err}`);
@@ -225,12 +216,11 @@ module.exports = {
.setDescription(`<@${killerStat.discordID}> received **$${totalBounty.toFixed(2).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})}** in bounty rewards.`);
victimStat.bounties = []; // clear bounties after claimed
victimStat.bountiesLength = 0;
}
if (killerStatIndex == -1) stats.push(killerStat);
else stats[killerStatIndex] = killerStat;
if (victimStatIndex == -1) stats.push(victimStat);
else stats[victimStatIndex] = victimStat;
await UpdatePlayer(client, victimStat);
await UpdatePlayer(client, killerStat);
const coord = showCoords ? `\n***Location [${info.victimPOS[0]}, ${info.victimPOS[1]}](https://www.izurvive.com/chernarusplussatmap/#location=${info.victimPOS[0]};${info.victimPOS[1]})***\n${destination}` : '';
@@ -241,6 +231,6 @@ module.exports = {
if (client.exists(channel)) await channel.send({ embeds: [killEvent] });
if (client.exists(receivedBounty) && client.exists(channel)) await channel.send({ content: `<@${killerStat.discordID}>`, embeds: [receivedBounty] });
return stats;
return;
}
}
+41 -46
View File
@@ -1,14 +1,15 @@
const { EmbedBuilder } = require('discord.js');
const { HandleAlarmsAndUAVs } = require('./AlarmsHandler');
const { SendConnectionLogs, DetectCombatLog } = require('./AdminLogsHandler');
const { getDefaultPlayerStats } = require('../database/playerStatistics');
const { getDefaultPlayer } = require('../database/player');
const { FetchServerSettings } = require('../util/NitradoAPI');
const { UpdatePlayer } = require('../database/player')
let lastSendMessage;
module.exports = {
HandlePlayerLogs: async (client, guildId, stats, line, combatLogTimer = 5) => {
HandlePlayerLogs: async (client, GuildDB, line, combatLogTimer = 5) => {
const connectTemplate = /(.*) \| Player \"(.*)\" is connected \(id=(.*)\)/g;
const disconnectTemplate = /(.*) \| Player \"(.*)\"\(id=(.*)\) has been disconnected/g;
@@ -18,7 +19,7 @@ module.exports = {
if (line.includes(' connected')) {
const data = [...line.matchAll(connectTemplate)][0];
if (!data) return stats;
if (!data) return;
const info = {
time: data[1],
@@ -26,16 +27,15 @@ module.exports = {
playerID: data[3],
};
if (!client.exists(info.player) || !client.exists(info.playerID)) return stats;
let playerStat = stats.find(stat => stat.playerID == info.playerID);
let playerStatIndex = stats.indexOf(playerStat);
if (playerStat === undefined) playerStat = getDefaultPlayerStats(info.player, info.playerID);
if (!client.exists(info.player) || !client.exists(info.playerID)) return;
let playerStat = await client.dbo.collection("players").findOne({"playerID": info.playerID});
if (!client.exists(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID, client.config.Nitrado.ServerID);
const newDt = await client.getDateEST(info.time);
playerStat.lastConnectionDate = newDt;
playerStat.connected = true;
playerStat.connections++;
// Track adjusted sessions this instance has handled (e.g. no bot crashes or restarts).
if (client.playerSessions.has(info.playerID)) {
@@ -51,20 +51,19 @@ module.exports = {
client.playerSessions.set(info.playerID, newSession);
}
if (playerStatIndex === -1) stats.push(playerStat);
else stats[playerStatIndex] = playerStat;
await SendConnectionLogs(client, guildId, {
await SendConnectionLogs(client, GuildDB, {
time: info.time,
player: info.player,
connected: true,
lastConnectionDate: null,
});
return await UpdatePlayer(client, playerStat);
}
if (line.includes(' disconnected')) {
const data = [...line.matchAll(disconnectTemplate)][0];
if (!data) return stats;
if (!data) return;
const info = {
time: data[1],
@@ -72,16 +71,19 @@ module.exports = {
playerID: data[3],
};
if (!client.exists(info.player) || !client.exists(info.playerID)) return stats;
if (!client.exists(info.player) || !client.exists(info.playerID)) return;
let playerStat = stats.find(stat => stat.playerID == info.playerID);
let playerStatIndex = stats.indexOf(playerStat);
if (playerStat === undefined) playerStat = getDefaultPlayerStats(info.player, info.playerID);
let playerStat = await client.dbo.collection("players").findOne({"playerID": info.playerID});
if (!client.exists(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID, client.config.Nitrado.ServerID);
let oldUnixTime;
let sessionTimeSeconds;
const newDt = await client.getDateEST(info.time);
const unixTime = Math.round(newDt.getTime() / 1000); // Seconds
const oldUnixTime = Math.round(playerStat.lastConnectionDate.getTime() / 1000); // Seconds
const sessionTimeSeconds = unixTime - oldUnixTime;
if (playerStat.lastConnectionDate != null) {
oldUnixTime = Math.round(playerStat.lastConnectionDate.getTime() / 1000); // Seconds
sessionTimeSeconds = unixTime - oldUnixTime;
} else sessionTimeSeconds = 0;
if (!client.exists(playerStat.longestSessionTime)) playerStat.longestSessionTime = 0;
playerStat.totalSessionTime = playerStat.totalSessionTime + sessionTimeSeconds;
@@ -90,10 +92,7 @@ module.exports = {
playerStat.lastDisconnectionDate = newDt;
playerStat.connected = false;
if (playerStatIndex === -1) stats.push(playerStat);
else stats[playerStatIndex] = playerStat;
await SendConnectionLogs(client, guildId, {
await SendConnectionLogs(client, GuildDB, {
time: info.time,
player: info.player,
connected: false,
@@ -101,7 +100,7 @@ module.exports = {
});
if (combatLogTimer != 0) {
DetectCombatLog(client, guildId, {
await DetectCombatLog(client, GuildDB, {
time: info.time,
player: info.player,
pos: playerStat.pos,
@@ -111,11 +110,13 @@ module.exports = {
combatLogTimer: combatLogTimer,
});
}
return await UpdatePlayer(client, playerStat);
}
if (line.includes('pos=<') && !line.includes('hit by')) {
const data = [...line.matchAll(positionTemplate)][0];
if (!data) return stats;
if (!data) return;
const info = {
time: data[1],
@@ -124,11 +125,10 @@ module.exports = {
pos: data[4].split(', ').map(v => parseFloat(v))
};
if (!client.exists(info.player) || !client.exists(info.playerID)) return stats;
if (!client.exists(info.player) || !client.exists(info.playerID)) return;
let playerStat = stats.find(stat => stat.playerID == info.playerID);
let playerStatIndex = stats.indexOf(playerStat);
if (playerStat === undefined) playerStat = getDefaultPlayerStats(info.player, info.playerID);
let playerStat = await client.dbo.collection("players").findOne({"playerID": info.playerID});
if (!client.exists(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID, client.config.Nitrado.ServerID);
if (!client.exists(playerStat.lastConnectionDate)) playerStat.lastConnectionDate = await client.getDateEST(info.time);
playerStat.lastPos = playerStat.pos;
@@ -138,22 +138,21 @@ module.exports = {
playerStat.time = `${info.time} EST`;
playerStat.date = await client.getDateEST(info.time);
if (playerStatIndex === -1) stats.push(playerStat);
else stats[playerStatIndex] = playerStat;
if (line.includes('hit by') || line.includes('killed by')) return; // prevent additional information from being fed to Alarms & UAVs
if (line.includes('hit by') || line.includes('killed by')) return stats; // prevent additional information from being fed to Alarms & UAVs
HandleAlarmsAndUAVs(client, guildId, {
await HandleAlarmsAndUAVs(client, GuildDB, {
time: info.time,
player: info.player,
playerID: info.playerID,
pos: info.pos,
});
return await UpdatePlayer(client, playerStat)
}
if (line.includes('hit by Player')) {
const data = line.includes('(DEAD)') ? [...line.matchAll(deadTemplate)][0] : [...line.matchAll(damageTemplate)][0];
if (!data) return stats;
if (!data) return;
const info = {
time: data[1],
@@ -163,23 +162,21 @@ module.exports = {
attackerID: data[7]
};
if (!client.exists(info.player) || !client.exists(info.playerID)) return stats;
if (!client.exists(info.player) || !client.exists(info.playerID)) return;
let playerStat = stats.find(stat => stat.playerID == info.playerID);
let playerStatIndex = stats.indexOf(playerStat);
if (playerStat === undefined) playerStat = getDefaultPlayerStats(info.player, info.playerID);
let playerStat = await client.dbo.collection("players").findOne({"playerID": info.playerID});
if (!client.exists(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID, client.config.Nitrado.ServerID);
playerStat.lastDamageDate = await client.getDateEST(info.time);
playerStat.lastHitBy = info.attacker;
if (playerStatIndex === -1) stats.push(playerStat);
else stats[playerStatIndex] = playerStat;
return await UpdatePlayer(client, playerStat);
}
return stats;
return;
},
HandleActivePlayersList: async (client, guildId) => {
HandleActivePlayersList: async (client, guild) => {
client.activePlayersTick = 0; // reset hour tick
const data = await FetchServerSettings(client, 'HandleActivePlayersList'); // Fetch server status
@@ -207,12 +204,10 @@ module.exports = {
statusText = "Unknown Status";
}
let guild = await client.GetGuild(guildId);
if (!client.exists(guild.playerstats)) guild.playerstats = [];
if (!client.exists(guild.activePlayersChannel)) return;
const channel = client.GetChannel(guild.activePlayersChannel);
let activePlayers = guild.playerstats.filter(p => p.connected === true);
let activePlayers = await client.dbo.collection("players").find({"connected": true}).toArray();
let des = ``;
for (let i = 0; i < activePlayers.length; i++) {