Add darktable ghost publish plugin
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
110
hosts/common/configs/user/gui/darktable/publish/src/api.ts
Normal file
110
hosts/common/configs/user/gui/darktable/publish/src/api.ts
Normal 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;
|
||||
};
|
||||
Reference in New Issue
Block a user