From 49f49112b30d4364379be1b365127d18b8b5dc54 Mon Sep 17 00:00:00 2001 From: Ian Cooperman Date: Mon, 1 Aug 2022 15:01:37 -0700 Subject: [PATCH 1/9] Imported node-fetch into joplin api wrapper module --- joplin.js | 8 ++++++++ package.json | 1 + 2 files changed, 9 insertions(+) create mode 100644 joplin.js diff --git a/joplin.js b/joplin.js new file mode 100644 index 0000000..a77b8f6 --- /dev/null +++ b/joplin.js @@ -0,0 +1,8 @@ +import fetch from 'node-fetch'; + +async function main() { + const res = await fetch("https://example.com"); + console.log(res.body); +} + +const res = main(); \ No newline at end of file diff --git a/package.json b/package.json index e1b46c7..296324a 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "type": "module", "dependencies": { "@notionhq/client": "^2.1.1", "dotenv": "^16.0.1", From a4bfa7dd053779367e3f8152807b8cd9d4b7f563 Mon Sep 17 00:00:00 2001 From: Ian Cooperman Date: Mon, 1 Aug 2022 19:00:19 -0700 Subject: [PATCH 2/9] Began work on interfacing with the Joplin Data API --- joplin.js | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/joplin.js b/joplin.js index a77b8f6..9b2aa95 100644 --- a/joplin.js +++ b/joplin.js @@ -1,8 +1,33 @@ -import fetch from 'node-fetch'; +import fetch from 'node-fetch' +import 'dotenv/config' -async function main() { - const res = await fetch("https://example.com"); - console.log(res.body); +let url = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/notes") +url.searchParams.append("token", process.env.JOPLIN_TOKEN) + + +async function getNotes(notebookID) { + let foldersURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/folders/" + process.env.JOPLIN_NOTEBOOK_ID + "/notes") + + foldersURL.searchParams.append("token", process.env.JOPLIN_TOKEN) + + const res = await fetch(foldersURL.href) + const data = await res.json() + + return data } -const res = main(); \ No newline at end of file +async function getNoteData(noteID) { + let noteURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/notes/" + noteID) + + const res = await fetch(noteURL.href) + const data = await res.json() + + return data +} + +getNotes() + .then(res => { + res.items.forEach(element => { + console.log(element.id) + }); + }) \ No newline at end of file From 2a6c968a996ac497f6711dd6a09d0946e97ee347 Mon Sep 17 00:00:00 2001 From: Ian Cooperman Date: Tue, 2 Aug 2022 12:25:08 -0700 Subject: [PATCH 3/9] Now getting note data for each note --- joplin.js | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/joplin.js b/joplin.js index 9b2aa95..5a6581b 100644 --- a/joplin.js +++ b/joplin.js @@ -5,9 +5,8 @@ let url = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/note url.searchParams.append("token", process.env.JOPLIN_TOKEN) -async function getNotes(notebookID) { +async function getNoteMetadataFromNotebook(notebookID) { let foldersURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/folders/" + process.env.JOPLIN_NOTEBOOK_ID + "/notes") - foldersURL.searchParams.append("token", process.env.JOPLIN_TOKEN) const res = await fetch(foldersURL.href) @@ -16,18 +15,35 @@ async function getNotes(notebookID) { return data } -async function getNoteData(noteID) { +async function getNote(noteID) { let noteURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/notes/" + noteID) + noteURL.searchParams.append("token", process.env.JOPLIN_TOKEN) + noteURL.searchParams.append("fields", "id,title,body") + console.log(noteURL.href) const res = await fetch(noteURL.href) - const data = await res.json() + const note = await res.json() - return data + return note } -getNotes() +getNoteMetadataFromNotebook() .then(res => { - res.items.forEach(element => { - console.log(element.id) + let noteIDs = [] + res.items.forEach(note => { + noteIDs.push(note.id) }); + return noteIDs + }) + .then(async noteIDs => { + let notes = [] + for (let i = 0; i < noteIDs.length; i++) { + const note = await getNote(noteIDs[i]) + notes.push(note) + } + + return notes + }) + .then(notes => { + notes.forEach(note => console.log(note.body)) }) \ No newline at end of file From 8bca7443ca46a15cb37aa30e9b38d7c9e97944e2 Mon Sep 17 00:00:00 2001 From: Ian Cooperman Date: Tue, 2 Aug 2022 12:29:56 -0700 Subject: [PATCH 4/9] Function getNote no longer proved necessary --- joplin.js | 37 ++++--------------------------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/joplin.js b/joplin.js index 5a6581b..c03d734 100644 --- a/joplin.js +++ b/joplin.js @@ -5,9 +5,10 @@ let url = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/note url.searchParams.append("token", process.env.JOPLIN_TOKEN) -async function getNoteMetadataFromNotebook(notebookID) { +async function getNotesFromNotebook(notebookID) { let foldersURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/folders/" + process.env.JOPLIN_NOTEBOOK_ID + "/notes") foldersURL.searchParams.append("token", process.env.JOPLIN_TOKEN) + foldersURL.searchParams.append("fields", "id,title,body") const res = await fetch(foldersURL.href) const data = await res.json() @@ -15,35 +16,5 @@ async function getNoteMetadataFromNotebook(notebookID) { return data } -async function getNote(noteID) { - let noteURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/notes/" + noteID) - noteURL.searchParams.append("token", process.env.JOPLIN_TOKEN) - noteURL.searchParams.append("fields", "id,title,body") - console.log(noteURL.href) - - const res = await fetch(noteURL.href) - const note = await res.json() - - return note -} - -getNoteMetadataFromNotebook() - .then(res => { - let noteIDs = [] - res.items.forEach(note => { - noteIDs.push(note.id) - }); - return noteIDs - }) - .then(async noteIDs => { - let notes = [] - for (let i = 0; i < noteIDs.length; i++) { - const note = await getNote(noteIDs[i]) - notes.push(note) - } - - return notes - }) - .then(notes => { - notes.forEach(note => console.log(note.body)) - }) \ No newline at end of file +getNotesFromNotebook() + .then(res => console.log(res)) \ No newline at end of file From aab9cada6d7ef75cc98f4ec261f43b49a0a2cf81 Mon Sep 17 00:00:00 2001 From: Ian Cooperman Date: Tue, 2 Aug 2022 12:36:49 -0700 Subject: [PATCH 5/9] Changed note retrieval URL parameters to obtain additional useful info --- joplin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/joplin.js b/joplin.js index c03d734..a1a26d4 100644 --- a/joplin.js +++ b/joplin.js @@ -8,7 +8,7 @@ url.searchParams.append("token", process.env.JOPLIN_TOKEN) async function getNotesFromNotebook(notebookID) { let foldersURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/folders/" + process.env.JOPLIN_NOTEBOOK_ID + "/notes") foldersURL.searchParams.append("token", process.env.JOPLIN_TOKEN) - foldersURL.searchParams.append("fields", "id,title,body") + foldersURL.searchParams.append("fields", "id,title,body,created_time,updated_time,latitude,longitude,altitude,is_todo,todo_due,todo_completed") const res = await fetch(foldersURL.href) const data = await res.json() From e5d4bdf90d7b65ad971f9c96f851af7c570848e4 Mon Sep 17 00:00:00 2001 From: Ian Cooperman Date: Thu, 4 Aug 2022 15:16:02 -0700 Subject: [PATCH 6/9] Adjusted getNotesFromNotebook() to also take the fields to retrive --- joplin.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/joplin.js b/joplin.js index a1a26d4..ae2cae7 100644 --- a/joplin.js +++ b/joplin.js @@ -1,14 +1,16 @@ import fetch from 'node-fetch' import 'dotenv/config' -let url = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/notes") -url.searchParams.append("token", process.env.JOPLIN_TOKEN) +//This function gets notes from a specified notebook, using the notebook's ID. The fields parameter specifies which fields to include in the response. +// @param {string=} notebookID - The id of the notebook you want to get notes from, as extracted from the notebook's external link +// @param {Array[string]=} fields - The specific fields wanted in the returned response. Valid fields can be found in this table: https://joplinapp.org/api/references/rest_api/#properties +async function getNotesFromNotebook(notebookID, fields) { + const fieldsString = fields.join() -async function getNotesFromNotebook(notebookID) { - let foldersURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/folders/" + process.env.JOPLIN_NOTEBOOK_ID + "/notes") + let foldersURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/folders/" + notebookID + "/notes") foldersURL.searchParams.append("token", process.env.JOPLIN_TOKEN) - foldersURL.searchParams.append("fields", "id,title,body,created_time,updated_time,latitude,longitude,altitude,is_todo,todo_due,todo_completed") + foldersURL.searchParams.append("fields", fieldsString) const res = await fetch(foldersURL.href) const data = await res.json() @@ -16,5 +18,5 @@ async function getNotesFromNotebook(notebookID) { return data } -getNotesFromNotebook() +getNotesFromNotebook(process.env.JOPLIN_NOTEBOOK_ID, ["id", "title", "body", "created_time", "latitude", "longitude", "altitude", "is_todo", "todo_due", "todo_completed"]) .then(res => console.log(res)) \ No newline at end of file From bce9f8a04de17e6e617cdbaa8cc00eae69bbe756 Mon Sep 17 00:00:00 2001 From: Ian Cooperman Date: Thu, 4 Aug 2022 16:25:28 -0700 Subject: [PATCH 7/9] Moved joplin wrapper functions to class for cleaner usage --- joplin.js | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/joplin.js b/joplin.js index ae2cae7..c1c5256 100644 --- a/joplin.js +++ b/joplin.js @@ -2,21 +2,40 @@ import fetch from 'node-fetch' import 'dotenv/config' -//This function gets notes from a specified notebook, using the notebook's ID. The fields parameter specifies which fields to include in the response. -// @param {string=} notebookID - The id of the notebook you want to get notes from, as extracted from the notebook's external link -// @param {Array[string]=} fields - The specific fields wanted in the returned response. Valid fields can be found in this table: https://joplinapp.org/api/references/rest_api/#properties -async function getNotesFromNotebook(notebookID, fields) { - const fieldsString = fields.join() +class Joplin { + constructor(joplinToken, joplinPort) { + this.token = joplinToken + this.port = joplinPort + console.log(this.port) - let foldersURL = new URL("http://localhost:" + process.env.JOPLIN_CLIPPER_PORT + "/folders/" + notebookID + "/notes") - foldersURL.searchParams.append("token", process.env.JOPLIN_TOKEN) - foldersURL.searchParams.append("fields", fieldsString) + this.getNotesFromNotebook.bind(this) + } - const res = await fetch(foldersURL.href) - const data = await res.json() + + //This function gets notes from a specified notebook, using the notebook's ID. The fields parameter specifies which fields to include in the response. + // @param {string=} notebookID - The id of the notebook you want to get notes from, as extracted from the notebook's external link + // @param {Array[string]=} fields - The specific fields wanted in the returned response. Valid fields can be found in this table: https://joplinapp.org/api/references/rest_api/#properties + async getNotesFromNotebook(notebookID, fields) { + const fieldsString = fields.join() + + let tempURL = "http://localhost:" + this.port + "/folders/" + notebookID + "/notes" + console.log(tempURL) + let foldersURL = new URL(tempURL) + foldersURL.searchParams.append("token", this.token) + foldersURL.searchParams.append("fields", fieldsString) - return data + const res = await fetch(foldersURL.href) + const data = await res.json() + + return data + } } -getNotesFromNotebook(process.env.JOPLIN_NOTEBOOK_ID, ["id", "title", "body", "created_time", "latitude", "longitude", "altitude", "is_todo", "todo_due", "todo_completed"]) + +let joplin = new Joplin(process.env.JOPLIN_TOKEN, process.env.JOPLIN_CLIPPER_PORT) + + + + +joplin.getNotesFromNotebook(process.env.JOPLIN_NOTEBOOK_ID, ["id", "title", "body", "created_time", "latitude", "longitude", "altitude", "is_todo", "todo_due", "todo_completed"]) .then(res => console.log(res)) \ No newline at end of file From c1ad4f0d6cc58d4dd4f5415fe0998b3cae4674a0 Mon Sep 17 00:00:00 2001 From: Ian Cooperman Date: Thu, 4 Aug 2022 18:16:28 -0700 Subject: [PATCH 8/9] Added loop to account for multiple fetches needed to retrieve all data --- joplin.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/joplin.js b/joplin.js index c1c5256..cfc524a 100644 --- a/joplin.js +++ b/joplin.js @@ -6,7 +6,6 @@ class Joplin { constructor(joplinToken, joplinPort) { this.token = joplinToken this.port = joplinPort - console.log(this.port) this.getNotesFromNotebook.bind(this) } @@ -18,24 +17,30 @@ class Joplin { async getNotesFromNotebook(notebookID, fields) { const fieldsString = fields.join() - let tempURL = "http://localhost:" + this.port + "/folders/" + notebookID + "/notes" - console.log(tempURL) - let foldersURL = new URL(tempURL) - foldersURL.searchParams.append("token", this.token) - foldersURL.searchParams.append("fields", fieldsString) - - const res = await fetch(foldersURL.href) - const data = await res.json() + let items = [] + let pageNum = 1 + let data = null + + do { + let tempURL = "http://localhost:" + this.port + "/folders/" + notebookID + "/notes" + let foldersURL = new URL(tempURL) + foldersURL.searchParams.append("token", this.token) + foldersURL.searchParams.append("fields", fieldsString) + foldersURL.searchParams.append("page", pageNum) - return data + const res = await fetch(foldersURL.href) + data = await res.json() + items = items.concat(data.items) + + pageNum++ + } + while (data.has_more) + + return items } } let joplin = new Joplin(process.env.JOPLIN_TOKEN, process.env.JOPLIN_CLIPPER_PORT) - - - - joplin.getNotesFromNotebook(process.env.JOPLIN_NOTEBOOK_ID, ["id", "title", "body", "created_time", "latitude", "longitude", "altitude", "is_todo", "todo_due", "todo_completed"]) .then(res => console.log(res)) \ No newline at end of file From 5be9f56c12ff88e2ee7519d3881bdd06fc7dd84d Mon Sep 17 00:00:00 2001 From: Ian Cooperman Date: Thu, 4 Aug 2022 19:37:38 -0700 Subject: [PATCH 9/9] Cleaned up joplin.js. Ready for merge into main. --- joplin.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/joplin.js b/joplin.js index cfc524a..a231db9 100644 --- a/joplin.js +++ b/joplin.js @@ -1,7 +1,7 @@ import fetch from 'node-fetch' import 'dotenv/config' - +// This class is used to interact with the Joplin Data API. It provides a method for getting notes from a specified notebook, using the notebook's ID. The fields parameter specifies which fields to include in the response. class Joplin { constructor(joplinToken, joplinPort) { this.token = joplinToken @@ -40,7 +40,4 @@ class Joplin { } } - -let joplin = new Joplin(process.env.JOPLIN_TOKEN, process.env.JOPLIN_CLIPPER_PORT) -joplin.getNotesFromNotebook(process.env.JOPLIN_NOTEBOOK_ID, ["id", "title", "body", "created_time", "latitude", "longitude", "altitude", "is_todo", "todo_due", "todo_completed"]) - .then(res => console.log(res)) \ No newline at end of file +export default Joplin