Files
2023-08-01 13:49:46 +02:00

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