diff options
Diffstat (limited to 'src/reddit.ts')
| -rw-r--r-- | src/reddit.ts | 208 |
1 files changed, 0 insertions, 208 deletions
diff --git a/src/reddit.ts b/src/reddit.ts deleted file mode 100644 index 5b4ded7..0000000 --- a/src/reddit.ts +++ /dev/null @@ -1,208 +0,0 @@ -import type { TimePeriod } from "./discord/types.ts"; - -export interface RedditPost { - id: string; - title: string; - author: string; - score: number; - num_comments: number; - created_utc: number; - permalink: string; - url: string; - selftext: string; - is_gallery?: boolean; - over_18: boolean; - link_flair_text?: string; - thumbnail?: string; - preview?: { - images: Array<{ - source: { - url: string; - width: number; - height: number; - }; - resolutions: Array<{ - url: string; - width: number; - height: number; - }>; - }>; - enabled: boolean; - }; - media?: { - reddit_video?: { - fallback_url: string; - }; - }; - secure_media?: { - reddit_video?: { - fallback_url: string; - }; - }; -} - -export interface RedditResponse { - data: { - children: Array<{ - data: RedditPost; - }>; - }; -} - -type SortType = "hot" | "top"; - -const fetchWithRetry = async ( - 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 const fetchRedditPosts = async ( - 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 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 (err) { - if ( - err instanceof Error && - err.message.includes("blocked by network security") - ) - throw err; - } - - throw new Error(errorText); - } - - const data: RedditResponse = await response.json(); - - return data.data.children.map((post) => post.data); -}; - -export const filterPostsByFlair = ( - posts: RedditPost[], - excludedFlairs: string[] = [], - includedFlairs: string[] = [], -): RedditPost[] => { - return posts.filter((post) => { - if (post.is_gallery) return false; - - const hasMedia = - post.media?.reddit_video?.fallback_url || - post.secure_media?.reddit_video?.fallback_url || - post.url; - - if (!hasMedia) return false; - - const postFlair = post.link_flair_text?.toLowerCase() || ""; - const isNSFW = post.over_18 || postFlair.includes("nsfw"); - - if ( - includedFlairs.length > 0 && - includedFlairs.some((flair) => flair.toLowerCase() === "nsfw") - ) - if (includedFlairs.some((flair) => flair.toLowerCase() === "nsfw")) - return isNSFW; - - if (isNSFW) return false; - - if (includedFlairs.length > 0) - return includedFlairs.some((flair) => - postFlair.includes(flair.toLowerCase()), - ); - - if (excludedFlairs.length > 0) - return !excludedFlairs.some((flair) => - postFlair.includes(flair.toLowerCase()), - ); - - return true; - }); -}; - -const getRandomPost = (posts: RedditPost[]): RedditPost => { - if (posts.length === 0) - throw new Error("No posts found matching the criteria"); - - const randomIndex = Math.floor(Math.random() * posts.length); - - return posts[randomIndex]; -}; - -export const getCutePost = async (): Promise<RedditPost> => { - const posts = await fetchRedditPosts("hot"); - const filteredPosts = filterPostsByFlair(posts, ["roleplay", "announcement"]); - - return getRandomPost(filteredPosts); -}; - -export const getRoleplayPost = async (): Promise<RedditPost> => { - const posts = await fetchRedditPosts("hot"); - const filteredPosts = filterPostsByFlair(posts, [], ["roleplay"]); - - return getRandomPost(filteredPosts); -}; - -export const getNSFWPost = async (): Promise<RedditPost> => { - const posts = await fetchRedditPosts("hot"); - const filteredPosts = filterPostsByFlair(posts, [], ["nsfw"]); - - return getRandomPost(filteredPosts); -}; - -export const getTopPost = async ( - time: TimePeriod = "day", -): Promise<RedditPost> => { - const posts = await fetchRedditPosts("top", time); - const filteredPosts = filterPostsByFlair(posts, ["roleplay", "announcement"]); - - return getRandomPost(filteredPosts); -}; |