Initial Code

This commit is contained in:
2025-11-23 13:22:13 -05:00
parent b16d4adfd2
commit c3e52d6a03
96 changed files with 7088 additions and 135 deletions

View File

@@ -0,0 +1,121 @@
import BotCommand from "../../libs/BotCommand";
import BotClient from "../../libs/BotClient";
import { ChatInputCommandInteraction, MessageFlags, EmbedBuilder, AttachmentBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle, TextChannel } from "discord.js";
import QuestionScheduler from "../../libs/QuestionScheduler";
import AnswerGrader from "../../libs/AnswerGrader";
const SUBJECTS = ["Mathematics", "Physics", "Chemistry", "Biology", "Computer Science", "Engineering"];
export default class WeeklyCommand extends BotCommand {
constructor() {
super("weekly", "Answer this week's weekly STEM question", "/weekly");
this.data.addStringOption(option =>
option.setName("subject")
.setDescription("Choose a subject")
.addChoices(
{ name: "Mathematics", value: "mathematics" },
{ name: "Physics", value: "physics" },
{ name: "Chemistry", value: "chemistry" },
{ name: "Organic Chemistry", value: "organic chemistry" },
{ name: "Biology", value: "biology" },
{ name: "Computer Science", value: "computer science" },
{ name: "Engineering", value: "engineering" }
)
.setRequired(true)
);
}
override async execute(Discord: any, client: BotClient, interaction: ChatInputCommandInteraction): Promise<any> {
try {
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
const subject = interaction.options.getString("subject", true);
const scheduler = new QuestionScheduler();
await scheduler.initialize();
const question = await scheduler.getQuestionForPeriod(subject, "weekly");
if (!question) {
return interaction.editReply({ content: `Failed to load this week's ${subject} question. Please try again later.` });
}
const hasAnswered = await scheduler.hasUserAnswered(interaction.user.id, question.id);
if (hasAnswered) {
return interaction.editReply({ content: "You've already submitted an answer for this week's question! Check back next Sunday." });
}
const imagePath = await client.typst.renderToImage(question.typst_source);
if (!imagePath) {
// Log error to logs channel
const logsChannelId = process.env.LOGS_CHANNEL_ID;
if (logsChannelId) {
try {
const logsChannel = await client.channels.fetch(logsChannelId) as TextChannel;
if (logsChannel?.isTextBased()) {
const errorEmbed = new EmbedBuilder()
.setTitle("❌ Typst Render Error - Weekly Question")
.setColor(0xef4444)
.addFields(
{ name: "Subject", value: subject, inline: true },
{ name: "Question ID", value: question.id, inline: true },
{ name: "Topic", value: question.topic, inline: false },
{ name: "User", value: `<@${interaction.user.id}>`, inline: true },
{ name: "Error", value: "Failed to render Typst image", inline: false }
)
.setTimestamp();
await logsChannel.send({ embeds: [errorEmbed] });
}
} catch (logErr) {
console.error("Failed to send error to logs channel:", logErr);
}
}
return interaction.editReply({
content: `❌ An error occurred while generating the question image. This has been reported to administrators.`
});
}
const embed = new EmbedBuilder()
.setTitle(`🎓 Weekly ${subject} Question (PhD Level)`)
.setDescription(`**Topic:** ${question.topic}\n**Difficulty:** ${question.difficulty_rating}`)
.setColor(0xfacc15)
.setImage(`attachment://weekly_${subject}.png`)
.setFooter({ text: `Resets at 12 AM Sunday` })
.setTimestamp();
const attachment = new AttachmentBuilder(imagePath, { name: `weekly_${subject}.png` });
const row = new ActionRowBuilder<ButtonBuilder>()
.addComponents(
new ButtonBuilder()
.setCustomId(`weekly_answer_${question.id}`)
.setLabel("Submit Answer")
.setStyle(ButtonStyle.Primary)
.setEmoji("✍️"),
new ButtonBuilder()
.setCustomId(`weekly_report_${question.id}`)
.setLabel("Report Issue")
.setStyle(ButtonStyle.Danger)
.setEmoji("⚠️")
);
await interaction.editReply({
embeds: [embed],
files: [attachment],
components: [row],
});
} catch (err) {
console.error("Error executing weekly command:", err);
try {
if (interaction.deferred || interaction.replied) {
await interaction.editReply({ content: "An error occurred. Please try again later." });
} else {
await interaction.reply({ content: "An error occurred. Please try again later.", flags: MessageFlags.Ephemeral });
}
} catch (e) {
console.error("Error sending error reply:", e);
}
}
}
}