132 lines
4.6 KiB
JavaScript
132 lines
4.6 KiB
JavaScript
const { SlashCommandBuilder } = require('@discordjs/builders');
|
|
const { AttachmentBuilder } = require("discord.js");
|
|
const fs = require('node:fs');
|
|
const { submissions, commands } = require("../config/config.js");
|
|
const { parse } = require("csv-parse/sync");
|
|
const { getSubmissionLine, safeCsvFormat } = require("../common.js");
|
|
const Sugar = require("sugar-date");
|
|
const { Buffer } = require("buffer");
|
|
|
|
/**
|
|
* @param {import('discord.js').ChatInputCommandInteraction} interaction
|
|
*/
|
|
async function execute(interaction) {
|
|
const game = interaction.options.getString("game", true);
|
|
|
|
const fname = submissions[game];
|
|
if (fname === undefined) {
|
|
await interaction.editReply("🚫 Invalid game specified!");
|
|
return;
|
|
}
|
|
|
|
if (!fs.existsSync(fname)) {
|
|
await interaction.editReply(`No submissions exist yet for ${game}.`);
|
|
return;
|
|
}
|
|
|
|
const afterDateStr = interaction.options.getString("after_date");
|
|
const beforeDateStr = interaction.options.getString("before_date");
|
|
let afterTimestamp = undefined;
|
|
let beforeTimestamp = undefined;
|
|
|
|
// Using Sugar for magic date parsing
|
|
if (afterDateStr) {
|
|
const afterDate = Sugar.Date.create(afterDateStr);
|
|
if (isNaN(afterDate)) {
|
|
await interaction.editReply(`🚫 Could not convert '${afterDateStr}' to a valid date.`);
|
|
return;
|
|
}
|
|
afterTimestamp = Math.round(afterDate / 1000);
|
|
}
|
|
|
|
if (beforeDateStr) {
|
|
const beforeDate = Sugar.Date.create(beforeDateStr);
|
|
if (isNaN(beforeDate)) {
|
|
await interaction.editReply(`🚫 Could not convert '${beforeDateStr}' to a valid date.`);
|
|
return;
|
|
}
|
|
beforeTimestamp = Math.round(beforeDate / 1000);
|
|
}
|
|
|
|
if (!isNaN(afterTimestamp) && !isNaN(beforeTimestamp) && beforeTimestamp < afterTimestamp) {
|
|
await interaction.editReply(`🚫 Your date range is invalid: ${getDateRangeString(afterTimestamp, beforeTimestamp)}.`);
|
|
return;
|
|
}
|
|
|
|
const csvFile = fs.readFileSync(fname);
|
|
|
|
const lines = parse(csvFile, {delimiter: ',', fromLine: 2});
|
|
|
|
let csvString = "map_id,unix_timestamp,date_string,user_id,username,display_name,creator\n";
|
|
let found = false;
|
|
for (let lineStr of lines) {
|
|
const line = getSubmissionLine(lineStr);
|
|
|
|
// Must be between the given date range
|
|
if ((!isNaN(afterTimestamp) && line.timestamp < afterTimestamp) ||
|
|
(!isNaN(beforeTimestamp) && line.timestamp > beforeTimestamp)) {
|
|
continue;
|
|
}
|
|
|
|
found = true;
|
|
const dateStr = new Date(line.timestamp * 1000).toLocaleString("en-US", {dateStyle: "short"});
|
|
csvString += `${line.modelId},${line.timestamp},${dateStr},${line.userId},${safeCsvFormat(line.username)},${safeCsvFormat(line.displayName)},${safeCsvFormat(line.creator)}\n`;
|
|
}
|
|
|
|
if (!found) {
|
|
let msg;
|
|
const dateRangeStr = getDateRangeString(afterTimestamp, beforeTimestamp);
|
|
if (dateRangeStr) {
|
|
msg = `Could not find any submissions ${dateRangeStr}.`;
|
|
}
|
|
else {
|
|
msg = "Could not find any submissions.";
|
|
}
|
|
await interaction.editReply(msg);
|
|
return;
|
|
}
|
|
|
|
const file = new AttachmentBuilder(Buffer.from(csvString), { name: fname });
|
|
const dateRangeStr = getDateRangeString(afterTimestamp, beforeTimestamp);
|
|
if (dateRangeStr) {
|
|
await interaction.editReply({content: `Using date range ${dateRangeStr}:`, files: [file]});
|
|
}
|
|
else {
|
|
await interaction.editReply({files: [file]});
|
|
}
|
|
}
|
|
|
|
function getDateRangeString(afterTimestamp, beforeTimestamp) {
|
|
if (!isNaN(afterTimestamp) && !isNaN(beforeTimestamp)) {
|
|
return `between <t:${afterTimestamp}:d> to <t:${beforeTimestamp}:d>`;
|
|
}
|
|
else if (!isNaN(afterTimestamp)) {
|
|
return `after <t:${afterTimestamp}:d>`;
|
|
}
|
|
else if (!isNaN(beforeTimestamp)) {
|
|
return `before <t:${beforeTimestamp}:d>`;
|
|
}
|
|
else {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('submissions')
|
|
.setDescription('View the submissions in .csv format')
|
|
.addStringOption(option =>
|
|
option.setName("game")
|
|
.setDescription("Select the maptest game")
|
|
.setRequired(true)
|
|
.addChoices(...commands))
|
|
.addStringOption(option =>
|
|
option.setName("after_date")
|
|
.setDescription("Filter out submissions that weren't submitted after the given date"))
|
|
.addStringOption(option =>
|
|
option.setName("before_date")
|
|
.setDescription("Filter out submissions that weren't submitted before the given date"))
|
|
,
|
|
execute
|
|
};
|