Add darktable ghost publish plugin

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2024-12-22 21:39:55 +02:00
parent 98ce774210
commit f44dac4158
17 changed files with 2624 additions and 19 deletions

View File

@@ -0,0 +1,110 @@
import { sign } from "jsonwebtoken";
import { file } from "bun";
const getAdminApiKey = async () => {
const keyPath = process.env.GHOST_ADMIN_API_KEY_PATH;
if (!keyPath) {
throw new Error(
"Environment variable GHOST_ADMIN_API_KEY_PATH is not set.",
);
}
const keyFile = file(keyPath);
if (!(await keyFile.exists())) {
throw new Error(`Key file not found at path: ${keyPath}`);
}
return await keyFile.text();
};
const getEndpoint = () => {
const endpoint = process.env.GHOST_URL;
if (!endpoint) {
throw new Error("Environment variable GHOST_URL is not set.");
}
return endpoint;
};
const createJwt = (key: string) => {
const [id, secret] = key.split(":");
if (!id || !secret) {
throw new Error("Invalid API key format. Expected format: {id}:{secret}");
}
return sign({}, Buffer.from(secret, "hex"), {
keyid: id,
algorithm: "HS256",
expiresIn: "5m",
audience: `/admin/`,
});
};
const upload = async (
slug: string,
path: string,
type: string | undefined,
): Promise<any> => {
const endpoint = getEndpoint();
const fullEndpoint = `${endpoint}${slug}`;
const key = await getAdminApiKey();
const token = createJwt(key);
const f = Bun.file(path, { type });
const formData = new FormData();
formData.append("file", f);
const response = await fetch(fullEndpoint, {
method: "POST",
headers: {
Authorization: `Ghost ${token}`,
},
body: formData,
});
if (!response.ok) {
throw new Error(
`Failed to upload to ${fullEndpoint}: ${response.status} ${response.statusText}`,
);
}
return await response.json();
};
export const uploadImage = async (imagePath: string): Promise<string> => {
const slug = `/ghost/api/admin/images/upload`;
return (await upload(slug, imagePath, "image/jpeg")).images[0].url;
};
export const uploadFile = async (filePath: string): Promise<string> => {
const slug = `/ghost/api/admin/files/upload`;
return (await upload(slug, filePath, undefined)).files[0].url;
};
export const uploadPost = async (post: any): Promise<string> => {
const endpoint = getEndpoint();
const fullEndpoint = `${endpoint}/ghost/api/admin/posts`;
const key = await getAdminApiKey();
const token = createJwt(key);
const response = await fetch(fullEndpoint, {
method: "POST",
headers: {
Authorization: `Ghost ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
posts: [post],
}),
});
if (!response.ok) {
throw new Error(
`Failed to upload to ${fullEndpoint}: ${response.status} ${response.statusText}`,
);
}
return (await response.json()).posts[0].url;
};