diff --git a/modules/aoc/aocCommand.ts b/modules/aoc/aocCommand.ts index 110833b..586f3b2 100644 --- a/modules/aoc/aocCommand.ts +++ b/modules/aoc/aocCommand.ts @@ -1,7 +1,8 @@ import {ISlashCommand} from "../../types"; -import {CommandInteraction} from "discord.js"; -import {embedLeaderboard} from "./aocLeaderboardParser"; +import {ApplicationCommandOptionType, CommandInteraction, CommandInteractionOptionResolver} from "discord.js"; +import {embedLeaderboard} from "./aocEmbedGenerator"; import {get} from "../../lib/configmanager"; +import {DateTime} from "luxon"; /** * Slash command definition for /aoc, a command that sends the current leaderboard @@ -9,10 +10,23 @@ import {get} from "../../lib/configmanager"; export default { command: { name: "aoc", - description: "Returns the Advent of Code Leaderboard" + description: "Returns the Advent of Code Leaderboard", + options:[ + { + type: ApplicationCommandOptionType.Integer, + name: "year", + description: "the year of the Advent of Code", + min_value: 2022, + max_value: DateTime.now().setZone("Europe/Berlin").year, + required: false + } + ] }, handler: async function(interaction: CommandInteraction) { - const embed = await embedLeaderboard(get("id", "aoc") as number, get("year", "aoc") as number); + const options = interaction.options as CommandInteractionOptionResolver; + const requestedYear = options.getInteger("year", false); + const year = (requestedYear === undefined)? DateTime.now().setZone("Europe/Berlin").year : requestedYear; + const embed = await embedLeaderboard(get("id", "aoc") as number, year); await interaction.reply({ embeds: [embed] }); } } as ISlashCommand; diff --git a/modules/aoc/aocEmbedGenerator.ts b/modules/aoc/aocEmbedGenerator.ts new file mode 100644 index 0000000..23131a5 --- /dev/null +++ b/modules/aoc/aocEmbedGenerator.ts @@ -0,0 +1,32 @@ +import {EmbedBuilder} from "discord.js"; +import {requestLeaderboard} from "./aocLeaderboardParser"; + + +/** + * Generates the embed for displaying a leaderboard + * + * @param id ID of the leaderboard + * @param year Year of this AoC competition + * @returns The Embed for showing the leaderboard + */ +export async function embedLeaderboard(id:number, year: number) : Promise { + const members = await requestLeaderboard(id, year); + const map = {} as {[key:string]: string}; + for(const m of members) { + map[m.name] = ""; + for (const k in m.completion_day_level) { + let emoji = ":eight_pointed_black_star:"; + if (m.completion_day_level[k]["1"].get_star_ts != 0) { + if (m.completion_day_level[k]["2"].get_star_ts != 0) { + emoji = ":star2:"; + } else { + emoji = ":star:"; + } + } + map[m.name] = map[m.name] + emoji; + } + } + return new EmbedBuilder().setURL("https://adventofcode.com").setTitle("Advent of Code Leaderboard") + .addFields({name:"Ranking", value:members.map(e => { return e.name + ": " + e.local_score + map[e.name]; }).join("\n")}); + +} diff --git a/modules/aoc/aocLeaderboardParser.ts b/modules/aoc/aocLeaderboardParser.ts index c29fbcb..ab62fb8 100644 --- a/modules/aoc/aocLeaderboardParser.ts +++ b/modules/aoc/aocLeaderboardParser.ts @@ -1,36 +1,9 @@ import axios from "axios"; -import {EmbedBuilder} from "discord.js"; +import {aocData, aocMember} from "./aocTypes"; const url = "https://adventofcode.com/"; const path = "/leaderboard/private/view/"; -interface aoc_data { - event: string - owner_id: number - members: { - [id:number]:aoc_member - } -} -interface aoc_member { - last_start_ts: number - id: number - local_score: number - stars: number - name: string - global_score: number - completion_day_level: { - [day:number]: { - 1: { - get_star_ts: number - star_index: number - } - 2: { - get_star_ts: number - star_index: number - } - } - } -} /** * Gets the current leaderboard data from the AoC servers @@ -39,10 +12,10 @@ interface aoc_member { * @param year Year of this AoC competition * @returns Array of members of this leaderboard */ -export async function requestLeaderboard(id: number, year: number) : Promise { +export async function requestLeaderboard(id: number, year: number) : Promise { const concaturl = url + year + path + id + ".json"; const answer = await axios.get(concaturl, {headers: {'Content-Type' : 'application/json', 'cookie':'session=' + process.env.AOC_SESSION}}); - const data = answer.data as aoc_data; + const data = answer.data as aocData; const members = Object.values(data.members); members.sort((a, b)=> { if (a.local_score < b.local_score) { @@ -55,33 +28,5 @@ export async function requestLeaderboard(id: number, year: number) : Promise { - const members = await requestLeaderboard(id, year); - const map = {} as {[key:string]: string}; - for(const m of members) { - map[m.name] = ""; - for (const k in m.completion_day_level) { - let a = ":eight_pointed_black_star:"; - if (m.completion_day_level[k]["1"].get_star_ts != 0) { - if (m.completion_day_level[k]["2"].get_star_ts != 0) { - a = ":star2:"; - } else { - a = ":star:"; - } - } - map[m.name] = map[m.name] + a; - } - } - const embed = new EmbedBuilder().setURL("https://adventofcode.com").setTitle("Advent of Code Leaderboard") - .addFields({name:"Ranking", value:members.map(e => { return e.name + ": " + e.local_score + map[e.name]; }).join("\n")}); - return embed; -} diff --git a/modules/aoc/aocTask.ts b/modules/aoc/aocTask.ts index 77dbf01..c80846c 100644 --- a/modules/aoc/aocTask.ts +++ b/modules/aoc/aocTask.ts @@ -1,6 +1,6 @@ import {Client, TextChannel} from "discord.js"; import {TaskExecutor} from "../../types"; -import {embedLeaderboard} from "./aocLeaderboardParser"; +import {embedLeaderboard} from "./aocEmbedGenerator"; import {get} from "../../lib/configmanager"; import {DateTime} from "luxon"; diff --git a/modules/aoc/aocTypes.ts b/modules/aoc/aocTypes.ts new file mode 100644 index 0000000..5b8848e --- /dev/null +++ b/modules/aoc/aocTypes.ts @@ -0,0 +1,28 @@ +export interface aocData { + event: string + owner_id: number + members: { + [id:number]:aocMember + } +} + +export interface aocMember { + last_start_ts: number + id: number + local_score: number + stars: number + name: string + global_score: number + completion_day_level: { + [day:number]: { + 1: { + get_star_ts: number + star_index: number + } + 2: { + get_star_ts: number + star_index: number + } + } + } +} \ No newline at end of file