11import { load } from 'cheerio' ;
22import dayjs from 'dayjs' ;
33
4+ import { config } from '@/config' ;
45import type { DataItem , Route } from '@/types' ;
56import cache from '@/utils/cache' ;
6- import puppeteer from '@/utils/puppeteer ' ;
7+ import ofetch from '@/utils/ofetch ' ;
78
89export const route : Route = {
910 path : '/chatgpt-atlas/release-notes' ,
1011 categories : [ 'program-update' ] ,
1112 example : '/openai/chatgpt-atlas/release-notes' ,
1213 features : {
1314 requireConfig : false ,
14- requirePuppeteer : true ,
15+ requirePuppeteer : false ,
1516 antiCrawler : false ,
1617 supportBT : false ,
1718 supportPodcast : false ,
@@ -28,117 +29,52 @@ async function handler() {
2829 const cacheIn = await cache . tryGet (
2930 articleUrl ,
3031 async ( ) => {
31- const browser = await puppeteer ( ) ;
32- const page = await browser . newPage ( ) ;
33- await page . setRequestInterception ( true ) ;
34- page . on ( 'request' , ( request ) => {
35- request . resourceType ( ) === 'document' || request . resourceType ( ) === 'script' ? request . continue ( ) : request . abort ( ) ;
36- } ) ;
37- await page . goto ( articleUrl , {
38- waitUntil : 'domcontentloaded' ,
39- } ) ;
40- const html = await page . evaluate ( ( ) => document . documentElement . innerHTML ) ;
41- await page . close ( ) ;
42-
43- const $ = load ( html ) ;
32+ const response = await ofetch ( articleUrl ) ;
33+ const $ = load ( response ) ;
4434 const articleContent = $ ( '.article-content' ) ;
4535
4636 if ( articleContent . length === 0 ) {
47- throw new Error ( 'Failed to find article content. Possible Cloudflare protection. ' ) ;
37+ throw new Error ( 'Failed to find article content.' ) ;
4838 }
4939
5040 const feedTitle = $ ( 'h1' ) . first ( ) . text ( ) ;
5141 const feedDesc = 'ChatGPT Atlas Release Notes' ;
5242
53- const items : DataItem [ ] = [ ] ;
54-
55- articleContent . children ( 'h1' ) . each ( ( _ , element ) => {
56- const $h1 = $ ( element ) ;
57- const text = $h1 . text ( ) . trim ( ) ;
58-
59- const dateMatch = text . match ( / ( \w + \s + \d + [ s t n d r h ] * , \s + \d { 4 } ) / i) ;
60- let pubDate : Date | undefined ;
61- if ( dateMatch ) {
62- const dateStr = dateMatch [ 1 ] ;
63- const parsedDate = dayjs ( dateStr , [ 'MMMM Do, YYYY' , 'MMMM D, YYYY' ] , 'en' ) ;
64- if ( parsedDate . isValid ( ) ) {
65- pubDate = parsedDate . toDate ( ) ;
66- }
67- }
68-
69- const buildMatch = text . match ( / (?: B u i l d \s * N u m b e r \s * : | B u i l d \s * : ) \s * ( \d + \. \d + \. \d + \. \d + ) / i) ;
70- let buildInfo = '' ;
71- let titleText = text ;
72-
73- if ( buildMatch ) {
74- buildInfo = `<p>Build: ${ buildMatch [ 1 ] } </p>` ;
75- titleText = text . replace ( buildMatch [ 0 ] , '' ) . trim ( ) ;
76- }
77-
78- let description = buildInfo ;
79-
80- $h1 . nextUntil ( 'h1' ) . each ( ( _ , sib ) => {
81- const $sib = $ ( sib ) ;
82- const tagName = sib . tagName . toLowerCase ( ) ;
83-
84- switch ( tagName ) {
85- case 'h2' :
86- case 'h3' :
87- case 'h4' :
88- case 'h5' :
89- case 'h6' :
90- description += `<${ tagName } >${ $sib . html ( ) ?. trim ( ) || '' } </${ tagName } >` ;
91- break ;
92-
93- case 'ul' :
94- case 'ol' : {
95- const listItems = $sib
96- . find ( 'li' )
97- . toArray ( )
98- . map ( ( li ) => {
99- const $li = $ ( li ) ;
100- const liHtml = $li . html ( ) ?. trim ( ) ;
101- return liHtml ? `<li>${ liHtml } </li>` : null ;
102- } )
103- . filter ( Boolean ) ;
104- if ( listItems . length > 0 ) {
105- description += `<${ tagName } >${ listItems . join ( '' ) } </${ tagName } >` ;
106- }
107- break ;
108- }
109- case 'p' : {
110- const pHtml = $sib . html ( ) ?. trim ( ) ;
111- if ( pHtml && ! pHtml . toLowerCase ( ) . includes ( 'public link to lgpl bundle' ) ) {
112- description += `<p>${ pHtml } </p>` ;
113- }
114- break ;
115- }
116- case 'br' :
117- description += '<br>' ;
118- break ;
119- default : {
120- const html = $sib . html ( ) ?. trim ( ) ;
121- if ( html ) {
122- description += html ;
123- }
43+ const items = $ ( 'h1' , articleContent )
44+ . toArray ( )
45+ . map ( ( element ) => {
46+ const $h1 = $ ( element ) ;
47+ const text = $h1 . text ( ) . trim ( ) ;
48+
49+ const dateMatch = text . match ( / ( \w + \s + \d + [ s t n d r h ] * , \s + \d { 4 } ) / i) ;
50+ let pubDate : Date | undefined ;
51+ if ( dateMatch ) {
52+ const dateStr = dateMatch [ 1 ] ;
53+ const parsedDate = dayjs ( dateStr , [ 'MMMM Do, YYYY' , 'MMMM D, YYYY' ] , 'en' ) ;
54+ if ( parsedDate . isValid ( ) ) {
55+ pubDate = parsedDate . toDate ( ) ;
12456 }
12557 }
126- } ) ;
127-
128- items . push ( {
129- guid : `${ articleUrl } #${ pubDate ? pubDate . getTime ( ) : titleText } ` ,
130- title : titleText ,
131- link : articleUrl ,
132- pubDate,
133- description,
134- } ) ;
135- } ) ;
13658
137- await browser . close ( ) ;
59+ const content = $h1
60+ . nextUntil ( 'h1' )
61+ . toArray ( )
62+ . map ( ( el ) => $ ( el ) . prop ( 'outerHTML' ) )
63+ . join ( '' ) ;
64+ const description = content ;
65+
66+ return {
67+ guid : `${ articleUrl } #${ pubDate ? pubDate . getTime ( ) : text } ` ,
68+ title : text ,
69+ link : articleUrl ,
70+ pubDate,
71+ description,
72+ } ;
73+ } ) as DataItem [ ] ;
13874
13975 return { feedTitle, feedDesc, items } ;
14076 } ,
141- 86400 ,
77+ config . cache . routeExpire ,
14278 false
14379 ) ;
14480
0 commit comments