From 6a4b939509642487b8f618dadf7f388e006641ce Mon Sep 17 00:00:00 2001 From: StevenRCE0 <40051361+StevenRCE0@users.noreply.github.com> Date: Sun, 6 Mar 2022 20:06:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(route):=20=E6=9C=BA=E6=A0=B8=E7=BD=91?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=86=E7=B1=BB=E6=A0=87=E7=AD=BE=E5=92=8C?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E8=B7=AF=E7=94=B1=20(#9239)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Gcores tagging * Gcore tags * Comfort v2 * Update router * Update router.js * refactor: use cache.tryGet --- docs/new-media.md | 8 +++ lib/router.js | 3 - lib/routes/gcores/category.js | 127 ---------------------------------- lib/v2/gcores/category.js | 126 +++++++++++++++++++++++++++++++++ lib/v2/gcores/maintainer.js | 4 ++ lib/v2/gcores/radar.js | 19 +++++ lib/v2/gcores/router.js | 4 ++ lib/v2/gcores/tag.js | 126 +++++++++++++++++++++++++++++++++ 8 files changed, 287 insertions(+), 130 deletions(-) delete mode 100644 lib/routes/gcores/category.js create mode 100644 lib/v2/gcores/category.js create mode 100644 lib/v2/gcores/maintainer.js create mode 100644 lib/v2/gcores/radar.js create mode 100644 lib/v2/gcores/router.js create mode 100644 lib/v2/gcores/tag.js diff --git a/docs/new-media.md b/docs/new-media.md index e13843510f..8536725a82 100644 --- a/docs/new-media.md +++ b/docs/new-media.md @@ -2031,6 +2031,14 @@ others = 热点新闻 + 滚动新闻 +### 标签 + + + +分类名同上。 + + + ## 加美财经 diff --git a/lib/router.js b/lib/router.js index 7f1b646e8f..d0c072bd9e 100644 --- a/lib/router.js +++ b/lib/router.js @@ -338,9 +338,6 @@ router.get('/t66y/:id/:type?', lazyloadRouteHandler('./routes/t66y/index')); // 色中色 router.get('/sexinsex/:id/:type?', lazyloadRouteHandler('./routes/sexinsex/index')); -// 机核 -router.get('/gcores/category/:category', lazyloadRouteHandler('./routes/gcores/category')); - // 国家地理 router.get('/natgeo/dailyphoto', lazyloadRouteHandler('./routes/natgeo/dailyphoto')); router.get('/natgeo/:cat/:type?', lazyloadRouteHandler('./routes/natgeo/natgeo')); diff --git a/lib/routes/gcores/category.js b/lib/routes/gcores/category.js deleted file mode 100644 index 6123db5da1..0000000000 --- a/lib/routes/gcores/category.js +++ /dev/null @@ -1,127 +0,0 @@ -const got = require('@/utils/got'); -const cheerio = require('cheerio'); - -module.exports = async (ctx) => { - const category = ctx.params.category; - const url = `https://www.gcores.com/${category}`; - const res = await got({ - method: 'get', - url, - }); - const data = res.data; - const $ = cheerio.load(data); - const feedTitle = $('title').text(); - - const list = $('.original.am_card.original-normal') - .map(function () { - const item = { - url: $(this).find('a.am_card_content.original_content').attr('href'), - title: $(this).find('h3.am_card_title').text(), - }; - return item; - }) - .get(); - - const out = await Promise.all( - list.map(async (item) => { - const articleUrl = `https://www.gcores.com${item.url}`; - - const cache = await ctx.cache.get(articleUrl); - if (cache) { - return Promise.resolve(JSON.parse(cache)); - } - const itemRes = await got({ - method: 'get', - url: articleUrl, - }); - - const itemPage = itemRes.data; - const $ = cheerio.load(itemPage); - - let articleData = await got(`https://www.gcores.com/gapi/v1${item.url}?include=media`); - articleData = articleData.data.data; - let cover; - if (articleData.attributes.cover) { - cover = ``; - } else if (articleData.attributes.thumb) { - cover = ``; - } else { - cover = ''; - } - - // replace figure with img - const articleContent = JSON.parse(articleData.attributes.content); - const entityRangeMap = {}; - for (const block of articleContent.blocks || []) { - if (block.entityRanges.length) { - entityRangeMap[block.key] = block.entityRanges; - } - } - - $('figure').each((i, elem) => { - const keyAttr = elem.attribs['data-offset-key']; - const keyMatch = /^(\w+)-(\d+)-(\d)$/.exec(keyAttr); - let actualContent = ''; - if (keyMatch) { - const [, key, index] = keyMatch; - if (entityRangeMap[key] && entityRangeMap[key][index]) { - const entityKey = entityRangeMap[key] && entityRangeMap[key][index].key; - const entity = articleContent.entityMap[entityKey]; - actualContent = convertEntityToContent(entity); - } - } - - if (actualContent) { - $(elem).replaceWith(actualContent); - } - }); - - // remove editor toolbar img - $('.md-editor-toolbar').replaceWith(''); - // remove hidden tip block - $('.story_hidden').replaceWith(''); - - const content = $('.story.story-show').html(); - const single = { - title: item.title, - description: cover + content, - link: articleUrl, - guid: articleUrl, - }; - ctx.cache.set(articleUrl, JSON.stringify(single)); - return Promise.resolve(single); - }) - ); - ctx.state.data = { - title: feedTitle, - link: url, - item: out, - }; -}; - -function convertEntityToContent(entity) { - const { type, data } = entity; - switch (type) { - case 'IMAGE': - return ` -
-${data.caption || ''} -${data.caption ? `
${data.caption}
` : ''} -
`; - - case 'GALLERY': - return data.images - .map( - (image, i, arr) => ` -
-${image.caption || ''} -
${data.caption || ''} (${i + 1}/${arr.length}) ${image.caption || ''}
-
- ` - ) - .join(''); - - default: - return ''; - } -} diff --git a/lib/v2/gcores/category.js b/lib/v2/gcores/category.js new file mode 100644 index 0000000000..a289b33f0c --- /dev/null +++ b/lib/v2/gcores/category.js @@ -0,0 +1,126 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); + +module.exports = async (ctx) => { + const category = ctx.params.category; + const url = `https://www.gcores.com/${category}`; + const res = await got({ + method: 'get', + url, + }); + const data = res.data; + const $ = cheerio.load(data); + const feedTitle = $('title').text(); + + const list = $('.original.am_card.original-normal') + .map(function () { + const item = { + url: $(this).find('a.am_card_content.original_content').attr('href'), + title: $(this).find('h3.am_card_title').text(), + category: $(this).find('span.original_category>a').text(), + }; + return item; + }) + .get(); + + const out = await Promise.all( + list.map((item) => { + const articleUrl = `https://www.gcores.com${item.url}`; + + return ctx.cache.tryGet(articleUrl, async () => { + const itemRes = await got({ + method: 'get', + url: articleUrl, + }); + + const itemPage = itemRes.data; + const $ = cheerio.load(itemPage); + + let articleData = await got(`https://www.gcores.com/gapi/v1${item.url}?include=media`); + + articleData = articleData.data.data; + let cover; + if (articleData.attributes.cover) { + cover = ``; + } else if (articleData.attributes.thumb) { + cover = ``; + } else { + cover = ''; + } + + // replace figure with img + const articleContent = JSON.parse(articleData.attributes.content); + const entityRangeMap = {}; + for (const block of articleContent.blocks || []) { + if (block.entityRanges.length) { + entityRangeMap[block.key] = block.entityRanges; + } + } + + $('figure').each((i, elem) => { + const keyAttr = elem.attribs['data-offset-key']; + const keyMatch = /^(\w+)-(\d+)-(\d)$/.exec(keyAttr); + let actualContent = ''; + if (keyMatch) { + const [, key, index] = keyMatch; + if (entityRangeMap[key] && entityRangeMap[key][index]) { + const entityKey = entityRangeMap[key] && entityRangeMap[key][index].key; + const entity = articleContent.entityMap[entityKey]; + actualContent = convertEntityToContent(entity); + } + } + + if (actualContent) { + $(elem).replaceWith(actualContent); + } + }); + + // remove editor toolbar img + $('.md-editor-toolbar').replaceWith(''); + // remove hidden tip block + $('.story_hidden').replaceWith(''); + + const content = $('.story.story-show').html(); + return { + title: item.title, + description: cover + content, + category: item.category, + link: articleUrl, + guid: articleUrl, + }; + }); + }) + ); + ctx.state.data = { + title: feedTitle, + link: url, + item: out, + }; +}; + +function convertEntityToContent(entity) { + const { type, data } = entity; + switch (type) { + case 'IMAGE': + return ` +
+${data.caption || ''} +${data.caption ? `
${data.caption}
` : ''} +
`; + + case 'GALLERY': + return data.images + .map( + (image, i, arr) => ` +
+${image.caption || ''} +
${data.caption || ''} (${i + 1}/${arr.length}) ${image.caption || ''}
+
+ ` + ) + .join(''); + + default: + return ''; + } +} diff --git a/lib/v2/gcores/maintainer.js b/lib/v2/gcores/maintainer.js new file mode 100644 index 0000000000..f1842790b2 --- /dev/null +++ b/lib/v2/gcores/maintainer.js @@ -0,0 +1,4 @@ +module.exports = { + '/category/:category': ['MoguCloud', 'StevenRCE0'], + '/tag/:tag/:category?': ['StevenRCE0'], +}; diff --git a/lib/v2/gcores/radar.js b/lib/v2/gcores/radar.js new file mode 100644 index 0000000000..40bfcdb529 --- /dev/null +++ b/lib/v2/gcores/radar.js @@ -0,0 +1,19 @@ +module.exports = { + 'gcores.com': { + _name: '机核网', + '.': [ + { + title: '分类', + docs: 'https://docs.rsshub.app/new-media.html#ji-he-wang-fen-lei', + source: ['/:category'], + target: '/gcores/category/:category', + }, + { + title: '标签', + docs: 'https://docs.rsshub.app/new-media.html#ji-he-wang-biao-qian', + source: ['/categories/:tag', '/'], + target: '/gcores/tag/:tag', + }, + ], + }, +}; diff --git a/lib/v2/gcores/router.js b/lib/v2/gcores/router.js new file mode 100644 index 0000000000..4cf4aa2751 --- /dev/null +++ b/lib/v2/gcores/router.js @@ -0,0 +1,4 @@ +module.exports = function (router) { + router.get('/category/:category', require('./category')); + router.get('/tag/:tag/:category?', require('./tag')); +}; diff --git a/lib/v2/gcores/tag.js b/lib/v2/gcores/tag.js new file mode 100644 index 0000000000..8722ce1623 --- /dev/null +++ b/lib/v2/gcores/tag.js @@ -0,0 +1,126 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); + +module.exports = async (ctx) => { + const tag = ctx.params.tag; + const category = ctx.params.category; + const url = `https://www.gcores.com/categories/${tag + (category ? `?tab=${category}` : '')}`; + const res = await got({ + method: 'get', + url, + }); + const data = res.data; + const $ = cheerio.load(data); + const feedTitle = $('title').text(); + + const list = $('.original.am_card.original-normal') + .map(function () { + const item = { + url: $(this).find('a.am_card_content.original_content').attr('href'), + title: $(this).find('h3.am_card_title').text(), + category: $(this).find('span.original_category>a').text(), + }; + return item; + }) + .get(); + + const out = await Promise.all( + list.map((item) => { + const articleUrl = `https://www.gcores.com${item.url}`; + + return ctx.cache.tryGet(articleUrl, async () => { + const itemRes = await got({ + method: 'get', + url: articleUrl, + }); + + const itemPage = itemRes.data; + const $ = cheerio.load(itemPage); + + let articleData = await got(`https://www.gcores.com/gapi/v1${item.url}?include=media`); + + articleData = articleData.data.data; + let cover; + if (articleData.attributes.cover) { + cover = ``; + } else if (articleData.attributes.thumb) { + cover = ``; + } else { + cover = ''; + } + + // replace figure with img + const articleContent = JSON.parse(articleData.attributes.content); + const entityRangeMap = {}; + for (const block of articleContent.blocks || []) { + if (block.entityRanges.length) { + entityRangeMap[block.key] = block.entityRanges; + } + } + + $('figure').each((i, elem) => { + const keyAttr = elem.attribs['data-offset-key']; + const keyMatch = /^(\w+)-(\d+)-(\d)$/.exec(keyAttr); + let actualContent = ''; + if (keyMatch) { + const [, key, index] = keyMatch; + if (entityRangeMap[key] && entityRangeMap[key][index]) { + const entityKey = entityRangeMap[key] && entityRangeMap[key][index].key; + const entity = articleContent.entityMap[entityKey]; + actualContent = convertEntityToContent(entity); + } + } + + if (actualContent) { + $(elem).replaceWith(actualContent); + } + }); + + // remove editor toolbar img + $('.md-editor-toolbar').replaceWith(''); + // remove hidden tip block + $('.story_hidden').replaceWith(''); + + const content = $('.story.story-show').html(); + return { + title: item.title, + description: cover + content, + link: articleUrl, + guid: articleUrl, + }; + }); + }) + ); + ctx.state.data = { + title: feedTitle, + link: url, + item: out, + }; +}; + +function convertEntityToContent(entity) { + const { type, data } = entity; + switch (type) { + case 'IMAGE': + return ` +
+${data.caption || ''} +${data.caption ? `
${data.caption}
` : ''} +
`; + + case 'GALLERY': + return data.images + .map( + (image, i, arr) => ` +
+${image.caption || ''} +
${data.caption || ''} (${i + 1}/${arr.length}) ${image.caption || ''}
+
+ ` + ) + .join(''); + + default: + return ''; + } +}