rsshub
Version:
Make RSS Great Again!
160 lines (159 loc) • 7.09 kB
JavaScript
import { t as rofetch } from "./ofetch-C3ts-Hud.mjs";
import "./types-DNj6Etbg.mjs";
import { t as parseDate } from "./parse-date-Cr0wQjV_.mjs";
import { jsx, jsxs } from "hono/jsx/jsx-runtime";
import { load } from "cheerio";
import { renderToString } from "hono/jsx/dom/server";
//#region lib/routes/scoop/apps.tsx
const orderbys = (desc) => {
const base = {
0: "search.score() desc, Metadata/OfficialRepositoryNumber desc, NameSortable asc",
1: "NameSortable asc, Metadata/OfficialRepositoryNumber desc, Metadata/RepositoryStars desc, Metadata/Committed desc",
2: "Metadata/Committed desc, Metadata/OfficialRepositoryNumber desc, Metadata/RepositoryStars desc"
};
if (desc === "1") return base;
const inverted = {};
for (const key in base) inverted[key] = base[key].replaceAll(/\b(desc|asc)\b/gi, (match) => match.toLowerCase() === "desc" ? "asc" : "desc");
return inverted;
};
const filters = {
o: "Metadata/OfficialRepositoryNumber eq 1",
dm: "Metadata/DuplicateOf eq null"
};
const handler = async (ctx) => {
const { query = "s=2&d=1&n=true&dm=true&o=true" } = ctx.req.param();
const limit = Number(ctx.req.query("limit") ?? "50");
const baseUrl = "https://scoop.sh";
const apiBaseUrl = "https://scoopsearch.search.windows.net";
const targetUrl = new URL(`/#/apps?${query}`, baseUrl).href;
const apiUrl = new URL("indexes/apps/docs/search", apiBaseUrl).href;
const targetResponse = await rofetch(targetUrl);
const language = load(targetResponse)("html").attr("lang") ?? "en";
const scriptRegExp = /<script type="module" crossorigin src="(.*?)"><\/script>/;
const scriptUrl = scriptRegExp.test(targetResponse) ? new URL(targetResponse.match(scriptRegExp)?.[1], baseUrl).href : "";
if (!scriptUrl) throw new Error("JavaScript file not found.");
const key = (await rofetch(scriptUrl, { parseResponse: (txt) => txt })).match(/VITE_APP_AZURESEARCH_KEY:"(.*?)"/)?.[1];
if (!key) throw new Error("Key not found.");
const isOffcial = !query.includes("o=false");
const isDistinct = !query.includes("dm=false");
const sort = query.match(/s=(\d+)/)?.[1] ?? "2";
const desc = query.match(/d=(\d+)/)?.[1] ?? "1";
const items = (await rofetch(apiUrl, {
method: "post",
query: { "api-version": "2020-06-30" },
headers: {
"api-key": key,
origin: baseUrl,
referer: baseUrl
},
body: {
count: true,
search: "",
searchMode: "all",
filter: [isOffcial ? filters.o : void 0, isDistinct ? filters.dm : void 0].filter(Boolean).join(" and "),
orderby: orderbys(desc)[sort],
skip: 0,
top: limit,
select: "Id,Name,NamePartial,NameSuffix,Description,Notes,Homepage,License,Version,Metadata/Repository,Metadata/FilePath,Metadata/OfficialRepository,Metadata/RepositoryStars,Metadata/Committed,Metadata/Sha",
highlight: "Name,NamePartial,NameSuffix,Description,Version,License,Metadata/Repository",
highlightPreTag: "<mark>",
highlightPostTag: "</mark>"
}
})).value.slice(0, limit).map((item) => {
const repositoryName = item.Metadata.Repository.split(/\//).slice(-2).join("/");
const title = `${item.Name} ${item.Version} in ${repositoryName}`;
const description = renderToString(/* @__PURE__ */ jsx(ScoopDescription, { item }));
const pubDate = item.Metadata.Committed;
const linkUrl = item.Homepage;
const authors = [{
name: repositoryName,
url: item.Metadata.Repository,
avatar: void 0
}];
const guid = `scoop-${item.Name}-${item.Version}-${item.Metadata.Sha}`;
const updated = pubDate;
return {
title,
description,
pubDate: pubDate ? parseDate(pubDate) : void 0,
link: linkUrl,
author: authors,
guid,
id: guid,
content: {
html: description,
text: description
},
updated: updated ? parseDate(updated) : void 0,
language
};
});
const author = "Scoop";
return {
title: `${author} - Apps`,
description: void 0,
link: targetUrl,
item: items,
allowEmpty: true,
author,
language,
id: targetUrl
};
};
const ScoopDescription = ({ item }) => {
const repositoryName = item.Metadata.Repository.split(/\//).slice(-2).join("/");
return /* @__PURE__ */ jsx("table", { children: /* @__PURE__ */ jsxs("tbody", { children: [
item.Name ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "Name" }), /* @__PURE__ */ jsx("td", { children: item.Name })] }) : null,
item.Repository ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "Repository" }), /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("a", {
href: item.Metadata.Repository,
children: repositoryName
}) })] }) : null,
item.Committed ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "Committed" }), /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("a", {
href: `${item.Metadata.Repository}/commit/${item.Metadata.Sha}`,
children: item.Metadata.Committed
}) })] }) : null,
item.Version ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "Version" }), /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("a", {
href: `${item.Metadata.Repository}/blob/${item.Metadata.FilePath}`,
children: ["v", item.Version]
}) })] }) : null,
item.Description ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "Description" }), /* @__PURE__ */ jsx("td", { children: item.Description })] }) : null,
item.Homepage ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "Homepage" }), /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("a", {
href: item.Homepage,
children: item.Homepage
}) })] }) : null,
item.License ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "License" }), /* @__PURE__ */ jsx("td", { children: item.License })] }) : null,
item.Note ? /* @__PURE__ */ jsxs("tr", { children: [/* @__PURE__ */ jsx("th", { children: "Note" }), /* @__PURE__ */ jsx("td", { children: item.Note })] }) : null
] }) });
};
const route = {
path: "/apps/:query?",
name: "Apps",
url: "scoop.sh",
maintainers: ["nczitzk"],
handler,
example: "/scoop/apps",
parameters: { query: { description: "Query, `s=2&d=1&n=true&dm=true&o=true` by default" } },
description: `::: tip
To subscribe to [Apps](https://scoop.sh/#/apps?s=2\\&d=1\\&n=true\\&dm=true\\&o=true), where the source URL is \`https://scoop.sh/#/apps?s=2&d=1&n=true&dm=true&o=true\`, extract the certain parts from this URL to be used as parameters, resulting in the route as [\`/scoop/apps/s=2&d=1&n=true&dm=true&o=true\`](https://rsshub.app/scoop/apps/s=2\\&d=1\\&n=true\\&dm=true\\&o=true).
:::`,
categories: ["program-update"],
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportRadar: true,
supportBT: false,
supportPodcast: false,
supportScihub: false
},
radar: [{
source: ["scoop.sh/#/apps", "scoop.sh"],
target: (_, url) => {
const query = new URL(url).searchParams.toString() ?? void 0;
return `/scoop/apps${query ? `/${query}` : ""}`;
}
}],
view: 5
};
//#endregion
export { handler, route };