feat: route for furstar.jp, 最新角色和画家 (#5194)
Co-authored-by: Henry Wang <hi@henry.wang>
This commit is contained in:
parent
bf5b5a5807
commit
da88193f04
|
|
@ -10,6 +10,20 @@ pageClass: routes
|
|||
|
||||
<Route author="luyuhuang" example="/alter-cn/news" path="/alter-cn/news"/>
|
||||
|
||||
## Furstar
|
||||
|
||||
### 最新售卖角色列表
|
||||
|
||||
<Route author="NeverBehave" example="/furstar/characters/cn" path="/furstar/characters/:lang?" :paramsDesc="['语言, 留空为jp, 支持cn, en']"/>
|
||||
|
||||
### 已经出售的角色列表
|
||||
|
||||
<Route author="NeverBehave" example="/furstar/archive/cn" path="/furstar/archive/:lang?" :paramsDesc="['语言, 留空为jp, 支持cn, en']"/>
|
||||
|
||||
### 画师列表
|
||||
|
||||
<Route author="NeverBehave" example="/furstar/artists/cn" path="/furstar/artists/:lang?" :paramsDesc="['语言, 留空为jp, 支持cn, en']"/>
|
||||
|
||||
## LeBonCoin
|
||||
|
||||
### Ads
|
||||
|
|
|
|||
|
|
@ -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'));
|
||||
|
|
|
|||
|
|
@ -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: `<img src="${e.headImage}"/> ${utils.renderAuthor(e.author)}`,
|
||||
pubDate: dateParser(new Date().toISOString()), // No Time for now
|
||||
link: e.detailPage,
|
||||
})),
|
||||
};
|
||||
};
|
||||
|
|
@ -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: `<img src="${e.avatar}"/><a href="${base}/${e.link}">${e.name}</a>`,
|
||||
pubDate: dateParser(new Date().toISOString()), // No Time for now
|
||||
link: `${base}/${e.link}`,
|
||||
})),
|
||||
};
|
||||
};
|
||||
|
|
@ -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,
|
||||
})),
|
||||
};
|
||||
};
|
||||
|
|
@ -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) => `<div>
|
||||
<img src="${author.avatar}" />
|
||||
<a href="${author.link ? author.link : '//example.com'}">${author.name}</a>
|
||||
</div>`;
|
||||
|
||||
const renderDesc = (desc, pics, author) => {
|
||||
const rpics = pics.map((e) => `<img src="${e}"/>`).join('\n');
|
||||
const rauthor = renderAuthor(author);
|
||||
return `<p>${desc}</p>${rpics}${rauthor}`;
|
||||
};
|
||||
|
||||
const authorDetail = (el) => {
|
||||
const $ = cheerio.load(el);
|
||||
// if there is <a>
|
||||
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,
|
||||
};
|
||||
Loading…
Reference in New Issue