Home / GitHub Page

Python script for importing notes from Synology's Note Station into Joplin

I created a Python script that extracts notes (including attachments) from Synology’s Note Station and imports them into the Joplin app. Feel free to test it and/or improve it.

https://github.com/KraxelHuber/notestation-to-joplin

notestation-to-joplin

Imports a Synology Note Station .nsx file into Joplin notes app

Installing this Python script

Getting your notes out of Synology’s Note Station into Joplin note taking app

Step 1: Export your notes

  • Open your Synology Note Station app in DSM.
  • At the top of Note Station, click Settings.
  • Under Import and Export, click Export to launch the export wizard.
  • Follow the wizard instructions to export your notebooks.
  • Save your .nsx file into /notestation_to_joplin/src/

Step 2:

  • Open Joplin notes app
  • Go to Tools/Options/Web Clipper
  • Copy authorization token

Step 3:

  • Open /src/nsx2joplin.py within your project folder.
  • Replace nsx_file = p.joinpath("notestation-test-books.nsx") with your .nsx file
    nsx_file = p.joinpath("YOUR_NSX_FILE")
  • At the end of the script, replace the line joplin_token = "" with your token:
    joplin_token = "PASTE_YOUR_TOKEN_HERE"

Step 4:

  • Run the script (your Joplin app needs to be open).

This script is partly based on the great work of @Maboroshy script, which converts a .nsx file into markdown: Note-Station-to-markdown

Also, it makes use of the very good joplin-api project of @foxmask:
joplin-api

5 Likes

Great, our collection of tools and scripts is growing! :+1:

So excited to see this, thank you!

Trying to get it to work, but am stymied.
I created a test notebook in Note Station - 4 notes, including 2 attachments.
When I run the script it creates the appropriate directories and places the attached files in the attachments folder, but no md (or any other) files are created.

Here is what the output of the script looks like.
Perhaps someone can point me in the right direction?

Found pandoc 1.19.2.4
Extracting notes from /home/raven/notestation-to-joplin/src/20200616_125920_2699_me.nsx
Reading notebook Joplin Import Test Notebook
Reading note 1/4: A Joplin Import note with an attachment
Reading note 2/4: A Joplin Import note with embedded links
Reading note 3/4: A Joplin Import note with an embedded image
Reading note 4/4: A Joplin Import test note
Writing note 1/4 in Joplin Import Test Notebook: A Joplin Import note with an attachment
Traceback (most recent call last):
File “nsx2joplin.py”, line 463, in
nsx.export_to_joplin(token=joplin_token, nsx_content=nsx_content)
File “nsx2joplin.py”, line 406, in export_to_joplin
note[“content”] = asyncio.run(
File “/usr/lib/python3.8/asyncio/runners.py”, line 43, in run
return loop.run_until_complete(main)
File “/usr/lib/python3.8/asyncio/base_events.py”, line 608, in run_until_complete
return future.result()
File “nsx2joplin.py”, line 345, in create_resource
res = await joplin.create_resource(
File “/home/raven/.local/lib/python3.8/site-packages/joplin_api/core.py”, line 474, in create_resource
return await self.query(‘post’, ‘/resources/’, **data)
File “/home/raven/.local/lib/python3.8/site-packages/joplin_api/core.py”, line 106, in query
res = await self.client.post(self.JOPLIN_HOST + ‘/resources’,
File “/home/raven/.local/lib/python3.8/site-packages/httpx/_client.py”, line 1374, in post
return await self.request(
File “/home/raven/.local/lib/python3.8/site-packages/httpx/_client.py”, line 1147, in request
response = await self.send(
File “/home/raven/.local/lib/python3.8/site-packages/httpx/_client.py”, line 1168, in send
response = await self.send_handling_redirects(
File “/home/raven/.local/lib/python3.8/site-packages/httpx/_client.py”, line 1195, in send_handling_redirects
response = await self.send_handling_auth(
File “/home/raven/.local/lib/python3.8/site-packages/httpx/_client.py”, line 1232, in send_handling_auth
response = await self.send_single_request(request, timeout)
File “/home/raven/.local/lib/python3.8/site-packages/httpx/_client.py”, line 1264, in send_single_request
) = await transport.request(
File “/home/raven/.local/lib/python3.8/site-packages/httpcore/_async/connection_pool.py”, line 152, in request
response = await connection.request(
File “/home/raven/.local/lib/python3.8/site-packages/httpcore/_async/connection.py”, line 78, in request
return await self.connection.request(method, url, headers, stream, timeout)
File “/home/raven/.local/lib/python3.8/site-packages/httpcore/_async/http11.py”, line 62, in request
) = await self._receive_response(timeout)
File “/home/raven/.local/lib/python3.8/site-packages/httpcore/_async/http11.py”, line 115, in _receive_response
event = await self._receive_event(timeout)
File “/home/raven/.local/lib/python3.8/site-packages/httpcore/_async/http11.py”, line 145, in _receive_event
data = await self.socket.read(self.READ_NUM_BYTES, timeout)
File “/home/raven/.local/lib/python3.8/site-packages/httpcore/_backends/asyncio.py”, line 134, in read
return await asyncio.wait_for(
File “/usr/lib/python3.8/asyncio/tasks.py”, line 483, in wait_for
return fut.result()
File “/usr/lib/python3.8/asyncio/streams.py”, line 701, in read
await self._wait_for_data(‘read’)
File “/usr/lib/python3.8/asyncio/streams.py”, line 534, in _wait_for_data
await self._waiter
RuntimeError: Task <Task pending name=‘Task-4255’ coro=<StreamReader.read() running at /usr/lib/python3.8/asyncio/streams.py:701> cb=[_release_waiter(()]>)() at /usr/lib/python3.8/asyncio/tasks.py:429]> got Future attached to a different loop

Im trying to run this script and it seams to read all my notes but begins to fail when trying to write them into Joplin. Im not sure how to fix this, but I know I cant switch if I cant get my notes out.

Traceback (most recent call last):
  File "nsx2joplin.py", line 463, in <module>
nsx.export_to_joplin(token=joplin_token, nsx_content=nsx_content)
  File "nsx2joplin.py", line 382, in export_to_joplin
joplin_id = asyncio.run(create_folder(notebook["title"]))
  File "/usr/lib/python3.8/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
  File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
return future.result()
  File "nsx2joplin.py", line 332, in create_folder
res = await joplin.create_folder(folder=notebook_title)
  File "/home/relink/joplinimport/joplin-api/joplin_api/core.py", line 296, in create_folder
return await self.query('post', '/folders/', **data)
  File "/home/relink/joplinimport/joplin-api/joplin_api/core.py", line 116, in query
res = await self.client.post(full_path, json=payload, params=params)
  File "/home/relink/.local/lib/python3.8/site-packages/httpx/_client.py", line 1374, in post
return await self.request(
  File "/home/relink/.local/lib/python3.8/site-packages/httpx/_client.py", line 1147, in request
response = await self.send(
  File "/home/relink/.local/lib/python3.8/site-packages/httpx/_client.py", line 1168, in send
response = await self.send_handling_redirects(
  File "/home/relink/.local/lib/python3.8/site-packages/httpx/_client.py", line 1195, in send_handling_redirects
response = await self.send_handling_auth(
  File "/home/relink/.local/lib/python3.8/site-packages/httpx/_client.py", line 1232, in send_handling_auth
response = await self.send_single_request(request, timeout)
  File "/home/relink/.local/lib/python3.8/site-packages/httpx/_client.py", line 1264, in send_single_request
) = await transport.request(
  File "/home/relink/.local/lib/python3.8/site-packages/httpcore/_async/connection_pool.py", line 152, in request
response = await connection.request(
  File "/home/relink/.local/lib/python3.8/site-packages/httpcore/_async/connection.py", line 65, in request
self.socket = await self._open_socket(timeout)
  File "/home/relink/.local/lib/python3.8/site-packages/httpcore/_async/connection.py", line 85, in _open_socket
return await self.backend.open_tcp_stream(
  File "/home/relink/.local/lib/python3.8/site-packages/httpcore/_backends/auto.py", line 38, in open_tcp_stream
return await self.backend.open_tcp_stream(hostname, port, ssl_context, timeout)
  File "/home/relink/.local/lib/python3.8/site-packages/httpcore/_backends/asyncio.py", line 233, in open_tcp_stream
return SocketStream(
  File "/usr/lib/python3.8/contextlib.py", line 131, in __exit__
self.gen.throw(type, value, traceback)
  File "/home/relink/.local/lib/python3.8/site-packages/httpcore/_exceptions.py", line 12, in map_exceptions
raise to_exc(exc) from None
httpcore._exceptions.ConnectError: [Errno 111] Connect call failed ('127.0.0.1', 41184)

Your web clipper server is not running. Go to Joplin Preferences -> Web Clipper -> Step 1: Enable Web Clipper Service

I didn’t notice that, thanks. Interestingly I’m still having issues though.

So in the folder where the script is located I get a folder created for each of my notebooks, and within each folder are any attachments my notes had. However in Joplin only 1 notebook transferred over, and none of the notes come with it. So I have 1 empty notebook that moved over…

I didn’t write the script, so we have to wait until @KraxelHuber can have a look.

Well hopefully I can get it sorted out soon. I don’t mind the Synology apps, except in this case because I cant easily get my notes back out “intact”.

Im really wanting to give Joplin a shot, especially since it now has a wysiwyg editor.

I am now stuck at the exact same error. Hopefully we can get it sorted soon.