UNPKG

rsshub

Version:
277 lines (275 loc) • 8.89 kB
import "./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 cache_default } from "./cache-Bo__VnGm.mjs"; import "./helpers-DxBp0Pty.mjs"; import { t as got_default } from "./got-KxxWdaxq.mjs"; //#region lib/routes/wikipedia/current-events.ts function getCurrentEventsDatePath(date) { return `Portal:Current_events/${date.getFullYear()}_${[ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ][date.getMonth()]}_${date.getDate()}`; } function parseCurrentEventsTemplate(wikitext) { if (!wikitext || typeof wikitext !== "string") return null; const contentMatch = wikitext.match(/\{\{Current events\s*\|[\s\S]*?content\s*=\s*([\s\S]*)\}\}$/); if (!contentMatch) return null; let content = contentMatch[1].trim(); content = stripComments(content); if (/^\s*\*+\s*$/.test(content)) return null; return content; } function stripTemplates(wikitext) { return wikitext.replaceAll(/\{\{([^}]+)\}\}/g, "$1"); } function convertWikiLinks(html) { html = html.replaceAll(/\[\[([^|\]]+)\|([^\]]+)\]\]/g, "<a href=\"https://en.wikipedia.org/wiki/$1\">$2</a>"); html = html.replaceAll(/\[\[([^\]]+)\]\]/g, "<a href=\"https://en.wikipedia.org/wiki/$1\">$1</a>"); return html; } function convertExternalLinks(html) { html = html.replaceAll(/\[([^\s\]]+)\s+([^\]]+)\]/g, "<a href=\"$1\">$2</a>"); html = html.replaceAll(/\[([^\s\]]+)\]/g, "<a href=\"$1\">$1</a>"); return html; } function convertTextFormatting(html) { html = html.replaceAll(/'''([^']+)'''/g, "<strong>$1</strong>"); html = html.replaceAll(/''([^']+)''/g, "<em>$1</em>"); return html; } function createListProcessorState() { return { result: [], depthStack: [], lastDepth: 0 }; } function addIndentedTag(state, tag) { state.result.push(" ".repeat(state.depthStack.length) + tag); } function closeAllListsAndAddParagraph(state) { while (state.depthStack.length > 0) { state.depthStack.pop(); addIndentedTag(state, "</ul>"); if (state.depthStack.length > 0) addIndentedTag(state, "</li>"); } state.lastDepth = 0; } function openNestedLists(state, targetDepth) { for (let d = state.lastDepth; d < targetDepth; d++) { addIndentedTag(state, "<ul>"); state.depthStack.push(d + 1); } } function closeNestedLists(state, targetDepth) { while (state.depthStack.length > 0 && state.depthStack.at(-1) > targetDepth) { addIndentedTag(state, "</li>"); state.depthStack.pop(); addIndentedTag(state, "</ul>"); if (state.depthStack.length > 0 && state.depthStack.at(-1) > targetDepth) {} else if (state.depthStack.length > 0) addIndentedTag(state, "</li>"); } } function closePreviousListItem(state) { if (state.depthStack.length > 0) addIndentedTag(state, "</li>"); } function closeAllOpenLists(state) { if (state.depthStack.length === 0) return; addIndentedTag(state, "</li>"); state.depthStack.pop(); while (state.depthStack.length > 0) { state.result.push(" ".repeat(state.depthStack.length) + "</ul>", " ".repeat(state.depthStack.length) + "</li>"); state.depthStack.pop(); } state.result.push("</ul>"); } function processListsAndLines(html) { const lines = html.split("\n"); const state = createListProcessorState(); for (const line of lines) { const trimmedLine = line.trim(); if (!trimmedLine) { closeAllListsAndAddParagraph(state); continue; } const bulletMatch = trimmedLine.match(/^(\*+)\s*(.*)$/); if (bulletMatch) { const depth = bulletMatch[1].length; const content = bulletMatch[2]; if (!content) continue; if (depth > state.lastDepth) openNestedLists(state, depth); else if (depth < state.lastDepth) closeNestedLists(state, depth); else closePreviousListItem(state); addIndentedTag(state, `<li>${content}`); state.lastDepth = depth; } else { closeAllListsAndAddParagraph(state); state.result.push(trimmedLine); } } closeAllOpenLists(state); return state.result.join("\n"); } function stripComments(html) { return html.replaceAll(/<!--[\s\S]*?-->/g, ""); } function wikiToHtml(wikitext) { let html = wikitext; html = stripTemplates(html); html = convertWikiLinks(html); html = convertExternalLinks(html); html = convertTextFormatting(html); html = processListsAndLines(html); return html; } async function fetchMultipleWikiContent(pageNames) { const url = "https://en.wikipedia.org/w/api.php"; const titles = pageNames.join("|"); const results = {}; let continueParams = {}; let hasMore = true; while (hasMore) { const response = await got_default(url, { searchParams: { action: "query", format: "json", titles, prop: "revisions", rvprop: "content", rvslots: "main", ...continueParams }, headers: { "User-Agent": config.trueUA } }); const data = JSON.parse(response.body); if (data.query && data.query.pages) { for (const page of Object.values(data.query.pages)) if (page.revisions && page.revisions[0] && page.revisions[0].slots && page.revisions[0].slots.main) { const wikitext = page.revisions[0].slots.main["*"]; const content = parseCurrentEventsTemplate(wikitext); if (content) { const html = wikiToHtml(content); const normalizedTitle = page.title.replace(/Portal:Current events\/(\d{4}) (\w+) (\d+)/, "Portal:Current_events/$1_$2_$3"); results[normalizedTitle] = html; } } } if (data.continue) continueParams = data.continue; else hasMore = false; } return results; } const route = { path: "/current-events/:includeToday?", categories: ["new-media"], example: "/wikipedia/current-events", parameters: { includeToday: { description: "Include current day events (may be incomplete early in the day)", default: "auto", options: [ { label: "Auto (include after 18:00 UTC)", value: "auto" }, { label: "Always include current day", value: "always" }, { label: "Never include current day", value: "never" }, { label: "Include after specific UTC hour (0-23)", value: "0-23" } ] } }, features: { requireConfig: false, requirePuppeteer: false, antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false }, radar: [{ source: ["en.wikipedia.org/wiki/Portal:Current_events"], target: "/wikipedia/current-events" }], name: "Current Events", maintainers: ["aavanian"], handler, description: "Wikipedia Portal: Current events - Latest news and events from the past 7 days" }; async function handler(ctx) { const dates = determineDates(ctx.req.param("includeToday") ?? "auto"); const pageNames = dates.map((date) => getCurrentEventsDatePath(date)); const cacheKey = "wikipedia:current-events:batch:" + pageNames.join("|"); try { const contentMap = await cache_default.tryGet(cacheKey, async () => await fetchMultipleWikiContent(pageNames), config.cache.contentExpire); return { title: "Wikipedia: Portal: Current events", link: "https://en.wikipedia.org/wiki/Portal:Current_events", description: "Current events from Wikipedia - Latest news and events", item: dates.map((date) => { const pageName = getCurrentEventsDatePath(date); const html = contentMap[pageName]; if (html) { const year = date.getFullYear(); const dateStr = `${year}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`; const endOfDayGMTMinus12 = Date.UTC(year, date.getMonth(), date.getDate() + 1, 11, 59, 59); return { title: `Current events: ${dateStr}`, link: `https://en.wikipedia.org/wiki/${pageName}`, description: html, pubDate: new Date(Math.min(endOfDayGMTMinus12, Date.now())), guid: `wikipedia-current-events-${dateStr}` }; } return null; }).filter((item) => item !== null) }; } catch (error) { const message = error instanceof Error ? error.message : String(error); throw new Error(`Failed to fetch Wikipedia current events: ${message}`); } } function determineDates(includeToday) { const currentHourUTC = (/* @__PURE__ */ new Date()).getUTCHours(); let shouldIncludeToday = false; switch (includeToday) { case "always": shouldIncludeToday = true; break; case "never": shouldIncludeToday = false; break; case "auto": shouldIncludeToday = currentHourUTC >= 18; break; default: if (/^\d+$/.test(includeToday)) { const targetHour = Number.parseInt(includeToday, 10); if (targetHour >= 0 && targetHour <= 23) shouldIncludeToday = currentHourUTC >= targetHour; } } const startOffset = shouldIncludeToday ? 0 : 1; return Array.from({ length: 7 }, (_, i) => { const date = /* @__PURE__ */ new Date(); date.setDate(date.getDate() - (i + startOffset)); return date; }); } //#endregion export { route, wikiToHtml };