diff options
| -rw-r--r-- | src/reddit.ts | 52 | ||||
| -rw-r--r-- | src/register.ts | 2 | ||||
| -rw-r--r-- | src/server.ts | 22 |
3 files changed, 58 insertions, 18 deletions
diff --git a/src/reddit.ts b/src/reddit.ts index 79475b1..5c5ae0b 100644 --- a/src/reddit.ts +++ b/src/reddit.ts @@ -1,4 +1,4 @@ -import type { TimePeriod } from './commands.js'; +import type { TimePeriod } from './commands.ts'; export interface RedditPost { id: string; @@ -35,26 +35,58 @@ export interface RedditResponse { type SortType = 'hot' | 'top'; -async function fetchRedditPosts( +async function fetchWithRetry(url: string, maxRetries: number = 3): Promise<Response> { + for (let attempt = 0; attempt < maxRetries; attempt++) + try { + await new Promise(resolve => setTimeout(resolve, Math.random() * 1000 + 500)); + + const response = await fetch(url, { + headers: { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Language': 'en-US,en;q=0.5', + 'Accept-Encoding': 'gzip, deflate, br', + 'DNT': '1', + 'Connection': 'keep-alive', + 'Upgrade-Insecure-Requests': '1', + }, + }); + + return response; + } catch (error) { + if (attempt === maxRetries - 1) throw error; + + const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000; + + console.log(`Attempt ${attempt + 1} failed, retrying in ${delay}ms ...`); + + await new Promise(resolve => setTimeout(resolve, delay)); + } + + throw new Error('Max retries exceeded'); +} + +export async function fetchRedditPosts( sort: SortType = 'hot', time: TimePeriod = 'day', ): Promise<RedditPost[]> { const url = `https://www.reddit.com/r/okbuddyumamusume/${sort}.json${sort === 'top' ? `?t=${time}` : ''}`; - const response = await fetch(url, { - headers: { - 'User-Agent': 'UmaBot/0.1.0', - }, - }); + const response = await fetchWithRetry(url); if (!response.ok) { let errorText = `Error fetching ${response.url}: ${response.status} ${response.statusText}`; try { const error = await response.text(); + + if (error.includes('You\'ve been blocked by network security') || + error.includes('blocked by network security')) + throw new Error('Reddit is blocking requests due to network security. This may be due to rate limiting or bot detection. Please try again later.'); if (error) errorText = `${errorText} \n\n ${error}`; - } catch { - // + } catch (err) { + if (err instanceof Error && err.message.includes('blocked by network security')) + throw err; } throw new Error(errorText); @@ -65,7 +97,7 @@ async function fetchRedditPosts( return data.data.children.map((post) => post.data); } -function filterPostsByFlair( +export function filterPostsByFlair( posts: RedditPost[], excludedFlairs: string[] = [], includedFlairs: string[] = [], diff --git a/src/register.ts b/src/register.ts index 632b2b8..94bb420 100644 --- a/src/register.ts +++ b/src/register.ts @@ -4,7 +4,7 @@ import { ROLEPLAY_COMMAND, TOP_COMMAND, type DiscordCommand, -} from './commands.js'; +} from './commands.ts'; import dotenv from 'dotenv'; import process from 'node:process'; diff --git a/src/server.ts b/src/server.ts index 3f54f63..bb0c458 100644 --- a/src/server.ts +++ b/src/server.ts @@ -9,15 +9,15 @@ import { ROLEPLAY_COMMAND, NSFW_COMMAND, TOP_COMMAND, -} from './commands.js'; +} from './commands.ts'; import { getCutePost, getRoleplayPost, getNSFWPost, getTopPost, type RedditPost, -} from './reddit.js'; -import type { TimePeriod } from './commands.js'; +} from './reddit.ts'; +import type { TimePeriod } from './commands.ts'; interface Environment { DISCORD_APPLICATION_ID: string; @@ -167,7 +167,9 @@ router.post('/', async (request: Request, environment: Environment) => { embeds: [embed], }, }); - } catch { + } catch (error) { + console.error('Error in hot command:', error); + return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { @@ -189,7 +191,9 @@ router.post('/', async (request: Request, environment: Environment) => { embeds: [embed], }, }); - } catch { + } catch (error) { + console.error('Error in roleplay command:', error); + return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { @@ -221,7 +225,9 @@ router.post('/', async (request: Request, environment: Environment) => { embeds: [embed], }, }); - } catch { + } catch (error) { + console.error('Error in NSFW command:', error); + return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { @@ -245,7 +251,9 @@ router.post('/', async (request: Request, environment: Environment) => { embeds: [embed], }, }); - } catch { + } catch (error) { + console.error('Error in top command:', error); + return new JSONResponse({ type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE, data: { |