diff --git a/docs/en/new-media.md b/docs/en/new-media.md index 97dfca98f8..bce3147394 100644 --- a/docs/en/new-media.md +++ b/docs/en/new-media.md @@ -13,7 +13,7 @@ pageClass: routes Supported sub-sites: | 9To5Mac | 9To5Google | 9To5Toys | | ------- | ---------- | -------- | -| Mac | Google | Toys | +| Mac | Google | Toys | @@ -152,6 +152,32 @@ Compared to the official one, this feed: +## Soomal + +### 话题 + + + +- Available languages: + +| Simplified Chinese | Traditional Chinese | English | +| ------------------ | ------------------- | ------- | +| zh | zh_tw | en | + +- Available topics by locale: + +| Languages | | | | | | +| ------------------- | -------- | ----- | -------- | -------- | -------- | +| Simplified Chinese | 最新文章 | 科普 | 测评报告 | 发烧入门 | 摄影入门 | 古典音乐入门 | +| Traditional Chinese | 最新文章 | 科普 | 測評報告 | 發燒入門 | 攝影入門 | 古典音樂入門 | +| English | Phone | Audio | Album | Review | + +- Soomal offers official RSS subscriptions + - Soomal website:[http://www.soomal.com/doc/101.rss.xml](http://www.soomal.com/doc/101.rss.xml) + - Soomal forum and comments:[http://www.soomal.com/bbs/101.rss.xml](http://www.soomal.com/bbs/101.rss.xml) + + + ## The Verge diff --git a/docs/new-media.md b/docs/new-media.md index 59dbc377f8..617a2c23fd 100644 --- a/docs/new-media.md +++ b/docs/new-media.md @@ -316,6 +316,32 @@ pageClass: routes +## Soomal + +### 话题 + + + +- 可选语言: + +| 简体中文 | 正体中文 | 英语 | +| -------- | -------- | ---- | +| zh | zh_tw | en | + +- 可选话题(按语言分类): + +| 语言 | | | | | | | +| -------- | -------- | ----- | -------- | -------- | -------- | ------------ | +| 简体中文 | 最新文章 | 科普 | 测评报告 | 发烧入门 | 摄影入门 | 古典音乐入门 | +| 正体中文 | 最新文章 | 科普 | 測評報告 | 發燒入門 | 攝影入門 | 古典音樂入門 | +| 英语 | Phone | Audio | Album | Review | | | + +- Soomal 提供官方 RSS 订阅 + - Soomal 网站更新: + - Soomal 论坛与留言系统的更新: + + + ## The Verge ### The Verge diff --git a/lib/router.js b/lib/router.js index 8384e717f3..1485669e45 100644 --- a/lib/router.js +++ b/lib/router.js @@ -3088,6 +3088,9 @@ router.get('/souyun/today', require('./routes/souyun/today')); // 生物谷 router.get('/bioon/latest', require('./routes/bioon/latest')); +// soomal +router.get('/soomal/topics/:category/:language?', require('./routes/soomal/topics')); + // NASA router.get('/nasa/apod', require('./routes/nasa/apod')); router.get('/nasa/apod-ncku', require('./routes/nasa/apod-ncku')); diff --git a/lib/routes/soomal/topics.js b/lib/routes/soomal/topics.js new file mode 100644 index 0000000000..48785583c7 --- /dev/null +++ b/lib/routes/soomal/topics.js @@ -0,0 +1,130 @@ +const got = require('@/utils/got'); +const cheerio = require('cheerio'); +const url = require('url'); +const iconv = require('iconv-lite'); + +module.exports = async (ctx) => { + const category = ctx.params.category; + const lang = ctx.params.language; + + let index_url; + let character_set; + switch (lang) { + case 'zh_tw': + index_url = 'http://www.soomal.com/doc/index201000_0001_00.htm'; + character_set = 'big5'; + break; + case 'en': + index_url = 'http://eng.soomal.com/edoc/index101000_0001_00.htm'; + character_set = 'ISO-8859-5'; + break; + default: + index_url = 'http://www.soomal.com/doc/index101000_0001_00.htm'; + character_set = 'gbk'; + break; + } + + let category_list; + let url_list; + + const category_url = await ctx.cache.tryGet([lang, category], async () => { + const front_page = await got.get(index_url, { + responseType: 'buffer', + }); + + const front_data = iconv.decode(front_page.data, character_set); + + const $ = cheerio.load(front_data); + if (lang !== 'en') { + const container_list = $('div.container.cf').slice(0, 2); + category_list = container_list + .find('ul.ul-reset') + .find('h3') + .children() + .get() + .map((item) => $(item).text()); + url_list = container_list + .find('ul.ul-reset') + .find('h3') + .children() + .get() + .map((item) => $(item).attr('href')); + } else { + category_list = $('div.menu') + .find('a') + .get() + .map((item) => $(item).text()); + url_list = $('div.menu') + .find('a') + .get() + .map((item) => $(item).attr('href')); + } + + return url.resolve(index_url, url_list[category_list.indexOf(category)]); + }); + + const response = await got.get(category_url, { + responseType: 'buffer', + }); + + const data = iconv.decode(response.data, character_set); + const $ = cheerio.load(data); + + const list = $('div.item') + .find('div.title') + .children('a') + .get() + .map((item) => url.resolve(category_url, $(item).attr('href'))); + + const out = await Promise.all( + list.map(async (link) => { + const [title, author, pubDate, description] = await ctx.cache.tryGet(link, async () => { + const response = await got.get(link, { + responseType: 'buffer', + }); + + const data = iconv.decode(response.data, character_set); + const $ = cheerio.load(data); + + let [title, author, pubDate, description] = ''; + if (lang !== 'en') { + title = $('div.titlebox').find('div.title').text(); + author = $('div.titlebox').find('div.info').children('a').text(); + pubDate = Date.parse( + $('div.titlebox') + .find('div.info') + .text() + .match(/\d{4}([.\-/ ])\d{2}\1\d{2}\s\d{2}[:]\d{2}[:]\d{2}/)[0] + ); + + $('div.toolbar,div.grade').remove(); + description = $('div.Doc').html(); + } else { + title = $('div.titlebox').find('div.title').text(); + author = $('div.titlebox').find('div.infobox').children('a').text(); + pubDate = new Date(); + + $('div.grade').remove(); + description = $('div.textbox').html(); + } + + return [title, author, pubDate, description]; + }); + + const item = { + title: title, + description: description, + pubDate: pubDate, + link: link, + author: author, + }; + return Promise.resolve(item); + }) + ); + + ctx.state.data = { + title: 'Soomal.com - ' + category, + link: category_url, + item: out, + }; +};