Skip to content

Commit

Permalink
feat(importer): add Wordpress importer
Browse files Browse the repository at this point in the history
Closes #13
  • Loading branch information
g-div committed Jan 4, 2018
1 parent e724da9 commit 0f929fb
Showing 1 changed file with 125 additions and 46 deletions.
171 changes: 125 additions & 46 deletions src/importer.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,97 @@
const fs = require('fs');
const path = require('path');
const xml2js = require('xml2js');
const sqlite = require('sqlite');
const queries = require('./db/queries');
const xml2js = require('xml2js');
const toMarkdown = require('to-markdown');
const dbPromise = sqlite.open('./comments.db', { Promise });
let db;

const filename = process.argv.slice(2, 3).pop();
if (!filename) {
console.error('Pass the filepath to your XML file as argument');
process.exit(1);
}

function run() {
const parser = new xml2js.Parser({explicitArray: false});
const xmlFilePath = path.resolve(__dirname, '..', filename);
fs.readFile(xmlFilePath, (err, data) =>
parser.parseString(data, async function (err, result) {
if (err) console.error(`Error parsing the XML file '${xmlFilePath}':`, err);
const db = await dbPromise;

// for each post save it and store the id
// for each post that is a reply replace reply_to with the stored id
const threads = result.disqus.thread;
const posts = result.disqus.post.map(comment => importComment(threads, comment));

for (post of posts) {
const newComment = await saveComment(post);
post.new_id = newComment;
}
// Promisify readFile
async function readFile(file) {
const promise = await new Promise((resolve, reject) => {
fs.readFile(file, (err, data) => {
if (err) reject(err);
else resolve(data.toString());
});
});
return promise;
}

// Promisify parse XML
async function parse(file) {
const promise = await new Promise((resolve, reject) => {
const parser = new xml2js.Parser({explicitArray: false});

parser.parseString(file, (error, result) => {
if (error) reject(error);
else resolve(result);
});
});
return promise;
}

function getWPAuthor(comment) {
return [
'wordpress',
comment['wp:comment_author'],
comment['wp:comment_author'],
comment['wp:comment_author'],
0
];
}

for (post of posts) {
const replies = posts.filter(p => p.comment[3] === post.id); // replies to current post
if (replies) {
for (reply of replies) {
const { id, new_id } = post;
const res = await db.run(`UPDATE comment SET reply_to = ? WHERE reply_to = ?`, [new_id, id]);
}
}
function getWPComment(thread, comment) {
return [
thread['wp:post_name'],
comment['wp:comment_content'],
comment['wp:comment_parent'],
comment['wp:comment_date'],
comment['wp:comment_approved']
];
}

function formatWPComment(comment, thread) {
return {
author: getWPAuthor(comment),
comment: getWPComment(thread, comment),
id: comment['wp:comment_id']
};
}

async function parseWP(data) {
const threads = data.rss.channel.item;
for (thread of threads) {
const comments = thread['wp:comment'];
if (comments) {
if (comments.length) {
const formatted = comments.map(comment => formatWPComment(comment, thread));
const result = await saveComments(formatted)
} else {
const formatted = formatWPComment(comments, thread);
const result = await saveComments([formatted]);
}
})
);
};
}
}
}

async function saveComment(post) {
const db = await dbPromise;
db = await dbPromise;
const { comment, author } = post;

if (!author.username) {
author.username = 'Anonymous Guest';
if (!author[1]) {
author[1] = 'Anonymous Guest';
}
const user = [
'disqus',
author.username,
author.name,
author.username,
0
];

try {
await db.run(queries.create_user, user);
const newUser = await db.get(queries.find_user, ['disqus', author.username]);
await db.run(queries.create_user, author);
const newUser = await db.get(queries.find_user, [author[0], author[1]]);
if (newUser.id) comment.unshift(newUser.id); // push user_id to the front
const res = await db.run(`INSERT INTO comment
(user_id, slug, comment, reply_to, created_at, approved, rejected)
Expand All @@ -69,11 +100,28 @@ async function saveComment(post) {
} catch (err) {
console.error(`Error saving the comment for the slug ${comment[0]}:`, err);
}
};
}

function importComment(threads, comment) {
const { author } = comment;
const thread = threads.filter(thread => thread.$['dsq:id'] === comment.thread.$['dsq:id'])[0].id
async function saveComments(posts) {
for (post of posts) {
const newComment = await saveComment(post);
post.new_id = newComment;
}

for (post of posts) {
const replies = posts.filter(p => p.comment[3] === post.id); // replies to current post
if (replies) {
for (reply of replies) {
const { id, new_id } = post;
const res = await db.run(`UPDATE comment SET reply_to = ? WHERE reply_to = ?`, [new_id, id]);
}
}
}
}

function getDisqusComments(threads, comment) {
const { author } = comment;
const thread = threads.filter(thread => thread.$['dsq:id'] === comment.thread.$['dsq:id'])[0].id;
const reply_to = comment.parent ? comment.parent.$['dsq:id'] : null;
const message = toMarkdown(comment.message.trim());
const timestamp = comment.createdAt;
Expand All @@ -88,8 +136,39 @@ function importComment(threads, comment) {
approved
],
id: comment.$['dsq:id'],
author
author: [
'disqus',
author.username,
author.name,
author.username,
0
]
};
};

async function parseDisqus(data) {
const threads = data.disqus.thread;
const posts = data.disqus.post.map(comment => getDisqusComments(threads, comment));

const result = await saveComments(posts);
}

// Main
async function run() {
try {
const filePath = path.resolve(__dirname, '..', filename);
const content = await readFile(filePath)
const result = await parse(content);

if (result.disqus) {
parseDisqus(result);
} else if (result.rss) {
parseWP(result);
}
} catch (error) {
console.error('Error parsing the file:', filename);
console.error(error);
}
}

run();

0 comments on commit 0f929fb

Please sign in to comment.