Log all events to files accessable via web

This commit is contained in:
Christopher Cookman 2025-06-18 18:42:49 -06:00
parent a3066ec5a3
commit af643a86fb
4 changed files with 165 additions and 23 deletions

2
.gitignore vendored
View file

@ -134,3 +134,5 @@ dist
.yarn/build-state.yml .yarn/build-state.yml
.yarn/install-state.gz .yarn/install-state.gz
.pnp.* .pnp.*
event-logs/

View file

@ -14,6 +14,7 @@ const path = require('path');
const markdown = require('markdown-it')(); const markdown = require('markdown-it')();
const ejs = require('ejs'); const ejs = require('ejs');
const { connect } = require('http2'); const { connect } = require('http2');
const serveIndex = require('serve-index');
const app = express(); const app = express();
expressWs(app); expressWs(app);
@ -41,6 +42,12 @@ app.get("/", (req, res) => {
res.render('docViewer', {title: 'Websocket Docs', htmlContent: htmlContent}); res.render('docViewer', {title: 'Websocket Docs', htmlContent: htmlContent});
}); });
}); });
app.use('/event-logs',
serveIndex(path.join(__dirname, 'event-logs'), { icons: true, view: 'details' }),
express.static(path.join(__dirname, 'event-logs'))
);
var socketStatus; var socketStatus;
app.get('/health', (req, res) => { app.get('/health', (req, res) => {
res.status(200).json({ res.status(200).json({
@ -285,27 +292,6 @@ const convertDate = function (date) {
return new Date(Date.UTC(year, month - 1, day, hours, mins, secs)); return new Date(Date.UTC(year, month - 1, day, hours, mins, secs));
} }
// Get number of unique channels in the database
const getUniqueChannels = function () {
return new Promise((resolve, reject) => {
db.all(`SELECT DISTINCT channelid FROM channels`, (err, rows) => {
if (err) {
console.error(err.message);
}
// Go through channels. and get number of unique guilds
const guilds = [];
rows.forEach((row) => {
const channel = discord.channels.cache.get(row.channelid);
if (!channel) return;
if (!guilds.includes(channel.guild.id)) {
guilds.push(channel.guild.id);
}
});
resolve({ channels: rows.length, guilds: guilds.length });
});
});
}
// Get first url in a string, return object {string, url} remove the url from the string // Get first url in a string, return object {string, url} remove the url from the string
const getFirstURL = function (string) { const getFirstURL = function (string) {
@ -466,6 +452,31 @@ xmpp.on("stanza", (stanza) => {
// get product id from "x" tag // get product id from "x" tag
var evt = events[product_id.pil.substring(0, 3)]; var evt = events[product_id.pil.substring(0, 3)];
// Log the full event object to a file named "productid-timestamp-channelname.json"
const nowDate = new Date();
const year = nowDate.getFullYear();
const month = String(nowDate.getMonth() + 1).padStart(2, '0');
const day = String(nowDate.getDate()).padStart(2, '0');
const logDir = path.join(__dirname, "event-logs", year.toString(), month, day);
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
const logFilename = `${product_id_raw}-${product_id.timestamp.toISOString()}-${fromChannel}.json`.replace(/[:]/g, "_");
const logPath = path.join(logDir, logFilename);
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return "WARN: CIRC";
}
seen.add(value);
}
return value;
};
};
fs.writeFileSync(logPath, JSON.stringify({evt, stanza, product_id, product_id_raw, bodyData, body}, getCircularReplacer(), 2), 'utf8');
if (!evt) { if (!evt) {
evt = { name: "Unknown", priority: 3 } evt = { name: "Unknown", priority: 3 }
console.log(`${colors.red("[ERROR]")} Unknown event type: ${product_id.pil.substring(0, 3)}. Fix me`); console.log(`${colors.red("[ERROR]")} Unknown event type: ${product_id.pil.substring(0, 3)}. Fix me`);

130
package-lock.json generated
View file

@ -16,7 +16,8 @@
"express": "^5.1.0", "express": "^5.1.0",
"express-ws": "^5.0.2", "express-ws": "^5.0.2",
"html-entities": "^2.6.0", "html-entities": "^2.6.0",
"markdown-it": "^14.1.0" "markdown-it": "^14.1.0",
"serve-index": "^1.9.1"
} }
}, },
"node_modules/@ampproject/remapping": { "node_modules/@ampproject/remapping": {
@ -935,6 +936,12 @@
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
"integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
"license": "MIT"
},
"node_modules/binary-extensions": { "node_modules/binary-extensions": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@ -3570,6 +3577,127 @@
"node": ">= 18" "node": ">= 18"
} }
}, },
"node_modules/serve-index": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
"integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
"license": "MIT",
"dependencies": {
"accepts": "~1.3.4",
"batch": "0.6.1",
"debug": "2.6.9",
"escape-html": "~1.0.3",
"http-errors": "~1.6.2",
"mime-types": "~2.1.17",
"parseurl": "~1.3.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/serve-index/node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"license": "MIT",
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/serve-index/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/serve-index/node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/serve-index/node_modules/http-errors": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
"license": "MIT",
"dependencies": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.0",
"statuses": ">= 1.4.0 < 2"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/serve-index/node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
"license": "ISC"
},
"node_modules/serve-index/node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/serve-index/node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/serve-index/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"license": "MIT"
},
"node_modules/serve-index/node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/serve-index/node_modules/setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
"license": "ISC"
},
"node_modules/serve-index/node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/serve-static": { "node_modules/serve-static": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz",

View file

@ -17,6 +17,7 @@
"express": "^5.1.0", "express": "^5.1.0",
"express-ws": "^5.0.2", "express-ws": "^5.0.2",
"html-entities": "^2.6.0", "html-entities": "^2.6.0",
"markdown-it": "^14.1.0" "markdown-it": "^14.1.0",
"serve-index": "^1.9.1"
} }
} }