import fs from "fs"; import fetch from "node-fetch"; import unionBy from "lodash-es/unionBy.js"; import domain from "./metadata.js"; // Load .env variables with dotenv import "dotenv/config.js"; // Configuration Parameters const CACHE_DIR = '_cache'; const API_ORIGIN = 'https://webmention.io/api/mentions.jf2'; const TOKEN = process.env.WEBMENTION_IO_TOKEN; async function fetchWebmentions(since, perPage = 10000) { // If we don't have a domain name or token, abort if (!domain || !TOKEN) { console.warn('>>> unable to fetch webmentions: missing domain or token'); return false; } let url = `${API_ORIGIN}?domain=${domain}&token=${TOKEN}&per-page=${perPage}`; if (since) url += `&since=${since}`; // only fetch new mentions const response = await fetch(url); if (response.ok) { const feed = await response.json(); console.log(`>>> ${feed.children.length} new webmentions fetched from ${API_ORIGIN}`); return feed; } return null; } // Merge fresh webmentions with cached entries, unique per id function mergeWebmentions(a, b) { return unionBy(a.children, b.children, 'wm-id'); } // save combined webmentions in cache file function writeToCache(data) { const filePath = `${CACHE_DIR}/webmentions.json`; const fileContent = JSON.stringify(data, null, 2); // create cache folder if it doesnt exist already if (!fs.existsSync(CACHE_DIR)) { fs.mkdirSync(CACHE_DIR); } // write data to cache json file fs.writeFile(filePath, fileContent, err => { if (err) throw err; console.log(`>>> webmentions cached to ${filePath}`); }); } // get cache contents from json file function readFromCache() { const filePath = `${CACHE_DIR}/webmentions.json`; if (fs.existsSync(filePath)) { const cacheFile = fs.readFileSync(filePath); return JSON.parse(cacheFile); }; // no cache found return { lastFetched: null, children: [] }; } export default async function() { console.log('>>> Reading webmentions from cache...'); const cache = readFromCache(); if (cache.children.length) { console.log(`>>> ${cache.children.length} webmentions loaded from cache`); }; // Only fetch new mentions in production if (process.env.ELEVENTY_ENV === 'production') { console.log('>>> Checking for new webmentions...'); const feed = await fetchWebmentions(cache.lastFetched); if (feed) { const webmentions = { lastFetched: new Date().toISOString(), children: mergeWebmentions(cache, feed) } writeToCache(webmentions); return webmentions; } } return cache; }