From 453f22df143582ddbc180db6dc5fd62b916d8ba4 Mon Sep 17 00:00:00 2001 From: azivner Date: Thu, 11 Jan 2018 23:54:17 -0500 Subject: [PATCH] work in progress reddit plugin --- plugins/reddit.js | 127 ++++++++++++++++++++++++++++++++++++++++++++ services/options.js | 17 ++++-- 2 files changed, 139 insertions(+), 5 deletions(-) create mode 100644 plugins/reddit.js diff --git a/plugins/reddit.js b/plugins/reddit.js new file mode 100644 index 000000000..fb427f720 --- /dev/null +++ b/plugins/reddit.js @@ -0,0 +1,127 @@ +const sql = require('../services/sql'); +const notes = require('../services/notes'); +const axios = require('axios'); +const log = require('../services/log'); +const utils = require('../services/utils'); +const unescape = require('unescape'); +const sync_table = require('../services/sync_table'); +const options = require('../services/options'); + +const REDDIT_ROOT = 'reddit_root'; +const SOURCE_ID = 'reddit_plugin'; + +async function importReddit(accounts) { + const accountName = accounts[0]; + + let rootNoteId = await sql.getFirst(`SELECT notes.note_id FROM notes JOIN attributes USING(note_id) + WHERE attributes.name = '${REDDIT_ROOT}' AND notes.is_deleted = 0`); + + if (!rootNoteId) { + rootNoteId = (await notes.createNewNote('root', { + note_title: 'Reddit', + target: 'into', + is_protected: false + }, SOURCE_ID)).noteId; + + await createAttribute(rootNoteId, REDDIT_ROOT); + } + + const response = await axios.get(`https://www.reddit.com/user/${accountName}.json`); + const listing = response.data; + + if (listing.kind !== 'Listing') { + log.info(`Unknown kind ${listing.kind}`); + return; + } + + const children = listing.data.children; + console.log(children[0]); + + for (const child of children) { + const comment = child.data; + + let commentNoteId = await getNoteIdWithAttribute('reddit_comment_id', comment.id); + + if (commentNoteId) { + continue; + } + + const dateTimeStr = utils.dateStr(new Date(comment.created_utc * 1000)); + const dateStr = dateTimeStr.substr(0, 10); + + let dateNoteId = await getNoteIdWithAttribute('date_note', dateStr); + + if (!dateNoteId) { + dateNoteId = (await notes.createNewNote(rootNoteId, { + note_title: dateStr, + target: 'into', + is_protected: false + }, SOURCE_ID)).noteId; + + await createAttribute(dateNoteId, "date_note", dateStr); + } + + commentNoteId = (await notes.createNewNote(dateNoteId, { + note_title: comment.link_title, + target: 'into', + is_protected: false + }, SOURCE_ID)).noteId; + + console.log("Created note " + commentNoteId); + + const body = + `

${comment.link_permalink}

+

author: ${comment.author}, subreddit: ${comment.subreddit}, karma: ${comment.score}, created at ${dateTimeStr}

` + + unescape(comment.body_html); + + await sql.execute("UPDATE notes SET note_text = ? WHERE note_id = ?", [body, commentNoteId]); + + await createAttribute(commentNoteId, "reddit_kind", child.kind); + await createAttribute(commentNoteId, "reddit_id", comment.id); + await createAttribute(commentNoteId, "reddit_created_utc", comment.created_utc); + } +} + +async function createAttribute(noteId, name, value = null) { + const now = utils.nowDate(); + const attributeId = utils.newAttributeId(); + + await sql.insert("attributes", { + attribute_id: attributeId, + note_id: noteId, + name: name, + value: value, + date_modified: now, + date_created: now + }); + + await sync_table.addAttributeSync(attributeId, SOURCE_ID); +} + +async function getNoteIdWithAttribute(name, value) { + return await sql.getFirstValue(`SELECT notes.note_id FROM notes JOIN attributes USING(note_id) + WHERE notes.is_deleted = 0 AND attributes.name = ? AND attributes.value = ?`, [name, value]); +} + +sql.dbReady.then(async () => { + const enabledOption = await options.getOptionOrNull("reddit_enabled"); + const accountsOption = await options.getOptionOrNull("reddit_accounts"); + + if (!enabledOption) { + await options.createOption("reddit_enabled", "false", true); + await options.createOption("reddit_accounts", "[]", true); + return; + } + + if (enabledOption.opt_value !== "true") { + return; + } + + if (!accountsOption) { + log.info("No reddit accounts defined in option 'reddit_accounts'"); + } + + const redditAccounts = JSON.parse(accountsOption.opt_value); + + await importReddit(redditAccounts); +}); diff --git a/services/options.js b/services/options.js index 0ffbe71a7..c9a57a5ac 100644 --- a/services/options.js +++ b/services/options.js @@ -3,8 +3,12 @@ const utils = require('./utils'); const sync_table = require('./sync_table'); const app_info = require('./app_info'); +async function getOptionOrNull(optName) { + return await sql.getFirstOrNull("SELECT opt_value FROM options WHERE opt_name = ?", [optName]); +} + async function getOption(optName) { - const row = await sql.getFirstOrNull("SELECT opt_value FROM options WHERE opt_name = ?", [optName]); + const row = await getOptionOrNull(optName); if (!row) { throw new Error("Option " + optName + " doesn't exist"); @@ -30,9 +34,10 @@ async function setOption(optName, optValue, sourceId = null) { async function createOption(optName, optValue, isSynced, sourceId = null) { await sql.insert("options", { - opt_name: optName, - opt_value: optValue, - is_synced: isSynced + opt_name: optName, + opt_value: optValue, + is_synced: isSynced, + date_modified: utils.nowDate() }); if (isSynced) { @@ -63,6 +68,8 @@ async function initOptions(startNotePath) { module.exports = { getOption, + getOptionOrNull, setOption, - initOptions + initOptions, + createOption }; \ No newline at end of file