diff --git a/src/database/structures/GuildWebhook.ts b/src/database/structures/GuildWebhook.ts index 1c4bc6ae..bdc91b76 100644 --- a/src/database/structures/GuildWebhook.ts +++ b/src/database/structures/GuildWebhook.ts @@ -30,6 +30,18 @@ export default class GitCordGuildWebhook { return `/webhooks/${this.guild.guildId}/${this.id}`; } + /** + * Adds a repository to the list of repositories + * @param repository The repository to add + * @param threadId The thread associated with the thread + */ + public async setRepository(repository: string, threadId: string) { + this.repositories.set(repository, threadId); + + const prismaRepositories = this.repositories.map((thread, repo) => ({ [repo]: thread })).reduce((a, b) => ({ ...a, ...b }), {}); + await this.guild.client.prisma.guildWebhook.update({ where: { webhookId: this.id }, data: { repositories: prismaRepositories } }); + } + private parseRepositories(repositories: Prisma.JsonValue[]) { const schema = z.array( z.object({ diff --git a/src/github/lib/embed/GitHubEmbedLoader.ts b/src/github/lib/embed/GitHubEmbedLoader.ts index 34dd4d02..60f1cc46 100644 --- a/src/github/lib/embed/GitHubEmbedLoader.ts +++ b/src/github/lib/embed/GitHubEmbedLoader.ts @@ -6,6 +6,7 @@ import { fileURLToPath } from "node:url"; import { readdir } from "node:fs/promises"; import { statSync } from "node:fs"; import { underline } from "colorette"; +import type { Repository } from "@octokit/webhooks-types"; const __dirname = dirname(fileURLToPath(import.meta.url)); @@ -36,6 +37,20 @@ export default class GitHubEmbedLoader { return embed; } + /** + * Returns the repository name or DEFAULT if none is found + * @param payload The event payload + */ + public getRepository(payload: string) { + const parsed = JSON.parse(payload); + if ("repository" in parsed) { + const repository = parsed.repository as Repository; + return repository.full_name; + } + + return "DEFAULT"; + } + /** * Gets all the files from a directory * @param path The filepath of a directory to read diff --git a/src/github/lib/webhook/GitHubWebhookManager.ts b/src/github/lib/webhook/GitHubWebhookManager.ts index c317f46c..4b3ab6df 100644 --- a/src/github/lib/webhook/GitHubWebhookManager.ts +++ b/src/github/lib/webhook/GitHubWebhookManager.ts @@ -97,24 +97,30 @@ export default class GitHubWebhookManager { if (embed === null) return; if (embed) { - let threadName: string | undefined; + let threadId: string | undefined; if (webhook.type === "FORUM") { - const parsedPayload = JSON.parse(payload); - if ("repository" in parsedPayload) threadName = parsedPayload.repository.full_name as string; + const repository = this.manager.embedLoader.getRepository(payload); + threadId = webhook.repositories.get(repository); const channel = await this.client.channels.fetch(webhook.id); - if (!channel) return; - - if (channel.type === ChannelType.GuildForum && !channel.threads.cache.get(threadName!)) { - await channel.threads.create({ - name: threadName!, - message: { content: `GitHub Notifications for **${threadName}**: https://github.com/${threadName}` } - }); + if (!channel || channel.type !== ChannelType.GuildForum) return; // Invalid channel provided means we cannot post messages + + if (!threadId) { + const thread = await channel.threads + .create({ + name: repository, + message: { content: `GitHub Notifications for **${repository}**: https://github.com/${repository}` } + }) + .catch(() => null); + + if (!thread) return; // No thread created means we cannot post a message + threadId = thread.id; + await webhook.setRepository(repository, threadId); } } await webhook.discordWebhook - .send({ embeds: [embed], avatarURL: GITHUB_AVATAR_URL, username: "GitCord", threadName }) + .send({ embeds: [embed], avatarURL: GITHUB_AVATAR_URL, username: "GitCord", threadId }) .catch((err) => this.client.logger.error(err)); return; }