import json import logging import sys import time from pathlib import Path import frontmatter import dateparser logger = logging.getLogger("to_ghost") logging.basicConfig(stream=sys.stderr, level=logging.INFO) def main(): meta = {"exported_on": round(time.time() * 1000), "version": "5.75.0"} posts = [] seen_tags = [] tags = [] posts_tags = [] post_id = 0 for folder in (Path() / "content" / "posts").iterdir(): if not folder.is_dir(): logger.info("%s is not dir, ignoring", folder) continue post_id += 1 index = folder / "index.md" with index.open("r") as f: article = frontmatter.load(f) ghost_post = make_post(article) if not ghost_post.get("slug"): ghost_post["slug"] = folder.name ghost_post["id"] = post_id posts.append(ghost_post) for tag in article.get("tags", []): if tag not in seen_tags: seen_tags.append(tag) tags.append({"id": seen_tags.index(tag), "name": tag}) posts_tags.append({"tag_id": seen_tags.index(tag), "post_id": post_id}) print(json.dumps({"meta": meta, "data": {"posts": posts, "tags": tags, "posts_tags": posts_tags}})) def make_post(article: frontmatter.Post) -> dict: article_date = article["date"].timestamp() * 1000 ghost_post = { "title": article["title"], # Lexical is used to represent your content "lexical": "", "feature_image": None, "feature_image_alt": None, "feature_image_caption": None, "featured": 0, # boolean indicating featured status "page": 0, # boolean indicating if this is a page or post "status": "published", # or draft "published_at": article_date, # epoch time in milliseconds "published_by": 1, # the first user created has an id of 1 "meta_title": None, "meta_description": None, "email_only": False, # boolean indicating email-only type of post "author_id": 1, # the first user created has an id of 1 "created_at": article_date, # epoch time in milliseconds "created_by": 1, # the first user created has an id of 1 "updated_at": article_date, # epoch time in milliseconds "updated_by": 1 # the first user created has an id of 1 } if slug := article.get("canonicalURL"): ghost_post["slug"] = slug return ghost_post def convert_date(article_date: str) -> int: return 0 if __name__ == '__main__': main() d = { "meta": { "exported_on": 1388805572000, # epoch time in milliseconds "version": "2.14.0" }, "data": { "posts": [ { "id": 1, "title": "my blog post title", "slug": "my-blog-post-title", # Optional, will be generated by Ghost if missing # Lexical is used to represent your content "lexical": "{\"root\":{\"children\":[{\"children\":[{\"detail\":0,\"format\":0,\"mode\":\"normal\",\"style\":\"\",\"text\":\"Hello, beautiful world! 👋\",\"type\":\"extended-text\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1}],\"direction\":\"ltr\",\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}", "feature_image": None, "feature_image_alt": None, "feature_image_caption": None, "featured": 0, # boolean indicating featured status "page": 0, # boolean indicating if this is a page or post "status": "published", # or draft "published_at": 1283780649000, # epoch time in milliseconds "published_by": 1, # the first user created has an id of 1 "meta_title": None, "meta_description": None, "email_only": False, # boolean indicating email-only type of post "author_id": 1, # the first user created has an id of 1 "created_at": 1283780649000, # epoch time in milliseconds "created_by": 1, # the first user created has an id of 1 "updated_at": 1286958624000, # epoch time in milliseconds "updated_by": 1 # the first user created has an id of 1 } ], "tags": [ { "id": 5, "name": "Colorado Ho!", "slug": "colorado-ho", # Optional, will be generated by Ghost if missing "description": "" } ], "posts_tags": [ {"tag_id": 5, "post_id": 1}, ], "users": [ { "id": 3, "name": "Jo Bloggs", "slug": "jo-blogs", # Optional, will be generated by Ghost if missing "email": "jo@example.com", "profile_image": None, "cover_image": None, "bio": None, "website": None, "location": None, "accessibility": None, "meta_title": None, "meta_description": None, "created_at": 1283780649000, # epoch time in millis "created_by": 1, "updated_at": 1286958624000, # epoch time in millis "updated_by": 1 } ], # Provide this if you want different roles to the default "Author" role "roles_users": [ # { # "user_id": 2, # "role_id": ObjectId # This must reference the id from your database # } ] } }