-
-
Save chrisburnell/4e29dcf84431808b6c915d87a3b5790e to your computer and use it in GitHub Desktop.
Eleventy Webmentions Data File (webmentions.js)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require("fs") | |
const fetch = require("node-fetch") | |
const { DateTime } = require("luxon") | |
const uniqBy = require("lodash/uniqBy") | |
const domain = "example.com" | |
// You could do this better, though, like so: | |
// const domain = require("./site.json").url.replace("https://", "") | |
// Load .env variables with dotenv | |
require("dotenv").config() | |
// Define Cache Location and API Endpoint | |
const CACHE_DIR = ".cache" | |
const API_ORIGIN = "https://webmention.io/api/mentions.jf2" | |
// Make sure you've got your token set in an .env file | |
const TOKEN = process.env.WEBMENTION_IO_TOKEN | |
const getBaseUrl = (url) => { | |
let hashSplit = url.split("#"); | |
let queryparamSplit = hashSplit[0].split("?"); | |
return queryparamSplit[0].replace(/\/?$/, "/"); | |
}; | |
async function fetchWebmentions(since, perPage = 9001) { | |
// If we dont have a token, abort | |
if (!TOKEN) { | |
console.warn("Unable to fetch WebMentions: no access token specified in environment!") | |
return false | |
} | |
// If we dont have a domain, abort | |
if (!domain) { | |
console.warn("Unable to fetch WebMentions: no url specified in site metadata!") | |
return false | |
} | |
// TODO move to use since_id instead of since date | |
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} WebMentions fetched from ${API_ORIGIN}`) | |
return feed | |
} | |
return null | |
} | |
function webmentionsEnabled() { | |
return process.env.ELEVENTY_FEATURES && process.env.ELEVENTY_FEATURES.split(",").indexOf("webmentions") > -1 | |
} | |
// 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 | |
async function readFromCache() { | |
const filePath = `${CACHE_DIR}/webmentions.json` | |
let cacheExists = await fs.existsSync(filePath) | |
if (cacheExists) { | |
const cacheFile = await fs.readFileSync(filePath) | |
return JSON.parse(cacheFile) | |
} | |
return { | |
lastFetched: null, | |
mentions: {} | |
} | |
} | |
module.exports = async function() { | |
const cache = await readFromCache() | |
const { lastFetched, mentions } = cache | |
const now = new Date() | |
if ((webmentionsEnabled() && now - lastFetched > 3600) || !lastFetched) { | |
const feed = await fetchWebmentions(lastFetched) | |
if (feed) { | |
for (let webmention of feed.children) { | |
let url = getBaseUrl(webmention["wm-target"]) | |
if (!mentions[url]) { | |
mentions[url] = [] | |
} | |
mentions[url].push(webmention) | |
} | |
let totalCount = 0 | |
for (let url in mentions) { | |
mentions[url] = uniqBy(mentions[url], function(entry) { | |
return entry["wm-id"] | |
}) | |
totalCount += mentions[url].length | |
mentions[url].sort((a, b) => { | |
return DateTime.fromISO(a.published || a["wm-received"], { zone: "utc" }).toJSDate().getTime() - DateTime.fromISO(b.published || b["wm-received"], { zone: "utc" }).toJSDate().getTime() | |
}) | |
} | |
const webmentions = { | |
lastFetched: new Date(), | |
count: totalCount, | |
mentions: mentions | |
} | |
writeToCache(webmentions) | |
console.log(`Wrote ${webmentions.count} webmentions to cache.`) | |
return webmentions | |
} | |
} | |
// console.log(`Loaded ${cache.count} WebMentions from cache.`) | |
return cache | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment