summaryrefslogtreecommitdiff
path: root/src/server.ts
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-09-09 18:05:15 -0700
committerFuwn <[email protected]>2025-09-09 18:05:15 -0700
commit9678e4e1e87a5d73c47683fe85848888ca8e857b (patch)
tree42235ab613eba920ef46ceaba946f2fdc6362427 /src/server.ts
parentfix: Properly handle videos (diff)
downloadumabotdiscord-9678e4e1e87a5d73c47683fe85848888ca8e857b.tar.xz
umabotdiscord-9678e4e1e87a5d73c47683fe85848888ca8e857b.zip
refactor: Move Discord APIs to Discord module
Diffstat (limited to 'src/server.ts')
-rw-r--r--src/server.ts190
1 files changed, 7 insertions, 183 deletions
diff --git a/src/server.ts b/src/server.ts
index baeb607..5f43763 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -1,179 +1,25 @@
import { AutoRouter } from 'itty-router';
-import {
- InteractionResponseType,
- InteractionType,
- verifyKey,
-} from 'discord-interactions';
+import { InteractionResponseType, InteractionType } from 'discord-interactions';
import {
HOT_COMMAND,
ROLEPLAY_COMMAND,
NSFW_COMMAND,
TOP_COMMAND,
-} from './commands.ts';
+} from './discord/commands.ts';
import {
getCutePost,
getRoleplayPost,
getNSFWPost,
getTopPost,
- type RedditPost,
} from './reddit.ts';
-import type { TimePeriod } from './commands.ts';
-
-interface Environment {
- DISCORD_APPLICATION_ID: string;
- DISCORD_PUBLIC_KEY: string;
- DISCORD_TOKEN: string;
-}
-
-interface DiscordInteraction {
- type: number;
- data: {
- name: string;
- options?: Array<{
- name: string;
- value: string;
- }>;
- };
- channel_id?: string;
- channel?: {
- nsfw: boolean;
- };
-}
-
-interface DiscordEmbed {
- title: string;
- description: string;
- url: string;
- color: number;
- author: {
- name: string;
- url: string;
- };
- fields: Array<{
- name: string;
- value: string;
- inline: boolean;
- }>;
- timestamp: string;
- footer: {
- text: string;
- };
- image?: { url: string };
-}
-
-interface DiscordResponse {
- type: number;
- data?: {
- content?: string;
- embeds?: DiscordEmbed[];
- flags?: number;
- };
-}
-
-class JSONResponse extends Response {
- constructor(body: DiscordResponse | { error: string }, init?: ResponseInit) {
- const jsonBody = JSON.stringify(body);
-
- init = init || {
- headers: {
- 'content-type': 'application/json;charset=UTF-8',
- },
- };
-
- super(jsonBody, init);
- }
-}
+import type { TimePeriod } from './discord/types.ts';
+import type { Environment } from './discord/interfaces.ts';
+import { createPostEmbed } from './discord/embeds.ts';
+import { JSONResponse } from './discord/responses.ts';
+import { verifyDiscordRequest } from './discord/verification.ts';
const router = AutoRouter();
-function decodeHtmlEntities(str: string): string {
- return str
- .replace(/&amp;/g, '&')
- .replace(/&lt;/g, '<')
- .replace(/&gt;/g, '>')
- .replace(/&quot;/g, '"')
- .replace(/&#x27;/g, "'")
- .replace(/&#x2F;/g, '/')
- .replace(/&#x60;/g, '`')
- .replace(/&#x3D;/g, '=');
-}
-
-function createPostEmbed(post: RedditPost): DiscordEmbed {
- const mediaUrl =
- post.media?.reddit_video?.fallback_url ||
- post.secure_media?.reddit_video?.fallback_url ||
- post.url;
-
- let description = post.selftext || '';
-
- if (description.length > 1000)
- description = description.substring(0, 997).trim() + ' ...';
-
- const embed: DiscordEmbed = {
- title: post.title,
- description: description,
- url: `https://reddit.com${post.permalink}`,
- color: 0xff4500,
- author: {
- name: `u/${post.author}`,
- url: `https://reddit.com/u/${post.author}`,
- },
- fields: [
- {
- name: 'Score',
- value: `${post.score} ā¬†ļø`,
- inline: true,
- },
- {
- name: 'Comments',
- value: `${post.num_comments} šŸ’¬`,
- inline: true,
- },
- ],
- timestamp: new Date(post.created_utc * 1000).toISOString(),
- footer: {
- text: 'r/okbuddyumamusume',
- },
- };
-
- if (mediaUrl)
- if (post.media?.reddit_video || post.secure_media?.reddit_video) {
- if (!description) description = '';
-
- description +=
- '\n\nšŸ“¹ **This post contains a video** - [Click here to view](' +
- mediaUrl +
- ')';
- embed.description = description;
-
- if (post.preview?.images?.[0]?.source?.url) {
- const decodedURL = decodeHtmlEntities(
- post.preview.images[0].source.url,
- );
-
- console.log('Using preview image:', decodedURL);
-
- embed.image = { url: decodedURL };
- } else if (
- post.thumbnail &&
- post.thumbnail !== 'self' &&
- post.thumbnail !== 'default'
- ) {
- const decodedThumbnail = decodeHtmlEntities(post.thumbnail);
-
- console.log('Using thumbnail:', decodedThumbnail);
-
- embed.image = { url: decodedThumbnail };
- } else {
- console.log('No suitable thumbnail found for video post');
- }
- } else {
- embed.image = { url: mediaUrl };
- }
-
- return embed;
-}
-
router.get('/', (_request: Request, environment: Environment) => {
return new Response(`šŸ‘‹ ${environment.DISCORD_APPLICATION_ID}`);
});
@@ -314,28 +160,6 @@ router.post('/', async (request: Request, environment: Environment) => {
router.all('*', () => new Response('Not Found.', { status: 404 }));
-async function verifyDiscordRequest(
- request: Request,
- environment: Environment,
-): Promise<{ isValid: boolean; interaction?: DiscordInteraction }> {
- const signature = request.headers.get('x-signature-ed25519');
- const timestamp = request.headers.get('x-signature-timestamp');
- const body = await request.text();
- const isValidRequest =
- signature &&
- timestamp &&
- (await verifyKey(
- body,
- signature,
- timestamp,
- environment.DISCORD_PUBLIC_KEY,
- ));
-
- if (!isValidRequest) return { isValid: false };
-
- return { interaction: JSON.parse(body) as DiscordInteraction, isValid: true };
-}
-
const server = {
verifyDiscordRequest,
fetch: router.fetch,