rsshub
Version:
Make RSS Great Again!
150 lines (132 loc) • 7.12 kB
JavaScript
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 "./ofetch-BIyrKU3Y.mjs";
import { t as parseDate } from "./parse-date-BrP7mxXf.mjs";
import { t as cache_default } from "./cache-Bo__VnGm.mjs";
import "./helpers-DxBp0Pty.mjs";
import { t as art } from "./render-BQo6B4tL.mjs";
import { t as got_default } from "./got-KxxWdaxq.mjs";
import path from "node:path";
import { load } from "cheerio";
//#region lib/routes/osu/beatmaps/latest-ranked.ts
init_esm_shims();
const descriptionDoc = `
Subscribe to the new beatmaps on https://osu.ppy.sh/beatmapsets.
#### Parameter Description
Parameters allows you to:
- Filter game mode
- Limit beatmap difficulty
- Show/hide game mode in feed title
Below is a table of all allowed parameters passed to \`routeParams\`
| Name | Default | Description |
| ----------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \`includeMode\` | All mode | Could be \`osu\`, \`mania\`, \`fruits\` or \`taiko\`. Specify included game mode of beatmaps. Including this paramseter multiple times to specify multiple game modes, e.g.: \`includeMode=osu&includeMode=mania\`. Subscribe to all game modes if not specified |
| \`difficultyLimit\` | None | Lower/upper limit of star rating of the beatmaps in the beatmapset item, e.g.:\`difficultyLimit=U6\`. Checkout tips in descriptions for detailed explaination and examples. |
| \`modeInTitle\` | \`true\` | \`true\` or \`false\` Add mode info into feed title.
This actual parameters should be passed as \`routeParams\` in URL Query String format without \`?\`, e.g.:
/osu/latest-ranked/modeInTitle=true&includeMode=osu
::: tip
You could make use of \`difficultyLimit\` paramters to create a "high difficulty/low difficulty only" only feed.
For example, if you only wants to play low star rating beatmap like 1 or 2 star, you could subscribe to:
/osu/latest-ranked/difficultyLimit=U2
This will filter out all beatmapsets that do not provide at least one beatmap with star rating<=\`2.00\`.
Similarly, you could use lower bound to filter out beatmapsets which don't have at least one beatmap
with star rating higher than a certain threshold.
/osu/latest-ranked/difficultyLimit=L6
Now all beatmapsets that don't provided at least one beatmap with star rating higher than \`6.00\` will be filtered.
:::`;
const route = {
path: "/latest-ranked/:routeParams?",
categories: ["game"],
example: "/osu/latest-ranked/includeMode=osu&difficultyLimit=L3&difficultyLimit=U7",
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
supportRadar: true
},
parameters: { routeParams: {
description: "Used to pass route parameters in Query String format. Check out route description for more info.",
default: "null"
} },
name: "Latest Ranked Beatmap",
description: descriptionDoc,
maintainers: ["nfnfgo"],
radar: [{ source: ["osu.ppy.sh/beatmapsets"] }],
handler
};
async function handler(ctx) {
const pathParams = ctx.req.param("routeParams");
const searchParams = new URL(`https://osu.ppy.sh?${pathParams}`).searchParams;
const includeModes = searchParams.getAll("includeMode");
const difficultyLimits = searchParams.getAll("difficultyLimit");
const modeInTitle = searchParams.get("modeInTitle") ?? "true";
let beatmapsetList = await cache_default.tryGet("https://osu.ppy.sh/beatmapsets:JSON", async () => {
const $ = load((await got_default.get("https://osu.ppy.sh/beatmapsets")).data);
const beatmapList = JSON.parse($("#json-beatmaps").text() ?? "{\"beatmapsets\": undefined}").beatmapsets;
if (beatmapList === void 0) throw new Error("Failed to retrieve JSON beatmap info from osu! website");
return beatmapList;
}, config.cache.routeExpire, false);
for (const item of beatmapsetList) item.beatmaps.sort((a, b) => a.difficulty_rating - b.difficulty_rating);
if (includeModes?.length && includeModes?.length > 0) beatmapsetList = beatmapsetList.filter((bm) => includeModes.includes(bm.beatmaps[0].mode));
let upperLimit = 99;
let lowerLimit = 0;
if (difficultyLimits && difficultyLimits.length > 0 && difficultyLimits.length < 2) {
for (const dfLimit of difficultyLimits) if (dfLimit.startsWith("U")) upperLimit = Number.parseFloat(dfLimit.slice(1));
else if (dfLimit.startsWith("L")) lowerLimit = Number.parseFloat(dfLimit.slice(1));
const difficultyRateFilterFunc = (item) => {
if (item.beatmaps.at(0).difficulty_rating > upperLimit) return false;
if (item.beatmaps.at(-1).difficulty_rating < lowerLimit) return false;
return true;
};
beatmapsetList = beatmapsetList.filter((item) => difficultyRateFilterFunc(item));
}
function getReadableFeedConfig() {
if (!pathParams) return "";
let readableConf = "Feed Configurations:\n";
readableConf += `Game Mode: ${includeModes.length > 0 ? JSON.stringify(includeModes) : "All modes"}\n`;
readableConf += `Star Rating Limit: Lower=${lowerLimit}, Upper=${upperLimit}`;
return readableConf;
}
const rssItems = beatmapsetList.map((beatmapset) => {
const pubDate = parseDate(beatmapset.ranked_date);
const coverImage = beatmapset.covers["cover@2x"] || beatmapset.covers.cover;
const bannerImage = beatmapset.covers["card@2x"] || beatmapset.covers.card;
const readableTotalLength = `${Math.floor(beatmapset.beatmaps[0].total_length / 60).toString().padStart(2, "0")}:${(beatmapset.beatmaps[0].total_length % 60).toString().padStart(2, "0")}`;
const modeLiteralToDisplayNameMap = {
osu: "Osu!",
fruits: "Osu!Catch",
taiko: "Osu!Taiko",
mania: "Osu!Mania"
};
const description = art(path.join(__dirname, "templates/beatmapset-d6071e15.art"), {
...beatmapset,
readableTotalLength,
modeLiteralToDisplayNameMap
});
return {
title: `${modeInTitle === "true" ? `[${modeLiteralToDisplayNameMap[beatmapset.beatmaps[0].mode]}] ` : ``}${beatmapset.title_unicode ?? beatmapset.title}`,
description,
pubDate,
link: `https://osu.ppy.sh/beatmapsets/${beatmapset.id}`,
category: ["osu!", "game"],
author: [{ name: beatmapset.creator }],
image: coverImage,
banner: bannerImage,
updated: beatmapset.last_updated
};
});
return {
title: "Osu! Latest Ranked Map",
link: "https://osu.ppy.sh/beatmapsets",
description: `Newly ranked beatmaps at https://osu.ppy.sh/beatmapsets.\n${getReadableFeedConfig()}`,
item: rssItems
};
}
//#endregion
export { route };