UNPKG

rsshub

Version:
170 lines (167 loc) 10.8 kB
import { t as parseDate } from "./parse-date-Cr0wQjV_.mjs"; import { r as getSubPath } from "./common-utils-DtQojudb.mjs"; import { t as got_default } from "./got-BTowW50G.mjs"; import { t as timezone } from "./timezone-BBvDwS_3.mjs"; import dayjs from "dayjs"; import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime"; import { load } from "cheerio"; import { renderToString } from "hono/jsx/dom/server"; import { raw } from "hono/html"; //#region lib/routes/dlsite/templates/description.tsx const formatDate = (date) => date ? dayjs(date).format("YYYY-MM-DD HH:mm") : ""; const renderDescription = ({ detail, images, authors, discountRate, discountEndDate, updatedDate, pubDate, workCategories, searchTags, description }) => { const localePrices = detail.locale_price_str ?? {}; const localeOfficialPrices = detail.locale_official_price_str ?? {}; const hasOfficialPrice = Boolean(detail.official_price_str); const hasLocaleOfficialPrices = Boolean(detail.locale_official_price_str); const price = detail.price_str; return renderToString(/* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("table", { children: /* @__PURE__ */ jsxs("tbody", { children: [ discountRate ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "割引" }), /* @__PURE__ */ jsxs("td", { children: [discountRate, "%"] })] }) : null, discountEndDate ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "割引終了時間" }), /* @__PURE__ */ jsx("td", { children: formatDate(discountEndDate) })] }) : null, price ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "価格\xA0(JPY)" }), /* @__PURE__ */ jsxs("td", { children: [ raw(price), /* @__PURE__ */ jsx("i", { children: "\xA0円" }), "\xA0\xA0", hasOfficialPrice ? /* @__PURE__ */ jsx("del", { children: /* @__PURE__ */ jsxs("small", { children: [raw(detail.official_price_str), /* @__PURE__ */ jsx("i", { children: "\xA0円" })] }) }) : null ] })] }) : null, localePrices.en_US ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "価格\xA0(USD)" }), /* @__PURE__ */ jsxs("td", { children: [raw(localePrices.en_US), hasLocaleOfficialPrices ? /* @__PURE__ */ jsx("del", { children: /* @__PURE__ */ jsx("small", { children: raw(localeOfficialPrices.en_US) }) }) : null] })] }) : null, localePrices.ko_KR ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "価格\xA0(KRW)" }), /* @__PURE__ */ jsxs("td", { children: [raw(localePrices.ko_KR), hasLocaleOfficialPrices ? /* @__PURE__ */ jsx("del", { children: /* @__PURE__ */ jsx("small", { children: raw(localeOfficialPrices.ko_KR) }) }) : null] })] }) : null, localePrices.zh_CN ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "価格\xA0(RMB)" }), /* @__PURE__ */ jsxs("td", { children: [raw(localePrices.zh_CN), hasLocaleOfficialPrices ? /* @__PURE__ */ jsx("del", { children: /* @__PURE__ */ jsx("small", { children: raw(localeOfficialPrices.zh_CN) }) }) : null] })] }) : null, localePrices.zh_TW ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "価格\xA0(TWD)" }), /* @__PURE__ */ jsxs("td", { children: [raw(localePrices.zh_TW), hasLocaleOfficialPrices ? /* @__PURE__ */ jsx("del", { children: /* @__PURE__ */ jsx("small", { children: raw(localeOfficialPrices.zh_TW) }) }) : null] })] }) : null, detail.default_point_str ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "ポイント" }), /* @__PURE__ */ jsxs("td", { children: [detail.default_point_str, "\xA0pt"] })] }) : null, authors?.length ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "作者" }), /* @__PURE__ */ jsx("td", { children: authors.map((author) => /* @__PURE__ */ jsx("a", { href: author.link, children: author.name })) })] }) : null, updatedDate ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "発売日" }), /* @__PURE__ */ jsx("td", { children: formatDate(updatedDate) })] }) : null, pubDate ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "販売日" }), /* @__PURE__ */ jsx("td", { children: formatDate(pubDate) })] }) : null, workCategories?.length ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "作品形式" }), /* @__PURE__ */ jsx("td", { children: workCategories.map((category) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("a", { href: category.link, children: category.text }), ",\xA0"] })) })] }) : null, searchTags?.length ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "ジャンル" }), /* @__PURE__ */ jsx("td", { children: searchTags.map((tag) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("a", { href: tag.link, children: tag.text }), ",\xA0"] })) })] }) : null, description ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "概要" }), /* @__PURE__ */ jsx("td", { children: description })] }) : null ] }) }), images?.length ? images.map((image) => /* @__PURE__ */ jsx("img", { src: image })) : null] })); }; //#endregion //#region lib/routes/dlsite/utils.ts const rootUrl = "https://www.dlsite.com"; const defaultFilters = { show_type: 1, show_layout: 1, per_page: 100 }; const addFilters = (url, filters) => { const keys = Object.keys(filters); const filterStr = keys.map((k) => `/${k}/${filters[k]}`).join(""); const newUrl = url.replaceAll(new RegExp(String.raw`(/${keys.join(String.raw`/\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) => { return (await got_default({ method: "get", url: `${rootUrl}/home-touch/product/info/ajax?product_id=${works}` })).data; }; const ProcessItems = async (ctx) => { const subPath = getSubPath(ctx) === "/" ? "/home/new" : getSubPath(ctx); const limit = ctx.req.query("limit") ? Number.parseInt(ctx.req.query("limit")) : 100; const currentUrl = `${rootUrl}${addFilters(subPath, defaultFilters)}`; const $ = load((await got_default({ method: "get", url: currentUrl })).data); const works = $("dt.work_name").slice(0, limit); const updatedDate = $(".work_update").length === 0 ? void 0 : 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) => { const $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").replaceAll("'", "\"")).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) : void 0; 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: renderDescription({ detail, images, authors, discountRate, discountEndDate, updatedDate, pubDate, workCategories, searchTags, description }) }; }); return { title: $("title").text(), description: $("meta[name=\"description\"]").attr("content"), link: currentUrl, item: items, allowEmpty: true }; }; //#endregion //#region lib/routes/dlsite/z-index/index.ts const route = { path: "/:path{.+}?", categories: ["anime"], example: "/dlsite/home/new", parameters: { path: "Path, `/home/new` by default, as Release Calendar" }, description: `::: tip To subscribe to this route, you can first visit the site and specify filters, and then fill in the field after \`https://www.dlsite.com/\` in the URL of the corresponding page at the path of the route. Here are 2 examples. If you subscribe to [Voice / ASMR works Release date - New to Old](https://www.dlsite.com/home/works/type/=/work_type_category/audio/order/release_d), at the URL of the corresponding page \`https://www.dlsite.com/home/works/type/=/work_type_category/audio/order/release_d\` and after \`https://www.dlsite.com/\` is \`home/works/type/=/work_type_category/audio/order/release_d\`, which can be seen as the path. In this case the route is [\`/dlsite/home/works/type/=/work_type_category/audio/order/release_d\`](https://rsshub.app/dlsite/home/works/type/=/work_type_category/audio/order/release_d) If you subscribe to [Discounted works Latest Discounts - Newest to Oldest](https://www.dlsite.com/home/works/discount/=/order/cstart_d), at the URL of the corresponding page \`https://www.dlsite.com/home/works/discount/=/order/cstart_d\` and after \`https://www.dlsite.com/\` is \`home/works/discount/=/order/cstart_d\`, which can be seen as the path. In this case the route is [\`/dlsite/home/works/discount/=/order/cstart_d\`](https://rsshub.app/dlsite/home/works/discount/=/order/cstart_d) :::`, name: "General", maintainers: ["nczitzk"], handler, features: { nsfw: true } }; async function handler(ctx) { return await ProcessItems(ctx); } //#endregion export { route };