import { AutoRouter } from "itty-router"; import { InteractionResponseType, InteractionType } from "discord-interactions"; import { HOT_COMMAND, ROLEPLAY_COMMAND, NSFW_COMMAND, TOP_COMMAND, COMPLAIN_COMMAND, } from "./discord/commands.ts"; import { getCutePost, getRoleplayPost, getNSFWPost, getTopPost, } from "./reddit.ts"; import type { TimePeriod } from "./discord/types.ts"; import type { Environment, DiscordEmbed } from "./discord/interfaces.ts"; import { createPostEmbed, createComplaintEmbed } from "./discord/embeds.ts"; import { JSONResponse } from "./discord/responses.ts"; import { verifyDiscordRequest } from "./discord/verification.ts"; const router = AutoRouter(); const COMPLAINT_CHANNEL_ID = "1415868433714778204"; const sendComplaintToChannel = async ( environment: Environment, embed: DiscordEmbed, ): Promise => { const url = `https://discord.com/api/v10/channels/${COMPLAINT_CHANNEL_ID}/messages`; try { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bot ${environment.DISCORD_TOKEN}`, }, body: JSON.stringify({ embeds: [embed], }), }); return response.ok; } catch (error) { console.error("Error sending complaint to channel:", error); return false; } }; router.get("/", (_request: Request, environment: Environment) => { return new Response(`👋 ${environment.DISCORD_APPLICATION_ID}`); }); router.post("/", async (request: Request, environment: Environment) => { const { isValid, interaction } = await server.verifyDiscordRequest( request, environment, ); if (!isValid || !interaction) return new Response("Bad request signature.", { status: 401 }); if (interaction.type === InteractionType.PING) return new JSONResponse({ type: InteractionResponseType.PONG, }); if (interaction.type === InteractionType.APPLICATION_COMMAND) { switch (interaction.data.name.toLowerCase()) { case HOT_COMMAND.name.toLowerCase(): { try { const post = await getCutePost(); const embed = createPostEmbed(post); return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { embeds: [embed], }, }); } catch (error) { console.error("Error in hot command:", error); return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { content: "❌ No posts found. Try again later!", flags: 64, }, }); } } case ROLEPLAY_COMMAND.name.toLowerCase(): { try { const post = await getRoleplayPost(); const embed = createPostEmbed(post); return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { embeds: [embed], }, }); } catch (error) { console.error("Error in roleplay command:", error); return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { content: "❌ No roleplay posts found. Try again later!", flags: 64, }, }); } } case NSFW_COMMAND.name.toLowerCase(): { if (!interaction.channel_id || !interaction.channel?.nsfw) { return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { content: "❌ This command can only be used in NSFW channels.", flags: 64, }, }); } try { const post = await getNSFWPost(); const embed = createPostEmbed(post); return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { embeds: [embed], }, }); } catch (error) { console.error("Error in NSFW command:", error); return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { content: "❌ No NSFW posts found. Try again later!", flags: 64, }, }); } } case TOP_COMMAND.name.toLowerCase(): { try { const time = (interaction.data.options?.[0]?.value as TimePeriod) || "day"; const post = await getTopPost(time); const embed = createPostEmbed(post); return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { embeds: [embed], }, }); } catch (error) { console.error("Error in top command:", error); return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { content: "❌ No top posts found. Try again later!", flags: 64, }, }); } } case COMPLAIN_COMMAND.name.toLowerCase(): { try { const complaintMessage = interaction.data.options?.[0] ?.value as string; if (!complaintMessage) return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { content: "❌ Please provide a message for your complaint.", flags: 64, }, }); const complainant = { username: interaction.member?.user?.username || interaction.user?.username || "Unknown", id: interaction.member?.user?.id || interaction.user?.id || "Unknown", avatar: interaction.member?.user?.avatar || interaction.user?.avatar, }; const isDM = !interaction.guild_id; const complaintEmbed = createComplaintEmbed( complaintMessage, complainant, Date.now(), isDM, ); const success = await sendComplaintToChannel( environment, complaintEmbed, ); if (success) { return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { content: "✅ Your complaint has been submitted successfully!", flags: 64, }, }); } else { return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { content: "❌ Failed to submit your complaint. Please try again later.", flags: 64, }, }); } } catch (error) { console.error("Error in complain command:", error); return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { content: "❌ An error occurred while processing your complaint.", flags: 64, }, }); } } default: return new JSONResponse({ error: "Unknown Type" }, { status: 400 }); } } console.error("Unknown Type"); return new JSONResponse({ error: "Unknown Type" }, { status: 400 }); }); router.all("*", () => new Response("Not Found.", { status: 404 })); const server = { verifyDiscordRequest, fetch: router.fetch, }; export default server;