rsshub
Version:
Make RSS Great Again!
257 lines (253 loc) • 8.16 kB
JavaScript
import "./esm-shims-CzJ_djXG.mjs";
import "./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 "./helpers-DxBp0Pty.mjs";
import { t as got_default } from "./got-KxxWdaxq.mjs";
import bbobHTML from "@bbob/html";
import presetHTML5 from "@bbob/preset-html5";
import { getUniqAttr } from "@bbob/plugin-helper";
//#region lib/routes/steam/news.ts
const route = {
path: "/news/:appid/:language?",
name: "News",
url: "steamcommunity.com",
maintainers: ["keocheung"],
handler,
example: "/news/958260/english",
parameters: {
appid: "Game App ID, all digits, can be found in the URL",
language: "Language, english by default, see below for more languages"
},
description: `
<details>
<summary>More languages</summary>
| 语言代码 | 语言名称 |
| ------------------------------------------------- | ---------- |
| English | english |
| Español - España (Spanish - Spain) | spanish |
| Français (French) | french |
| Italiano (Italian) | italian |
| Deutsch (German) | german |
| Ελληνικά (Greek) | greek |
| 한국어 (Korean) | koreana |
| 简体中文 (Simplified Chinese) | schinese |
| 繁體中文 (Traditional Chinese) | tchinese |
| Русский (Russian) | russian |
| ไทย (Thai) | thai |
| 日本語 (Japanese) | japanese |
| Português (Portuguese) | portuguese |
| Português - Brasil (Portuguese - Brazil) | brazilian |
| Polski (Polish) | polish |
| Dansk (Danish) | danish |
| Nederlands (Dutch) | dutch |
| Suomi (Finnish) | finnish |
| Norsk (Norwegian) | norwegian |
| Svenska (Swedish) | swedish |
| Čeština (Czech) | czech |
| Magyar (Hungarian) | hungarian |
| Română (Romanian) | romanian |
| Български (Bulgarian) | bulgarian |
| Türkçe (Turkish) | turkish |
| Українська (Ukrainian) | ukrainian |
| Tiếng Việt (Vietnamese) | vietnamese |
| Español - Latinoamérica (Spanish - Latin America) | latam |
</details>
`,
categories: ["game"],
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportRadar: true,
supportBT: false,
supportPodcast: false,
supportScihub: false
},
radar: [{
title: "News",
source: [
"steamcommunity.com/app/:appid",
"steamcommunity.com/app/:appid/allnews",
"steamcommunity.com/app/:appid/announcements",
"steamcommunity.com/app/:appid/news"
],
target: "/news/:appid"
}]
};
const langMap = {
english: "en",
german: "de",
french: "fr",
italian: "it",
korean: "ko",
spanish: "es",
schinese: "zh-Hans",
tchinese: "zh-Hant",
japanese: "ja",
portuguese: "pt-PT",
brazilian: "pt-BR",
russian: "ru",
polish: "pl",
danish: "da",
dutch: "nl",
finnish: "fi",
norwegian: "no",
swedish: "sv",
czech: "cs",
hungarian: "hu",
turkish: "tr",
thai: "th",
ukrainian: "uk",
vietnamese: "vi",
romanian: "ro",
greek: "el",
arabic: "ar",
latam: "es-419",
bulgarian: "bg"
};
async function handler(ctx) {
const { appid = "958260", language = "english" } = ctx.req.param();
const limitQuery = ctx.req.query("limit");
const limit = limitQuery ? Number.parseInt(limitQuery, 10) : 100;
const rootUrl = "https://steamcommunity.com";
const apiRootUrl = "https://store.steampowered.com";
const clanRootUrl = "https://clan.fastly.steamstatic.com";
const sharedRootUrl = "https://shared.fastly.steamstatic.com";
const apiUrl = new URL("events/ajaxgetpartnereventspageable/", apiRootUrl).href;
const { data: response } = await got_default(apiUrl, { searchParams: {
clan_accountid: 0,
appid,
offset: 0,
count: limit,
l: language
} });
const items = response.events.slice(0, limit).map((item) => {
const title = item.event_name;
const description = `<div lang="${langMap[language] || ""}">${bbobHTML(item.announcement_body.body.replaceAll("{STEAM_CLAN_IMAGE}", `${clanRootUrl}/images`).replaceAll("[olist]", "[list=1]").replaceAll("[/olist]", "[/list]").replaceAll(/(\[\/h\d\])\n/g, "$1").replaceAll(/(\[list(?:=.*?)?\])\n/g, "$1"), [
customPreset(),
linebreakRenderer,
plainUrlRenderer
])}</div>`;
const jsondata = JSON.parse(item.jsondata);
const titleImage = jsondata.localized_title_image?.[0];
const capsuleImage = jsondata.localized_capsule_image?.[0];
return {
title,
description,
pubDate: parseDate(item.announcement_body.posttime, "X"),
link: new URL(`games/${appid}/announcements/detail/${item.announcement_body.gid}`, rootUrl).href,
category: item.announcement_body.tags,
content: {
html: description,
text: item.announcement_body.body
},
updated: parseDate(item.announcement_body.updatetime, "X"),
image: capsuleImage ? new URL(`images/${item.announcement_body.clanid}/${capsuleImage}`, clanRootUrl).href : void 0,
banner: titleImage ? new URL(`images/${item.announcement_body.clanid}/${titleImage}`, clanRootUrl).href : void 0
};
});
return {
title: `App ${appid} News`,
link: new URL(`app/${appid}/allnews/`, rootUrl).href,
image: new URL(`store_item_assets/steam/apps/${appid}/hero_capsule.jpg`, sharedRootUrl).href,
item: items,
language: langMap[language] || null
};
}
const linebreakRenderer = (tree) => tree.walk((node) => {
if (typeof node === "string" && node === "\n") return {
tag: "br",
content: null
};
return node;
});
const plainUrlRenderer = (tree) => tree.walk((node) => {
if (typeof node === "string" && /https?:\/\/[^\s]+/.test(node)) {
let lastIndex = 0;
let match;
const content = [];
const urlRe = /https?:\/\/[^\s]+/g;
while ((match = urlRe.exec(node)) !== null) {
if (match.index > lastIndex) content.push(node.slice(lastIndex, match.index));
content.push({
tag: "a",
attrs: {
href: match[0],
rel: "noopener",
target: "_blank"
},
content: match[0]
});
lastIndex = match.index + match[0].length;
}
if (lastIndex < node.length) content.push(node.slice(lastIndex));
if (content.length === 0) return node;
if (content.length === 1) return content[0];
return {
tag: "span",
content
};
}
return node;
});
const customPreset = presetHTML5.extend((tags) => ({
...tags,
b: (node) => ({
tag: "b",
content: node.content
}),
i: (node) => ({
tag: "i",
content: node.content
}),
u: (node) => ({
tag: "u",
content: node.content
}),
s: (node) => ({
tag: "s",
content: node.content
}),
url: (node) => ({
tag: "a",
attrs: {
href: Object.keys(node.attrs)[0],
rel: "noopener",
target: "_blank"
},
content: node.content
}),
previewyoutube: (node) => ({
tag: "iframe",
attrs: {
src: `https://www.youtube-nocookie.com/embed/${getUniqAttr(node.attrs).match(/[A-Za-z0-9_-]+/)?.[0]}`,
title: "YouTube video player",
frameborder: "0",
allowFullScreen: "1",
refererpolicy: "strict-origin-when-cross-origin"
}
}),
video: (node, { render }) => ({
tag: "video",
attrs: {
controls: "",
preload: "metadata",
poster: node.attrs?.poster
},
content: render(Object.entries({
webm: "video/webm",
mp4: "video/mp4"
}).map(([key, type]) => ({
tag: "source",
attrs: {
src: node.attrs?.[key],
type
}
})))
})
}));
//#endregion
export { route };