← back to Ventura Claw
server/connectors/wikipedia.js
62 lines
// Wikipedia / Wikimedia REST API. No key.
// https://en.wikipedia.org/api/rest_v1/
const BASE = "https://en.wikipedia.org/api/rest_v1";
async function call(path) {
const r = await fetch(`${BASE}${path}`, {
headers: { "User-Agent": "VenturaClaw/1.0 (steve@venturaclaw.com)", Accept: "application/json" },
signal: AbortSignal.timeout(15_000),
});
if (!r.ok) throw new Error(`wikipedia ${r.status}`);
return r.json();
}
module.exports = {
meta: { id: "wikipedia", name: "Wikipedia", category: "data", docsUrl: "https://en.wikipedia.org/api/rest_v1/", auth: "none", realImpl: true },
fields: [],
configured() { return true; },
async health() {
try {
const d = await call("/page/summary/Designer_Wallcoverings");
return { ok: true, label: "live · " + (d.title || "english wikipedia") };
} catch (e) {
// Fallback to a guaranteed page
try {
await call("/page/summary/Earth");
return { ok: true, label: "live · english wikipedia" };
} catch (e2) { return { ok: false, reason: e2.message }; }
}
},
actions: {
async "summary"({ title }) {
if (!title) throw new Error("title required");
const d = await call(`/page/summary/${encodeURIComponent(title.replace(/\s+/g, "_"))}`);
return {
title: d.title, description: d.description, extract: d.extract,
thumbnail: d.thumbnail?.source, url: d.content_urls?.desktop?.page,
wikibase_item: d.wikibase_item, type: d.type, lang: d.lang,
};
},
async "search"({ q, limit }) {
if (!q) throw new Error("q required");
const qs = new URLSearchParams({ q, limit: String(Math.min(limit || 10, 50)) });
const r = await fetch(`https://en.wikipedia.org/w/rest.php/v1/search/page?${qs}`, {
headers: { "User-Agent": "VenturaClaw/1.0", Accept: "application/json" },
signal: AbortSignal.timeout(15_000),
});
if (!r.ok) throw new Error(`wikipedia search ${r.status}`);
const d = await r.json();
return {
pages: (d.pages || []).map(p => ({
id: p.id, title: p.title, excerpt: p.excerpt?.replace(/<[^>]+>/g, ""), thumbnail: p.thumbnail?.url,
url: `https://en.wikipedia.org/wiki/${encodeURIComponent(p.key)}`,
})),
};
},
async "onthisday"({ type, month, day }) {
const t = type || "events";
const m = String(month || (new Date().getMonth() + 1)).padStart(2, "0");
const d = String(day || new Date().getDate()).padStart(2, "0");
return await call(`/feed/onthisday/${t}/${m}/${d}`);
},
},
};