* first pass * test * test * priority * Reduce boilerplate further * Update server/utils/PluginManager.ts Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com> * fix: matchesNode error in destroyed editor transaction * fix: Individual imported files do not display source correctly in 'Insights' * chore: Add sleep before Slack notification * docs * fix: Error logged about missing plugin.json * Remove email template glob --------- Co-authored-by: Apoorv Mishra <apoorvmishra101092@gmail.com>
80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
import type { Unfurl } from "@shared/types";
|
|
import { Day } from "@shared/utils/time";
|
|
import { InternalError } from "@server/errors";
|
|
import Logger from "@server/logging/Logger";
|
|
import Redis from "@server/storage/redis";
|
|
import fetch from "@server/utils/fetch";
|
|
import env from "./env";
|
|
|
|
class Iframely {
|
|
private static apiUrl = `${env.IFRAMELY_URL}/api`;
|
|
private static apiKey = env.IFRAMELY_API_KEY;
|
|
private static cacheKeyPrefix = "unfurl";
|
|
private static defaultCacheExpiry = Day;
|
|
|
|
private static cacheKey(url: string) {
|
|
return `${this.cacheKeyPrefix}-${url}`;
|
|
}
|
|
|
|
private static async cache(url: string, response: any) {
|
|
// do not cache error responses
|
|
if (response.error) {
|
|
return;
|
|
}
|
|
try {
|
|
await Redis.defaultClient.set(
|
|
this.cacheKey(url),
|
|
JSON.stringify(response),
|
|
"EX",
|
|
response.cache_age || this.defaultCacheExpiry
|
|
);
|
|
} catch (err) {
|
|
// just log it, can skip caching and directly return response
|
|
Logger.error("Could not cache Iframely response", err);
|
|
}
|
|
}
|
|
|
|
public static async fetch(url: string, type = "oembed") {
|
|
const res = await fetch(
|
|
`${this.apiUrl}/${type}?url=${encodeURIComponent(url)}&api_key=${
|
|
this.apiKey
|
|
}`
|
|
);
|
|
return res.json();
|
|
}
|
|
|
|
private static async cached(url: string) {
|
|
try {
|
|
const val = await Redis.defaultClient.get(this.cacheKey(url));
|
|
if (val) {
|
|
return JSON.parse(val);
|
|
}
|
|
} catch (err) {
|
|
// just log it, response can still be obtained using the fetch call
|
|
Logger.error("Could not fetch cached Iframely response", err);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches the preview data for the given url using Iframely oEmbed API
|
|
*
|
|
* @param url
|
|
* @returns Preview data for the url
|
|
*/
|
|
public static async get(url: string): Promise<Unfurl | false> {
|
|
try {
|
|
const cached = await Iframely.cached(url);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
const res = await Iframely.fetch(url);
|
|
await Iframely.cache(url, res);
|
|
return res;
|
|
} catch (err) {
|
|
throw InternalError(err);
|
|
}
|
|
}
|
|
}
|
|
|
|
export default Iframely;
|