diff --git a/server/src/modules/announceOnDiscourse.ts b/server/src/modules/announceOnDiscourse.ts new file mode 100644 index 0000000..8ffd1f2 --- /dev/null +++ b/server/src/modules/announceOnDiscourse.ts @@ -0,0 +1,54 @@ +/** + * @copyright nhcarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ +/* eslint-disable @typescript-eslint/naming-convention -- we are making raw API calls. */ + +import type { AnnouncementType } from "../interfaces/announcementType.js"; + +const announcementCategoryId = 16; + +const tags: Record = { + community: "Community", + company: "Company", + products: "Products", +}; + +/** + * Posts an announcement to the NHCarrigan Discourse support forum. + * @param title - The title of the announcement. + * @param content - The main body of the announcement in markdown. + * @param type - Whether the announcement is for a product, community, or company. + * @returns A message indicating the success or failure of the operation. + */ +export const announceOnDiscourse = async( + title: string, + content: string, + type: AnnouncementType, +): Promise => { + if (process.env.FORUM_API_KEY === undefined) { + return "Discourse API key is not set."; + } + + const response = await fetch("https://support.nhcarrigan.com/posts.json", { + body: JSON.stringify({ + category: announcementCategoryId, + raw: content, + tags: [ tags[type] ], + title: title, + }), + headers: { + "Api-Key": process.env.FORUM_API_KEY, + "Api-Username": "hikari", + "Content-Type": "application/json", + }, + method: "POST", + }); + + if (!response.ok) { + return `Failed to post to Discourse. Status: ${response.status.toString()} ${response.statusText}`; + } + + return "Successfully posted announcement to Discourse~! ✨"; +}; diff --git a/server/src/routes/announcement.ts b/server/src/routes/announcement.ts index 178d865..75f7bc8 100644 --- a/server/src/routes/announcement.ts +++ b/server/src/routes/announcement.ts @@ -8,6 +8,7 @@ import { blockedIps } from "../cache/blockedIps.js"; import { database } from "../db/database.js"; import { announceOnBluesky } from "../modules/announceOnBluesky.js"; import { announceOnDiscord } from "../modules/announceOnDiscord.js"; +import { announceOnDiscourse } from "../modules/announceOnDiscourse.js"; import { announceOnFacebook } from "../modules/announceOnFacebook.js"; import { announceOnMastodon } from "../modules/announceOnMastodon.js"; import { announceOnReddit } from "../modules/announceOnReddit.js"; @@ -119,10 +120,15 @@ export const announcementRoutes: FastifyPluginAsync = async(server) => { const facebookPost = await announceOnFacebook(plaintext); const threadsPost = await announceOnThreads(threaded); const mastodonPost = await announceOnMastodon(threaded); + const discoursePost = await announceOnDiscourse( + markdownTitle, + markdownContent, + type, + ); return await reply.status(201).send({ alert: `Please remember to manually post to: LinkedIn, Peerlist, Ko-fi, and Patreon.`, cost: announcement.cost, - message: `Announcement processed. Discord: ${discordPost}, Reddit: ${redditPost}, Bluesky: ${blueskyPost}, Twitter: ${twitterPost}, Facebook: ${facebookPost}, Threads: ${threadsPost}, Mastodon: ${mastodonPost}`, + message: `Announcement processed. Discord: ${discordPost}, Reddit: ${redditPost}, Bluesky: ${blueskyPost}, Twitter: ${twitterPost}, Facebook: ${facebookPost}, Threads: ${threadsPost}, Mastodon: ${mastodonPost}, Discourse: ${discoursePost}`, rawPost: announcement.response, }); },