diff --git a/src/commands/jobs/jobs.ts b/src/commands/jobs/jobs.ts index 3dff16e0..36f404bf 100644 --- a/src/commands/jobs/jobs.ts +++ b/src/commands/jobs/jobs.ts @@ -279,7 +279,7 @@ export default class extends Command { await db.findOne({ discordId: userID }) )?.jobPreferences; - if (!jobformAnswers) { + if (!jobformAnswers || !jobformAnswers.answers) { await interaction.reply( "You haven't set up your job preferences yet. Please use `/jobform` first." ); diff --git a/src/commands/jobs/histogram.ts b/src/commands/jobs/jobsalarygraph.ts similarity index 78% rename from src/commands/jobs/histogram.ts rename to src/commands/jobs/jobsalarygraph.ts index ce6ffcf6..dc0fb99b 100644 --- a/src/commands/jobs/histogram.ts +++ b/src/commands/jobs/jobsalarygraph.ts @@ -7,8 +7,8 @@ import { ChartConfiguration } from 'chart.js'; export default class extends Command { - description = `Get a listing of jobs based on your interests and preferences.`; - extendedHelp = `This command will return a listing of jobs based on your interests and preferences.`; + description = `View a histogram of how many jobs are available at different salary ranges.`; + extendedHelp = `See how many jobs are available at different salaries`; options: ApplicationCommandOptionData[] = [ { name: 'job', @@ -26,16 +26,22 @@ export default class extends Command { const URL_BASE = `https://api.adzuna.com/v1/api/jobs/us/histogram?app_id=${ADZUNA_APP_ID}&app_key=${ADZUNA_APP_KEY}&what=${encodedJobTitle}`; - const response = await axios.get(URL_BASE); - const data = Object.entries(response.data.histogram).map(([value, frequency]: [string, number]) => ({ - value, - frequency - })); + try { + const response = await axios.get(URL_BASE); - const image = await generateHistogram(data, jobTitle); + const data = Object.entries(response.data.histogram).map(([value, frequency]: [string, number]) => ({ + value, + frequency + })); + const image = await generateHistogram(data, jobTitle); - await interaction.followUp({ files: [{ attachment: image, name: 'histogram.png' }] }); // Send the file as a follow-up + await interaction.followUp({ files: [{ attachment: image, name: 'histogram.png' }] }); // Send the file as a follow-up + } catch (e) { + console.error('Error fetching job salary data', e); + await interaction.followUp({ content: 'There was an issue fetching the job salary data. Please try again later.' }); + return; + } } } diff --git a/src/lib/utils/jobUtils/Adzuna_job_search.ts b/src/lib/utils/jobUtils/Adzuna_job_search.ts index 46abf51b..0d370b43 100644 --- a/src/lib/utils/jobUtils/Adzuna_job_search.ts +++ b/src/lib/utils/jobUtils/Adzuna_job_search.ts @@ -32,6 +32,10 @@ export default async function fetchJobListings(jobData: JobData, interests?: Int for (const interest of keys) { const value = interests[interest]; + if (!value) { + delete interests[interest]; + continue; + } whatInterests += value.replace(/\s+/g, '-'); // Replace spaces with dashes if (value !== lastValue) whatInterests += ' '; } diff --git a/src/pieces/commandManager.ts b/src/pieces/commandManager.ts index 6006d42e..fc9c66b8 100644 --- a/src/pieces/commandManager.ts +++ b/src/pieces/commandManager.ts @@ -1,9 +1,25 @@ -import { Collection, Client, ApplicationCommand, - GuildMember, SelectMenuInteraction, - ModalSubmitInteraction, TextChannel, GuildMemberRoleManager, - ButtonInteraction, ModalBuilder, TextInputBuilder, ActionRowBuilder, - ModalActionRowComponentBuilder, ApplicationCommandType, ApplicationCommandDataResolvable, ChannelType, ApplicationCommandPermissionType, TextInputStyle, - ChatInputCommandInteraction } from 'discord.js'; +import { + Collection, + Client, + ApplicationCommand, + GuildMember, + SelectMenuInteraction, + ModalSubmitInteraction, + TextChannel, + GuildMemberRoleManager, + ButtonInteraction, + ModalBuilder, + TextInputBuilder, + ActionRowBuilder, + ModalActionRowComponentBuilder, + ApplicationCommandType, + ApplicationCommandDataResolvable, + ChannelType, + ApplicationCommandPermissionType, + TextInputStyle, + ChatInputCommandInteraction, + MessageFlags +} from 'discord.js'; import { isCmdEqual, readdirRecursive } from '@root/src/lib/utils/generalUtils'; import { Command } from '@lib/types/Command'; import { SageData } from '@lib/types/SageData'; @@ -326,14 +342,14 @@ async function runCommand(interaction: ChatInputCommandInteraction, bot: Client) if (!success) return interaction.reply(failMessages[Math.floor(Math.random() * failMessages.length)]); try { - bot.commands.get(interaction.commandName).run(interaction) - ?.catch(async (error: Error) => { // Idk if this is needed now, but keeping in case removing it breaks stuff... - bot.emit('error', new CommandError(error, interaction)); - interaction.reply({ content: `An error occurred. ${MAINTAINERS} have been notified.`, ephemeral: true }); - }); + await bot.commands.get(interaction.commandName).run(interaction); } catch (error) { bot.emit('error', new CommandError(error, interaction)); - interaction.reply({ content: `An error occurred. ${MAINTAINERS} have been notified.`, ephemeral: true }); + if (interaction.replied || interaction.deferred) { + await interaction.followUp({ content: `An error occurred. ${MAINTAINERS} have been notified.`, flags: MessageFlags.Ephemeral }); + } else { + await interaction.reply({ content: `An error occurred. ${MAINTAINERS} have been notified.`, flags: MessageFlags.Ephemeral }); + } console.log(error.errors); } } diff --git a/src/pieces/tasks.ts b/src/pieces/tasks.ts index 6834a769..61f92d7a 100644 --- a/src/pieces/tasks.ts +++ b/src/pieces/tasks.ts @@ -30,7 +30,7 @@ import nodemailer from 'nodemailer'; import { JobPreferences } from '../lib/types/JobPreferences'; import axios from 'axios'; import { PDFDocument, PDFFont, rgb, StandardFonts } from 'pdf-lib'; -import { generateHistogram } from '../commands/jobs/histogram'; +import { generateHistogram } from '../commands/jobs/jobsalarygraph'; async function register(bot: Client): Promise { schedule('0/30 * * * * *', () => {