diff --git a/docs/en/new-media.md b/docs/en/new-media.md
index b168c45cc7..7736e9a201 100644
--- a/docs/en/new-media.md
+++ b/docs/en/new-media.md
@@ -454,11 +454,11 @@ Provides a better reading experience (full text articles) over the official one.
-## Line
+## LINE
-### Today
+### TODAY
-
+
Edition
@@ -468,6 +468,10 @@ Edition
+### TODAY - Channel
+
+
+
## Macfilos
### Blog
diff --git a/docs/new-media.md b/docs/new-media.md
index 428754a12b..2984a616ee 100644
--- a/docs/new-media.md
+++ b/docs/new-media.md
@@ -816,11 +816,11 @@ Tag
-## Line
+## LINE
-### Today
+### TODAY
-
+
Edition
@@ -830,6 +830,10 @@ Edition
+### TODAY - 频道
+
+
+
## LVV2
### 频道
diff --git a/lib/v2/line/maintainer.js b/lib/v2/line/maintainer.js
index ed80783719..2a8ca077d5 100644
--- a/lib/v2/line/maintainer.js
+++ b/lib/v2/line/maintainer.js
@@ -1,3 +1,4 @@
module.exports = {
'/today/:edition?/:tab?': ['nczitzk'],
+ '/today/:edition/publisher/:id': ['TonyRL'],
};
diff --git a/lib/v2/line/publisher.js b/lib/v2/line/publisher.js
new file mode 100644
index 0000000000..15e4154042
--- /dev/null
+++ b/lib/v2/line/publisher.js
@@ -0,0 +1,53 @@
+const got = require('@/utils/got');
+const { baseUrl, parseList, parseItems } = require('./utils');
+
+module.exports = async (ctx) => {
+ const { edition, id } = ctx.params;
+
+ const { data: publisherInfo } = await got(`${baseUrl}/webapi/portal/page/setting`, {
+ searchParams: {
+ entityId: id,
+ country: edition,
+ pageType: 'CP',
+ },
+ });
+
+ let cpLatest;
+ if (edition === 'th') {
+ const { data } = await got(`${baseUrl}/webapi/portal/embedded/page/cplatest`, {
+ searchParams: {
+ entityId: id,
+ pageType: 'CP',
+ country: edition,
+ },
+ });
+ cpLatest = data;
+ }
+
+ const modules = edition !== 'th' ? publisherInfo.modules : cpLatest.modules;
+ const mod = modules.find((item) => item.source === 'CP_LATEST');
+ const listing = mod.listings[0];
+
+ const { data: listResponse } = await got(`${baseUrl}/webapi/trending/cp/latest/listings/${mod.id}`, {
+ searchParams: {
+ offset: listing.offset,
+ length: listing.length,
+ country: edition,
+ targetContent: listing.params.targetContent,
+ cps: listing.params.cps,
+ publishedWithin: listing.params.publishedWithin,
+ },
+ });
+
+ const list = parseList(listResponse.items);
+
+ const items = await parseItems(list, ctx.cache.tryGet);
+
+ ctx.state.data = {
+ title: `${publisherInfo.data.name} - Line Today`,
+ description: publisherInfo.data.introduction,
+ image: `https://obs.line-scdn.net/${publisherInfo.data.icon.hash}`,
+ link: `${baseUrl}/${edition}/v2/publisher/${id}`,
+ item: items,
+ };
+};
diff --git a/lib/v2/line/radar.js b/lib/v2/line/radar.js
index cbd04d1eb2..5ffb4f77a7 100644
--- a/lib/v2/line/radar.js
+++ b/lib/v2/line/radar.js
@@ -1,13 +1,19 @@
module.exports = {
'line.me': {
- _name: 'LINE Today',
+ _name: 'LINE',
'.': [
{
- title: 'LINE Today',
+ title: 'Today',
docs: 'https://docs.rsshub.app/new-media.html#line-today',
source: ['/'],
target: '/line/today/:edition?/:tab?',
},
+ {
+ title: 'Today - 频道',
+ docs: 'https://docs.rsshub.app/new-media.html#line-today',
+ source: ['/:edition/v2/publisher/:id'],
+ target: '/line/today/:edition/publisher/:id',
+ },
],
},
};
diff --git a/lib/v2/line/router.js b/lib/v2/line/router.js
index 5ea3e1edc9..fbe5ea3887 100644
--- a/lib/v2/line/router.js
+++ b/lib/v2/line/router.js
@@ -1,3 +1,4 @@
module.exports = function (router) {
router.get('/today/:edition?/:tab?', require('./today'));
+ router.get('/today/:edition/publisher/:id', require('./publisher'));
};
diff --git a/lib/v2/line/today.js b/lib/v2/line/today.js
index a44a87c600..92ac773e8d 100644
--- a/lib/v2/line/today.js
+++ b/lib/v2/line/today.js
@@ -1,12 +1,10 @@
const got = require('@/utils/got');
-const cheerio = require('cheerio');
-const { parseDate } = require('@/utils/parse-date');
+const { baseUrl: rootUrl, parseList, parseItems } = require('./utils');
module.exports = async (ctx) => {
const edition = ctx.params.edition || 'tw';
const tab = ctx.params.tab || 'top';
- const rootUrl = 'https://today.line.me';
const tabUrl = `${rootUrl}/webapi/portal/page/${tab}?country=${edition}`;
const recommendationUrl = `${rootUrl}/webapi/api/v6/recommendation/articles/listings/mytoday_rec:id?offset=0&length=50&country=${edition}&gender=&age=&excludeNoThumbnail=0&containMainSnapshot=0`;
const currentUrl = `${rootUrl}/${edition}/v2/tab/${tab}`;
@@ -34,37 +32,9 @@ module.exports = async (ctx) => {
url: tab === 'recommendation' ? recommendationUrl : moduleUrl,
});
- const list = response.data.items.map((item) => ({
- title: item.title,
- link: `${rootUrl}/${edition}/v2/article/${item.url.hash}`,
- pubDate: parseDate(item.publishTimeUnix),
- hash: item.url.hash,
- category: item.categoryName,
- }));
+ const list = parseList(response.data.items);
- const items = await Promise.all(
- list.map((item) =>
- ctx.cache.tryGet(item.link, async () => {
- const { data } = await got({
- method: 'get',
- url: `${rootUrl}/webapi/portal/page/setting/article?country=${edition}&hash=${item.hash}&group=NA`,
- });
-
- const $ = cheerio.load(data.data.content, null, false);
-
- $('img').each((_, img) => {
- delete img.attribs['data-hashid'];
- img.attribs.src = img.attribs.src.replace(/\/w\d+$/, '');
- });
-
- item.description = $.html();
- item.author = data.data.author;
- item.category = [...new Set([item.category, ...data.data.exploreLinks.map((link) => link.name)])];
-
- return item;
- })
- )
- );
+ const items = await parseItems(list, ctx.cache.tryGet);
ctx.state.data = {
title: `${title} - Line Today`,
diff --git a/lib/v2/line/utils.js b/lib/v2/line/utils.js
new file mode 100644
index 0000000000..90f925b945
--- /dev/null
+++ b/lib/v2/line/utils.js
@@ -0,0 +1,43 @@
+const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const { parseDate } = require('@/utils/parse-date');
+
+const baseUrl = 'https://today.line.me';
+
+const parseList = (items) =>
+ items.map((item) => ({
+ title: item.title,
+ link: item.url.url,
+ pubDate: parseDate(item.publishTimeUnix),
+ hash: item.url.hash,
+ category: item.categoryName,
+ }));
+
+const parseItems = (list, tryGet) =>
+ Promise.all(
+ list.map((item) =>
+ tryGet(item.link, async () => {
+ const edition = item.link.match(/today\.line\.me\/(\w+?)\/v2\/.*$/)[1];
+ const { data } = await got(`${baseUrl}/webapi/portal/page/setting/article?country=${edition}&hash=${item.hash}&group=NA`);
+
+ const $ = cheerio.load(data.data.content, null, false);
+
+ $('img').each((_, img) => {
+ delete img.attribs['data-hashid'];
+ img.attribs.src = img.attribs.src.replace(/\/w\d+$/, '');
+ });
+
+ item.description = $.html();
+ item.author = data.data.author;
+ item.category = [...new Set([item.category, ...data.data.exploreLinks.map((link) => link.name)])];
+
+ return item;
+ })
+ )
+ );
+
+module.exports = {
+ baseUrl,
+ parseList,
+ parseItems,
+};