From 6f90d46003c043935c211134f711a66169cb3dc9 Mon Sep 17 00:00:00 2001 From: wha7ev9r Date: Wed, 15 Jul 2026 07:53:38 +0800 Subject: [PATCH 1/4] route: fix dongqiudi routes for new __NUXT__ data structure --- lib/routes/dongqiudi/daily.ts | 2 +- lib/routes/dongqiudi/player-news.ts | 2 +- lib/routes/dongqiudi/result.ts | 25 ++++++++------ lib/routes/dongqiudi/special.ts | 14 +++++--- lib/routes/dongqiudi/top-news.ts | 2 +- lib/routes/dongqiudi/utils.ts | 53 +++++++++++++++-------------- 6 files changed, 56 insertions(+), 42 deletions(-) diff --git a/lib/routes/dongqiudi/daily.ts b/lib/routes/dongqiudi/daily.ts index 5c0611eaf04c..f0ec8fa57eb6 100644 --- a/lib/routes/dongqiudi/daily.ts +++ b/lib/routes/dongqiudi/daily.ts @@ -19,5 +19,5 @@ export const route: Route = { }; function handler(ctx) { - ctx.set('redirect', '/dongqiudi/special/48'); + return ctx.set('redirect', '/dongqiudi/special/48'); } diff --git a/lib/routes/dongqiudi/player-news.ts b/lib/routes/dongqiudi/player-news.ts index 0074ff5e0f0f..6487f3cfbd15 100644 --- a/lib/routes/dongqiudi/player-news.ts +++ b/lib/routes/dongqiudi/player-news.ts @@ -21,5 +21,5 @@ export const route: Route = { async function handler(ctx) { const playerId = ctx.req.param('id'); - await utils.ProcessFeed(ctx, 'player', playerId); + return await utils.ProcessFeed(ctx, 'player', playerId); } diff --git a/lib/routes/dongqiudi/result.ts b/lib/routes/dongqiudi/result.ts index 1b424d07a66b..49a813691ea8 100644 --- a/lib/routes/dongqiudi/result.ts +++ b/lib/routes/dongqiudi/result.ts @@ -1,5 +1,3 @@ -import { JSDOM } from 'jsdom'; - import type { Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -24,20 +22,27 @@ async function handler(ctx) { const team = ctx.req.param('team'); const link = `https://www.dongqiudi.com/team/${team}.html`; - const response = await got(link); - const dom = new JSDOM(response.data, { - runScripts: 'dangerously', - }); - const data = dom.window.__NUXT__.data[0]; - const resultData = data.teamScheduleData.filter((data) => data.fs_A && data.fs_B); + const { data: scheduleData } = await got(`https://api.dongqiudi.com/data/v1/team/schedule/${team}`); + const lastSeason = scheduleData.season_list.find((s) => !s.current); + + if (!lastSeason) { + return { + title: `${team} 比赛结果`, + link, + item: [], + }; + } + + const { data: seasonResp } = await got(lastSeason.url); + const resultData = seasonResp.data.filter((match) => match.fs_A && match.fs_B); - const teamName = data.teamDetail.base_info.team_name; + const teamName = resultData.length ? (resultData[0].team_A_id === team ? resultData[0].team_A_name : resultData[0].team_B_name) : team; const out = resultData.map((result) => ({ title: `${result.match_title} ${result.team_A_name} ${result.fs_A}-${result.fs_B} ${result.team_B_name}`, guid: result.match_id, link: result.scheme.replace('dongqiudi:///game/', 'https://www.dongqiudi.com/liveDetail/'), - pubDate: parseDate(result.start_time), + pubDate: parseDate(result.start_play), })); return { diff --git a/lib/routes/dongqiudi/special.ts b/lib/routes/dongqiudi/special.ts index 206051771fa9..4c684bcfcabf 100644 --- a/lib/routes/dongqiudi/special.ts +++ b/lib/routes/dongqiudi/special.ts @@ -30,16 +30,22 @@ async function handler(ctx) { const list = response.data.map((item) => ({ title: item.title, link: `https://www.dongqiudi.com/articles/${item.aid}.html`, - mobileLink: `https://m.dongqiudi.com/article/${item.aid}.html`, pubDate: parseDate(item.show_time, 'X'), })); const out = await Promise.all( list.map((item) => cache.tryGet(item.link, async () => { - const { data: response } = await got(item.mobileLink); - - utils.ProcessFeedType3(item, response); + try { + const { data: response } = await got(item.link); + const success = utils.ProcessFeedType2(item, response); + if (!success) { + throw new Error('No article data'); + } + } catch { + const { data: mobileResponse } = await got(`https://m.dongqiudi.com/article/${item.link.match(/\d+/)[0]}.html`); + utils.ProcessFeedType3(item, mobileResponse); + } return item; }) diff --git a/lib/routes/dongqiudi/top-news.ts b/lib/routes/dongqiudi/top-news.ts index 98b9a7cf8e95..6b45e94ed540 100644 --- a/lib/routes/dongqiudi/top-news.ts +++ b/lib/routes/dongqiudi/top-news.ts @@ -42,7 +42,7 @@ async function handler(ctx) { title: item.title, link: `https://www.dongqiudi.com/articles/${item.id}.html`, category: [item.category, ...(item.secondary_category ?? [])], - pubDate: parseDate(item.show_time), + pubDate: parseDate(item.show_time, 'X'), })); const out = await Promise.all( diff --git a/lib/routes/dongqiudi/utils.ts b/lib/routes/dongqiudi/utils.ts index 2b27887d450d..49f5bced484a 100644 --- a/lib/routes/dongqiudi/utils.ts +++ b/lib/routes/dongqiudi/utils.ts @@ -68,17 +68,19 @@ const ProcessFeed = async (ctx, type, id) => { const apiUrl = 'https://api.dongqiudi.com/v3/archive/app/channel/feeds'; const { data: response } = await got(link); - let name; - const { window } = new JSDOM(response, { runScripts: 'dangerously', }); - const typeInfo = window.__NUXT__.data[0][`${type}Detail`].base_info; + const nuxtData = window.__NUXT__.data[0]; + let name; + let image; if (type === 'team') { - name = typeInfo.team_name; - } else if (type === 'player') { - name = typeInfo.person_name; + name = nuxtData.teamInfo.name; + image = nuxtData.teamInfo.logo; + } else { + name = nuxtData.detail.base_info.person_name; + image = nuxtData.detail.base_info.person_logo; } const { data } = await got(apiUrl, { @@ -95,7 +97,7 @@ const ProcessFeed = async (ctx, type, id) => { title: article.title, link: `https://www.dongqiudi.com/articles/${article.id}.html`, category: [article.category, ...(article.secondary_category ?? [])], - pubDate: parseDate(article.show_time), + pubDate: parseDate(article.show_time, 'X'), })); const out = await Promise.all( @@ -113,7 +115,7 @@ const ProcessFeed = async (ctx, type, id) => { return { title: `${name} - 相关新闻`, link, - image: type === 'team' ? typeInfo.team_logo : typeInfo.person_logo, + image, item: out, }; }; @@ -123,38 +125,39 @@ const ProcessFeedType2 = (item, response) => { runScripts: 'dangerously', }); - const data = dom.window.__NUXT__.data[0].newData; + const data = dom.window.__NUXT__?.data?.[0]?.article; // filter out undefined item if (!data) { - return; + return false; } - if (Object.keys(data).length > 0) { - const body = ProcessVideo(load(data.body, null, false)); - ProcessHref(body('a')); - ProcessImg(body('img')); - item.description = body.html(); - item.author = data.writer; - item.pubDate = parseDate(data.show_time, 'X'); - } + const body = ProcessVideo(load(data.rawBody, null, false)); + ProcessHref(body('a')); + ProcessImg(body('img')); + item.description = body.html(); + item.author = data.author; + return true; }; const ProcessFeedType3 = (item, response) => { const $ = load(response); - const initialState = JSON.parse( - $('script:contains("window.__INITIAL_STATE__")') - .text() - .match(/window\.__INITIAL_STATE__\s*=\s*((?:\S.*?)??);\(/)[1] - ); + const match = $('script:contains("window.__INITIAL_STATE__")') + .text() + .match(/window\.__INITIAL_STATE__\s*=\s*((?:\S.*?)??);\(/); + if (!match) { + return; + } + + const initialState = JSON.parse(match[1]); // filter out undefined item if (!initialState) { return; } - if (Object.keys(initialState.articleContent).length) { - const data = Object.values(initialState.articleContent)[0]; + if (initialState?.articleContent && Object.keys(initialState.articleContent).length) { + const data = Object.values(initialState.articleContent)[0] as Record; const body = ProcessVideo(load(data.body, null, false)); ProcessHref(body('a')); ProcessImg(body('img')); From db2940d3ae0833bed64b1dc8519acc3628f96781 Mon Sep 17 00:00:00 2001 From: wha7ev9r Date: Wed, 22 Jul 2026 07:13:12 +0800 Subject: [PATCH 2/4] fix(dongqiudi): remove unused mobile fallback --- lib/routes/dongqiudi/special.ts | 13 ++----------- lib/routes/dongqiudi/utils.ts | 28 +--------------------------- 2 files changed, 3 insertions(+), 38 deletions(-) diff --git a/lib/routes/dongqiudi/special.ts b/lib/routes/dongqiudi/special.ts index 4c684bcfcabf..05edbe1528bc 100644 --- a/lib/routes/dongqiudi/special.ts +++ b/lib/routes/dongqiudi/special.ts @@ -36,17 +36,8 @@ async function handler(ctx) { const out = await Promise.all( list.map((item) => cache.tryGet(item.link, async () => { - try { - const { data: response } = await got(item.link); - const success = utils.ProcessFeedType2(item, response); - if (!success) { - throw new Error('No article data'); - } - } catch { - const { data: mobileResponse } = await got(`https://m.dongqiudi.com/article/${item.link.match(/\d+/)[0]}.html`); - utils.ProcessFeedType3(item, mobileResponse); - } - + const { data: response } = await got(item.link); + utils.ProcessFeedType2(item, response); return item; }) ) diff --git a/lib/routes/dongqiudi/utils.ts b/lib/routes/dongqiudi/utils.ts index 49f5bced484a..03e0465848ba 100644 --- a/lib/routes/dongqiudi/utils.ts +++ b/lib/routes/dongqiudi/utils.ts @@ -140,30 +140,4 @@ const ProcessFeedType2 = (item, response) => { return true; }; -const ProcessFeedType3 = (item, response) => { - const $ = load(response); - const match = $('script:contains("window.__INITIAL_STATE__")') - .text() - .match(/window\.__INITIAL_STATE__\s*=\s*((?:\S.*?)??);\(/); - if (!match) { - return; - } - - const initialState = JSON.parse(match[1]); - - // filter out undefined item - if (!initialState) { - return; - } - - if (initialState?.articleContent && Object.keys(initialState.articleContent).length) { - const data = Object.values(initialState.articleContent)[0] as Record; - const body = ProcessVideo(load(data.body, null, false)); - ProcessHref(body('a')); - ProcessImg(body('img')); - item.description = body.html(); - item.author = data.writer; - } -}; - -export default { ProcessVideo, ProcessFeed, ProcessFeedType2, ProcessFeedType3, ProcessHref, ProcessImg }; +export default { ProcessVideo, ProcessFeed, ProcessFeedType2, ProcessHref, ProcessImg }; From ac84d7bac915147b7ec68bc95f2a8d510a99e4fa Mon Sep 17 00:00:00 2001 From: wha7ev9r Date: Wed, 22 Jul 2026 07:54:10 +0800 Subject: [PATCH 3/4] fix(dongqiudi): tolerate unavailable special articles --- lib/routes/dongqiudi/special.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/routes/dongqiudi/special.ts b/lib/routes/dongqiudi/special.ts index 05edbe1528bc..c1bcaeafea62 100644 --- a/lib/routes/dongqiudi/special.ts +++ b/lib/routes/dongqiudi/special.ts @@ -9,7 +9,9 @@ export const route: Route = { path: '/special/:id', categories: ['sport'], example: '/dongqiudi/special/41', - parameters: { id: '专题 id, 可自行通过 https://www.dongqiudi.com/special/+数字匹配' }, + parameters: { + id: '专题 id, 可自行通过 https://www.dongqiudi.com/special/+数字匹配', + }, radar: [ { source: ['www.dongqiudi.com/special/:id'], @@ -36,8 +38,15 @@ async function handler(ctx) { const out = await Promise.all( list.map((item) => cache.tryGet(item.link, async () => { - const { data: response } = await got(item.link); - utils.ProcessFeedType2(item, response); + try { + const { data: response } = await got(item.link); + utils.ProcessFeedType2(item, response); + } catch (error) { + if (!(error instanceof Error) || !['HTTPError', 'RequestError', 'FetchError'].includes(error.name)) { + throw error; + } + // Keep the list item when the article page is gone or temporarily unavailable. + } return item; }) ) From 5591927ca77a6d4a89265fe0d83ce1e926611fa5 Mon Sep 17 00:00:00 2001 From: wha7ev9r Date: Fri, 24 Jul 2026 07:27:17 +0800 Subject: [PATCH 4/4] fix(dongqiudi): remove unnecessary bool return from ProcessFeedType2 --- lib/routes/dongqiudi/utils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/routes/dongqiudi/utils.ts b/lib/routes/dongqiudi/utils.ts index 03e0465848ba..cdb4d51d5f63 100644 --- a/lib/routes/dongqiudi/utils.ts +++ b/lib/routes/dongqiudi/utils.ts @@ -129,7 +129,7 @@ const ProcessFeedType2 = (item, response) => { // filter out undefined item if (!data) { - return false; + return; } const body = ProcessVideo(load(data.rawBody, null, false)); @@ -137,7 +137,6 @@ const ProcessFeedType2 = (item, response) => { ProcessImg(body('img')); item.description = body.html(); item.author = data.author; - return true; }; export default { ProcessVideo, ProcessFeed, ProcessFeedType2, ProcessHref, ProcessImg };