Skip to content

Commit

Permalink
Merge branch 'master' of github.com:Nick-NCSU/hpbot into add-guild-co…
Browse files Browse the repository at this point in the history
…mmands
  • Loading branch information
Nick-NCSU committed Aug 7, 2022
2 parents f9178df + 3b09567 commit 6369f1f
Showing 19 changed files with 1,353 additions and 761 deletions.
12 changes: 7 additions & 5 deletions commands/categories.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { MessageEmbed } = require("discord.js");
const { EmbedBuilder } = require("discord.js");
const { SlashCommandBuilder } = require("@discordjs/builders");
const tokens = require("../index.js");

@@ -26,14 +26,14 @@ module.exports = {
return await interaction.editReply(`No results found for **${game}**.`);
}
const [dataArr] = data;
const embed = new MessageEmbed()
.setColor("118855")
const embed = new EmbedBuilder()
.setColor("#118855")
.setTitle(dataArr.names.international)
.setURL(dataArr.weblink)
.setThumbnail(dataArr.assets["cover-large"].uri);
// Iterates through all the categories for the game
let size = 0;
for (const category of dataArr.categories.data) {
for (const category of dataArr.categories.data.slice(0, 25)) {
let variables = "";
// Checks if variables exist
if (category.variables.data[0]) {
@@ -55,7 +55,9 @@ module.exports = {
if(size > 6000) {
break;
}
embed.addField(string, string2);
embed.addFields([
{ name: string, value: string2, }
]);
}
return await interaction.editReply({ embeds: [embed] });
},
18 changes: 10 additions & 8 deletions commands/dream.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { MessageEmbed } = require("discord.js");
const { EmbedBuilder } = require("discord.js");
const { SlashCommandBuilder } = require("@discordjs/builders");

/**
@@ -59,14 +59,16 @@ module.exports = {
const difference = pMax >= 42 ? "+" + pMax - 42 : pMax - 42;
// Compares rods to Dream
const difference2 = rMax >= 211 ? "+" + rMax - 211 : rMax - 211;
const embed = new MessageEmbed()
.setColor("118855")
const embed = new EmbedBuilder()
.setColor("#118855")
.setTitle("Your Results:")
.addField("Number of simulations: ", String(sim))
.addField("Average number of pearl trades: ", String(pTotal / sim))
.addField("Average number of rods: ", String(rTotal / sim))
.addField("Max number of pearl trades: " + pMax + "/262", "Number of pearl trades (Dream): 42/262")
.addField("Max number of rods: " + rMax + "/305", "Number of rods (Dream): 211/305")
.addFields([
{ name: "Number of simulations: ", value: String(sim) },
{ name: "Average number of pearl trades: ", value: String(pTotal / sim ) },
{ name: "Average number of rods: ", value: String(rTotal / sim ) },
{ name: "Max number of pearl trades: " + pMax + "/262", value: "Number of pearl trades (Dream) 42/262" },
{ name: "Max number of rods: " + rMax + "/305", value: "Number of rods (Dream) 211/305" }
])
.setFooter({ text: "Difference: " + difference + "/" + difference2 });
await interaction.editReply({ embeds: [embed] });
},
28 changes: 15 additions & 13 deletions commands/help.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { MessageEmbed } = require("discord.js");
const { EmbedBuilder } = require("discord.js");
const { SlashCommandBuilder } = require("@discordjs/builders");

/**
@@ -12,20 +12,22 @@ module.exports = {
.setName("help")
.setDescription("Provides a list of commands and descriptions."),
async execute(interaction) {
const embed = new MessageEmbed()
.setColor("118855")
const embed = new EmbedBuilder()
.setColor("#118855")
.setTitle("Help")
.setThumbnail("https://www.speedrun.com/images/1st.png")
.addField("/help", "Shows this help message.")
.addField("/hypixel", "Provides helpful links for Hypixel Speedruns")
.addField("/link <game>", "Sends a link to the provided game.")
.addField("/categories <game>", "Shows the categories/variables for the provided game.")
.addField("/search <keyword> (page)", "Searches for games containing the keyword(s).")
.addField("/leaderboard <game>", "Provides a leaderboard for the given game.")
.addField("/verified <user>", "Provides the number of runs verified by the given user.")
.addField("/queuelength <game>", "Provides the number of unverified runs for the given game.")
.addField("/dream (simulations)", "Simulates Dream's pearl and blaze rod odds.")
.addField("/ping", "Provides bot response time.");
.addFields([
{ name: "/help", value: "Shows this help message." },
{ name: "/hypixel", value: "Provides helpful links for Hypixel Speedruns" },
{ name: "/link <game>", value: "Sends a link to the provided game." },
{ name: "/categories <game>", value: "Shows the categories/variables for the provided game." },
{ name: "/search <keyword> (page)", value: "Searches for games containing the keyword(s)." },
{ name: "/leaderboard <game>", value: "Provides a leaderboard for the given game." },
{ name: "/verified <user>", value: "Provides the number of runs verified by the given user." },
{ name: "/queuelength <game>", value: "Provides the number of unverified runs for the given game." },
{ name: "/dream (simulations)", value: "Simulates Dream's pearl and blaze rod odds." },
{ name: "/ping", value: "Provides bot response time." }
]);
await interaction.editReply("Sending you help!");
await interaction.followUp({ embeds: [embed], ephemeral: true });
},
18 changes: 9 additions & 9 deletions commands/hypixel.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { MessageActionRow, MessageSelectMenu, MessageButton } = require("discord.js");
const { ActionRowBuilder, SelectMenuBuilder, ButtonBuilder, InteractionType, ButtonStyle } = require("discord.js");
const { SlashCommandBuilder } = require("@discordjs/builders");

/**
@@ -13,10 +13,10 @@ module.exports = {
.setDescription("Provides helpful links for Hypixel Speedruns"),
async execute(interaction) {
// Initial running of the command
if(interaction.isCommand()) {
const row = new MessageActionRow()
if(interaction.type === InteractionType.ApplicationCommand) {
const row = new ActionRowBuilder()
.addComponents(
new MessageSelectMenu()
new SelectMenuBuilder()
.setCustomId("type")
.setPlaceholder("Nothing selected")
.addOptions([
@@ -171,9 +171,9 @@ module.exports = {
];
break;
}
const row = new MessageActionRow()
const row = new ActionRowBuilder()
.addComponents(
new MessageSelectMenu()
new SelectMenuBuilder()
.setCustomId("link")
.setPlaceholder("Nothing selected")
.addOptions(options),
@@ -256,11 +256,11 @@ module.exports = {
url = "https://twitter.com/speedruncom";
break;
}
const row = new MessageActionRow()
const row = new ActionRowBuilder()
.addComponents(
new MessageButton()
new ButtonBuilder()
.setLabel(interaction.values[0])
.setStyle("LINK")
.setStyle(ButtonStyle.Link)
.setURL(url),
);
await interaction.update({ content: interaction.values[0] + " Link:", components: [row] });
139 changes: 84 additions & 55 deletions commands/leaderboard.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const tokens = require("../index.js");
const { MessageEmbed } = require("discord.js");
const { EmbedBuilder } = require("discord.js");
const { SlashCommandBuilder } = require("@discordjs/builders");

/**
@@ -16,13 +16,28 @@ module.exports = {
option.setName("game")
.setDescription("Game to get leaderboard")
.setRequired(true)
)
.addBooleanOption(option =>
option.setName("misc")
.setDescription("Include misc categories? Default: true")
)
.addBooleanOption(option =>
option.setName("fullgame")
.setDescription("Include Full Game Categories? Default: true")
)
.addBooleanOption(option =>
option.setName("ils")
.setDescription("Include Individual Levels? Default: true")
),
async execute(interaction) {
// From rsp via https://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in-javascript
// Provides cartesian product of arrays
const cartesian = (...a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())));

const game = interaction.options.get("game").value.toLowerCase();
const misc = interaction.options.get("misc")?.value ?? true;
const fullgame = interaction.options.get("fullgame")?.value ?? true;
const ils = interaction.options.get("ils")?.value ?? true;

// Retrieves all subcategories for the full game and ILs
const {data} = await tokens.fetch(`https://www.speedrun.com/api/v1/games/${game}?embed=categories.variables,levels.variables`);
@@ -37,37 +52,20 @@ module.exports = {
* Provides an array containing all subcategories for full game
* Format: [categoryID, [Array containing ids of each variable for the category], [Array containing all combinations of variable ids]]
*/
for(const category of data.categories.data) {
if(category.type == "per-game") {
let subArr = [];
let idArr = [];
for(const sub of category.variables.data) {
if(sub["is-subcategory"]){
const options = Object.keys(sub.values.values);
subArr.push(options);
idArr.push(sub.id);
}
}
let combinations = [];
if(subArr.length != 0) {
combinations = cartesian(...subArr);
}
subcategories.push([category.id, idArr, combinations]);
}
}

/**
* Provides an array containing all subcategories for individual levels
* Format: [levelID, [categoryID, [Array containing ids of each variable for the category], [Array containing all combinations of variable ids]]]
*/
for(const level of data.levels.data) {
if(fullgame) {
for(const category of data.categories.data) {
if(category.type == "per-level") {
if(!misc && category.miscellaneous) {
continue;
}
if(category.type == "per-game") {
let subArr = [];
let idArr = [];
for(const sub of level.variables.data) {
if(sub["is-subcategory"] && (!sub.category || sub.category == category.id)) {
const options = Object.keys(sub.values.values);
for(const sub of category.variables.data) {
if(sub["is-subcategory"]){
let options = Object.keys(sub.values.values);
if(!misc) {
options = options.filter(option => sub.values.values[option].flags.miscellaneous !== true);
}
subArr.push(options);
idArr.push(sub.id);
}
@@ -76,7 +74,36 @@ module.exports = {
if(subArr.length != 0) {
combinations = cartesian(...subArr);
}
sublevels.push([level.id, [category.id, idArr, combinations]]);
subcategories.push([category.id, idArr, combinations]);
}
}
}
/**
* Provides an array containing all subcategories for individual levels
* Format: [levelID, [categoryID, [Array containing ids of each variable for the category], [Array containing all combinations of variable ids]]]
*/
if(ils) {
for(const level of data.levels.data) {
for(const category of data.categories.data) {
if(category.type == "per-level") {
let subArr = [];
let idArr = [];
for(const sub of level.variables.data) {
if(sub["is-subcategory"] && (!sub.category || sub.category == category.id)) {
let options = Object.keys(sub.values.values);
if(!misc) {
options = options.filter(option => sub.values[option].flags.miscellaneous !== true);
}
subArr.push(options);
idArr.push(sub.id);
}
}
let combinations = [];
if(subArr.length != 0) {
combinations = cartesian(...subArr);
}
sublevels.push([level.id, [category.id, idArr, combinations]]);
}
}
}
}
@@ -108,18 +135,20 @@ module.exports = {
}
}

if(count + count2 > 500) {
if(!game.startsWith("hypixel_") && count + count2 > 500) {
return await interaction.editReply(`Game ${game} has too many categories. Number of categories: ${count + count2}.`);
}

let date = new Date().toISOString().slice(0, 10);
let embed = new MessageEmbed()
.setColor("118855")
let embed = new EmbedBuilder()
.setColor("#118855")
.setTitle("Leaderboard for " + game + ":")
.setThumbnail(data.assets["cover-large"].uri)
.setFooter({ text: date })
.addField("Full Game Progress:", `${progress}/${count}`)
.addField("Individual Levels Progress:", `${progress2}/${count2}`);
.addFields([
{ name: "Full Game Progress:", value: `${progress}/${count}` },
{ name: "Individual Levels Progress:", value: `${progress2}/${count2}` }
]);
await interaction.editReply({ embeds: [embed] });
let playerList = [];
// Iterates through each category
@@ -204,13 +233,15 @@ module.exports = {
}
// Update embed if enough progress has been made
if(Math.floor(progress/10) > lastEmbed) {
embed = new MessageEmbed()
.setColor("118855")
embed = new EmbedBuilder()
.setColor("#118855")
.setTitle("Leaderboard for " + game + ":")
.setThumbnail(data.assets["cover-large"].uri)
.setFooter({ text: date })
.addField("Full Game Progress:", `${progress}/${count}`)
.addField("Individual Levels Progress:", `${progress2}/${count2}`);
.addFields([
{ name: "Full Game Progress:", value: `${progress}/${count}` },
{ name: "Individual Levels Progress:", value: `${progress2}/${count2}` }
]);
await interaction.editReply({ embeds: [embed] });
lastEmbed = Math.floor(progress/10);
}
@@ -298,13 +329,15 @@ module.exports = {
}
// Update embed if enough progress has been made
if(Math.floor(progress2/10) > lastEmbed) {
embed = new MessageEmbed()
.setColor("118855")
embed = new EmbedBuilder()
.setColor("#118855")
.setTitle("Leaderboard for " + game + ":")
.setThumbnail(data.assets["cover-large"].uri)
.setFooter({ text: date })
.addField("Full Game Progress:", `${progress}/${count}`)
.addField("Individual Levels Progress:", `${progress2}/${count2}`);
.addFields([
{ name: "Full Game Progress:", value: `${progress}/${count}` },
{ name: "Individual Levels Progress:", value: `${progress2}/${count2}` }
]);
await interaction.editReply({ embeds: [embed] });
lastEmbed = Math.floor(progress2/10);
}
@@ -318,24 +351,20 @@ module.exports = {
playerList = playerList.filter(word => word[0].toLowerCase() !== "n/a");
// Which place to display
let place = 1;
let iterator = 0;
let countPlayer = 0;
embed = new MessageEmbed()
.setColor("118855")
embed = new EmbedBuilder()
.setColor("#118855")
.setTitle("Leaderboard for " + game + ":")
.setThumbnail(data.assets["cover-large"].uri)
.setFooter({ text: date });
for(const player of playerList) {
embed.addField("#" + place + " " + player[0].replace(/[\\*_~]/g, "\\$&"), `WRs:${player[1]}`, true);
countPlayer++;
for(let i = 0; i < 25; i++) {
const player = playerList[i];
embed.addFields([
{ name: "#" + place + " " + player[0].replace(/[\\*_~]/g, "\\$&"), value: `WRs:${player[1]}`, inline: true }
]);
// Increment only if next WR count is not equal to this count
if(playerList[iterator + 1] && playerList[iterator + 1][1] != playerList[iterator][1]) {
if(playerList[i + 1] && playerList[i + 1][1] != playerList[i][1]) {
place++;
}
if(countPlayer > 30) {
break;
}
iterator++;
}
await interaction.editReply({ embeds: [embed] });
},
6 changes: 3 additions & 3 deletions commands/link.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { MessageEmbed } = require("discord.js");
const { EmbedBuilder } = require("discord.js");
const { SlashCommandBuilder } = require("@discordjs/builders");
const tokens = require("../index.js");

@@ -27,8 +27,8 @@ module.exports = {
return await interaction.editReply(`No results found for **${game}**.`);
}
// Embed to return
const embed = new MessageEmbed()
.setColor("118855")
const embed = new EmbedBuilder()
.setColor("#118855")
.setTitle(answer.names.international)
.setURL(answer.weblink)
.setThumbnail(answer.assets["cover-large"].uri);
Loading

0 comments on commit 6369f1f

Please sign in to comment.