Skip to main content

Python API for Joplin

Project description

joppy

Python interface for the Joplin data API (client) and the Joplin server API.

build lint tests codecov

https://img.shields.io/badge/Joplin-3.0.15-blueviolet Python version

Features

Client API Wrapper Server API Wrapper
Supported All functions from the data API Some reverse engineered functions with a similar interface like the client API wrapper. See the example below and the source code for details.
Not Supported - - Encryption
- Some functions that were either to complex or I didn't see a use for automation.

:computer: Installation

From pypi:

pip install joppy

From source:

git clone https://github.com/marph91/joppy.git
cd joppy
pip install .

:wrench: Usage

Please backup your data before use!

General function description

  • add_<type>(): Create a new element.
  • delete_<type>(): Delete an element by ID.
  • get_<type>(): Get an element by ID.
  • get_all_<type>(): Get all elements of a kind.
  • modify_<type>(): Modify an elements property by ID.
  • search_all(): Search elements using joplins search engine.

For details, consult the implementation, joplin documentation or create an issue.

:bulb: Example snippets

Client API

Start joplin and get your API token. Click to expand the examples.

Get all notes
from joppy.client_api import ClientApi

# Create a new Api instance.
api = ClientApi(token=YOUR_TOKEN)

# Get all notes. Note that this method calls get_notes() multiple times to assemble the unpaginated result.
notes = api.get_all_notes()
Add a tag to a note
from joppy.client_api import ClientApi

# Create a new Api instance.

api = ClientApi(token=YOUR_TOKEN)

# Add a notebook.

notebook_id = api.add_notebook(title="My first notebook")

# Add a note in the previously created notebook.

note_id = api.add_note(title="My first note", body="With some content", parent_id=notebook_id)

# Add a tag, that is not yet attached to a note.

tag_id = api.add_tag(title="introduction")

# Link the tag to the note.

api.add_tag_to_note(tag_id=tag_id, note_id=note_id)
Add a resource to a note
from joppy.client_api import ClientApi
from joppy import tools

# Create a new Api instance.
api = ClientApi(token=YOUR_TOKEN)

# Add a notebook.
notebook_id = api.add_notebook(title="My first notebook")

# Option 1: Add a note with an image data URL. This works only for images.
image_data = tools.encode_base64("path/to/image.png")
api.add_note(
    title="My first note",
    image_data_url=f"data:image/png;base64,{image_data}",
)

# Option 2: Create note and resource separately. Link them later. This works for arbitrary attachments.
note_id = api.add_note(title="My second note")
resource_id = api.add_resource(filename="path/to/image.png", title="My first resource")
api.add_resource_to_note(resource_id=resource_id, note_id=note_id)
Bulk remove tags

Inspired by https://discourse.joplinapp.org/t/bulk-tag-delete-python-script/5497/1.

import re

from joppy.client_api import ClientApi

# Create a new Api instance.
api = ClientApi(token=YOUR_TOKEN)

# Iterate through all tags.
for tag in api.get_all_tags():

    # Delete all tags that match the regex. I. e. start with "!".
    if re.search("^!", tag.title) is not None:
        api.delete_tag(tag.id)
Remove unused tags

Reference: https://discourse.joplinapp.org/t/prune-empty-tags-from-web-clipper/36194

from joppy.client_api import ClientApi

# Create a new Api instance.
api = ClientApi(token=YOUR_TOKEN)

for tag in api.get_all_tags():
    notes_for_tag = api.get_all_notes(tag_id=tag.id)
    if len(notes_for_tag) == 0:
        print("Deleting tag:", tag.title)
        api.delete_tag(tag.id)
Remove spaces from tags

Reference: https://www.reddit.com/r/joplinapp/comments/pozric/batch_remove_spaces_from_all_tags/

import re

from joppy.client_api import ClientApi

# Create a new Api instance.
api = ClientApi(token=YOUR_TOKEN)

# Define the conversion function.
def to_camel_case(name: str) -> str:
    name = re.sub(r"(_|-)+", " ", name).title().replace(" ", "")
    return "".join([name[0].lower(), name[1:]])

# Iterate through all tags and apply the conversion.
for tag in api.get_all_tags():
    api.modify_tag(id_=tag.id, title=to_camel_case(tag.title))
Remove orphaned resources

Inspired by https://discourse.joplinapp.org/t/joplin-vacuum-a-python-script-to-remove-orphaned-resources/19742. Note: The note history is not considered. See: https://discourse.joplinapp.org/t/joplin-vacuum-a-python-script-to-remove-orphaned-resources/19742/13.

import re

from joppy.client_api import ClientApi

# Create a new Api instance.
api = ClientApi(token=YOUR_TOKEN)

# Getting the referenced resource directly doesn't work:
# https://github.com/laurent22/joplin/issues/4535
# So we have to find the referenced resources by regex.

# Iterate through all notes and find the referenced resources.
referenced_resources = set()
for note in api.get_all_notes(fields="id,body"):
    matches = re.findall(r"\[.*\]\(:.*\/([A-Za-z0-9]{32})\)", note.body)
    referenced_resources.update(matches)

assert len(referenced_resources) > 0, "sanity check"

for resource in api.get_all_resources():
    if resource.id not in referenced_resources:
        print("Deleting resource:", resource.title)
        api.delete_resource(resource.id)

For more usage examples, check the example scripts or tests.

Server API

The server API should work similarly to the client API in most cases. Be aware that the server API is experimental and may break at any time. I can't provide any help at sync issues or lost data. Make sure you have a backup and know how to restore it.

from joppy.server_api import ServerApi

# Create a new Api instance.
api = ServerApi(user="admin@localhost", password="admin", url="http://localhost:22300")

# Acquire a lock.
with api.sync_lock():

    # Add a notebook.
    notebook_id = api.add_notebook(title="My first notebook")

    # Add a note in the previously created notebook.
    note_id = api.add_note(title="My first note", body="With some content", parent_id=notebook_id)

:newspaper: Examples

Before using joppy, you should check the Joplin plugins. They are probably more convenient. However, if you need a new feature or just want to code in python, you can use joppy.

Apps

App Description
jimmy A tool to import your notes to Joplin
joplin-sticky-notes Stick your Joplin notes to the desktop
joplin-vieweb A simple web viewer for Joplin

Scripts

Script Description
custom_export.py Export resources next to notes, instead of a separate folder.
note_export.py Export notes to any format supported by pandoc.
note_stats.py Get some simple statistics about your notes, based on nltk.
note_tree_export.py Joplin only supports PDF export of a single note. This script allows to export one, multiple or all notebooks to PDF or TXT.
visualize_note_locations.py Visualize the locations of your notes.
joplin-ui-tests System tests for the joplin desktop app. Based on selenium.

:sunny: Tests

To run the tests, some additional system packages and python modules are needed. After installing them, just run:

python -m unittest

It's possible to configure the test run via some environment variables:

  • SLOW_TESTS: Set this variable to run the slow tests. Default not set.
  • API_TOKEN: Set this variable if there is already a joplin instance running. Don't use your default joplin profile! By default, a joplin instance is started inside xvfb. This takes some time, but works for CI.

:book: Changelog

1.0.0

  • Rename the client API. It should be used by from joppy.client_api import ClientApi instead of from joppy.client_api import ClientApi now.
  • Add support for the server API (https://github.com/marph91/joppy/pull/27). It should be used by from joppy.server_api import ServerApi.

0.2.3

  • Don't use the root logger for logging.
  • Add support for revisions.

0.2.2

0.2.1

  • Fix PDF output example (https://github.com/marph91/joppy/issues/19).
  • :warning: Drop tests for python 3.6, since it's EOL. It may still work.
  • Fix the type of todo_completed and todo_due. They are a unix timestamp, not a bool.

0.1.1

  • Add typing support to the pypi module.

0.1.0

0.0.7

0.0.6

  • Add convenience method for deleting all notes.
  • Add example scripts.

0.0.5

  • Fix package publishing workflow.

0.0.4

  • Add support for python 3.6 and 3.7.

0.0.3

0.0.2

  • CI and test improvements.
  • Move complete setup to setup.cfg.

0.0.1

  • Initial release.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

joppy-1.0.0.tar.gz (36.4 kB view details)

Uploaded Source

Built Distribution

joppy-1.0.0-py3-none-any.whl (25.1 kB view details)

Uploaded Python 3

File details

Details for the file joppy-1.0.0.tar.gz.

File metadata

  • Download URL: joppy-1.0.0.tar.gz
  • Upload date:
  • Size: 36.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.5

File hashes

Hashes for joppy-1.0.0.tar.gz
Algorithm Hash digest
SHA256 0b415cde65a04dbe83e4a1ece97babba7f242918017ee920176971d0a6888e2a
MD5 2e9097ad47f02382f20d2513d60d739b
BLAKE2b-256 8ba7786606efe86ac64b713454b5008550b822310fc42eccedca1c866fa2668c

See more details on using hashes here.

File details

Details for the file joppy-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: joppy-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 25.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.12.5

File hashes

Hashes for joppy-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 98b4091c95aa5195797fb727c4491b9babc013eacde0c1f6d8ac9d695df0f698
MD5 1d4fcb331d80224ba250504f3c95ab69
BLAKE2b-256 78a4068c62731052222cfacea558c705440b37c2c0d8368aa54ffb6269d07b3d

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page