UNPKG

wikipedia-summary

Version:

Wikipedia API wrapper — summaries, search, random articles, On This Day events, multi-language support.

178 lines (153 loc) 6.01 kB
const fetch = require("node-fetch"); /** * Fetches a Wikipedia summary for a given topic. * @param {string} topic - The topic to search for. * @param {string} [lang="en"] - The language code (default: "en"). * @returns {Promise<Object>} - Wikipedia summary including title, description, extract, and image. */ async function getSummary(topic, lang = "en") { try { if (!topic || typeof topic !== "string") { throw new Error("A valid topic string is required."); } const url = `https://${lang}.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent(topic)}`; const response = await fetch(url); const data = await response.json(); if (data?.title === "Not found.") { throw new Error("Topic not found on Wikipedia. Please try another search term."); } if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return { title: data.title, description: data.description || "No description available.", extract: data.extract || "No summary available.", pageUrl: data.content_urls?.desktop?.page || `https://${lang}.wikipedia.org/wiki/${encodeURIComponent(topic)}`, imageUrl: data.originalimage?.source || null, thumbnailUrl: data.thumbnail?.source || null, language: lang, type: data.type || "standard", lastModified: data.timestamp || null, }; } catch (error) { throw new Error(`Error fetching Wikipedia summary: ${error.message}`); } } /** * Searches Wikipedia for matching articles. * @param {string} query - Search query. * @param {string} [lang="en"] - Language code. * @param {number} [limit=10] - Max results (1-50). * @returns {Promise<Object[]>} - Array of search results with title, description, and URL. */ async function search(query, lang = "en", limit = 10) { try { if (!query || typeof query !== "string") { throw new Error("A valid search query is required."); } limit = Math.min(Math.max(limit, 1), 50); const url = `https://${lang}.wikipedia.org/w/api.php?action=query&list=search&srsearch=${encodeURIComponent(query)}&srlimit=${limit}&format=json&origin=*`; const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const data = await response.json(); if (!data.query?.search) return []; return data.query.search.map((item) => ({ title: item.title, snippet: item.snippet.replace(/<[^>]+>/g, ""), // Strip HTML wordCount: item.wordcount, pageUrl: `https://${lang}.wikipedia.org/wiki/${encodeURIComponent(item.title)}`, })); } catch (error) { throw new Error(`Wikipedia search failed: ${error.message}`); } } /** * Gets a random Wikipedia article summary. * @param {string} [lang="en"] - Language code. * @returns {Promise<Object>} - Random article summary. */ async function getRandomArticle(lang = "en") { try { const url = `https://${lang}.wikipedia.org/api/rest_v1/page/random/summary`; const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const data = await response.json(); return { title: data.title, description: data.description || "No description available.", extract: data.extract || "No summary available.", pageUrl: data.content_urls?.desktop?.page || null, imageUrl: data.originalimage?.source || null, thumbnailUrl: data.thumbnail?.source || null, language: lang, }; } catch (error) { throw new Error(`Random article fetch failed: ${error.message}`); } } /** * Gets "On this day" events from Wikipedia. * @param {string} [lang="en"] - Language code. * @param {string} [type="all"] - Type: "all", "selected", "births", "deaths", "events", "holidays". * @returns {Promise<Object[]>} - Array of on-this-day entries. */ async function getOnThisDay(lang = "en", type = "all") { try { const now = new Date(); const month = String(now.getMonth() + 1).padStart(2, "0"); const day = String(now.getDate()).padStart(2, "0"); const url = `https://${lang}.wikipedia.org/api/rest_v1/feed/onthisday/${type}/${month}/${day}`; const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const data = await response.json(); // Combine all event types const events = []; for (const key of Object.keys(data)) { if (Array.isArray(data[key])) { data[key].forEach((item) => { events.push({ type: key, text: item.text, year: item.year || null, pages: item.pages?.map((p) => ({ title: p.title, description: p.description || null, pageUrl: p.content_urls?.desktop?.page || null, })) || [], }); }); } } return events; } catch (error) { throw new Error(`On This Day fetch failed: ${error.message}`); } } /** * Gets multiple summaries at once. * @param {string[]} topics - Array of topics. * @param {string} [lang="en"] - Language code. * @returns {Promise<Object[]>} - Array of summaries. */ async function getMultipleSummaries(topics, lang = "en") { if (!Array.isArray(topics) || topics.length === 0) { throw new Error("Please provide an array of topics."); } const results = await Promise.allSettled( topics.map((topic) => getSummary(topic, lang)) ); return results.map((result, index) => { if (result.status === "fulfilled") { return result.value; } return { title: topics[index], error: result.reason.message }; }); } module.exports = { getSummary, search, getRandomArticle, getOnThisDay, getMultipleSummaries };