284 lines
11 KiB
JavaScript
284 lines
11 KiB
JavaScript
/*
|
|
* Commit Overflow Counting - Slash Command Definition File
|
|
* commit-count.js - Gets an initial commit count for Commit Overflow
|
|
*/
|
|
|
|
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
|
const {
|
|
convertSnowflakeToDate,
|
|
convertDateToSnowflake,
|
|
} = require('../utils/convert.js');
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('commit-count')
|
|
.setDescription('Counts Commits')
|
|
// .addStringOption(option =>
|
|
// option.setName('emoji')
|
|
// .setDescription('Optionally choose an emoji for verified messages'))
|
|
// .addMentionableOption(option =>
|
|
// option.setName('role')
|
|
// .setDescription('Choose a role for those that can react to verify'))
|
|
.addStringOption((option) =>
|
|
option
|
|
.setName('start')
|
|
.setDescription(
|
|
'Optionally specify a start date (MM/DD/YYYY preferred)',
|
|
),
|
|
)
|
|
.addStringOption((option) =>
|
|
option
|
|
.setName('end')
|
|
.setDescription('Optionally specify a end date (MM/DD/YYYY preferred)'),
|
|
)
|
|
.addStringOption((option) =>
|
|
option
|
|
.setName('ephemeral')
|
|
.setDescription('Post the avatar in the current channel')
|
|
.addChoices(
|
|
{ name: 'Send to me only', value: 'true' },
|
|
{ name: 'Send in channel', value: 'false' },
|
|
),
|
|
),
|
|
async execute(interaction) {
|
|
if (interaction.inGuild() && interaction.channel.isThread()) {
|
|
const threadStarterMessage =
|
|
await interaction.channel.fetchStarterMessage();
|
|
const emojiCheck =
|
|
interaction.options.getString('emoji') ?? 'gh_green_square';
|
|
const startDate = new Date(
|
|
interaction.options.getString('start-date') ??
|
|
threadStarterMessage.createdTimestamp,
|
|
);
|
|
// let endDate = new Date(
|
|
// interaction.options.getString('end-date') ??
|
|
// interaction.createdTimestamp,
|
|
// );
|
|
const isEphemeral =
|
|
interaction.options.getString('ephemeral') ?? 'true';
|
|
|
|
await interaction.deferReply({ ephemeral: (isEphemeral === 'true') });
|
|
|
|
// Fetch Messages
|
|
const sum_messages = [];
|
|
let first_id = convertDateToSnowflake(startDate);
|
|
let messageMap = new Map();
|
|
let continueFetching = true;
|
|
|
|
while (continueFetching) {
|
|
const options = { limit: 100 };
|
|
options.after = first_id;
|
|
|
|
try {
|
|
const messages = await interaction.channel.messages.fetch(options);
|
|
sum_messages.push(...messages.values());
|
|
|
|
for (const [snowflake, message] of messages) {
|
|
if (message.author.id === threadStarterMessage.author.id) {
|
|
const messageDate = convertSnowflakeToDate(snowflake);
|
|
let monthName = '';
|
|
|
|
// Assuming only Dec, Jan for now, can be expanded later
|
|
if (messageDate.getMonth() === 11) {
|
|
monthName = 'Dec.';
|
|
}
|
|
else if (messageDate.getMonth() === 0) {
|
|
monthName = 'Jan.';
|
|
}
|
|
|
|
const mapKey = monthName + ' ' + messageDate.getDate().toString();
|
|
|
|
if (messageMap.has(mapKey)) {
|
|
const mapValue = messageMap.get(mapKey);
|
|
mapValue.push(snowflake);
|
|
messageMap.set(mapKey, mapValue);
|
|
}
|
|
else {
|
|
const mapValue = [snowflake];
|
|
messageMap.set(mapKey, mapValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
first_id = messages.first().id;
|
|
|
|
if (messages.size < 100) {
|
|
continueFetching = false;
|
|
}
|
|
}
|
|
catch (error) {
|
|
console.error('Error fetching messages: ', error);
|
|
continueFetching = false;
|
|
}
|
|
}
|
|
|
|
messageMap = new Map([...messageMap.entries()].sort((a, b) => {
|
|
if (a[1] == b[1]) {
|
|
if (b > a) {
|
|
return -1;
|
|
}
|
|
else if (a < b) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
else if (a[1] < b[1]) {
|
|
return -1;
|
|
}
|
|
else {
|
|
return 1;
|
|
}
|
|
}));
|
|
|
|
// Start Commit Checking
|
|
let validString = '';
|
|
let invalidString = '';
|
|
const validDays = [];
|
|
|
|
for (const [date] of messageMap) {
|
|
let dateVerified = false;
|
|
let verifyReason = '';
|
|
|
|
const messageList = messageMap.get(date);
|
|
for (const messageId of messageList) {
|
|
// Complicated... But TLDR gives priority to Commit URL, then Attachment, then Reaction
|
|
if (verifyReason == '' || verifyReason != 'Attachment' || verifyReason != 'Reaction') {
|
|
await interaction.channel.messages
|
|
.fetch(messageId)
|
|
.then(async (message) => {
|
|
if (
|
|
/http.:\/\/.*\/(commit|compare|pull)\/.*/g.test(message.content)
|
|
) {
|
|
dateVerified = true;
|
|
verifyReason = 'Commit URL';
|
|
}
|
|
else if ((message.attachments.size > 0) && verifyReason != 'Commit URL') {
|
|
dateVerified = true;
|
|
verifyReason = 'Attachment';
|
|
}
|
|
else if ((message.reactions.cache.size > 0) && verifyReason != 'Commit URL' && verifyReason != 'Attachment') {
|
|
for (const reaction of message.reactions.cache.values()) {
|
|
const emojiName = reaction._emoji.name;
|
|
|
|
if (emojiName === emojiCheck) {
|
|
dateVerified = true;
|
|
verifyReason = 'Reaction';
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
})
|
|
.catch(console.error);
|
|
}
|
|
}
|
|
|
|
if (dateVerified) {
|
|
validString += `${date}: ${verifyReason}\n`;
|
|
validDays.push(date);
|
|
}
|
|
}
|
|
|
|
const resultsEmbed = {
|
|
title: 'Commits',
|
|
fields: [
|
|
{
|
|
name: 'Valid Commits',
|
|
value: validString,
|
|
},
|
|
],
|
|
};
|
|
|
|
const allDays = [];
|
|
const dayMap = new Map();
|
|
|
|
const currentDate = new Date(
|
|
interaction.options.getString('start-date') ??
|
|
threadStarterMessage.createdTimestamp,
|
|
);
|
|
const endDate = new Date(
|
|
interaction.options.getString('end-date') ??
|
|
new Date(),
|
|
);
|
|
|
|
while (currentDate <= endDate) {
|
|
allDays.push(new Date(currentDate));
|
|
currentDate.setDate(currentDate.getDate() + 1);
|
|
}
|
|
|
|
for (const day of allDays) {
|
|
let monthName = '';
|
|
// Assuming only Dec, Jan for ease at the moment. Can be changed later
|
|
if (day.getMonth() == 11) {
|
|
monthName = 'Dec.';
|
|
}
|
|
else if (day.getMonth() == 0) {
|
|
monthName = 'Jan.';
|
|
}
|
|
|
|
const formattedDay = monthName + ' ' + day.getDate().toString();
|
|
|
|
if (validDays.includes(formattedDay)) {
|
|
dayMap.set(formattedDay, true);
|
|
}
|
|
else if (formattedDay != (monthName + ' ' + (new Date()).getDate().toString())) {
|
|
invalidString += `${formattedDay}\n`;
|
|
dayMap.set(formattedDay, false);
|
|
}
|
|
}
|
|
|
|
let streakCount = 0;
|
|
const streaksArray = [];
|
|
|
|
for (const [, hasCommit] of dayMap) {
|
|
if (hasCommit) {
|
|
streakCount += 1;
|
|
}
|
|
else {
|
|
streaksArray.push(streakCount);
|
|
streakCount = 0;
|
|
}
|
|
}
|
|
|
|
streaksArray.push(streakCount);
|
|
streakCount = 0;
|
|
|
|
if (invalidString != '') {
|
|
resultsEmbed.fields.push({
|
|
name: 'Missed Days',
|
|
value: invalidString,
|
|
});
|
|
|
|
resultsEmbed.footer = {
|
|
text: `Organizers: Please check the above dates and react with ${emojiCheck} on any missed commits!`,
|
|
};
|
|
}
|
|
|
|
// Largest Array Value One Liner from https://stackoverflow.com/a/30850912
|
|
resultsEmbed.fields.push(
|
|
{
|
|
name: 'Total Commit Count',
|
|
value: validDays.length,
|
|
},
|
|
{
|
|
name: 'Largest Streak',
|
|
value:
|
|
streaksArray[
|
|
streaksArray.reduce(
|
|
(iMax, x, i, arr) => (x > arr[iMax] ? i : iMax),
|
|
0,
|
|
)
|
|
] ?? 0,
|
|
},
|
|
);
|
|
|
|
await interaction.editReply({ embeds: [resultsEmbed], ephemeral: (isEphemeral === 'true') });
|
|
}
|
|
else {
|
|
const notInThread = new EmbedBuilder()
|
|
.setColor(interaction.member.displayHexColor)
|
|
.setTitle('Not in a Thread')
|
|
.setDescription('You must run this command in a Thread!');
|
|
await interaction.reply({ embeds: [notInThread], ephemeral: true });
|
|
}
|
|
},
|
|
};
|