fix log file find/download

This commit is contained in:
SowinskiBraeden committed 2026-03-24 15:08:16 -07:00
1 parent df6b9140ec
commit e8303fc14a
3 files changed
+60 -54

No files matched your search

+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "dayzr-bot", "name": "dayzr-bot",
"version": "13.3.23", "version": "13.3.25",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "dayzr-bot", "name": "dayzr-bot",
"version": "13.3.23", "version": "13.3.25",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@discordjs/rest": "^1.1.0", "@discordjs/rest": "^1.1.0",
+23 -18
View File
@@ -6,7 +6,7 @@ const Logger = require("../util/Logger");
const crypto = require('crypto'); const crypto = require('crypto');
// custom util imports // custom util imports
const { DownloadNitradoFile, CheckServerStatus, FetchServerSettings, PostServerSettings, NitradoCredentialStatus } = require('../util/NitradoAPI'); const { DownloadNitradoFile, CheckServerStatus, FetchServerSettings, PostServerSettings, NitradoCredentialStatus, GetRemoteDir } = require('../util/NitradoAPI');
const { HandlePlayerLogs, HandleActivePlayersList } = require('../util/LogsHandler'); const { HandlePlayerLogs, HandleActivePlayersList } = require('../util/LogsHandler');
const { HandleKillfeed, UpdateLastDeathDate } = require('../util/KillfeedHandler'); const { HandleKillfeed, UpdateLastDeathDate } = require('../util/KillfeedHandler');
const { HandleExpiredUAVs, HandleEvents, PlaceFireplaceInAlarm } = require('../util/AlarmsHandler'); const { HandleExpiredUAVs, HandleEvents, PlaceFireplaceInAlarm } = require('../util/AlarmsHandler');
@@ -120,7 +120,7 @@ class DayzRBot extends Client {
this.log(`Interaction [${interaction.guild_id}] - ${command}`); this.log(`Interaction [${interaction.guild_id}] - ${command}`);
const rest = new REST({ version: '10' }).setToken(this.config.Token); const rest = new REST({ version: '10' }).setToken(this.config.Token);
// Easy to send response so ;) // Easy to send response so ;)
interaction.guild = await this.guilds.fetch(interaction.guild_id); interaction.guild = await this.guilds.fetch(interaction.guild_id);
const handleCallback = async (interactionType, message) => { const handleCallback = async (interactionType, message) => {
@@ -136,7 +136,7 @@ class DayzRBot extends Client {
interaction.send = async (message) => handleCallback(InteractionResponseType.ChannelMessageWithSource, message); interaction.send = async (message) => handleCallback(InteractionResponseType.ChannelMessageWithSource, message);
interaction.deferReply = async (message) => handleCallback(InteractionResponseType.DeferredChannelMessageWithSource, message); interaction.deferReply = async (message) => handleCallback(InteractionResponseType.DeferredChannelMessageWithSource, message);
interaction.showModal = async (message) => handleCallback(InteractionResponseType.Modal, message); interaction.showModal = async (message) => handleCallback(InteractionResponseType.Modal, message);
interaction.editReply = async (message) => { interaction.editReply = async (message) => {
return await rest.patch(Routes.webhookMessage(this.application.id, interaction.token), { return await rest.patch(Routes.webhookMessage(this.application.id, interaction.token), {
body: message, body: message,
@@ -187,7 +187,7 @@ class DayzRBot extends Client {
if (this.playerSessions.get(guild.Nitrado.ServerID).size === 0) { if (this.playerSessions.get(guild.Nitrado.ServerID).size === 0) {
let players = await this.dbo.collection('players').find({"nitradoServerID": guild.Nitrado.ServerID}) // Get all players of this server let players = await this.dbo.collection('players').find({"nitradoServerID": guild.Nitrado.ServerID}) // Get all players of this server
.toArray().then(all => all.filter(p => p.connected).map(p => p.connected = false)); // assume all players who were previously connected are not connected on init only. .toArray().then(all => all.filter(p => p.connected).map(p => p.connected = false)); // assume all players who were previously connected are not connected on init only.
for (let i = 0; i < players.length; i++) { for (let i = 0; i < players.length; i++) {
await UpdatePlayer(this, players[i]) await UpdatePlayer(this, players[i])
} }
@@ -203,7 +203,7 @@ class DayzRBot extends Client {
if (lines[i].includes('connected') || lines[i].includes('pos=<')) await HandlePlayerLogs(guild.Nitrado.ServerID, this, guild, lines[i], guild.combatLogTimer); if (lines[i].includes('connected') || lines[i].includes('pos=<')) await HandlePlayerLogs(guild.Nitrado.ServerID, this, guild, lines[i], guild.combatLogTimer);
if (lines[i].includes('killed by Zmb') || lines[i].includes('>) died.')) await UpdateLastDeathDate(guild.Nitrado.ServerID, this, lines[i]); // Updates users last death date for non PVP deaths. if (lines[i].includes('killed by Zmb') || lines[i].includes('>) died.')) await UpdateLastDeathDate(guild.Nitrado.ServerID, this, lines[i]); // Updates users last death date for non PVP deaths.
if (lines[i].includes(') placed Fireplace')) await PlaceFireplaceInAlarm(this, guild, lines[i]); if (lines[i].includes(') placed Fireplace')) await PlaceFireplaceInAlarm(this, guild, lines[i]);
// Handle killfeed logs // Handle killfeed logs
if ( if (
(lines[i].includes('killed by with') || lines[i].includes('killed by LandMineTrap')) || // Handle explosive deaths (lines[i].includes('killed by with') || lines[i].includes('killed by LandMineTrap')) || // Handle explosive deaths
@@ -222,18 +222,18 @@ class DayzRBot extends Client {
if (!channel) return; if (!channel) return;
const NAME = "DayZ.R Zone Alert"; const NAME = "DayZ.R Zone Alert";
const webhook = await GetWebhook(this, NAME, channel_id); const webhook = await GetWebhook(this, NAME, channel_id);
data.forEach(async (embeds, role) => { data.forEach(async (embeds, role) => {
let embedArrays = []; let embedArrays = [];
while (embeds.length > 0) while (embeds.length > 0)
embedArrays.push(embeds.splice(0, maxEmbed)); embedArrays.push(embeds.splice(0, maxEmbed));
for (let i = 0; i < embedArrays.length; i++) { for (let i = 0; i < embedArrays.length; i++) {
let content = { embeds: embedArrays[i] }; let content = { embeds: embedArrays[i] };
if (role != '-no-role-ping-') content.content = `<@&${role}>`; if (role != '-no-role-ping-') content.content = `<@&${role}>`;
WebhookSend(this, webhook, content); WebhookSend(this, webhook, content);
// if (role == '-no-role-ping-') channel.send({ embeds: embedArrays[i] }); // if (role == '-no-role-ping-') channel.send({ embeds: embedArrays[i] });
// else channel.send({ content: `<@&${role}>`, embeds: embedArrays[i] }); // else channel.send({ content: `<@&${role}>`, embeds: embedArrays[i] });
} }
@@ -266,7 +266,7 @@ class DayzRBot extends Client {
if (!this.exists(info.player) || !this.exists(info.playerID)) continue; // Skip this player if the player does not exist. 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); lastDetectedTime = await this.getDateEST(info.time);
let playerStat = await this.dbo.collection("players").findOne({"playerID": info.playerID}); let playerStat = await this.dbo.collection("players").findOne({"playerID": info.playerID});
if (!this.exists(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID, guild.Nitrado.ServerID); if (!this.exists(playerStat)) playerStat = getDefaultPlayer(info.player, info.playerID, guild.Nitrado.ServerID);
@@ -311,7 +311,7 @@ class DayzRBot extends Client {
c.guilds.cache.forEach(async (guild) => { c.guilds.cache.forEach(async (guild) => {
let GuildDB = await GetGuild(c, guild.id); let GuildDB = await GetGuild(c, guild.id);
/* /*
Note to self: Note to self:
return statements do not prematurely exit out of a forEach loop like it does in a for loop. return statements do not prematurely exit out of a forEach loop like it does in a for loop.
@@ -321,7 +321,7 @@ class DayzRBot extends Client {
if (GuildDB.Nitrado.Status == NitradoCredentialStatus.FAILED) return; // Continue if these credentials are marked as failed if (GuildDB.Nitrado.Status == NitradoCredentialStatus.FAILED) return; // Continue if these credentials are marked as failed
const NitradoCred = { const NitradoCred = {
ServerID: GuildDB.Nitrado.ServerID, ServerID: GuildDB.Nitrado.ServerID,
UserID: GuildDB.Nitrado.UserID, UserID: GuildDB.Nitrado.UserID,
Auth: decrypt( Auth: decrypt(
GuildDB.Nitrado.Auth, GuildDB.Nitrado.Auth,
@@ -349,8 +349,13 @@ class DayzRBot extends Client {
GuildDB.Nitrado.Mission = Missions[settings.settings.config.mission]; GuildDB.Nitrado.Mission = Missions[settings.settings.config.mission];
if (settings.game_specific.log_files.length == 0) return; // Ignore if no log files on Nitrado server console.log(`${settings.game_specific.path}config`);
const filename = settings.game_specific.log_files.sort((a, b) => a.length - b.length)[0]; let filenames = await GetRemoteDir(NitradoCred, c, `${settings.game_specific.path}config`);
filenames = filenames.map(path => path.path)
filenames = filenames.filter(path => path.includes(".ADM"))
const filename = filenames[filenames.length - 1];
// 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]}`; const path = `${settings.game_specific.path.slice(0, -1)}${filename.split(settings.game)[1]}`;
// Ensure Player List is logged for next update // Ensure Player List is logged for next update
@@ -396,8 +401,8 @@ class DayzRBot extends Client {
databaselogs.attempts = 0; // reset attempts databaselogs.attempts = 0; // reset attempts
this.databaseConnected = true; this.databaseConnected = true;
} catch (err) { } catch (err) {
databaselogs.attempts++; databaselogs.attempts++;
databaselogs.connected = false; databaselogs.connected = false;
let db = mongoURI.includes("@") ? mongoURI.split("@")[1] : mongoURI.split("//")[1]; let db = mongoURI.includes("@") ? mongoURI.split("@")[1] : mongoURI.split("//")[1];
db = db.includes("/") ? db.split("/")[0] : db; db = db.includes("/") ? db.split("/")[0] : db;
this.error(`Failed to connect to mongodb (mongodb://${db}/${dbo}): attempt ${databaselogs.attempts} - ${err}`); this.error(`Failed to connect to mongodb (mongodb://${db}/${dbo}): attempt ${databaselogs.attempts} - ${err}`);
@@ -416,7 +421,7 @@ class DayzRBot extends Client {
if (!this.databaseConnected) return; if (!this.databaseConnected) return;
let guilds = await this.dbo.collection("guilds").find({}).toArray(); let guilds = await this.dbo.collection("guilds").find({}).toArray();
/* /*
Initialize auto restart for enabled servers Initialize auto restart for enabled servers
Initialize last logs Initialize last logs
@@ -426,7 +431,7 @@ class DayzRBot extends Client {
if (!this.exists(guilds[i].Nitrado)) continue; if (!this.exists(guilds[i].Nitrado)) continue;
if (guilds[i].server.autoRestart) { if (guilds[i].server.autoRestart) {
const NitradoCred = { const NitradoCred = {
ServerID: guilds[i].Nitrado.ServerID, ServerID: guilds[i].Nitrado.ServerID,
UserID: guilds[i].Nitrado.UserID, UserID: guilds[i].Nitrado.UserID,
Auth: decrypt( Auth: decrypt(
guilds[i].Nitrado.Auth, guilds[i].Nitrado.Auth,
@@ -457,7 +462,7 @@ class DayzRBot extends Client {
} }
exists(n) { return typeof(n) == 'number' ? !isNaN(n) : null != n && undefined != n && "" != n } exists(n) { return typeof(n) == 'number' ? !isNaN(n) : null != n && undefined != n && "" != n }
secondsToDhms(seconds) { secondsToDhms(seconds) {
seconds = Number(seconds); seconds = Number(seconds);
const d = Math.floor(seconds / (3600 * 24)); const d = Math.floor(seconds / (3600 * 24));
+35 -34
View File
@@ -22,7 +22,7 @@ const UploadNitradoFile = async (nitrado_cred, client, remoteDir, remoteFilename
}).then(response => response.json()); }).then(response => response.json());
let contents = fs.readFileSync(localFileDir, 'utf8'); let contents = fs.readFileSync(localFileDir, 'utf8');
const uploadRes = await fetch(res.data.token.url, { const uploadRes = await fetch(res.data.token.url, {
method: "POST", method: "POST",
headers: { headers: {
@@ -63,36 +63,37 @@ const HandlePlayerBan = async (nitrado_cred, client, gamertag, ban) => {
} }
} }
const GetRemoteDir = async (nitrado_cred, client, dir="") => {
const dirParam = client.exists(dir) ? `?dir=${dir}` : "";
for (let retries = 0; retries <= maxRetries; retries++) {
try {
const res = await fetch(`https://api.nitrado.net/services/${nitrado_cred.ServerID}/gameservers/file_server/list${dirParam}`, {
headers: {
"Authorization": nitrado_cred.Auth
}
}).then(response =>
response.json().then(data => data)
).then(res => res);
if (res.status === "error") return 1;
return res.data.entries;
} catch (error) {
client.error(`GetRemoteDir: Error connecting to server (${nitrado_cred.ServerID}): ${error}`);
if (retries == maxRetries) {
client.error(`GetRemoteDir: Error connecting to server (${nitrado_cred.ServerID}) after ${maxRetries} retries`);
return 1;
}
}
await new Promise(resolve => setTimeout(resolve, retryDelay)); // Delay before retrying
}
}
// Public functions (called externally) // Public functions (called externally)
module.exports = { module.exports = {
GetRemoteDir: async (nitrado_cred, client, dir="") => {
const dirParam = client.exists(dir) ? `?dir=${dir}` : "";
for (let retries = 0; retries <= maxRetries; retries++) {
try {
const res = await fetch(`https://api.nitrado.net/services/${nitrado_cred.ServerID}/gameservers/file_server/list${dirParam}`, {
headers: {
"Authorization": nitrado_cred.Auth
}
}).then(response =>
response.json().then(data => data)
).then(res => res);
if (res.status === "error") return 1;
return res.data.entries;
} catch (error) {
client.error(`GetRemoteDir: Error connecting to server (${nitrado_cred.ServerID}): ${error}`);
if (retries == maxRetries) {
client.error(`GetRemoteDir: Error connecting to server (${nitrado_cred.ServerID}) after ${maxRetries} retries`);
return 1;
}
}
await new Promise(resolve => setTimeout(resolve, retryDelay)); // Delay before retrying
}
},
DownloadNitradoFile: async(nitrado_cred, client, filename, outputDir) => { DownloadNitradoFile: async(nitrado_cred, client, filename, outputDir) => {
for (let retries = 0; retries <= maxRetries; retries++) { for (let retries = 0; retries <= maxRetries; retries++) {
try { try {
@@ -100,7 +101,7 @@ module.exports = {
headers: { headers: {
"Authorization": nitrado_cred.Auth "Authorization": nitrado_cred.Auth
} }
}).then(response => }).then(response =>
response.json().then(data => data) response.json().then(data => data)
).then(res => res); ).then(res => res);
@@ -124,8 +125,8 @@ module.exports = {
}, },
/* /*
Export explicit function names; i.e BanPlayer() & UnbanPlayer() Export explicit function names; i.e BanPlayer() & UnbanPlayer()
that call to the private parent function HandlePlayerBan() that call to the private parent function HandlePlayerBan()
rather than write two whole different functions for each. rather than write two whole different functions for each.
*/ */
@@ -261,7 +262,7 @@ module.exports = {
const missionPath = remoteDirsFromBase[0].path; const missionPath = remoteDirsFromBase[0].path;
const cfggameplayPath = `${missionPath}/cfggameplay.json`; const cfggameplayPath = `${missionPath}/cfggameplay.json`;
const jsonDir = `./logs/cfggameplay.json`; const jsonDir = `./logs/cfggameplay.json`;
await module.exports.DownloadNitradoFile(nitrado_cred, client, cfggameplayPath, jsonDir); await module.exports.DownloadNitradoFile(nitrado_cred, client, cfggameplayPath, jsonDir);
let gameplay = JSON.parse(fs.readFileSync(jsonDir)); let gameplay = JSON.parse(fs.readFileSync(jsonDir));
@@ -272,7 +273,7 @@ module.exports = {
const uploaded = await UploadNitradoFile(nitrado_cred, client, missionPath, 'cfggameplay.json', jsonDir); const uploaded = await UploadNitradoFile(nitrado_cred, client, missionPath, 'cfggameplay.json', jsonDir);
if (uploaded == 1) return 1; if (uploaded == 1) return 1;
return 0; return 0;
}, },
@@ -289,7 +290,7 @@ module.exports = {
const missionPath = remoteDirsFromBase[0].path; const missionPath = remoteDirsFromBase[0].path;
const cfggameplayPath = `${missionPath}/cfggameplay.json`; const cfggameplayPath = `${missionPath}/cfggameplay.json`;
const jsonDir = `./logs/cfggameplay.json`; const jsonDir = `./logs/cfggameplay.json`;
await module.exports.DownloadNitradoFile(nitrado_cred, client, cfggameplayPath, jsonDir); await module.exports.DownloadNitradoFile(nitrado_cred, client, cfggameplayPath, jsonDir);
let gameplay = JSON.parse(fs.readFileSync(jsonDir)); let gameplay = JSON.parse(fs.readFileSync(jsonDir));
@@ -300,7 +301,7 @@ module.exports = {
const uploaded = await UploadNitradoFile(nitrado_cred, client, missionPath, 'cfggameplay.json', jsonDir); const uploaded = await UploadNitradoFile(nitrado_cred, client, missionPath, 'cfggameplay.json', jsonDir);
if (uploaded == 1) return 1; if (uploaded == 1) return 1;
return 0; return 0;
}, },