UNPKG

rsshub

Version:
205 lines (202 loc) • 6.21 kB
import { n as init_esm_shims, t as __dirname } from "./esm-shims-CzJ_djXG.mjs"; import { t as config } from "./config-C37vj7VH.mjs"; import "./dist-BInvbO1W.mjs"; import "./logger-Czu8UMNd.mjs"; import { t as ofetch_default } from "./ofetch-BIyrKU3Y.mjs"; import { t as parseDate } from "./parse-date-BrP7mxXf.mjs"; import { t as cache_default } from "./cache-Bo__VnGm.mjs"; import { t as art } from "./render-BQo6B4tL.mjs"; import { t as invalid_parameter_default } from "./invalid-parameter-rr4AgGpp.mjs"; import { t as isValidHost } from "./valid-host-C-u5eW3j.mjs"; import path from "node:path"; //#region lib/routes/fanbox/utils.ts init_esm_shims(); function getHeaders() { const sessionid = config.fanbox.session; return { origin: "https://fanbox.cc", cookie: sessionid ? `FANBOXSESSID=${sessionid}` : "" }; } function embedUrlMap(urlEmbed) { switch (urlEmbed.type) { case "html": return urlEmbed.html; case "fanbox.post": return art(path.join(__dirname, "templates/fanbox-post-12425d7b.art"), { postUrl: `https://${urlEmbed.postInfo.creatorId}.fanbox.cc/posts/${urlEmbed.postInfo.id}`, title: urlEmbed.postInfo.title, user: urlEmbed.postInfo.user, excerpt: urlEmbed.postInfo.excerpt }); default: return ""; } } function passageConv(p) { const seg = [...p.text]; if (p.styles) p.styles.map((s) => { switch (s.type) { case "bold": seg[s.offset] = `<b>` + seg[s.offset]; seg[s.offset + s.length - 1] += `</b>`; break; default: } return s; }); if (p.links) p.links.map((l) => { seg[l.offset] = `<a href="${l.url}">` + seg[l.offset]; seg[l.offset + l.length - 1] += `</a>`; return l; }); return seg.join(""); } function parseText(body) { return body.text || ""; } function parseImage(body) { let ret = body.text || ""; for (const i of body.images) ret += `<hr><img src="${i.originalUrl}">`; return ret; } function parseFile(body) { let ret = body.text || ""; for (const f of body.files) ret += `<br><a href="${f.url}" download="${f.name}.${f.extension}">${f.name}.${f.extension}</a>`; return ret; } async function parseVideo(body) { let ret = ""; switch (body.video.serviceProvider) { case "soundcloud": ret += await getSoundCloudEmbedUrl(body.video.videoId); break; case "youtube": ret += `<iframe src="https://www.youtube-nocookie.com/embed/${body.video.videoId}" frameborder="0" referrerpolicy="strict-origin-when-cross-origin"></iframe>`; break; case "vimeo": ret += `<iframe src="https://player.vimeo.com/video/${body.video.videoId}" frameborder="0"></iframe>`; break; default: } ret += `<br>${body.text}`; return ret; } async function parseArtile(body) { let ret = []; for (let x = 0; x < body.blocks.length; ++x) { const b = body.blocks[x]; ret.push("<p>"); switch (b.type) { case "p": ret.push(passageConv(b)); break; case "header": ret.push(`<h2>${b.text}</h2>`); break; case "image": { const i = body.imageMap[b.imageId]; ret.push(`<img src="${i.originalUrl}">`); break; } case "file": { const file = body.fileMap[b.fileId]; ret.push(`<a href="${file.url}" download="${file.name}.${file.extension}">${file.name}.${file.extension}</a>`); break; } case "url_embed": ret.push(embedUrlMap(body.urlEmbedMap[b.urlEmbedId])); break; default: } } ret = await Promise.all(ret); return ret.join(""); } async function parseDetail(i) { let ret = ""; if (i.feeRequired !== 0) ret += `Fee Required: <b>${i.feeRequired} JPY/month</b><hr>`; if (i.coverImageUrl) ret += `<img src="${i.coverImageUrl}"><hr>`; if (!i.body) { ret += i.excerpt; return ret; } switch (i.type) { case "text": ret += parseText(i.body); break; case "file": ret += parseFile(i.body); break; case "image": ret += parseImage(i.body); break; case "video": ret += await parseVideo(i.body); break; case "article": ret += await parseArtile(i.body); break; default: ret += "<b>Unsupported content (RSSHub)</b>"; } return ret; } function parseItem(item) { return cache_default.tryGet(`fanbox-${item.id}-${item.updatedDatetime}`, async () => { const postDetail = await ofetch_default(`https://api.fanbox.cc/post.info?postId=${item.id}`, { headers: { ...getHeaders(), "User-Agent": config.trueUA } }); return { title: item.title || `No title`, description: await parseDetail(postDetail.body), pubDate: parseDate(item.updatedDatetime), link: `https://${item.creatorId}.fanbox.cc/posts/${item.id}`, category: item.tags }; }); } async function getSoundCloudEmbedUrl(videoId) { const videoUrl = `https://soundcloud.com/${videoId}`; return (await ofetch_default(`https://soundcloud.com/oembed?url=${encodeURIComponent(videoUrl)}&format=json&maxheight=400&format=json`)).html; } //#endregion //#region lib/routes/fanbox/index.ts const route = { path: "/:creator", categories: ["social-media"], example: "/fanbox/official", parameters: { creator: "fanbox user name" }, maintainers: ["KarasuShin"], name: "Creator", handler, features: { requireConfig: [{ name: "FANBOX_SESSION_ID", description: "Required for private posts. Can be found in browser DevTools -> Application -> Cookies -> https://www.fanbox.cc -> FANBOXSESSID", optional: true }], nsfw: true } }; async function handler(ctx) { const creator = ctx.req.param("creator"); if (!isValidHost(creator)) throw new invalid_parameter_default("Invalid user name"); let title = `Fanbox - ${creator}`; let description; let image; try { const userInfoResponse = await ofetch_default(`https://api.fanbox.cc/creator.get?creatorId=${creator}`, { headers: getHeaders() }); title = `Fanbox - ${userInfoResponse.body.user.name}`; description = userInfoResponse.body.description; image = userInfoResponse.body.user.iconUrl; } catch {} const postListResponse = await ofetch_default(`https://api.fanbox.cc/post.listCreator?creatorId=${creator}&limit=20`, { headers: getHeaders() }); const items = await Promise.all(postListResponse.body.map((i) => parseItem(i))); return { title, link: `https://${creator}.fanbox.cc`, description, image, item: items }; } //#endregion export { route };