UNPKG

rsshub

Version:
281 lines (279 loc) 8.54 kB
import "./esm-shims-CzJ_djXG.mjs"; import "./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"; //#region lib/routes/netflix/newsroom.ts const route = { path: "/newsroom/:category?/:region?", categories: ["new-media"], example: "/netflix/newsroom", parameters: { category: { description: "Category", default: "all", options: [ { value: "all", label: "All News" }, { value: "business", label: "Business" }, { value: "entertainment", label: "Entertainment" }, { value: "product", label: "Product" }, { value: "impact", label: "Social Impact" } ] }, region: { description: "Region, can be found in the region URL", default: "en", options: [ { value: "ar", label: "اللغة العربية" }, { value: "de", label: "Deutsch" }, { value: "el", label: "Ελληνικά" }, { value: "en", label: "English" }, { value: "es", label: "Español (LatAm)" }, { value: "es-es", label: "Español (España)" }, { value: "fr", label: "Français" }, { value: "id", label: "Bahasa Indonesia" }, { value: "it", label: "Italiano" }, { value: "ja", label: "日本語" }, { value: "ko", label: "한국어" }, { value: "pl", label: "Polski" }, { value: "pt-br", label: "Português (Brasil)" }, { value: "pt-pt", label: "Português (Portugal)" }, { value: "ro", label: "Română" }, { value: "ru", label: "русский" }, { value: "th", label: "ไทย" }, { value: "tr", label: "Türkçe" }, { value: "vi", label: "Tiếng Việt" }, { value: "zh-hans", label: "简体中文" }, { value: "zh-hant", label: "繁體中文" } ] } }, radar: [{ source: ["about.netflix.com/:region/newsroom", "netflix.com"] }], name: "Newsroom", maintainers: ["nczitzk"], handler, url: "about.netflix.com/" }; const categories = { all: { title: "All News", id: "0" }, business: { title: "Business", id: "1GnkLu7bxeOTxTRNCeu5qm" }, entertainment: { title: "Entertainment", id: "3SGbaxYYG5U05Z0G4piPV7" }, product: { title: "Product", id: "5TzuQELMABTu9jOPjXXlFU" }, impact: { title: "Social Impact", id: "2bUcGjE2800LAsk3JDurGA" } }; const renderImage = ({ url, alt, caption }) => `<figure><img src="${url}" alt="${alt || ""}">${caption ? `<figcaption>${caption}</figcaption>` : ""}</figure>`; const renderVideo = ({ url, poster, contentType }) => `<video controls preload="metadata"${poster ? ` poster="${poster}"` : ""}><source src="${url}" type="${contentType}"></video>`; const renderYoutube = (youtubeId) => `<iframe id="ytplayer" type="text/html" width="640" height="360" src="https://www.youtube-nocookie.com/embed/${youtubeId}" frameborder="0" allowfullscreen referrerpolicy="strict-origin-when-cross-origin"></iframe>`; const render = (node) => { if (!node) return ""; switch (node.nodeType) { case "document": return node.content?.map((c) => render(c)).join("") || ""; case "paragraph": return `<p>${node.content?.map((c) => render(c)).join("") || ""}</p>`; case "heading-2": return `<h2>${node.content?.map((c) => render(c)).join("") || ""}</h2>`; case "heading-3": return `<h3>${node.content?.map((c) => render(c)).join("") || ""}</h3>`; case "heading-4": return `<h4>${node.content?.map((c) => render(c)).join("") || ""}</h4>`; case "heading-6": return `<h6>${node.content?.map((c) => render(c)).join("") || ""}</h6>`; case "hr": return "<hr>"; case "text": { let text = node.value || ""; if (!node.marks || node.marks.length === 0) return text; for (const mark of node.marks) switch (mark.type) { case "bold": text = `<strong>${text}</strong>`; break; case "italic": text = `<em>${text}</em>`; break; case "underline": text = `<u>${text}</u>`; break; case "strikethrough": text = `<s>${text}</s>`; break; default: throw new Error(`Unhandled mark type: ${mark.type}`); } return text; } case "hyperlink": return `<a href="${node.data?.uri || "#"}" target="_blank" rel="noopener noreferrer">${node.content?.map((c) => render(c)).join("") || ""}</a>`; case "embedded-asset-block": { const file = Object.values(node.data?.file)[0]; if (!file || !file.url) return ""; const url = file.url.startsWith("//") ? "https:" + file.url : file.url; const contentType = file.contentType || ""; const title = Object.values(node.data?.title)[0] || ""; if (contentType.startsWith("image/")) return `<img src="${url}" alt="${title}">`; else if (contentType.startsWith("video/")) return renderVideo({ url, contentType }); return ""; } case "embedded-entry-block": { let innerHTML = ""; if (node.data.display === "carousel") for (const img of node.data.images) { const file = Object.values(img.file)[0]; const url = file.url.startsWith("//") ? "https:" + file.url : file.url; innerHTML += renderImage({ url, alt: Object.values(img.title)[0], caption: img.description ? Object.values(img.description)[0] : "" }); } return innerHTML; } case "embedded-entry-inline": { const embedLink = node.data.embedLink; if (embedLink.startsWith("https://www.youtube.com/") || embedLink.startsWith("https://youtu.be/")) return renderYoutube(node.data.embedLink.split("youtube.com/watch?v=")[1]?.split("&")[0] || node.data.embedLink.split("youtu.be/")[1]?.split("?")[0]); return `<a href="${embedLink}" target="_blank" rel="noopener noreferrer">${node.data.title ?? embedLink}</a>`; } case "list-item": return `<li>${node.content?.map((c) => render(c)).join("") || ""}</li>`; case "unordered-list": return `<ul>${node.content?.map((c) => render(c)).join("") || ""}</ul>`; case "ordered-list": return `<ol>${node.content?.map((c) => render(c)).join("") || ""}</ol>`; default: throw new Error(`Unhandled node type: ${node.nodeType}`); } }; async function handler(ctx) { const { category = "all", region = "en" } = ctx.req.param(); const baseUrl = "https://about.netflix.com"; const response = await ofetch_default(`${baseUrl}/api/data/articles`, { query: { language: region, category: categories[category].id } }); const list = [...response.entities.region.regionArticles, ...response.entities.global.globalArticles].map((i) => ({ title: i.title, link: `${baseUrl}/${region}/news/${i.slug}`, pubDate: parseDate(i.rawPublishedDate), category: [...new Set([...i.categories.map((category$1) => category$1.label), ...i.locations.map((location) => location.label)])], image: i.heroImage?.url ? `https:${i.heroImage.url.replace("?w=2560", "")}` : null, slug: i.slug })); const items = await Promise.all(list.map((item) => cache_default.tryGet(item.link, async () => { const slug = (await ofetch_default("https://about.netflix.com/api/data/entity", { query: { language: region, entity: "slug", slug: item.slug } })).entity.slug; item.description = ""; if (slug.heroVideoUrl && !slug.heroVideoUrl.startsWith("https://www.youtube.com/")) item.description += renderVideo({ url: slug.heroVideoUrl, poster: slug.heroImage?.url ? `https:${slug.heroImage.url.replace("?w=2560", "")}` : "", contentType: "video/mp4" }); else if (slug.youtubeHero) item.description += renderYoutube(slug.youtubeHero.videoLink.split("youtube.com/watch?v=")[1]); else if (slug.heroGallery?.length) for (const image of slug.heroGallery) item.description += renderImage({ url: `https:${image.url}`, alt: image.alt, caption: image.description || image.alt }); else item.description += renderImage({ url: `https:${slug.heroImage.url.replace("?w=2560", "")}`, alt: slug.heroImage.alt, caption: slug.heroImage.description || slug.heroImage.alt }); item.description += render(slug.body); return item; }))); return { title: `${categories[category].title} - Newsroom - Netflix`, link: `${baseUrl}/${region}/newsroom`, image: `${baseUrl}/favicon.ico`, item: items }; } //#endregion export { route };