diff options
| author | Fuwn <[email protected]> | 2025-09-09 18:05:15 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-09-09 18:05:15 -0700 |
| commit | 9678e4e1e87a5d73c47683fe85848888ca8e857b (patch) | |
| tree | 42235ab613eba920ef46ceaba946f2fdc6362427 /src/server.ts | |
| parent | fix: Properly handle videos (diff) | |
| download | umabotdiscord-9678e4e1e87a5d73c47683fe85848888ca8e857b.tar.xz umabotdiscord-9678e4e1e87a5d73c47683fe85848888ca8e857b.zip | |
refactor: Move Discord APIs to Discord module
Diffstat (limited to 'src/server.ts')
| -rw-r--r-- | src/server.ts | 190 |
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(/&/g, '&') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/"/g, '"') - .replace(/'/g, "'") - .replace(///g, '/') - .replace(/`/g, '`') - .replace(/=/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, |