spb/social-runtime-crawler
Public
TypeScript 91.8%
HTML 3.2%
JavaScript 3%
SQL 1.4%
CSS 0.7%
1import type { EntityType, PageType } from "@src/shared";2import type { ClassifierHints } from "@src/observers";3import type { SocialPlatformAdapter, UrlEntityRule } from "./adapter.ts";45/** Reddit adapter — Phase 1 platform (new web UI, `shreddit-*` custom elements, GraphQL + `.json` payloads). */6const classifierHints: ClassifierHints = {7 platform: "reddit",8 idKeys: { postId: "post", commentId: "comment", subredditId: "community", authorId: "profile" },9 urlForId: (type: EntityType, id: string) => {10 if (type === "post" && /^t3_/.test(id)) return `https://www.reddit.com/comments/${id.slice(3)}`;11 if (type === "post" && /^[a-z0-9]{5,8}$/.test(id)) return `https://www.reddit.com/comments/${id}`;12 return undefined;13 },14};1516const urlEntityRules: UrlEntityRule[] = [17 { pattern: /^\/r\/([\w]+)\/comments\/([a-z0-9]+)\/[^/]*\/([a-z0-9]+)/, type: "comment", id: (m) => `t1_${m[3]}`, confidence: 0.9 },18 { pattern: /^\/r\/([\w]+)\/comments\/([a-z0-9]+)/, type: "post", id: (m) => `t3_${m[2]}`, confidence: 0.95 },19 { pattern: /^\/comments\/([a-z0-9]+)/, type: "post", id: (m) => `t3_${m[1]}`, confidence: 0.9 },20 { pattern: /^\/(?:user|u)\/([\w-]+)\/?(?:\?|$)/, type: "profile", id: (m) => m[1]?.toLowerCase(), confidence: 0.92 },21 { pattern: /^\/r\/([\w]+)\/?(?:\?|$)/, type: "community", id: (m) => m[1]?.toLowerCase(), confidence: 0.92 },22];2324export const redditAdapter: SocialPlatformAdapter = {25 platform: "reddit",26 homeUrl: "https://www.reddit.com/",27 hosts: /(^|\.)reddit\.com$|^redd\.it$/,28 pageTypeHints: [29 { pattern: /^\/search\/?\?/, page_type: "SEARCH_RESULTS", confidence: 0.95 },30 { pattern: /\/comments\//, page_type: "POST_DETAIL", confidence: 0.95 },31 { pattern: /^\/(user|u)\//, page_type: "PROFILE", confidence: 0.92 },32 { pattern: /^\/r\/[\w]+\/?(\?|$|\/(hot|new|top|rising))/, page_type: "GROUP", confidence: 0.9 },33 { pattern: /^\/?(\?|$)|^\/(popular|all|best)/, page_type: "HOME_FEED", confidence: 0.9 },34 ],35 urlEntityRules,36 classifierHints,37 searchUrl: (q) => `https://www.reddit.com/search/?q=${encodeURIComponent(q)}`,38 isNoiseLink: (href, text) => /^\/(settings|premium|coins|policies|help|topics|best\/communities|answers)/.test(href.pathname) || /^(Home|Popular|All|Accueil|Populaire)$/i.test(text),39 entityLabel: (t) => ({ post: "post", comment: "comment", profile: "user", community: "subreddit" } as Partial<Record<EntityType, string>>)[t] ?? t,40 expectedEntities: (t: PageType) => ({ HOME_FEED: 6, SEARCH_RESULTS: 5, POST_DETAIL: 3, GROUP: 6, PROFILE: 3 } as Partial<Record<PageType, number>>)[t] ?? 0,41};42