From d68e5a8d5431436e53aceefdee7ab10d3202d30b Mon Sep 17 00:00:00 2001 From: Ethan Shen Date: Thu, 31 Mar 2022 22:32:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(route):=20add=20Quicker=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=20(#9357)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(route): add Quicker动作更新 * fix typo * delete outdated routes * fix: add h2 header * fix: invalid pubDate --- docs/bbs.md | 10 ------ docs/program-update.md | 2 +- docs/programming.md | 52 +++++++++++++++++++++++++++++ lib/router.js | 8 ++--- lib/routes/quicker/person.js | 32 ------------------ lib/routes/quicker/qa.js | 41 ----------------------- lib/routes/quicker/update.js | 30 ----------------- lib/v2/quicker/maintainer.js | 7 ++++ lib/v2/quicker/qa.js | 65 ++++++++++++++++++++++++++++++++++++ lib/v2/quicker/radar.js | 31 +++++++++++++++++ lib/v2/quicker/router.js | 7 ++++ lib/v2/quicker/share.js | 61 +++++++++++++++++++++++++++++++++ lib/v2/quicker/user.js | 62 ++++++++++++++++++++++++++++++++++ lib/v2/quicker/versions.js | 36 ++++++++++++++++++++ 14 files changed, 326 insertions(+), 118 deletions(-) delete mode 100644 lib/routes/quicker/person.js delete mode 100644 lib/routes/quicker/qa.js delete mode 100644 lib/routes/quicker/update.js create mode 100644 lib/v2/quicker/maintainer.js create mode 100644 lib/v2/quicker/qa.js create mode 100644 lib/v2/quicker/radar.js create mode 100644 lib/v2/quicker/router.js create mode 100644 lib/v2/quicker/share.js create mode 100644 lib/v2/quicker/user.js create mode 100644 lib/v2/quicker/versions.js diff --git a/docs/bbs.md b/docs/bbs.md index 05fc4fb286..003f265bd8 100644 --- a/docs/bbs.md +++ b/docs/bbs.md @@ -218,16 +218,6 @@ pageClass: routes -## Quicker - -### 讨论区 - - - -### 用户动作更新 - - - ## RF 技术社区 ### 文章 diff --git a/docs/program-update.md b/docs/program-update.md index 3423f36b2e..b3ce8e2b33 100644 --- a/docs/program-update.md +++ b/docs/program-update.md @@ -382,7 +382,7 @@ pageClass: routes ### 版本更新 - + ## RescueTime diff --git a/docs/programming.md b/docs/programming.md index 8f0cb9097a..36de6faaef 100644 --- a/docs/programming.md +++ b/docs/programming.md @@ -503,6 +503,58 @@ GitHub 官方也提供了一些 RSS: +## Quicker + +### 动作分享 + + + +| 动作库最新更新 | 动作库最多赞 | 动作库新动作 | 动作库最近赞 | +| ------- | ----------- | ---------- | ----------- | +| Recent | Recommended | NewActions | RecentLiked | + +| 子程序 | 扩展热键 | 文本指令 | +| ----------- | --------- | ------------ | +| SubPrograms | PowerKeys | TextCommands | + + + +### 讨论区 + + + +分类 + +| 使用问题 | 动作开发 | BUG 反馈 | 功能建议 | +| ---- | ---- | ------ | ---- | +| 1 | 9 | 3 | 4 | + +| 动作需求 | 经验创意 | 动作推荐 | 信息发布 | +| ---- | ---- | ---- | ---- | +| 6 | 2 | 7 | 5 | + +| 随便聊聊 | 异常报告 | 全部 | +| ---- | ---- | --- | +| 8 | 10 | all | + +状态 + +| 全部 | 精华 | 已归档 | +| -- | ------ | ------- | +| | digest | achived | + + + +### 用户更新 + + + +| 动作 | 子程序 | 动作单 | +| ------- | ----------- | ----------- | +| Actions | SubPrograms | ActionLists | + + + ## react ### react-native diff --git a/lib/router.js b/lib/router.js index d66ab24a50..ae3caefb7b 100644 --- a/lib/router.js +++ b/lib/router.js @@ -25,10 +25,10 @@ const lazyloadRouteHandler = (routeHandlerPath) => (ctx) => { router.get('/1draw', lazyloadRouteHandler('./routes/1draw/index')); // quicker -router.get('/quicker/qa', lazyloadRouteHandler('./routes/quicker/qa.js')); -router.get('/quicker/update', lazyloadRouteHandler('./routes/quicker/update.js')); -router.get('/quicker/user/action/:uid/:person', lazyloadRouteHandler('./routes/quicker/person.js')); -router.get('/quicker/user/:uid/:person', lazyloadRouteHandler('./routes/quicker/person.js')); +// router.get('/quicker/qa', lazyloadRouteHandler('./routes/quicker/qa.js')); +// router.get('/quicker/update', lazyloadRouteHandler('./routes/quicker/update.js')); +// router.get('/quicker/user/action/:uid/:person', lazyloadRouteHandler('./routes/quicker/person.js')); +// router.get('/quicker/user/:uid/:person', lazyloadRouteHandler('./routes/quicker/person.js')); // Benedict Evans router.get('/benedictevans', lazyloadRouteHandler('./routes/benedictevans/recent.js')); diff --git a/lib/routes/quicker/person.js b/lib/routes/quicker/person.js deleted file mode 100644 index 03ce82096a..0000000000 --- a/lib/routes/quicker/person.js +++ /dev/null @@ -1,32 +0,0 @@ -const cheerio = require('cheerio'); -const got = require('@/utils/got'); - -module.exports = async (ctx) => { - const person = ctx.params.person; - const uid = ctx.params.uid; - const response = await got({ - method: 'get', - url: `https://getquicker.net/User/${uid}/${person}`, - }); - const data = response.data; - const $ = cheerio.load(data); - const list = $('.align-middle:nth-child(2) a:nth-child(1)'); - - const out = list - .map((index, item) => { - item = $(item); - return { - title: item.text(), - description: item.next().text(), - guid: item.text(), - link: item.attr('href'), - }; - }) - .get(); - - ctx.state.data = { - title: '用户动作 - Quicker', - link: 'https://getquicker.net/Help/Versions', - item: out, - }; -}; diff --git a/lib/routes/quicker/qa.js b/lib/routes/quicker/qa.js deleted file mode 100644 index 183f902d6d..0000000000 --- a/lib/routes/quicker/qa.js +++ /dev/null @@ -1,41 +0,0 @@ -const cheerio = require('cheerio'); -const got = require('@/utils/got'); - -module.exports = async (ctx) => { - const response = await got({ - method: 'get', - url: 'https://getquicker.net/QA', - }); - const data = response.data; - const $ = cheerio.load(data); - const list = $('div.question-title > a'); - - const out = await Promise.all( - list - .map(async (index, item) => { - item = $(item); - const response_item = await got({ - method: 'get', - url: 'https://getquicker.net' + item.attr('href'), - }); - const a = cheerio.load(response_item.data); - return Promise.resolve({ - title: item.text(), - description: `作者:${a('.user-link').first().text()}
描述:${a('.user-content').first().html()}`, - pubDate: - a('.user-content span') - .last() - .text() - .match(/最后更新于\s*\S+/) || '1900/1/1', - link: item.attr('href'), - }); - }) - .get() - ); - - ctx.state.data = { - title: '讨论区 - Quicker', - link: 'https://getquicker.net/QA', - item: out, - }; -}; diff --git a/lib/routes/quicker/update.js b/lib/routes/quicker/update.js deleted file mode 100644 index e47b382e69..0000000000 --- a/lib/routes/quicker/update.js +++ /dev/null @@ -1,30 +0,0 @@ -const cheerio = require('cheerio'); -const got = require('@/utils/got'); - -module.exports = async (ctx) => { - const response = await got({ - method: 'get', - url: 'https://getquicker.net/Help/Versions', - }); - const data = response.data; - const $ = cheerio.load(data); - const list = $('div.version-list > div'); - - const out = list - .map((index, item) => { - item = $(item); - return { - title: item.find('h2 > a').text(), - description: item.find('div.article-content').html(), - pubDate: item.find('div > span.text-secondary.d-lg-block.mb-2').text() || '1900/1/1', - link: item.find('h2 > a').attr('href'), - }; - }) - .get(); - - ctx.state.data = { - title: '版本更新 - Quicker', - link: 'https://getquicker.net/Help/Versions', - item: out, - }; -}; diff --git a/lib/v2/quicker/maintainer.js b/lib/v2/quicker/maintainer.js new file mode 100644 index 0000000000..d5e7b8dd53 --- /dev/null +++ b/lib/v2/quicker/maintainer.js @@ -0,0 +1,7 @@ +module.exports = { + '/qa/:category?/:state?': ['Cesaryuan', 'nczitzk'], + '/share/:category?': ['nczitzk'], + '/update': ['Cesaryuan', 'nczitzk'], + '/user/:category/:id': ['Cesaryuan', 'nczitzk'], + '/versions': ['Cesaryuan', 'nczitzk'], +}; diff --git a/lib/v2/quicker/qa.js b/lib/v2/quicker/qa.js new file mode 100644 index 0000000000..1fd2037920 --- /dev/null +++ b/lib/v2/quicker/qa.js @@ -0,0 +1,65 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const timezone = require('@/utils/timezone'); +const { parseDate, parseRelativeDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const category = ctx.params.category ?? 'all'; + const state = ctx.params.state ?? ''; + + const rootUrl = 'https://getquicker.net'; + const currentUrl = `${rootUrl}/QA${category !== 'all' ? `?category=${category}` : ''}${state ? `?state=${state}` : ''}`; + + const response = await got({ + method: 'get', + url: currentUrl, + }); + + const $ = cheerio.load(response.data); + + let items = $('a.question-title') + .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 25) + .toArray() + .map((item) => { + item = $(item); + + return { + title: item.text(), + link: `${rootUrl}${item.attr('href')}`, + }; + }); + + items = await Promise.all( + items.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-note="最后更新人信息"]').remove(); + + const pubDate = content('.info-text') + .first() + .text() + .replace(/创建于 /, '') + .trim(); + + item.description = content('.topic-body').html(); + item.author = content('.user-link').first().text(); + item.pubDate = timezone(/-/.test(pubDate) ? parseDate(pubDate) : parseRelativeDate(pubDate), +8); + + return item; + }) + ) + ); + + ctx.state.data = { + title: $('title').text(), + link: currentUrl, + item: items, + allowEmpty: true, + }; +}; diff --git a/lib/v2/quicker/radar.js b/lib/v2/quicker/radar.js new file mode 100644 index 0000000000..6333917e39 --- /dev/null +++ b/lib/v2/quicker/radar.js @@ -0,0 +1,31 @@ +module.exports = { + 'getquicker.net': { + _name: 'Quicker', + '.': [ + { + title: '动作分享', + docs: 'https://docs.rsshub.app/programming.html#quicker-dong-zuo-fen-xiang', + source: ['/Share/:category', '/'], + target: '/quicker/share/:category?', + }, + { + title: '讨论区', + docs: 'https://docs.rsshub.app/programming.html#quicker-tao-lun-qu', + source: ['/QA', '/'], + target: (params, url) => `/quicker/qa/${new URL(url).searchParams.get('category') ?? ''}/${new URL(url).searchParams.get('state') ?? ''}`, + }, + { + title: '用户动作更新', + docs: 'https://docs.rsshub.app/programming.html#quicker-yong-hu-dong-zuo-geng-xin', + source: ['/QA', '/'], + target: (params, url) => `/quicker/qa/${new URL(url).searchParams.get('category') ?? ''}/${new URL(url).searchParams.get('state') ?? ''}`, + }, + { + title: '版本更新', + docs: 'https://docs.rsshub.app/programming.html#quicker-ban-ben-geng-xin', + source: ['/Help/Versions', '/'], + target: '/quicker/versions', + }, + ], + }, +}; diff --git a/lib/v2/quicker/router.js b/lib/v2/quicker/router.js new file mode 100644 index 0000000000..6415b5e41c --- /dev/null +++ b/lib/v2/quicker/router.js @@ -0,0 +1,7 @@ +module.exports = function (router) { + router.get('/qa/:category?/:state?', require('./qa')); + router.get('/share/:category?', require('./share')); + router.get('/update', require('./versions')); + router.get('/user/:category/:id', require('./user')); + router.get('/versions', require('./versions')); +}; diff --git a/lib/v2/quicker/share.js b/lib/v2/quicker/share.js new file mode 100644 index 0000000000..d17cb5c320 --- /dev/null +++ b/lib/v2/quicker/share.js @@ -0,0 +1,61 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const timezone = require('@/utils/timezone'); +const { parseDate, parseRelativeDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const category = ctx.params.category ?? 'Recent'; + + const rootUrl = 'https://getquicker.net'; + const currentUrl = `${rootUrl}/Share/${category}`; + + const response = await got({ + method: 'get', + url: currentUrl, + }); + + const $ = cheerio.load(response.data); + + let items = $('table tbody tr') + .slice(1, ctx.query.limit ? parseInt(ctx.query.limit) : 25) + .toArray() + .map((item) => { + item = $(item).find('td a').first(); + + return { + title: item.text(), + link: `${rootUrl}${item.attr('href')}`, + }; + }); + + items = await Promise.all( + items.map((item) => + ctx.cache.tryGet(item.link, async () => { + const detailResponse = await got({ + method: 'get', + url: item.link, + }); + + const content = cheerio.load(detailResponse.data); + + content('section').last().remove(); + content('#app').children().slice(0, 2).remove(); + + const pubDate = content('.text-secondary a').not('.text-secondary').first().text()?.trim().replace(/\s*/g, '') || content('div.note-text').find('span').eq(3).text(); + + item.author = content('.user-link').first().text(); + item.description = content('div[data-info="动作信息"]').html() ?? content('#app').html() ?? content('.row').eq(1).html(); + item.pubDate = timezone(/-/.test(pubDate) ? parseDate(pubDate) : parseRelativeDate(pubDate), +8); + + return item; + }) + ) + ); + + ctx.state.data = { + title: $('title').text(), + link: currentUrl, + item: items, + allowEmpty: true, + }; +}; diff --git a/lib/v2/quicker/user.js b/lib/v2/quicker/user.js new file mode 100644 index 0000000000..cdd64c19f9 --- /dev/null +++ b/lib/v2/quicker/user.js @@ -0,0 +1,62 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const timezone = require('@/utils/timezone'); +const { parseDate, parseRelativeDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const category = ctx.params.category; + const id = ctx.params.id; + + const rootUrl = 'https://getquicker.net'; + const currentUrl = `${rootUrl}/User/${category}/${id}`; + + const response = await got({ + method: 'get', + url: currentUrl, + }); + + const $ = cheerio.load(response.data); + + let items = $('table tbody tr') + .slice(1, ctx.query.limit ? parseInt(ctx.query.limit) : 25) + .toArray() + .map((item) => { + item = $(item).find('td a').first(); + + return { + title: item.text(), + link: `${rootUrl}${item.attr('href')}`, + }; + }); + + items = await Promise.all( + items.map((item) => + ctx.cache.tryGet(item.link, async () => { + const detailResponse = await got({ + method: 'get', + url: item.link, + }); + + const content = cheerio.load(detailResponse.data); + + content('section').last().remove(); + content('#app').children().slice(0, 2).remove(); + + const pubDate = content('.text-secondary a').not('.text-secondary').first().text()?.trim().replace(/\s*/g, '') || content('div.note-text').find('span').eq(3).text(); + + item.author = content('.user-link').first().text(); + item.description = content('div[data-info="动作信息"]').html() ?? content('#app').html() ?? content('.row').eq(1).html(); + item.pubDate = timezone(/-/.test(pubDate) ? parseDate(pubDate) : parseRelativeDate(pubDate), +8); + + return item; + }) + ) + ); + + ctx.state.data = { + title: $('title').text(), + link: currentUrl, + item: items, + allowEmpty: true, + }; +}; diff --git a/lib/v2/quicker/versions.js b/lib/v2/quicker/versions.js new file mode 100644 index 0000000000..ece5f7a0e3 --- /dev/null +++ b/lib/v2/quicker/versions.js @@ -0,0 +1,36 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const { parseDate } = require('@/utils/parse-date'); + +module.exports = async (ctx) => { + const rootUrl = 'https://getquicker.net'; + const currentUrl = `${rootUrl}/Help/Versions`; + + const response = await got({ + method: 'get', + url: currentUrl, + }); + + const $ = cheerio.load(response.data); + + const items = $('.version') + .toArray() + .map((item) => { + item = $(item); + + const a = item.find('h2 a'); + + return { + title: a.text().trim(), + link: `${rootUrl}${a.attr('href')}`, + description: item.find('.article-content').html(), + pubDate: parseDate(item.find('.text-secondary').first().text()), + }; + }); + + ctx.state.data = { + title: $('title').text(), + link: currentUrl, + item: items, + }; +};