From da88193f04fafcf15e66c793b2164376c2ca6c86 Mon Sep 17 00:00:00 2001 From: NeverBehave Date: Tue, 28 Jul 2020 13:57:51 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20route=20for=20furstar.jp,=20=E6=9C=80?= =?UTF-8?q?=E6=96=B0=E8=A7=92=E8=89=B2=E5=92=8C=E7=94=BB=E5=AE=B6=20(#5194?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Henry Wang --- docs/shopping.md | 14 ++++++ lib/router.js | 7 +++ lib/routes/furstar/archive.js | 24 +++++++++ lib/routes/furstar/artists.js | 28 +++++++++++ lib/routes/furstar/index.js | 25 ++++++++++ lib/routes/furstar/utils.js | 91 +++++++++++++++++++++++++++++++++++ 6 files changed, 189 insertions(+) create mode 100644 lib/routes/furstar/archive.js create mode 100644 lib/routes/furstar/artists.js create mode 100644 lib/routes/furstar/index.js create mode 100644 lib/routes/furstar/utils.js diff --git a/docs/shopping.md b/docs/shopping.md index 093834e47..7e82a5d84 100644 --- a/docs/shopping.md +++ b/docs/shopping.md @@ -10,6 +10,20 @@ pageClass: routes +## Furstar + +### 最新售卖角色列表 + + + +### 已经出售的角色列表 + + + +### 画师列表 + + + ## LeBonCoin ### Ads diff --git a/lib/router.js b/lib/router.js index 6373c1bf3..e8137b781 100644 --- a/lib/router.js +++ b/lib/router.js @@ -2971,10 +2971,17 @@ router.get('/ngbj/cat/:cat', require('./routes/niaogebiji/cat')); // 东方我乐多丛志 router.get('/touhougarakuta/:language/:type', require('./routes/touhougarakuta')); +// furstar.jp +router.get('/furstar/characters/:lang?', require('./routes/furstar/index')); +router.get('/furstar/artists/:lang?', require('./routes/furstar/artists')); +router.get('/furstar/archive/:lang?', require('./routes/furstar/archive')); + // 北京物资学院 router.get('/bwu/news', require('./routes/universities/bwu/news')); + // Picuki router.get('/picuki/profile/:id', require('./routes/picuki/profile')); + // 新榜 router.get('/newrank/wechat/:wxid', require('./routes/newrank/wechat')); router.get('/newrank/douyin/:dyid', require('./routes/newrank/douyin')); diff --git a/lib/routes/furstar/archive.js b/lib/routes/furstar/archive.js new file mode 100644 index 000000000..4e20722ca --- /dev/null +++ b/lib/routes/furstar/archive.js @@ -0,0 +1,24 @@ +const utils = require('./utils'); +const got = require('@/utils/got'); +const dateParser = require('@/utils/dateParser'); + +module.exports = async (ctx) => { + const base = utils.langBase(ctx.params.lang); + const url = `${base}/archive.php`; + const res = await got.get(url); + const info = utils.fetchAllCharacters(res.data, base); + + ctx.state.data = { + title: 'Furstar 已出售角色', + link: 'https://furstar.jp', + description: 'Furstar 已经出售或预订的角色列表', + language: ctx.params.lang, + item: info.map((e) => ({ + title: e.title, + author: e.author.name, + description: ` ${utils.renderAuthor(e.author)}`, + pubDate: dateParser(new Date().toISOString()), // No Time for now + link: e.detailPage, + })), + }; +}; diff --git a/lib/routes/furstar/artists.js b/lib/routes/furstar/artists.js new file mode 100644 index 000000000..4842ec8c7 --- /dev/null +++ b/lib/routes/furstar/artists.js @@ -0,0 +1,28 @@ +const utils = require('./utils'); +const cheerio = require('cheerio'); +const got = require('@/utils/got'); +const dateParser = require('@/utils/dateParser'); + +module.exports = async (ctx) => { + const base = utils.langBase(ctx.params.lang); + const res = await got.get(base); + const $ = cheerio.load(res.data); + const artists = $('.filter-item') + .map((i, e) => utils.authorDetail(e)) + .get(); + artists.shift(); // the first one is "show all" + + ctx.state.data = { + title: 'furstar 所有画家', + link: 'https://furstar.jp', + description: 'Furstar 所有画家列表', + language: ctx.params.lang, + item: artists.map((e) => ({ + title: e.name, + author: e.name, + description: `${e.name}`, + pubDate: dateParser(new Date().toISOString()), // No Time for now + link: `${base}/${e.link}`, + })), + }; +}; diff --git a/lib/routes/furstar/index.js b/lib/routes/furstar/index.js new file mode 100644 index 000000000..e3e2a98fc --- /dev/null +++ b/lib/routes/furstar/index.js @@ -0,0 +1,25 @@ +const utils = require('./utils'); +const got = require('@/utils/got'); +const dateParser = require('@/utils/dateParser'); + +module.exports = async (ctx) => { + const base = utils.langBase(ctx.params.lang); + const res = await got.get(base); + const info = utils.fetchAllCharacters(res.data, base); + + const details = await Promise.all(info.map((e) => utils.detailPage(e.detailPage, ctx.cache))); + + ctx.state.data = { + title: 'Furstar 最新角色', + link: 'https://furstar.jp', + description: 'Furstar 最近更新的角色列表', + language: ctx.params.lang, + item: info.map((e, i) => ({ + title: e.title, + author: e.author.name, + description: utils.renderDesc(details[i].desc, details[i].pics, e.author), + pubDate: dateParser(new Date().toISOString()), // No Time for now + link: e.detailPage, + })), + }; +}; diff --git a/lib/routes/furstar/utils.js b/lib/routes/furstar/utils.js new file mode 100644 index 000000000..95bf0af9f --- /dev/null +++ b/lib/routes/furstar/utils.js @@ -0,0 +1,91 @@ +const cheerio = require('cheerio'); +const got = require('@/utils/got'); +const base = 'https://furstar.jp'; +const langBase = (lang) => (lang ? `${base}/${lang}` : base); // en, cn, (none, for JP) + +const renderAuthor = (author) => ``; + +const renderDesc = (desc, pics, author) => { + const rpics = pics.map((e) => ``).join('\n'); + const rauthor = renderAuthor(author); + return `

${desc}

${rpics}${rauthor}`; +}; + +const authorDetail = (el) => { + const $ = cheerio.load(el); + // if there is + const a = $('a'); + const result = { + name: null, + avatar: null, + link: null, + }; + + if (a.length > 0) { + const img = $('a img'); + result.name = img.attr('alt'); + result.avatar = img.attr('src'); + result.link = a.attr('href'); + } else { + const desc = $('img'); + result.name = desc.attr('alt'); + result.avatar = desc.attr('src'); + } + + return result; +}; + +const detailPage = async (link, cache) => + cache.tryGet(link, async () => { + const result = await got(link); + const $ = cheerio.load(result.data); + const title = $('.row .panel-heading h2').text().trim(); // Get first title + const desc = $('.character-description p').text().trim(); + const pics = $('.img-gallery .prettyPhoto') + .map((i, e) => { + const p = cheerio.load(e); + const link = p('a').attr('href').trim(); + return `${base}${link.substring(2)}`; + }) + .get(); + + return { + title, + pics, + desc, + author: authorDetail($('.character-description').html()), + }; + }); + +const fetchAllCharacters = (data, base) => { + // All character page + const $ = cheerio.load(data); + const characters = $('.character-article'); + const info = characters + .map((i, e) => { + const c = cheerio.load(e); + const r = { + title: c('.character-headline').text().trim(), + headImage: c('.character-images img').attr('src').trim(), + detailPage: `${base}/${c('.character-images a').attr('href').trim()}`, + author: authorDetail(c('.character-description').html()), + }; + return r; + }) + .get(); + + return info; +}; + +module.exports = { + BASE: base, + langBase, + fetchAllCharacters, + detailPage, + authorDetail, + renderDesc, + renderAuthor, +};