UNPKG

rsshub

Version:
131 lines (130 loc) 4.68 kB
import { t as InvalidParameterError } from "./invalid-parameter-CGxhjomn.mjs"; import { t as renderDescription } from "./description-D8tUoFfX.mjs"; import queryString from "query-string"; import { GenreNotation, NarouNovelFetch, R18Site, SearchBuilder, SearchBuilderR18 } from "narou"; //#region lib/routes/syosetu/types/search.ts let SyosetuSub = /* @__PURE__ */ function(SyosetuSub) { SyosetuSub["YOMOU"] = "yomou"; SyosetuSub["NOCTURNE"] = "noc"; SyosetuSub["MOONLIGHT"] = "mnlt"; SyosetuSub["MIDNIGHT"] = "mid"; return SyosetuSub; }({}); const syosetuSubToJapanese = { ["yomou"]: "小説を読もう", ["noc"]: "ノクターン", ["mnlt"]: "ムーンライト", ["mid"]: "ミッドナイト" }; //#endregion //#region lib/routes/syosetu/search.ts const route = { path: "/search/:sub/:query", categories: ["reading"], example: "/syosetu/search/noc/word=ハーレム&notword=&type=r&mintime=&maxtime=&minlen=30000&maxlen=&min_globalpoint=&max_globalpoint=&minlastup=&maxlastup=&minfirstup=&maxfirstup=&isgl=1&notbl=1&order=new?limit=5", parameters: { sub: { description: "The target Syosetu subsite.", options: Object.values(SyosetuSub).map((value) => ({ value, label: syosetuSubToJapanese[value] })) }, query: "Search parameters in Syosetu format." }, features: { requireConfig: false, requirePuppeteer: false, antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false }, name: "Search", maintainers: ["SnowAgar25"], handler }; const setIfExists = (value) => value ?? void 0; /** * This function converts query string generated by Syosetu website into API-compatible format. * It is not intended for users to freely adjust values. * * @see https://deflis.github.io/node-narou/index.html * @see https://dev.syosetu.com/man/api/ */ function mapToSearchParams(query, limit) { const params = queryString.parse(query); const searchParams = { gzip: 5, lim: limit, word: setIfExists(params.word), notword: setIfExists(params.notword), title: setIfExists(params.title), ex: setIfExists(params.ex), keyword: setIfExists(params.keyword), wname: setIfExists(params.wname), sasie: setIfExists(params.sasie), iszankoku: setIfExists(params.iszankoku), isbl: setIfExists(params.isbl), isgl: setIfExists(params.isgl), istensei: setIfExists(params.istensei), istenni: setIfExists(params.istenni), stop: setIfExists(params.stop), notzankoku: setIfExists(params.notzankoku), notbl: setIfExists(params.notbl), notgl: setIfExists(params.notgl), nottensei: setIfExists(params.nottensei), nottenni: setIfExists(params.nottenni), minlen: setIfExists(params.minlen), maxlen: setIfExists(params.maxlen), type: setIfExists(params.type), order: setIfExists(params.order), genre: setIfExists(params.genre), nocgenre: setIfExists(params.nocgenre) }; if (params.mintime || params.maxtime) searchParams.time = `${params.mintime || ""}-${params.maxtime || ""}`; return searchParams; } const isGeneral = (sub) => sub === "yomou"; function createNovelSearchBuilder(sub, searchParams) { if (isGeneral(sub)) return new SearchBuilder(searchParams, new NarouNovelFetch()); const r18Params = { ...searchParams }; switch (sub) { case "noc": r18Params.nocgenre = R18Site.Nocturne; break; case "mnlt": if (!r18Params.nocgenre) r18Params.nocgenre = [R18Site.MoonLight, R18Site.MoonLightBL].join("-"); break; case "mid": r18Params.nocgenre = R18Site.Midnight; break; default: throw new InvalidParameterError("Invalid Syosetu subsite.\nValid subsites are: yomou, noc, mnlt, mid"); } return new SearchBuilderR18(r18Params, new NarouNovelFetch()); } async function handler(ctx) { const { sub, query } = ctx.req.param(); const searchUrl = `https://${sub}.syosetu.com/search/search/search.php?${query}`; const searchParams = mapToSearchParams(query, Math.min(Number(ctx.req.query("limit") ?? 40), 40)); const items = (await createNovelSearchBuilder(sub, searchParams).execute()).values.map((novel) => ({ title: novel.title, link: `https://${isGeneral(sub) ? "ncode" : "novel18"}.syosetu.com/${String(novel.ncode).toLowerCase()}`, description: renderDescription({ novel, genreText: GenreNotation[novel.genre] }), author: novel.writer, category: novel.keyword.split(/[\s/\u{FF0F}]/u).filter(Boolean) })); const searchTerms = []; if (searchParams.word) searchTerms.push(searchParams.word); if (searchParams.notword) searchTerms.push(`-${searchParams.notword}`); return { title: searchTerms.length > 0 ? `Syosetu Search: ${searchTerms.join(" ")}` : "Syosetu Search", link: searchUrl, item: items }; } //#endregion export { route };