1
0

Ghost plugin update

This commit is contained in:
Zef Hemel 2022-04-09 18:25:42 +02:00
parent 6c943bacd0
commit ebfe62dd49
2 changed files with 74 additions and 65 deletions

View File

@ -6,10 +6,10 @@ functions:
downloadAllPosts: downloadAllPosts:
path: "./ghost.ts:downloadAllPosts" path: "./ghost.ts:downloadAllPosts"
env: server env: server
publishPostCommand: publishCommand:
path: "./ghost.ts:publishPostCommand" path: "./ghost.ts:publishCommand"
command: command:
name: "Ghost: Publish Post" name: "Ghost: Publish"
publishPost: publish:
path: "./ghost.ts:publishPost" path: "./ghost.ts:publish"
env: server env: server

View File

@ -5,6 +5,13 @@ import { invokeFunction } from "plugos-silverbullet-syscall/system";
import { getCurrentPage, getText } from "plugos-silverbullet-syscall/editor"; import { getCurrentPage, getText } from "plugos-silverbullet-syscall/editor";
import { cleanMarkdown } from "../markdown/markdown"; import { cleanMarkdown } from "../markdown/markdown";
type GhostConfig = {
url: string;
adminKey: string;
postPrefix: string;
pagePrefix: string;
};
type Post = { type Post = {
id: string; id: string;
uuid: string; uuid: string;
@ -100,23 +107,17 @@ class GhostAdmin {
return markdownPosts; return markdownPosts;
} }
async createPost(post: Partial<Post>): Promise<Post> { publishPost(post: Partial<Post>): Promise<any> {
let result = await json(`${this.url}/ghost/api/v3/admin/posts`, { return this.publish("posts", post);
method: "POST",
headers: {
Authorization: `Ghost ${this.token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
posts: [post],
}),
});
return result.posts[0];
} }
async updatePost(post: Partial<Post>): Promise<any> { publishPage(post: Partial<Post>): Promise<any> {
let oldPost = await json( return this.publish("pages", post);
`${this.url}/ghost/api/v3/admin/posts/${post.id}`, }
async publish(what: "pages" | "posts", post: Partial<Post>): Promise<any> {
let oldPostQuery = await json(
`${this.url}/ghost/api/v3/admin/${what}/slug/${post.slug}`,
{ {
headers: { headers: {
Authorization: `Ghost ${this.token}`, Authorization: `Ghost ${this.token}`,
@ -124,56 +125,60 @@ class GhostAdmin {
}, },
} }
); );
post.updated_at = oldPost.posts[0].updated_at; if (!oldPostQuery[what]) {
let result = await json(`${this.url}/ghost/api/v3/admin/posts/${post.id}`, { // New!
if (!post.status) {
post.status = "draft";
}
let result = await json(`${this.url}/ghost/api/v3/admin/${what}`, {
method: "POST",
headers: {
Authorization: `Ghost ${this.token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
[what]: [post],
}),
});
return result[what][0];
} else {
let oldPost: Post = oldPostQuery[what][0];
post.updated_at = oldPost.updated_at;
let result = await json(
`${this.url}/ghost/api/v3/admin/${what}/${oldPost.id}`,
{
method: "PUT", method: "PUT",
headers: { headers: {
Authorization: `Ghost ${this.token}`, Authorization: `Ghost ${this.token}`,
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
body: JSON.stringify({ body: JSON.stringify({
posts: [post], [what]: [post],
}), }),
}); }
return result.posts[0]; );
return result[what][0];
}
} }
} }
type GhostConfig = {
url: string;
adminKey: string;
pagePrefix: string;
};
function postToMarkdown(post: Post): string { function postToMarkdown(post: Post): string {
let text = mobileDocToMarkdown(post.mobiledoc); let text = mobileDocToMarkdown(post.mobiledoc);
return `<!-- #ghost-id: ${post.id} -->\n# ${post.title}\n${text}`; return `# ${post.title}\n${text}`;
} }
const publishedPostRegex = const postRegex = /#\s*([^\n]+)\n([^$]+)$/;
/<!-- #ghost-id:\s*(\w+)\s*-->\n#\s*([^\n]+)\n([^$]+)$/;
const newPostRegex = /#\s*([^\n]+)\n([^$]+)$/;
async function markdownToPost(text: string): Promise<Partial<Post>> { async function markdownToPost(text: string): Promise<Partial<Post>> {
let match = publishedPostRegex.exec(text); let match = postRegex.exec(text);
if (match) {
let [, id, title, content] = match;
return {
id,
title,
mobiledoc: markdownToMobileDoc(await cleanMarkdown(content)),
};
}
match = newPostRegex.exec(text);
if (match) { if (match) {
let [, title, content] = match; let [, title, content] = match;
return { return {
title, title,
status: "draft",
mobiledoc: markdownToMobileDoc(await cleanMarkdown(content)), mobiledoc: markdownToMobileDoc(await cleanMarkdown(content)),
}; };
} }
throw Error("Not a valid ghost post"); throw Error("Post should stat with a # header");
} }
async function getConfig(): Promise<GhostConfig> { async function getConfig(): Promise<GhostConfig> {
@ -184,6 +189,7 @@ async function getConfig(): Promise<GhostConfig> {
export async function downloadAllPostsCommand() { export async function downloadAllPostsCommand() {
await invokeFunction("server", "downloadAllPosts"); await invokeFunction("server", "downloadAllPosts");
} }
export async function downloadAllPosts() { export async function downloadAllPosts() {
let config = await getConfig(); let config = await getConfig();
let admin = new GhostAdmin(config.url, config.adminKey); let admin = new GhostAdmin(config.url, config.adminKey);
@ -191,30 +197,33 @@ export async function downloadAllPosts() {
let allPosts = await admin.listMarkdownPosts(); let allPosts = await admin.listMarkdownPosts();
for (let post of allPosts) { for (let post of allPosts) {
let text = mobileDocToMarkdown(post.mobiledoc); let text = mobileDocToMarkdown(post.mobiledoc);
text = `<!-- #ghost-id: ${post.id} -->\n# ${post.title}\n${text}`; text = `# ${post.title}\n${text}`;
await writePage(`${config.pagePrefix}${post.slug}`, text); await writePage(`${config.postPrefix}/${post.slug}`, text);
} }
} }
export async function publishPostCommand() { export async function publishCommand() {
await invokeFunction( await invokeFunction(
"server", "server",
"publishPost", "publish",
await getCurrentPage(), await getCurrentPage(),
await getText() await getText()
); );
} }
export async function publishPost(name: string, text: string) { export async function publish(name: string, text: string) {
let config = await getConfig(); let config = await getConfig();
let admin = new GhostAdmin(config.url, config.adminKey); let admin = new GhostAdmin(config.url, config.adminKey);
await admin.init(); await admin.init();
let post = await markdownToPost(text); let post = await markdownToPost(text);
post.slug = name.substring(config.pagePrefix.length); if (name.startsWith(config.postPrefix)) {
if (post.id) { post.slug = name.substring(config.postPrefix.length + 1);
await admin.updatePost(post); await admin.publishPost(post);
console.log("Done!");
} else if (name.startsWith(config.pagePrefix)) {
post.slug = name.substring(config.pagePrefix.length + 1);
await admin.publishPage(post);
console.log("Done!");
} else { } else {
let newPost = await admin.createPost(post); console.error("Not in either the post or page prefix");
text = `<!-- #ghost-id: ${newPost.id} -->\n${text}`;
await writePage(name, text);
} }
} }