@@ -5,6 +5,50 @@ const MATCH_RE =
55const FOLLOWUP_RE =
66 / ^ (?: h t t p s ? : \/ \/ ) ? (?: w w w \. | o l d \. | m \. ) ? r e d d i t \. c o m \/ r \/ (?< subreddit > \w + ) \/ c o m m e n t s \/ (?< post_id > [ a - z 0 - 9 ] + ) / ;
77
8+ async function fetchAccessToken ( env : {
9+ EMBED_USER_AGENT : string ;
10+ REDDIT_CLIENT_ID ?: string ;
11+ REDDIT_CLIENT_SECRET ?: string ;
12+ } ) {
13+ if ( ! env . REDDIT_CLIENT_ID || ! env . REDDIT_CLIENT_SECRET ) {
14+ throw {
15+ code : 500 ,
16+ message : "Reddit credentials are not configured" ,
17+ } ;
18+ }
19+
20+ const resp = await fetch ( "https://www.reddit.com/api/v1/access_token" , {
21+ method : "POST" ,
22+ headers : {
23+ Authorization : `Basic ${ btoa ( `${ env . REDDIT_CLIENT_ID } :${ env . REDDIT_CLIENT_SECRET } ` ) } ` ,
24+ "Content-Type" : "application/x-www-form-urlencoded" ,
25+ "User-Agent" : env . EMBED_USER_AGENT ,
26+ } ,
27+ body : new URLSearchParams ( { grant_type : "client_credentials" } ) ,
28+ } ) ;
29+
30+ if ( ! resp . ok ) {
31+ throw { code : resp . status , message : resp . statusText } ;
32+ }
33+
34+ const data = ( await resp . json ( ) ) as Record < string , any > ;
35+ return data . access_token as string ;
36+ }
37+
38+ async function fetchReddit (
39+ path : string ,
40+ env : { EMBED_USER_AGENT : string ; REDDIT_CLIENT_ID ?: string ; REDDIT_CLIENT_SECRET ?: string } ,
41+ ) {
42+ const token = await fetchAccessToken ( env ) ;
43+ return fetch ( `https://oauth.reddit.com${ path } ` , {
44+ method : "GET" ,
45+ headers : {
46+ Authorization : `Bearer ${ token } ` ,
47+ "User-Agent" : env . EMBED_USER_AGENT ,
48+ } ,
49+ } ) ;
50+ }
51+
852function parseMedia ( raw : Record < string , any > ) : NormalizedPost [ "media" ] {
953 if ( raw . domain === "i.redd.it" ) {
1054 return [
@@ -46,12 +90,17 @@ export const Reddit: Platform<"Reddit", Record<string, any>, {}> = {
4690 async match ( url , env ) {
4791 const match = url . match ( MATCH_RE ) ;
4892 if ( ! match ) return null ;
93+
94+ const directGroups = url . match ( FOLLOWUP_RE ) ?. groups ;
95+ if ( directGroups ) {
96+ const { subreddit, post_id } = directGroups ;
97+ return `${ subreddit } /${ post_id } ` ;
98+ }
99+
49100 const req = await fetch ( url , {
50101 method : "GET" ,
51102 redirect : "follow" ,
52- headers : {
53- "User-Agent" : env ?. EMBED_USER_AGENT ?? "curl/8.7.1" ,
54- } ,
103+ headers : env ? { "User-Agent" : env . EMBED_USER_AGENT } : undefined ,
55104 } ) ;
56105
57106 const groups = req . url . match ( FOLLOWUP_RE ) ?. groups ;
@@ -60,14 +109,18 @@ export const Reddit: Platform<"Reddit", Record<string, any>, {}> = {
60109 return `${ subreddit } /${ post_id } ` ;
61110 } ,
62111 async fetch ( id , env ) {
112+ if ( ! env ) {
113+ throw {
114+ code : 500 ,
115+ message : "Reddit environment is not configured" ,
116+ } ;
117+ }
118+
63119 const [ subreddit , reddit_id ] = id . split ( "/" ) ;
64- const url = `https://www.reddit.com/r/${ subreddit } /comments/${ reddit_id } .json?raw_json=1` ;
65- const postResp = await fetch ( url , {
66- method : "GET" ,
67- headers : {
68- "User-Agent" : env ?. EMBED_USER_AGENT ?? "curl/8.7.1" ,
69- } ,
70- } ) ;
120+ const postResp = await fetchReddit (
121+ `/r/${ subreddit } /comments/${ reddit_id } .json?raw_json=1` ,
122+ env ,
123+ ) ;
71124
72125 if ( ! postResp . ok ) {
73126 throw { code : postResp . status , message : postResp . statusText } ;
@@ -88,15 +141,7 @@ export const Reddit: Platform<"Reddit", Record<string, any>, {}> = {
88141 message : "Reddit post missing author information" ,
89142 } ;
90143 }
91- const profileResp = await fetch (
92- `https://www.reddit.com/user/${ authorName } /about.json?raw_json=1` ,
93- {
94- method : "GET" ,
95- headers : {
96- "User-Agent" : env ?. EMBED_USER_AGENT ?? "" ,
97- } ,
98- } ,
99- ) ;
144+ const profileResp = await fetchReddit ( `/user/${ authorName } /about.json?raw_json=1` , env ) ;
100145 if ( ! profileResp . ok ) {
101146 throw {
102147 code : profileResp . status ,
0 commit comments