/** * @copyright NHCarrigan * @license Naomi's Public License * @author Naomi Carrigan */ import { MessageFlags, type ChatInputCommandInteraction } from "discord.js"; import { ids } from "../config/ids.js"; import { logger } from "../utils/logger.js"; import type { Amari } from "../interfaces/amari.js"; /** * Creates a mentee repository and configures collaborator access. * @param amari - The Amari instance. * @param githubUsername - The mentee's GitHub username. * @returns The URL of the created or existing repository. */ const setupMenteeRepository = async( amari: Amari, githubUsername: string, ): Promise => { const orgApps = amari.githubApp.octokit.rest.apps; const { data: installation } = await orgApps.getOrgInstallation({ org: "nhcarrigan-mentorship", }); const mentorshipOctokit = await amari.githubApp.getInstallationOctokit(installation.id); let repoUrl = `https://github.com/nhcarrigan-mentorship/${githubUsername}`; try { const { data: repoData } = await mentorshipOctokit.rest.repos.createInOrg({ // eslint-disable-next-line @typescript-eslint/naming-convention -- Octokit API field. auto_init: true, name: githubUsername, org: "nhcarrigan-mentorship", }); repoUrl = repoData.html_url; } catch { // Repo likely already exists - use the default URL. } await mentorshipOctokit.rest.repos.addCollaborator({ owner: "nhcarrigan-mentorship", permission: "maintain", repo: githubUsername, username: githubUsername, }); return repoUrl; }; /** * Onboards a new mentee by creating their GitHub repository and notifying them. * @param amari - The Amari instance. * @param interaction - The Discord slash command interaction. */ export const onboardMentee = async( amari: Amari, interaction: ChatInputCommandInteraction, ): Promise => { if (interaction.user.id !== ids.users.naomi) { await interaction.reply({ content: "This command is restricted to Naomi.", flags: [ MessageFlags.Ephemeral ], }); return; } const menteeName = interaction.options.getString("mentee_name", true); const githubUsername = interaction.options.getString("github_username", true); const menteeUser = interaction.options.getUser("mentee", true); await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] }); try { const repoUrl = await setupMenteeRepository(amari, githubUsername); const channel = amari.discord.channels.cache.get(ids.channels.menteeChat) ?? await amari.discord.channels.fetch(ids.channels.menteeChat); if (channel?.isSendable() !== true) { await interaction.editReply({ content: "Repo created but could not send Discord notification.", }); return; } await channel.send({ content: `Hey <@${menteeUser.id}>! I've created your mentorship repository: ${repoUrl}\n\nYou should have received an invitation to collaborate - please accept it to get started!`, }); await logger.metric("onboarded_mentee", 1, { mentee: menteeName }); await interaction.editReply({ content: `✅ Successfully onboarded **${menteeName}**!\nRepository: ${repoUrl}`, }); } catch (error) { await logger.error("onboardmentee command", error instanceof Error ? error : new Error(String(error))); await interaction.editReply({ content: `❌ Failed to onboard mentee: ${String(error)}`, }); } };