a41b45c58f
These options make Seance go through the motions of processing a post without actually uploading images and/or pushing them to Ghost. This makes it easier to test out stuff for new features (or, more accurately, it reduces the need to clean up afterwards!)
197 lines
6.5 KiB
JavaScript
Executable file
197 lines
6.5 KiB
JavaScript
Executable file
#! /usr/bin/env node
|
|
|
|
const program = require('commander')
|
|
const path = require('path')
|
|
const prompt = require('prompt-async')
|
|
const readline = require('readline')
|
|
const os = require('os')
|
|
const fs = require('fs')
|
|
const yaml = require('js-yaml')
|
|
|
|
const config = require('./config')
|
|
|
|
const {
|
|
Seance,
|
|
} = require ('./seance')
|
|
|
|
|
|
// Set up Seance CLI notifications
|
|
const seance = new Seance()
|
|
|
|
seance.on('update', (e) => {
|
|
console.log(e.message)
|
|
})
|
|
|
|
seance.on('notification', (e) => {
|
|
console.warn(e.message)
|
|
})
|
|
|
|
seance.on('error', (e) => {
|
|
console.error(e.message)
|
|
})
|
|
|
|
program
|
|
.version('1.0.0-dev')
|
|
.description('pull posts from Medium and add them to a Ghost blog');
|
|
|
|
program.command('setup')
|
|
.description('Initial setup and configuration')
|
|
.action(async () => {
|
|
console.log('Hello and welcome to Seance.')
|
|
console.log(
|
|
'\n\nWe\'re going to take you through some steps' +
|
|
' to set up your system.\n'
|
|
)
|
|
console.log('First up: WebDAV details.')
|
|
console.log(
|
|
'Please enter your server url (including the port), ' +
|
|
'username, and password\n'
|
|
)
|
|
|
|
var res
|
|
prompt.start()
|
|
res = await prompt.get([
|
|
{ name: 'server_url', default: config.webdav.server_url || '' },
|
|
{ name: 'username', default: config.webdav.username || '' },
|
|
{ name: 'password', default: config.webdav.password || '' , hidden: true},
|
|
])
|
|
config.webdav.server_url = res.server_url
|
|
config.webdav.username = res.username
|
|
config.webdav.password = res.password
|
|
console.log(`\nOkay. So we have ${config.webdav.username} on ${config.webdav.server_url} with [ the password you set]`)
|
|
|
|
console.log(
|
|
'\nA couple more settings for your WebDAV: ' +
|
|
'we need to know the path prefix and the uploaded path prefix.\n' +
|
|
'The path prefix is the subfolder to which you upload, like ' +
|
|
'`/seance-uploads`, while the uploaded path prefix is what '+
|
|
'you\'d stick in front of the filename after uploading ' +
|
|
'(like `https://media.mysite.com/seance-uploads`).\n'
|
|
)
|
|
res = await prompt.get([
|
|
{ name: 'path_prefix', default: config.webdav.path_prefix || '' },
|
|
{ name: 'uploaded_path_prefix', default: config.webdav.uploaded_path_prefix || '' },
|
|
])
|
|
config.webdav.path_prefix = res.path_prefix
|
|
config.webdav.uploaded_path_prefix = res.uploaded_path_prefix
|
|
console.log(`Cool. So uploads to ${config.webdav.path_prefix} will go to ${config.webdav.uploaded_path_prefix}.`)
|
|
|
|
console.log('\n\nNext up: Ghost settings.')
|
|
console.log(
|
|
'The Ghost URL is basically the link to your main ' +
|
|
'Ghost site, and the admin API key can be found by going to ' +
|
|
'your Settings -> Integrations page.\n'
|
|
)
|
|
|
|
res = await prompt.get([
|
|
{ name: 'url', default: config.ghost.url || '' },
|
|
{ name: 'version', default: config.ghost.version || 'v2' },
|
|
{ name: 'admin_key', default: config.ghost.admin_key || '' },
|
|
])
|
|
config.ghost.url = res.url
|
|
config.ghost.version = res.version
|
|
config.ghost.admin_key = res.admin_key
|
|
console.log(`Right. So that's Ghost ${config.ghost.version} running at ${config.ghost.url} with key ${config.ghost.admin_key}`)
|
|
|
|
console.log(
|
|
'\n\nA final thing. Do you have a "scissors" or other image ' +
|
|
'used as a separator in your article? If so, enter the path ' +
|
|
'here and we\'ll check against it to auto-convert them to ' +
|
|
'Ghost-friendly separators. If you don\'t use scissors, you ' +
|
|
'can just press Enter without typing anything.\n'
|
|
)
|
|
|
|
res = await prompt.get([
|
|
{ name: 'scissors', default: config.scissors || '' },
|
|
])
|
|
config.scissors = res.scissors
|
|
if (config.scissors) {
|
|
console.log(`Done. Scissors set to ${config.scissors}`)
|
|
} else {
|
|
console.log('No scissors? That\'s fine. You\'ll get there one day :)')
|
|
}
|
|
|
|
console.log('\n\nFinal confirmation: would you like to save these settings?')
|
|
const { save } = await prompt.get(['save'])
|
|
if (save == '' || (save[0] && save[0].toLowerCase() != 'n')) {
|
|
const configDir = path.join(os.homedir(), '.config')
|
|
if (!fs.existsSync(configDir)) {
|
|
os.makeDirSync(configDir)
|
|
}
|
|
userConfig = path.join(configDir, 'seance.yaml')
|
|
data = yaml.safeDump(config)
|
|
fs.writeFileSync(userConfig, data)
|
|
console.log('\nThat\'s it - we\'re done!')
|
|
} else {
|
|
console.log('Not saving? What a pity!')
|
|
}
|
|
})
|
|
|
|
program.command('fetch-medium <post_url>')
|
|
.alias('fetch')
|
|
.description('fetch a Medium post')
|
|
.action((post_url) => {
|
|
new Seance().fetchFromMedium(post_url)
|
|
.then((post) => {
|
|
console.info(`"${post.title}" fetched successfully.`)
|
|
})
|
|
});
|
|
|
|
program.command('push-ghost <file>')
|
|
.alias('push')
|
|
.description('push a downloaded Medium post to Ghost')
|
|
.option('-d, --dry-run', "full dry run: doesn't upload anything (same as --no-upload --no-push)")
|
|
.option('--no-upload', "partial dry run: don't upload images")
|
|
.option('--no-push', "partial dry run: don't push to ghost")
|
|
.action((file, o) => {
|
|
seance.pushToGhost(file, {
|
|
dryRun: o.dryRun,
|
|
noUpload: !o.upload,
|
|
noPush: !o.push,
|
|
})
|
|
});
|
|
|
|
program.command('medium-to-ghost <mediumUrl>')
|
|
.alias('import')
|
|
.description('copy a Medium file over to Ghost')
|
|
.action((mediumUrl) => {
|
|
seance.pushToGhost(mediumUrl);
|
|
});
|
|
|
|
program.command('create-user <username> <email>')
|
|
.description('create ghost-import.json to import Medium user to Ghost')
|
|
.action(async (username, email) => {
|
|
const jsonOut = await seance.generateUserData(username, email)
|
|
.catch((err) => {
|
|
console.log(`Error: ${err.error}`)
|
|
return
|
|
})
|
|
|
|
const userSlug = JSON.parse(jsonOut).data.users[0].slug
|
|
const outFile = `user-${userSlug}.json`
|
|
await fs.promises.writeFile(outFile, jsonOut, 'utf-8')
|
|
console.log(`Saved to ${outFile}`);
|
|
});
|
|
|
|
program.command('webdav-test <file>')
|
|
.description('[test command] upload stuff to WebDAV')
|
|
.action(async (file) => {
|
|
// decide path
|
|
current_date = new Date();
|
|
var dir_path = path.join(
|
|
config.webdav.path_prefix,
|
|
current_date.getUTCFullYear().toString(),
|
|
current_date.getUTCMonth().toString(),
|
|
'test' // TODO: replace with article slug
|
|
)
|
|
new seance.uploadDav(dir_path, file);
|
|
});
|
|
|
|
program.command('check-scissors <file>')
|
|
.description('[test command] check if an image matches the set separator')
|
|
.action(async (file) => {
|
|
console.log(await seance.checkScissors(file))
|
|
})
|
|
|
|
program.parse(process.argv)
|