generated from nhcarrigan/template
fix: replace deprecated ephemeral flag and add error handling across modules
- Replace `ephemeral: true` with `flags: [ MessageFlags.Ephemeral ]` in all command files - Add try/catch with logger.error to logMenteeJoin, checkAchievements, processMentorshipRole - Extract handleIssueOpened and handlePrOpened helpers in processGitHubEvent to reduce complexity - Add logger.error calls in all newly introduced catch blocks
This commit is contained in:
@@ -95,7 +95,7 @@ export const createIssue = async(
|
|||||||
const title = interaction.options.getString("title", true);
|
const title = interaction.options.getString("title", true);
|
||||||
const description = interaction.options.getString("description") ?? "";
|
const description = interaction.options.getString("description") ?? "";
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const augmentedBody = await generateIssueBody(description, title);
|
const augmentedBody = await generateIssueBody(description, title);
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ export const createTask = async(
|
|||||||
const description = interaction.options.getString("description") ?? "";
|
const description = interaction.options.getString("description") ?? "";
|
||||||
const priority = interaction.options.getInteger("priority") ?? 3;
|
const priority = interaction.options.getInteger("priority") ?? 3;
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const augmentedDesc = await generateTaskDescription(description, title);
|
const augmentedDesc = await generateTaskDescription(description, title);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { logger } from "../utils/logger.js";
|
|||||||
const forwardToOwner = async(
|
const forwardToOwner = async(
|
||||||
interaction: MessageContextMenuCommandInteraction,
|
interaction: MessageContextMenuCommandInteraction,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] });
|
||||||
|
|
||||||
if (interaction.user.id !== ids.users.naomi) {
|
if (interaction.user.id !== ids.users.naomi) {
|
||||||
await interaction.editReply("❌ Only Naomi can use this command.");
|
await interaction.editReply("❌ Only Naomi can use this command.");
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export const onboardMentee = async(
|
|||||||
const githubUsername = interaction.options.getString("github_username", true);
|
const githubUsername = interaction.options.getString("github_username", true);
|
||||||
const menteeUser = interaction.options.getUser("mentee", true);
|
const menteeUser = interaction.options.getUser("mentee", true);
|
||||||
|
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const repoUrl = await setupMenteeRepository(amari, githubUsername);
|
const repoUrl = await setupMenteeRepository(amari, githubUsername);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
type MessageActionRowComponentBuilder,
|
type MessageActionRowComponentBuilder,
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
import { ids } from "../config/ids.js";
|
import { ids } from "../config/ids.js";
|
||||||
|
import { logger } from "../utils/logger.js";
|
||||||
import type { Amari } from "../interfaces/amari.js";
|
import type { Amari } from "../interfaces/amari.js";
|
||||||
|
|
||||||
const username = "naomilgbt";
|
const username = "naomilgbt";
|
||||||
@@ -91,28 +92,34 @@ export const checkRetroAchievements = async(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auth = buildAuthorization({ username, webApiKey });
|
try {
|
||||||
|
const auth = buildAuthorization({ username, webApiKey });
|
||||||
|
|
||||||
const recentAchievements = await getUserRecentAchievements(auth, {
|
const recentAchievements = await getUserRecentAchievements(auth, {
|
||||||
recentMinutes: 10,
|
recentMinutes: 10,
|
||||||
username: username,
|
username: username,
|
||||||
});
|
|
||||||
|
|
||||||
if (recentAchievements.length <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const channel = amari.discord.channels.cache.get(ids.channels.gaming)
|
|
||||||
?? await amari.discord.channels.fetch(ids.channels.gaming);
|
|
||||||
|
|
||||||
if (channel?.isSendable() !== true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(recentAchievements.map(async(achievement) => {
|
|
||||||
await channel.send({
|
|
||||||
components: constructComponents(achievement),
|
|
||||||
flags: [ MessageFlags.IsComponentsV2 ],
|
|
||||||
});
|
});
|
||||||
}));
|
|
||||||
|
if (recentAchievements.length <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = amari.discord.channels.cache.get(ids.channels.gaming)
|
||||||
|
?? await amari.discord.channels.fetch(ids.channels.gaming);
|
||||||
|
|
||||||
|
if (channel?.isSendable() !== true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(recentAchievements.map(async(achievement) => {
|
||||||
|
await channel.send({
|
||||||
|
components: constructComponents(achievement),
|
||||||
|
flags: [ MessageFlags.IsComponentsV2 ],
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
await logger.error("checkRetroAchievements module", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,25 +20,31 @@ export const logMenteeJoin = async(
|
|||||||
amari: Amari,
|
amari: Amari,
|
||||||
member: GuildMember,
|
member: GuildMember,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const request = await fetch(`https://forms.nhcarrigan.com/api/database/rows/table/756/?user_field_names=true&search=${member.id}`, { headers: {
|
try {
|
||||||
authorization: `Token ${process.env.BASEROW_TOKEN ?? "huh"}`,
|
const request = await fetch(`https://forms.nhcarrigan.com/api/database/rows/table/756/?user_field_names=true&search=${member.id}`, { headers: {
|
||||||
} });
|
authorization: `Token ${process.env.BASEROW_TOKEN ?? "huh"}`,
|
||||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Fetch accepts no generic here.
|
} });
|
||||||
const response = await request.json() as MentorshipRow;
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Fetch accepts no generic here.
|
||||||
|
const response = await request.json() as MentorshipRow;
|
||||||
|
|
||||||
if (response.count <= 0) {
|
if (response.count <= 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = amari.discord.channels.cache.get(ids.channels.general)
|
||||||
|
?? await amari.discord.channels.fetch(ids.channels.general);
|
||||||
|
|
||||||
|
if (channel?.isSendable() !== true) {
|
||||||
|
await logger.log(
|
||||||
|
"warn",
|
||||||
|
"General channel does not exist or is not sendable.",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await logger.metric("processed_mentee_join", 1, { user: member.id });
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
await logger.error("logMenteeJoin module", error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const channel = amari.discord.channels.cache.get(ids.channels.general)
|
|
||||||
?? await amari.discord.channels.fetch(ids.channels.general);
|
|
||||||
|
|
||||||
if (channel?.isSendable() !== true) {
|
|
||||||
await logger.log(
|
|
||||||
"warn",
|
|
||||||
"General channel does not exist or is not sendable.",
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await logger.metric("processed_mentee_join", 1, { user: member.id });
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,13 +21,78 @@ const isPull = (body: GithubPayload): body is PullRequestCreated => {
|
|||||||
return "pull_request" in body;
|
return "pull_request" in body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a newly opened GitHub issue by auto-assigning Naomi.
|
||||||
|
* @param amari - Amari's instance.
|
||||||
|
* @param body - The parsed issue webhook payload.
|
||||||
|
*/
|
||||||
|
const handleIssueOpened = async(
|
||||||
|
amari: Amari,
|
||||||
|
body: IssueCreated,
|
||||||
|
): Promise<void> => {
|
||||||
|
await logger.log("info", "Processing new issue");
|
||||||
|
const { issue, repository } = body;
|
||||||
|
const { number, user } = issue;
|
||||||
|
const { owner, name } = repository;
|
||||||
|
try {
|
||||||
|
await amari.github.rest.issues.addAssignees({
|
||||||
|
assignees: [ "naomi-lgbt" ],
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention -- Github SDK requirement.
|
||||||
|
issue_number: number,
|
||||||
|
owner: owner.login,
|
||||||
|
repo: name,
|
||||||
|
});
|
||||||
|
await logger.metric("processed_github_event", 1, {
|
||||||
|
action: "opened",
|
||||||
|
event: "issue",
|
||||||
|
user: user.login,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
await logger.error("processGitHubEvent module", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a newly opened GitHub pull request by requesting Naomi's review.
|
||||||
|
* @param amari - Amari's instance.
|
||||||
|
* @param body - The parsed pull request webhook payload.
|
||||||
|
*/
|
||||||
|
const handlePrOpened = async(
|
||||||
|
amari: Amari,
|
||||||
|
body: PullRequestCreated,
|
||||||
|
): Promise<void> => {
|
||||||
|
const { pull_request: pr, repository } = body;
|
||||||
|
const { number, user } = pr;
|
||||||
|
await logger.log("info", "Processing new PR");
|
||||||
|
const { owner, name } = repository;
|
||||||
|
try {
|
||||||
|
await amari.github.rest.pulls.requestReviewers({
|
||||||
|
owner: owner.login,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/naming-convention -- Github SDK requirement.
|
||||||
|
pull_number: number,
|
||||||
|
repo: name,
|
||||||
|
reviewers: [ "naomi-lgbt" ],
|
||||||
|
});
|
||||||
|
await logger.metric("processed_github_event", 1, {
|
||||||
|
action: "opened",
|
||||||
|
event: "pull_request",
|
||||||
|
user: user.login,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
await logger.error("processGitHubEvent module", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a payload from a GitHub webhook.
|
* Handles a payload from a GitHub webhook.
|
||||||
* @param amari - Amari's instance.
|
* @param amari - Amari's instance.
|
||||||
* @param request - The Fastify request payload.
|
* @param request - The Fastify request payload.
|
||||||
* @param response - The Fastify reply class.
|
* @param response - The Fastify reply class.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line max-statements, max-lines-per-function -- STFU.
|
|
||||||
export const processGithubEvent = async(
|
export const processGithubEvent = async(
|
||||||
amari: Amari,
|
amari: Amari,
|
||||||
request: FastifyRequest<{
|
request: FastifyRequest<{
|
||||||
@@ -58,40 +123,10 @@ export const processGithubEvent = async(
|
|||||||
const { action } = request.body;
|
const { action } = request.body;
|
||||||
await response.status(200).send({ message: "Payload received!" });
|
await response.status(200).send({ message: "Payload received!" });
|
||||||
if (action === "opened" && event === "issues" && isIssue(request.body)) {
|
if (action === "opened" && event === "issues" && isIssue(request.body)) {
|
||||||
await logger.log("info", "Processing new issue");
|
await handleIssueOpened(amari, request.body);
|
||||||
const { issue, repository } = request.body;
|
|
||||||
const { number, user } = issue;
|
|
||||||
const { owner, name } = repository;
|
|
||||||
await amari.github.rest.issues.addAssignees({
|
|
||||||
assignees: [ "naomi-lgbt" ],
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- Github SDK requirement.
|
|
||||||
issue_number: number,
|
|
||||||
owner: owner.login,
|
|
||||||
repo: name,
|
|
||||||
});
|
|
||||||
await logger.metric("processed_github_event", 1, {
|
|
||||||
action: "opened",
|
|
||||||
event: "issue",
|
|
||||||
user: user.login,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (action === "opened" && event === "pull_request" && isPull(request.body)) {
|
if (action === "opened" && event === "pull_request" && isPull(request.body)) {
|
||||||
const { pull_request: pr, repository } = request.body;
|
await handlePrOpened(amari, request.body);
|
||||||
const { number, user } = pr;
|
|
||||||
await logger.log("info", "Processing new PR");
|
|
||||||
await logger.metric("processed_github_event", 1, {
|
|
||||||
action: "opened",
|
|
||||||
event: "pull_request",
|
|
||||||
user: user.login,
|
|
||||||
});
|
|
||||||
const { owner, name } = repository;
|
|
||||||
await amari.github.rest.pulls.requestReviewers({
|
|
||||||
owner: owner.login,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention -- Github SDK requirement.
|
|
||||||
pull_number: number,
|
|
||||||
repo: name,
|
|
||||||
reviewers: [ "naomi-lgbt" ],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,20 +34,21 @@ export const processMentorshipRole = async(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const channel
|
try {
|
||||||
= amari.discord.channels.cache.get(ids.channels.menteeChat)
|
const channel
|
||||||
?? await amari.discord.channels.fetch(ids.channels.menteeChat);
|
= amari.discord.channels.cache.get(ids.channels.menteeChat)
|
||||||
|
?? await amari.discord.channels.fetch(ids.channels.menteeChat);
|
||||||
|
|
||||||
if (channel?.isSendable() !== true) {
|
if (channel?.isSendable() !== true) {
|
||||||
await logger.log(
|
await logger.log(
|
||||||
"warn",
|
"warn",
|
||||||
"Mentee Chat channel does not exist or is not sendable.",
|
"Mentee Chat channel does not exist or is not sendable.",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await channel.send({
|
await channel.send({
|
||||||
content: `Hey <@${updatedMember.id}>~! Welcome to the mentorship programme!
|
content: `Hey <@${updatedMember.id}>~! Welcome to the mentorship programme!
|
||||||
|
|
||||||
Please ping (mention, tag) Naomi in this channel with the following template to get started:
|
Please ping (mention, tag) Naomi in this channel with the following template to get started:
|
||||||
\`\`\`
|
\`\`\`
|
||||||
@@ -56,9 +57,14 @@ First name:
|
|||||||
Last name:
|
Last name:
|
||||||
\`\`\`
|
\`\`\`
|
||||||
Then read our [mentorship wiki](<https://docs.nhcarrigan.com/mentorship/00-faq/>) for the next steps!`,
|
Then read our [mentorship wiki](<https://docs.nhcarrigan.com/mentorship/00-faq/>) for the next steps!`,
|
||||||
});
|
});
|
||||||
addWelcomedMentee(updatedMember.id);
|
addWelcomedMentee(updatedMember.id);
|
||||||
await logger.metric("processed_mentorship_role", 1, {
|
await logger.metric("processed_mentorship_role", 1, {
|
||||||
user: updatedMember.id,
|
user: updatedMember.id,
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
await logger.error("processMentorshipRole module", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user