refactor/logs handler to support migrated player stats

This commit is contained in:
SowinskiBraeden committed 2023-10-27 15:42:48 -07:00
1 parent ffc2e40351
commit 9b849dfc39
12 files changed
+257 -221

No files matched your search

+3 -2
View File
@@ -7,8 +7,9 @@ dev-*.js
# Logs
logs/*
npm-debug.log
# env
.env
.DS_Store
# Admin Script backups
admin/backup/*
+60
View File
@@ -0,0 +1,60 @@
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));
if (version[0] < 12) throw new Error('Bot version does not meet requirements: v^12.0.0');
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");
let guild = await guilds.findOne({"server.serverID": guildId});
const dir = __dirname + '/backup';
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
guild.server.playerstats.map(stat => stat.nitradoServerID = NitradoServerID);
// 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.`);
const result = await players.insertMany(guild.server.playerstats, { ordered: true });
console.log(`${result.insertedCount} documents were inserted`);
delete guild.server.playerstats;
} 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()
+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",
+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,5 +1,11 @@
module.exports = {
getDefaultPlayerStats(gt, pID) {
UpdatePlayer: async (client, player) => {
return await client.dbo.collection("players").updateOne({"playerID": player.playerID}, {$set: player}, (err, _) => {
if (err) client.error(err);
});
},
getDefaultPlayer(gt, pID) {
return {
gamertag: gt,
playerID: pID,
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "dayzr-bot",
"version": "11.5.0",
"version": "12.0.0",
"description": "A General Purpose Discord Bot for DayZ Nitrado Servers.",
"main": "index.js",
"nodemonConfig": {
+29 -81
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');
@@ -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,25 +156,26 @@ 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.
}
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(client, 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(client, 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
@@ -211,8 +212,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.exits(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID);
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 +239,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 +252,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 +262,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 c.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,53 +416,7 @@ 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,
};
}
async GetGuild(GuildId) { return await GetGuild(this, GuildId) }
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);
+5 -12
View File
@@ -20,7 +20,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 +58,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 +136,7 @@ module.exports = {
}
},
HandleExpiredUAVs: async (client, guildId) => {
let guild = await client.GetGuild(guildId);
HandleExpiredUAVs: async (client, guild) => {
let uavs = guild.uavs;
let update = false;
@@ -199,7 +197,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 +210,6 @@ module.exports = {
victimPOS: 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 +238,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);
+21 -32
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,7 +42,7 @@ 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;
@@ -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.exits(victimStat)) playerStat = getDefaultPlayer(info.player, info.playerID);
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.exits(victimStat)) victimStat = getDefaultPlayer(info.victim, info.victimID);
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);
}
killerStat
KillInAlarm(client, guildId, 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.exits(victimStat)) victimStat = getDefaultPlayer(info.victim, info.victimID);
if (!client.exits(killerStat)) killerStat = getDefaultPlayer(info.killer, info.killerID);
killerStat.kills++;
killerStat.killStreak++;
@@ -198,7 +190,6 @@ 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, GuildDB.serverID, GuildDB.startingBalance, client)
if (!client.exists(banking)) return client.sendInternalError(interaction, err);
@@ -227,10 +218,8 @@ module.exports = {
victimStat.bounties = []; // clear bounties after claimed
}
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 +230,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;
}
}
+34 -44
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,12 +27,10 @@ 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.exits(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID);
const newDt = await client.getDateEST(info.time);
playerStat.lastConnectionDate = newDt;
@@ -51,20 +50,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,11 +70,10 @@ 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.exits(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID);
const newDt = await client.getDateEST(info.time);
const unixTime = Math.round(newDt.getTime() / 1000); // Seconds
@@ -90,10 +87,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 +95,7 @@ module.exports = {
});
if (combatLogTimer != 0) {
DetectCombatLog(client, guildId, {
await DetectCombatLog(client, GuildDB, {
time: info.time,
player: info.player,
pos: playerStat.pos,
@@ -111,11 +105,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 +120,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.exits(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID);
if (!client.exists(playerStat.lastConnectionDate)) playerStat.lastConnectionDate = await client.getDateEST(info.time);
playerStat.lastPos = playerStat.pos;
@@ -138,22 +133,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 +157,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.exits(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID);
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 +199,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 = client.dbo.collection("players").find({"connected": true})
let des = ``;
for (let i = 0; i < activePlayers.length; i++) {