wikipedia-summary
Version:
Wikipedia API wrapper — summaries, search, random articles, On This Day events, multi-language support.
178 lines (153 loc) • 6.01 kB
JavaScript
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 };