import { Command } from "commander"; import { createFileNode, createImageNode, createHeadingNode } from "./lexical"; import { extractShootingConditions, createImageCaption } from "./exif"; import { uploadFile, uploadImage, uploadPost } from "./api"; import { getBasenameWithExtension, prepareFiles } from "./files"; new Command() .name("darktable-publish") .description("Publish files to GHOST CMS with optional metadata.") .option("-t, --title [string]", "Specify the title") .option("-s, --slug [string]", "Specify the slug") .option("-k, --keywords [string...]", "Specify blog post keywords (tags)") .argument("", "Files to process") .action(async (files, options) => { if (!options.title) { throw new Error("Please specify a title."); } if (!options.slug) { throw new Error("Please specify a slug."); } const parsedFiles = await prepareFiles(files); const [ shootingConditions, uploadedJpegImages, uploadedJpegFiles, uploadedRawFiles, ] = await Promise.all([ Promise.all(parsedFiles.map(extractShootingConditions)), Promise.all(parsedFiles.map((f) => uploadImage(f.jpegPath))), Promise.all(parsedFiles.map((f) => uploadFile(f.jpegPath))), Promise.all( parsedFiles.map((f) => f.rawPath ? uploadFile(f.rawPath) : Promise.resolve(undefined), ), ), ]); const aggregatedFiles = parsedFiles.map((file, index) => ({ ...file, shootingConditions: shootingConditions[index], uploadedJpegImage: uploadedJpegImages[index], uploadedJpegFile: uploadedJpegFiles[index], uploadedRawFile: uploadedRawFiles[index], })); const result: any = { root: { children: [], direction: "ltr", format: "", indent: 0, type: "root", version: 1, }, }; if (aggregatedFiles.length > 1) { aggregatedFiles.slice(1).forEach((file) => result.root.children.push( createImageNode({ src: file.uploadedJpegImage, caption: createImageCaption(file.shootingConditions), }), ), ); } result.root.children.push(createHeadingNode("Downloads", "h2")); aggregatedFiles.forEach((file) => { result.root.children.push( createFileNode({ src: file.uploadedJpegFile, name: getBasenameWithExtension(file.jpegPath), size: file.jpegSize, }), ); if (file.uploadedRawFile && file.rawPath && file.rawSize) { result.root.children.push( createFileNode({ src: file.uploadedRawFile, name: getBasenameWithExtension(file.rawPath), size: file.rawSize, }), ); } }); const post = { title: options.title, slug: options.slug, lexical: JSON.stringify(result), feature_image: aggregatedFiles[0].uploadedJpegImage, feature_image_caption: createImageCaption( aggregatedFiles[0].shootingConditions, ), status: "published", visibility: "public", tags: options.keywords, published_at: aggregatedFiles[0].shootingConditions.timestamp, }; const url = await uploadPost(post); console.log(url); process.exit(0); }) .parse();