120 lines
4.1 KiB
JavaScript
120 lines
4.1 KiB
JavaScript
const path = require('path')
|
|
const https = require('https')
|
|
const Stream = require('stream').Transform
|
|
const hasha = require('hasha')
|
|
const md = require('markdown-it')()
|
|
const {httpsGetAsync, parseJSONData} = require('../../lib/request')
|
|
|
|
const GLITCH_API_ROOT = '/ghost/api/v0.1/'
|
|
|
|
// Retrieve ghost access token
|
|
const getToken = config => {
|
|
return new Promise((resolve, reject) => {
|
|
const tokenReqData = `grant_type=password&username=${config.ghost.username}&password=${config.ghost.password}&client_id=${config.ghost.id}&client_secret=${config.ghost.secret}`
|
|
const tokenReqOptions = {
|
|
host: config.ghost.host,
|
|
path: `${GLITCH_API_ROOT}authentication/token`,
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
'Content-Length': Buffer.byteLength(tokenReqData, 'utf8')}}
|
|
const collectToken = https.request(tokenReqOptions, res => {
|
|
const data = new Stream()
|
|
res.on('data', chunk => data.push(chunk))
|
|
res.on('end', parseJSONData.bind(null, data, resolve, reject))
|
|
})
|
|
collectToken.write(tokenReqData)
|
|
collectToken.end()
|
|
collectToken.on('error', error => reject(error))
|
|
})
|
|
}
|
|
|
|
const download = (image, config) => {
|
|
return new Promise(async (resolve, reject) => {
|
|
const src = `https://${config.ghost.host}${image}`
|
|
const dest = path.join(config.basepath, config.image_path, image)
|
|
const data = new Stream()
|
|
const res = await httpsGetAsync(src)
|
|
res.on('data', chunk => data.push(chunk))
|
|
res.on('end', () => {
|
|
const buf = data.read()
|
|
resolve({src, dest, hash: hasha(buf), original: buf, optimized: null, responsive: []})
|
|
})
|
|
})
|
|
}
|
|
|
|
// download images
|
|
const downloadImages = async (posts, config) => {
|
|
let images = []
|
|
posts.posts.forEach((post, idx) => {
|
|
let postImages = []
|
|
if (post.image) postImages.push(post.image)
|
|
// parse inline images
|
|
md.parse(post.markdown).forEach(token => {
|
|
if (token.type === 'image') postImages.push(token.attrs[0][1])
|
|
if (Array.isArray(token.children)) {
|
|
token.children.forEach(async child => {
|
|
if (child.type === 'image') postImages.push(child.attrs[0][1])
|
|
})
|
|
}
|
|
})
|
|
images.push(Promise.all(postImages.map(image => download(image, config))))
|
|
})
|
|
return Promise.all(images)
|
|
}
|
|
|
|
const mapPostPages = async (posts, images, config) => {
|
|
const postsWithMappedImages = posts.posts.map((post, idx) => Object.assign({}, post, {image: images[idx].pop()}, {images: images[idx]}))
|
|
const postsWithMappedFields = postsWithMappedImages.map(post => {
|
|
return {
|
|
id: post.id,
|
|
uuid: post.uuid,
|
|
title: post.title,
|
|
slug: post.slug,
|
|
url: post.url,
|
|
article: !post.page,
|
|
status: post.status,
|
|
language: post.language,
|
|
visibility: post.visibility,
|
|
meta_title: post.meta_title || post.title,
|
|
meta_description: post.meta_description,
|
|
created_at: new Date(post.created_at),
|
|
created_by: post.created_by,
|
|
updated_at: new Date(post.updated_at),
|
|
updated_by: post.updated_by,
|
|
published_at: new Date(post.published_at),
|
|
published_by: post.published_by,
|
|
tags: post.tags,
|
|
author: post.author,
|
|
image: post.image,
|
|
images: post.images,
|
|
markdown: post.markdown
|
|
}
|
|
})
|
|
return postsWithMappedFields
|
|
}
|
|
|
|
// fetch ghost posts
|
|
const getPosts = async config => {
|
|
const loadPosts = () => {
|
|
return new Promise(async (resolve, reject) => {
|
|
const token = await getToken(config)
|
|
const postsReqOptions = {
|
|
host: config.ghost.host,
|
|
path: `${GLITCH_API_ROOT}posts/?status=all&staticPages=all&include=tags&limit=30`,
|
|
headers: {
|
|
'authorization': `Bearer ${token.access_token}`,
|
|
'accept': 'application/json'}}
|
|
const data = new Stream()
|
|
const res = await httpsGetAsync(postsReqOptions)
|
|
res.on('data', chunk => data.push(chunk))
|
|
res.on('end', parseJSONData.bind(null, data, resolve, reject))
|
|
})
|
|
}
|
|
const posts = await loadPosts()
|
|
const images = await downloadImages(posts, config)
|
|
return mapPostPages(posts, images, config)
|
|
}
|
|
|
|
module.exports.getPosts = getPosts
|