Add social image cache (#223)

* feat: add social image cache

* feat: add cached entry expiration time
This commit is contained in:
DecafDev 2024-07-24 13:14:32 -06:00 committed by GitHub
parent 2c733540ef
commit bfd291e7d6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 73 additions and 4 deletions

BIN
bun.lockb

Binary file not shown.

View file

@ -36,6 +36,7 @@
"typescript": "4.7.4"
},
"dependencies": {
"idb": "^8.0.0",
"js-logger": "^1.6.1",
"lodash": "^4.17.21",
"nanoid": "^5.0.7",

View file

@ -13,7 +13,7 @@
import Icon from "src/svelte/shared/components/icon.svelte";
import { getIconIdForFile } from "../services/file-icon";
import License from "src/svelte/shared/services/license";
import { fetchSocialMediaImage } from "../services/social-media-image";
import { fetchSocialImage } from "../services/social-media-image";
import { PluginEvent } from "src/event/types";
import GridCardContainer from "./grid-card-container.svelte";
import GridCardTitle from "./grid-card-title.svelte";
@ -144,7 +144,7 @@
if (!loadSocialMediaImage) return;
if (imageUrl === null && url !== null) {
imgSrc = await fetchSocialMediaImage(url);
imgSrc = await fetchSocialImage(url);
}
}

View file

@ -1,7 +1,33 @@
import { DBSchema, IDBPDatabase, openDB } from "idb";
import Logger from "js-logger";
import { requestUrl } from "obsidian";
export const fetchSocialMediaImage = async (url: string) => {
const DATABASE_NAME = "vaultexplorer";
const STORE_NAME = "socialMediaImage";
const ENTRY_EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 7; //1 week
interface SocialImageDB extends DBSchema {
socialMediaImage: {
key: string;
value: {
url: string;
socialImageUrl: string;
timestamp: number;
};
};
}
export const clearSocialImageCache = async () => {
Logger.trace({
fileName: "social-media-image.ts",
functionName: "clearSocialMediaImageCache",
message: "called",
});
const db = await openDatabase();
await db.clear(STORE_NAME);
};
export const fetchSocialImage = async (url: string) => {
Logger.trace({
fileName: "social-media-image.ts",
functionName: "fetchSocialMediaImage",
@ -9,6 +35,28 @@ export const fetchSocialMediaImage = async (url: string) => {
});
try {
const entry = await getCachedSocialImageEntry(url);
if (entry !== null) {
Logger.trace(
{
fileName: "social-media-image.ts",
functionName: "fetchSocialMediaImage",
message: "found cached entry",
},
entry
);
if (Date.now() - entry.timestamp < ENTRY_EXPIRATION_TIME) {
const { socialImageUrl } = entry;
Logger.debug({
fileName: "social-media-image.ts",
functionName: "fetchSocialMediaImage",
message:
"timestamp is within expiration time. returning cached image url",
});
return socialImageUrl;
}
}
const response = await requestUrl({
url,
method: "GET",
@ -32,6 +80,7 @@ export const fetchSocialMediaImage = async (url: string) => {
},
{ imageUrl }
);
await putSocialImageUrl(url, imageUrl);
} else {
Logger.warn(
{
@ -51,7 +100,7 @@ export const fetchSocialMediaImage = async (url: string) => {
functionName: "fetchSocialMediaImage",
message: "failed to fetch",
},
{ url, error }
error
);
return null;
}
@ -63,3 +112,22 @@ const getMetaTagContent = (document: Document, property: string) => {
document.querySelector(`meta[name='${property}']`);
return tag ? tag.getAttribute("content") : "";
};
const putSocialImageUrl = async (url: string, socialImageUrl: string) => {
const db = await openDatabase();
db.put(STORE_NAME, { url, socialImageUrl, timestamp: Date.now() });
};
const getCachedSocialImageEntry = async (url: string) => {
const db = await openDatabase();
const cachedEntry = await db.get(STORE_NAME, url);
return cachedEntry ?? null;
};
const openDatabase = (): Promise<IDBPDatabase<SocialImageDB>> => {
return openDB<SocialImageDB>(DATABASE_NAME, 1, {
upgrade(db) {
db.createObjectStore(STORE_NAME, { keyPath: "url" });
},
});
};