omnichron
Version:
Unified interface for web archive providers
71 lines (69 loc) • 2.66 kB
JavaScript
import { createErrorResponse, createSuccessResponse, mergeOptions, normalizeDomain } from "./_utils.mjs";
import { cleanDoubleSlashes } from "ufo";
import { $fetch } from "ofetch";
//#region src/providers/archive-today.ts
/**
* Create an Archive.today archive provider.
*
* @param initOptions - Initial options for Archive.today (e.g., maxRedirects, cache settings).
* @returns ArchiveProvider instance for fetching snapshots from Archive.today.
*/
function archiveToday(initOptions = {}) {
return {
name: "Archive.today",
slug: "archive-today",
async getSnapshots(domain, reqOptions = {}) {
const _options = mergeOptions(initOptions, reqOptions);
const baseURL = "https://archive.is";
const _snapshotUrl = "https://archive.is";
const cleanDomain = normalizeDomain(domain, false);
try {
const fullUrl = cleanDomain.includes("://") ? cleanDomain : `http://${cleanDomain}`;
const timemapUrl = `/timemap/${fullUrl}`;
const timemapResponse = await $fetch(timemapUrl, {
baseURL,
retry: 5,
timeout: 6e4,
responseType: "text"
});
const pages = [];
const mementoRegex = /<(https?:\/\/archive\.(?:is|today|md|ph)\/([0-9]{8,14})\/(?:https?:\/\/)?([^>]+))>;\s*rel="(?:first\s+)?memento";\s*datetime="([^"]+)"/g;
let mementoMatch;
let index = 0;
while ((mementoMatch = mementoRegex.exec(timemapResponse)) !== null) {
const [, snapshotUrl, timestamp, origUrl, datetime] = mementoMatch;
if (origUrl.includes(cleanDomain)) try {
const parsedDate = new Date(datetime);
const isoTimestamp = Number.isNaN(parsedDate.getTime()) ? new Date().toISOString() : parsedDate.toISOString();
let cleanedUrl = cleanDoubleSlashes(origUrl.includes("://") ? origUrl : `https://${origUrl}`);
cleanedUrl = cleanedUrl.endsWith("/") ? cleanedUrl.slice(0, -1) : cleanedUrl;
let cleanedSnapshotUrl = snapshotUrl;
cleanedSnapshotUrl = cleanedSnapshotUrl.endsWith("/") ? cleanedSnapshotUrl.slice(0, -1) : cleanedSnapshotUrl;
pages.push({
url: cleanedUrl,
timestamp: isoTimestamp,
snapshot: cleanedSnapshotUrl,
_meta: {
hash: timestamp,
raw_date: datetime,
position: index
}
});
index++;
} catch (error) {
console.error("Error parsing archive.today snapshot:", error);
}
}
return createSuccessResponse(pages, "archive-today", {
domain: cleanDomain,
page: 1,
empty: pages.length === 0
});
} catch (error) {
return createErrorResponse(error, "archive-today", { domain: cleanDomain });
}
}
};
}
//#endregion
export { archiveToday as default };