RSSHub/lib/v2/dlsite/utils.js

177 lines
5.3 KiB
JavaScript

const got = require('@/utils/got');
const cheerio = require('cheerio');
const timezone = require('@/utils/timezone');
const { parseDate } = require('@/utils/parse-date');
const { art } = require('@/utils/render');
const path = require('path');
const dayjs = require('dayjs');
const rootUrl = 'https://www.dlsite.com';
const defaultFilters = {
show_type: 1,
show_layout: 1,
per_page: 100,
};
const formatDate = (date, format) => dayjs(date).format(format);
const addFilters = (url, filters) => {
const keys = Object.keys(filters);
const filterStr = keys.map((k) => `/${k}/${filters[k]}`).join('');
const newUrl = url.replace(new RegExp(`(/${keys.join('/\\w+|/')}/\\w+)`, 'g'), '');
return `${newUrl}${/=/.test(newUrl) ? '' : '/='}${filterStr}`;
};
const getPubDate = (raw) => {
const dateMatches = raw.match(/(\d{4}).*(\d{2}).*(\d{2})/);
if (dateMatches) {
return parseDate(`${dateMatches[1]}-${dateMatches[2]}-${dateMatches[3]}`, 'YYYY-MM-DD');
}
return parseDate(raw.split(':').pop().trim(), 'MMM/DD/YYYY');
};
const getDetails = async (works) => {
const apiUrl = `${rootUrl}/home-touch/product/info/ajax?product_id=${works}`;
const detailResponse = await got({
method: 'get',
url: apiUrl,
});
return detailResponse.data;
};
const ProcessItems = async (ctx) => {
art.defaults.imports.formatDate = formatDate;
ctx.path = ctx.path === '/' ? '/home/new' : ctx.path;
const limit = ctx.query.limit ? parseInt(ctx.query.limit) : 100;
const currentUrl = `${rootUrl}${addFilters(ctx.path, defaultFilters)}`;
const response = await got({
method: 'get',
url: currentUrl,
});
const $ = cheerio.load(response.data);
const works = $('dt.work_name').slice(0, limit);
const updatedDate = $('.work_update').length === 0 ? undefined : getPubDate($('.work_update').text());
const details = await getDetails(
works
.toArray()
.map(
(item) =>
$(item)
.find('a')
.attr('href')
.match(/_id\/(.*?)\.html/)[1]
)
.join(',')
);
const items = works.toArray().map((item) => {
item = $(item).parentsUntil('tbody, ul');
const a = item.find('.work_name a');
const title = a.text();
const link = a.attr('href');
const guid = link.match(/_id\/(.*?)\.html/)[1];
const description = item.find('.work_text').text();
const authors = item
.find('.maker_name a')
.toArray()
.map((a) => ({
name: $(a).text(),
link: $(a).attr('href'),
}));
let images = item.find('div[data-samples]').length === 0 ? [] : JSON.parse(item.find('div[data-samples]').attr('data-samples').replace(/'/g, '"')).map((s) => s.thumb);
const workCategories = item
.find('.work_category')
.find('a')
.toArray()
.map((i) => ({
text: $(i).text(),
link: $(i).attr('href'),
}));
const workGenres = item
.find('.work_genre')
.find('span[title]')
.toArray()
.map((i) => ({
text: $(i).text(),
}));
const searchTags = item
.find('.search_tag')
.find('a')
.toArray()
.map((i) => ({
text: $(i).text(),
link: $(i).attr('href'),
}));
const nameTags = item
.find('.icon_wrap')
.find('span[title]')
.toArray()
.map((i) => ({
text: $(i).text(),
}));
const detail = details[guid];
const pubDate = timezone(parseDate(detail.regist_date), +9);
const discountRate = detail.discount_rate;
const discountEndDate = detail.discount_end_date ? timezone(parseDate(detail.discount_end_date, 'MM/DD HH:mm'), +9) : undefined;
images = images.length === 0 ? [detail.work_image] : images;
return {
title: `${
discountRate
? `${discountRate}% OFF
${` ${discountEndDate ? `${dayjs(discountEndDate).format('YYYY-MM-DD HH:mm')} まで` : ''}`}`
: ' '
}${title}`,
link,
pubDate,
author: authors.map((a) => a.name).join(' / '),
category: [...workCategories.map((i) => i.text), ...workGenres.map((i) => i.text), ...searchTags.map((i) => i.text), ...nameTags.map((i) => i.text)],
guid: `dlsite-${guid}`,
description: art(path.join(__dirname, 'templates/description.art'), {
detail,
images,
authors,
discountRate,
discountEndDate,
updatedDate,
pubDate,
workCategories,
workGenres,
searchTags,
description,
}),
};
});
return {
title: $('title').text(),
description: $('meta[name="description"]').attr('content'),
link: currentUrl,
item: items,
allowEmpty: true,
};
};
module.exports = {
ProcessItems,
};