diff --git a/docs/bbs.md b/docs/bbs.md index 05fc4fb2865616..003f265bd8fb45 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 3423f36b2e1bab..b3ce8e2b337884 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 8f0cb9097a5be0..36de6faaeff0dc 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 d66ab24a5055ff..ae3caefb7bd754 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 03ce82096a5fa9..00000000000000 --- 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 183f902d6dde04..00000000000000 --- 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 e47b382e69a7f5..00000000000000 --- 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 00000000000000..d5e7b8dd533d36 --- /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 00000000000000..1fd2037920a8fb --- /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 00000000000000..6333917e396d34 --- /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 00000000000000..6415b5e41cca66 --- /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 00000000000000..d17cb5c320cbce --- /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 00000000000000..cdd64c19f90dd6 --- /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 00000000000000..ece5f7a0e3ca3e --- /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, + }; +};