fix(route): ABC News (#13482)

* fix(route): ABC News

* delete original file

* fix typo
This commit is contained in:
Ethan Shen 2023-10-09 21:21:39 +08:00 committed by GitHub
parent 4d764ef13e
commit ba4fa14a53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 205 additions and 14655 deletions

View File

@ -2033,7 +2033,7 @@ router.get('/icity/:id', lazyloadRouteHandler('./routes/icity/index'));
router.get('/anki/changes', lazyloadRouteHandler('./routes/anki/changes'));
// ABC News
router.get('/abc/:id?', lazyloadRouteHandler('./routes/abc'));
// router.get('/abc/:id?', lazyloadRouteHandler('./routes/abc'));
// 台湾中央通讯社
// router.get('/cna/:id?', lazyloadRouteHandler('./routes/cna/index'));

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,74 +0,0 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
const ids = require('./id');
const documentIds = require('./documentId');
module.exports = async (ctx) => {
const id = ctx.params.id ?? 'justin';
const isChannel = ids.hasOwnProperty(id) ? !/topic\//.test(ids[id].link) : documentIds.hasOwnProperty(id) ? !/topic\//.test(documentIds[id].link) : isNaN(id) ? undefined : true;
if (isChannel === undefined) {
throw Error('Bad id. See <a href="https://docs.rsshub.app/routes/traditional-media#abc-news-channel-topic">docs</a>');
}
const rootUrl = 'https://www.abc.net.au';
const currentUrl = `${rootUrl}/news/${ids.hasOwnProperty(id) ? ids[id].link : documentIds.hasOwnProperty(id) ? documentIds[id].link : id}`;
const apiUrl = `${rootUrl}/news-web/api/loader/${id === 'justin' ? 'justinstories?' : `${isChannel ? `channelrefetch` : `topicstories`}?name=PaginationArticles&documentId=${!isNaN(id) ? id : ids[id].documentId}&`}size=100`;
const response = await got({
method: 'get',
url: apiUrl,
});
const list = response.data.collection.slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 50).map((item) => ({
title: item.title.children,
link: `${rootUrl}${item.link.to}`,
pubDate: parseDate(item.timestamp.dates.firstPublished.labelDate),
}));
const items = await Promise.all(
list.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const detailResponse = await got({
method: 'get',
url: item.link,
});
const content = cheerio.load(detailResponse.data);
content('div[data-component="ZendeskForm"]').remove();
content('aside[data-component="RelatedCard"]').remove();
item.description = '';
const cover = content('div[data-component="FeatureMedia"]');
const coverImage = cover.find('img');
coverImage.attr('src', coverImage.attr('data-src'));
item.description += coverImage.toString() + cover.find('figcaption').toString();
content('.ZN39J')
.find('noscript')
.each(function () {
content(this).parent().parent().html(content(this).text());
});
item.description += content('.ZN39J').html();
item.category = content('meta[property="article:tag"]')
.toArray()
.map((tag) => content(tag).attr('content'));
return item;
})
)
);
ctx.state.data = {
title: `${ids.hasOwnProperty(id) ? ids[id].title : documentIds.hasOwnProperty(id) ? documentIds[id].title : id} - ABC`,
link: currentUrl,
item: items,
};
};

162
lib/v2/abc/index.js Normal file
View File

@ -0,0 +1,162 @@
const got = require('@/utils/got');
const cheerio = require('cheerio');
const { parseDate } = require('@/utils/parse-date');
const { art } = require('@/utils/render');
const path = require('path');
module.exports = async (ctx) => {
const { category = 'news/justin' } = ctx.params;
const limit = ctx.query.limit ? parseInt(ctx.query.limit, 10) : 30;
const rootUrl = 'https://www.abc.net.au';
const apiUrl = new URL('news-web/api/loader/channelrefetch', rootUrl).href;
let currentUrl = '';
let documentId = undefined;
if (!isNaN(category)) {
documentId = category;
const feedUrl = new URL(`news/feed/${documentId}/rss.xml`, rootUrl).href;
const { data: feedResponse } = await got(feedUrl);
currentUrl = feedResponse.match(/<link>([\w-.:/?]+)<\/link>/)[1];
} else {
currentUrl = new URL(category, rootUrl).href;
}
const { data: currentResponse } = await got(currentUrl);
const $ = cheerio.load(currentResponse);
documentId = documentId ?? $('div[data-uri^="coremedia://collection/"]').first().prop('data-uri').split(/\//).pop();
const { data: response } = await got(apiUrl, {
searchParams: {
name: 'PaginationArticles',
documentId,
size: limit,
},
});
let items = response.collection.slice(0, limit).map((i) => {
const item = {
title: i.title.children ?? i.title,
link: new URL(i.link.to, rootUrl).href,
description: art(path.join(__dirname, 'templates/description.art'), {
image: i.image
? {
src: i.image.imgSrc.split(/\?/)[0],
alt: i.image.alt,
}
: undefined,
}),
author: i.newsBylineProps?.authors?.map((a) => a.name).join('/') ?? undefined,
guid: `abc-${i.id}`,
pubDate: parseDate(i.timestamp.dates.firstPublished),
updated: i.timestamp.dates.lastUpdated ? parseDate(i.timestamp.dates.lastUpdated) : undefined,
};
if (i.mediaIndicator) {
item.enclosure_type = 'audio/mpeg';
item.itunes_item_image = i.image?.imgSrc.split(/\?/)[0] ?? undefined;
item.itunes_duration = i.mediaIndicator.duration;
}
return item;
});
items = await Promise.all(
items.map((item) =>
ctx.cache.tryGet(item.link, async () => {
try {
const { data: detailResponse } = await got(item.link);
const content = cheerio.load(detailResponse);
content('aside, header, [data-print="inline-media"], [data-component="EmbedBlock"]').remove();
content('#body *, div[data-component="FeatureMedia"]')
.children()
.each(function () {
const element = content(this);
if (element.prop('tagName').toLowerCase() === 'figure') {
element.replaceWith(
art(path.join(__dirname, 'templates/description.art'), {
image: {
src: element.find('img').prop('src').split(/\?/)[0],
alt: element.find('figcaption').text().trim(),
},
})
);
} else {
element.removeAttr('id class role data-component data-uri');
}
});
item.title = content('meta[property="og:title"]').prop('content');
item.description = '';
const enclosurePattern = '"(?:MIME|content)?Type":"([\\w]+/[\\w]+)".*?"(?:fileS|s)?ize":(\\d+),.*?"url":"([\\w-.:/?]+)"';
const enclosureMatches = detailResponse.match(new RegExp(enclosurePattern, 'g'));
if (enclosureMatches) {
const enclosureMatch = enclosureMatches
.map((e) => e.match(new RegExp(enclosurePattern)))
.sort((a, b) => parseInt(a[2], 10) - parseInt(b[2], 10))
.pop();
item.enclosure_url = enclosureMatch[3];
item.enclosure_length = enclosureMatch[2];
item.enclosure_type = enclosureMatch[1];
item.description = art(path.join(__dirname, 'templates/description.art'), {
enclosure: {
src: item.enclosure_url,
type: item.enclosure_type,
},
});
}
item.description =
art(path.join(__dirname, 'templates/description.art'), {
description: (content('div[data-component="FeatureMedia"]').html() || '') + (content('#body div[data-component="LayoutContainer"] div').first().html() || ''),
}) + item.description;
item.category = content('meta[property="article:tag"]')
.toArray()
.map((c) =>
content(c)
.prop('content')
.split(//)
.map((c) => c.trim())
)
.flat();
item.guid = `abc-${content('meta[name="ContentId"]').prop('content')}`;
item.pubDate = parseDate(content('meta[property="article:published_time"]').prop('content'));
item.updated = parseDate(content('meta[property="article:modified_time"]').prop('content'));
} catch (e) {
// eslint-disable-next-line
}
return item;
})
)
);
const icon = new URL($('link[rel="apple-touch-icon"]').prop('href'), rootUrl).href;
ctx.state.data = {
item: items,
title: $('title').first().text(),
link: currentUrl,
description: $('meta[property="og:description"]').prop('content'),
language: $('html').prop('lang'),
image: $('meta[property="og:image"]').prop('content').split('?')[0],
icon,
logo: icon,
subtitle: $('meta[property="og:title"]').prop('content'),
author: $('meta[name="generator"]').prop('content'),
allowEmpty: true,
};
};

3
lib/v2/abc/maintainer.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
'/:category?': ['nczitzk'],
};

13
lib/v2/abc/radar.js Normal file
View File

@ -0,0 +1,13 @@
module.exports = {
'abc.net.au': {
_name: 'ABC News',
'.': [
{
title: 'Channel & Topic',
docs: 'https://docs.rsshub.app/routes/traditional-media#abc-news',
source: ['/:category*'],
target: '/abc/:category',
},
],
},
};

3
lib/v2/abc/router.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = (router) => {
router.get('/:category*', require('./'));
};

View File

@ -0,0 +1,21 @@
{{ if image }}
<figure>
<img src="{{ image.src }}" alt="{{ image.alt }}">
<figcaption>{{ image.alt }}</figcaption>
</figure>
{{ /if }}
{{ if enclosure }}
<{{ enclosure.type.split(/\//)[0] }} controls>
<source
src="{{ enclosure.src }}"
type="{{ enclosure.type }}">
<object data="{{ enclosure.src }}">
<embed src="{{ enclosure.src }}">
</object>
</{{ enclosure.type.split(/\//)[0] }}>
{{ /if }}
{{ if description }}
{{@ description }}
{{ /if }}

View File

@ -10,52 +10,18 @@
### Channel & Topic {#abc-news-channel-topic}
<Route author="nczitzk" example="/abc" path="/abc/:id?" paramsDesc={['id, can be found in the Channel or Topic page, can also be filled in the `documentId` in the source code of the page, see below, Just In by default']}>
<Route author="nczitzk" example="/abc" path="/abc/:category?" paramsDesc={['Category, can be found in the URL, can also be filled in with the `documentId` in the source code of the page, `news/justin` as **Just In** by default']}>
:::tip
All Topics in [Topic Library](https://abc.net.au/news/topics) are supported, you can fill in the field after `topic` in its URL, or fill in the `documentId`.
For example, the URL for [Computers and Technology](https://www.abc.net.au/news/topic/computers-and-technology) is <https://www.abc.net.au/news/topic/computers-and-technology>, the field after `topic` is `computers-and-technology`, and the `documentId` of the Topic is `2302`, so the route is [/abc/computers-and-technology](https://rsshub.app/abc/computers-and-technology) and [/abc/2302](https://rsshub.app/abc/2302).
For example, the URL for [Computer Science](https://www.abc.net.au/news/topic/computer-science) is <https://www.abc.net.au/news/topic/computer-science>, the `category` is `news/topic/computer-science`, and the `documentId` of the Topic is `2302`, so the route is [/abc/news/topic/computer-science](https://rsshub.app/abc/news/topic/computer-science) and [/abc/2302](https://rsshub.app/abc/2302).
The supported channels are all listed in the table below. For other channels, please find the `documentId` in the source code of the channel page and fill it in as above.
:::
The following are some of the supported Channel and Topic ids.
| Just In | Coronavirus | Politics | World |
| ------- | ----------- | -------- | ----- |
| justin | coronavirus | politics | world |
| Asia Pacific | Business | Analysis & Opinion | Sport |
| ------------ | -------- | -------------------- | ----- |
| asia-pacific | business | analysis-and-opinion | sport |
| AFL | Rugby League | Rugby Union | Football |
| --- | ------------ | ----------- | -------- |
| afl | rugbyleague | rugbyunion | football |
| Cricket | Science | Astronomy (Space) | Computers and Technology |
| ------- | ------- | ----------------- | ------------------------ |
| cricket | science | astronomy-space | computers-and-technology |
| Environment | Archaeology | Health | Exercise and Fitness |
| ----------- | ----------- | ------ | -------------------- |
| environment | archaeology | health | exercise-and-fitness |
| Pharmaceuticals | Mental Health | Diet and Nutrition | Arts & Culture |
| --------------- | ------------- | ------------------ | -------------- |
| pharmaceuticals | mental-health | diet-and-nutrition | arts-culture |
| Fact Check | ABC 中文 | 澳洲时政 | 聚焦中港台 |
| ---------- | -------- | ------------------ | -------------- |
| factcheck | chinese | australia-politics | focus-on-china |
| 观点与分析 | 澳洲华人 | 解读澳洲 | Berita dalam Bahasa Indonesia | Tok Pisin |
| ----------------------- | -------------------- | ----------------- | ----------------------------- | --------- |
| analysis-and-opinion-zh | chinese-in-australia | curious-australia | indonesian | tok-pisin |
</Route>
## Aljazeera 半岛电视台 {#aljazeera-ban-dao-dian-shi-tai}