From ed2046981b30fcb73bba5e29b290283f621cd315 Mon Sep 17 00:00:00 2001 From: zengxs Date: Wed, 26 Jun 2019 02:04:32 +0800 Subject: [PATCH] feat: add lwn.net security alerts (#2491) --- docs/programming.md | 30 +++++++++++++++++++++ lib/router.js | 3 +++ lib/routes/lwn/alerts.js | 57 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 lib/routes/lwn/alerts.js diff --git a/docs/programming.md b/docs/programming.md index ba19721ec..519a7feb6 100644 --- a/docs/programming.md +++ b/docs/programming.md @@ -172,6 +172,36 @@ GitHub 官方也提供了一些 RSS: +## LWN.net + +### Security alerts + + + +| 发行版 | 标识 | +| :--------------- | :----------------- | +| Arch Linux | `Arch_Linux` | +| CentOS | `CentOS` | +| Debian | `Debian` | +| Fedora | `Fedora` | +| Gentoo | `Gentoo` | +| Mageia | `Mageia` | +| openSUSE | `openSUSE` | +| Oracle | `Oracle` | +| Red Hat | `Red_Hat` | +| Scientific Linux | `Scientific_Linux` | +| Slackware | `Slackware` | +| SUSE | `SUSE` | +| Ubuntu | `Ubuntu` | + +::: tip 提示 + +注意标识大小写 + +::: + + + ## segmentfault ### 频道 diff --git a/lib/router.js b/lib/router.js index ee0b458d4..70314bb90 100644 --- a/lib/router.js +++ b/lib/router.js @@ -1439,4 +1439,7 @@ router.get('/8btc/:authorid', require('./routes/8btc/author')); // VueVlog router.get('/vuevideo/:userid', require('./routes/vuevideo/user')); +// LWN.net Alerts +router.get('/lwn/alerts/:distributor', require('./routes/lwn/alerts')); + module.exports = router; diff --git a/lib/routes/lwn/alerts.js b/lib/routes/lwn/alerts.js new file mode 100644 index 000000000..ee8db6793 --- /dev/null +++ b/lib/routes/lwn/alerts.js @@ -0,0 +1,57 @@ +const url = require('url'); +const got = require('@/utils/got'); +const date = require('@/utils/date'); +const cheerio = require('cheerio'); + +module.exports = async (ctx) => { + const distributor = ctx.params.distributor; + const listUrl = `https://lwn.net/Alerts/${distributor}/`; + const res = await got({ + method: 'get', + url: listUrl, + }); + const $ = cheerio.load(res.data); + const title = $('.PageHeadline').text(); + const list = $('.ArticleText').find('table tbody tr:not(:first-of-type)'); + const count = []; + for (let i = 0; i < list.length; i++) { + count.push(i); + } + const resultItem = await Promise.all( + count.map(async (i) => { + const each = $(list[i]); + const originalUrl = each.find('td > a').attr('href'); + const link = url.resolve('https://lwn.net', originalUrl); + const pubDate = date(each.find('td:nth-of-type(3)').text()); + + const cacheKey = `LWN.net:${link}`; + const cacheValue = await ctx.cache.get(cacheKey); + + let item; + if (cacheValue) { + item = JSON.parse(cacheValue); + } else { + const detail = await got({ + method: 'get', + url: link, + }); + const content = cheerio.load(detail.data); + item = { + title: content('.PageHeadline').text(), + description: content('.ArticleText').html(), + link: link, + pubDate: pubDate, + }; + ctx.cache.set(cacheKey, JSON.stringify(item)); + } + + return Promise.resolve(item); + }) + ); + + ctx.state.data = { + title: title, + link: listUrl, + item: resultItem, + }; +};