246 lines
8.4 KiB
JavaScript
246 lines
8.4 KiB
JavaScript
import * as path from 'path';
|
|
import { sync as exists } from "@polymech/fs/exists";
|
|
import { sync as dir } from "@polymech/fs/dir";
|
|
import { sync as write } from "@polymech/fs/write";
|
|
import { sync as read } from "@polymech/fs/read";
|
|
import { resolve } from "@polymech/commons";
|
|
import { Promise as BPromise } from 'bluebird';
|
|
import { imageName, downloadFile } from './download';
|
|
const YAML = require('json-to-pretty-yaml');
|
|
const cheerio = require('cheerio');
|
|
import { toHTML } from '../markdown';
|
|
import { SYNC_TRACK_FILENAME } from '../discourse/constants';
|
|
import { cacheCategories, cacheTags, cacheUsers } from '../discourse/cache';
|
|
import { Instance } from '../discourse';
|
|
import { fromYAML } from './commons';
|
|
import { logger } from "../../index";
|
|
import * as md5 from 'md5';
|
|
export const createTopic = async (discourse, options, content) => {
|
|
let data;
|
|
try {
|
|
data = await discourse.createPost(options.title, content, options.cat);
|
|
}
|
|
catch (e) {
|
|
debugger;
|
|
}
|
|
if (data) {
|
|
logger.debug('created topic : ' + options.title + ' : ' + data.id);
|
|
if (data && data.id) {
|
|
try {
|
|
options.post_id = data.id;
|
|
options.topic_id = data.topic_id;
|
|
await discourse.changeOwner(options.post_id, options.topic_id, options.user_name);
|
|
}
|
|
catch (e) {
|
|
logger.error('changing owner ' + options.title + ' failed!', e);
|
|
}
|
|
}
|
|
else {
|
|
logger.debug('creating ' + options.title + ' failed!', data.errors);
|
|
if (data.errors) {
|
|
if (data.errors[0] && data.errors[0] === 'Title has already been used') {
|
|
logger.error('title already used : ' + options.title);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
export const updateTopic = async (discourse, options, topic_id, content) => {
|
|
let data;
|
|
try {
|
|
data = await discourse.updatePost(topic_id, content);
|
|
}
|
|
catch (e) {
|
|
}
|
|
if (data) {
|
|
logger.debug('created topic : ' + options.title + ' : ' + data.id);
|
|
if (data && data.id) {
|
|
try {
|
|
logger.debug('change user to ', options.owner);
|
|
options.post_id = data.id;
|
|
options.topic_id = data.topic_id;
|
|
await discourse.changeOwner(topic_id, topic_id, options.user_name);
|
|
}
|
|
catch (e) {
|
|
logger.debug('changing owner ' + options.title + ' failed!');
|
|
}
|
|
}
|
|
else {
|
|
logger.debug('creating ' + options.title + ' failed!', data.errors);
|
|
if (data.errors) {
|
|
if (data.errors[0] && data.errors[0] === 'Title has already been used') {
|
|
logger.error('title already used : ' + options.title);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const images_urls = (content) => {
|
|
const html = toHTML(content);
|
|
const $ = cheerio.load(html, {
|
|
xmlMode: true
|
|
});
|
|
const images = [];
|
|
const links = [];
|
|
$('img').each(function () {
|
|
images.push($(this).attr('src'));
|
|
});
|
|
return images;
|
|
};
|
|
const uploadImages = async (content, discourse, options) => {
|
|
const root = path.resolve(resolve(options.root));
|
|
if (!exists(root)) {
|
|
return false;
|
|
}
|
|
const track_path = path.join(root, SYNC_TRACK_FILENAME);
|
|
const track = read(track_path, 'json') || {};
|
|
const html = toHTML(content);
|
|
const $ = cheerio.load(html, {
|
|
xmlMode: true
|
|
});
|
|
const images = images_urls(content);
|
|
$('img').each(function () {
|
|
images.push($(this).attr('src'));
|
|
});
|
|
for await (const image of Object.entries(images)) {
|
|
const url = image[1];
|
|
if (url.startsWith('upload:')) {
|
|
continue;
|
|
}
|
|
if (options.uploadRemote && url.startsWith('http')) {
|
|
const contentHash = md5(content).substring(0, 5);
|
|
const cache_path = path.resolve(resolve('${OSR_CACHE}/discourse-downloads/' + contentHash));
|
|
if (!exists(cache_path)) {
|
|
dir(cache_path);
|
|
}
|
|
const image_name = imageName(url);
|
|
const image_local = path.join(cache_path, image_name);
|
|
if (!exists(image_local)) {
|
|
await downloadFile(url, cache_path);
|
|
}
|
|
if (exists(image_local)) {
|
|
const upped = await discourse.uploadFile(options.owner, image_local);
|
|
const data = upped.data;
|
|
if (data && data.id) {
|
|
track[url] = data;
|
|
write(track_path, track);
|
|
}
|
|
else {
|
|
console.error('error uploading image');
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
if (options.uploadLocal) {
|
|
const image_path = path.join(root, url);
|
|
if (exists(image_path) && !track[url]) {
|
|
const upped = await discourse.uploadFile(options.owner, image_path);
|
|
const data = upped.data;
|
|
if (data && data.id) {
|
|
track[url] = data;
|
|
write(track_path, track);
|
|
}
|
|
else {
|
|
console.error('error uploading image');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return track;
|
|
};
|
|
const syncFile = async (file, options) => {
|
|
const discourse = Instance(null, options.config);
|
|
let content = read(file);
|
|
const fm = fromYAML(content, options) || {};
|
|
let body = "" + fm.body;
|
|
let images_track;
|
|
if (options.uploadLocal || options.uploadRemote) {
|
|
images_track = await uploadImages(body, discourse, options);
|
|
const image_urls = images_urls(body);
|
|
image_urls.forEach((i) => {
|
|
if (images_track[i])
|
|
body = body.replace(i, images_track[i].short_url);
|
|
});
|
|
}
|
|
write('./out/md.md', body);
|
|
let dOpts = options.yaml ? fm.attributes : {
|
|
cat: options.cat,
|
|
id: options.id,
|
|
owner: options.owner,
|
|
tags: options.tags,
|
|
title: options.title
|
|
};
|
|
options = {
|
|
...options,
|
|
...dOpts
|
|
};
|
|
const cats = await cacheCategories(options, discourse);
|
|
const tags = await cacheTags(options, discourse);
|
|
const users = await cacheUsers(options, discourse);
|
|
const search = await discourse.search(dOpts.title);
|
|
let post_id, topic_id;
|
|
if (options.yaml) {
|
|
post_id = dOpts.post_id;
|
|
topic_id = dOpts.topic_id;
|
|
}
|
|
let dTopic;
|
|
let dPost;
|
|
if (search.posts && search.topics
|
|
&& search.posts[0] && search.topics[0]
|
|
&& search.topics[0].title === dOpts.title) {
|
|
dPost = search.posts[0];
|
|
dTopic = search.topics[0];
|
|
topic_id = dTopic.id;
|
|
post_id = dPost.id;
|
|
}
|
|
else if (post_id && topic_id) {
|
|
}
|
|
const user = users.find((u) => {
|
|
return u.id === dOpts.owner;
|
|
});
|
|
if (!user) {
|
|
logger.error('Invalid user : ', dOpts.owner);
|
|
return false;
|
|
}
|
|
options.user_name = user.username;
|
|
let topic = null;
|
|
if (post_id) {
|
|
topic = await updateTopic(discourse, options, post_id, body);
|
|
if (topic_id) {
|
|
topic = await discourse.updateTopic(topic_id, dOpts.cat, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : []);
|
|
}
|
|
}
|
|
else {
|
|
await createTopic(discourse, options, body);
|
|
topic_id = options.topic_id;
|
|
post_id = options.post_id;
|
|
await discourse.updateTopic(topic_id, dOpts.cat, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : []);
|
|
}
|
|
if (dTopic) {
|
|
options.topic_id = dTopic.id;
|
|
}
|
|
if (dPost) {
|
|
options.post_id = dPost.id;
|
|
}
|
|
if (options.yaml) {
|
|
let contentOut = `---\n`;
|
|
contentOut += YAML.stringify({
|
|
...fm.attributes,
|
|
topic_id: topic_id,
|
|
post_id: post_id
|
|
});
|
|
contentOut += `---\n`;
|
|
contentOut += fm.body;
|
|
write(file, contentOut);
|
|
}
|
|
return content;
|
|
};
|
|
export const syncYAML = async (options) => {
|
|
await BPromise.resolve(options.srcInfo.FILES).map((f) => {
|
|
return syncFile(f, options);
|
|
}, { concurrency: 1 });
|
|
};
|
|
export const sync = async (options) => {
|
|
return syncYAML(options);
|
|
};
|
|
//# sourceMappingURL=file.js.map
|