aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGertjan van den Burg <gertjanvandenburg@gmail.com>2021-01-08 22:10:37 +0000
committerGertjan van den Burg <gertjanvandenburg@gmail.com>2021-01-08 22:10:37 +0000
commitfc8fabb0b1e99e7eabfc6945b8ba012a624cd7e5 (patch)
tree1a827ed6aa0724f9e482e1a4be23be6de699e763
parentBump version and update changelog (diff)
downloadpaper2remarkable-fc8fabb0b1e99e7eabfc6945b8ba012a624cd7e5.tar.gz
paper2remarkable-fc8fabb0b1e99e7eabfc6945b8ba012a624cd7e5.zip
[WIP] Add support for using rmapy as reMarkable client
-rw-r--r--paper2remarkable/providers/_base.py2
-rw-r--r--paper2remarkable/remarkable.py182
-rw-r--r--paper2remarkable/utils.py34
-rw-r--r--setup.py1
4 files changed, 185 insertions, 34 deletions
diff --git a/paper2remarkable/providers/_base.py b/paper2remarkable/providers/_base.py
index 0453c7a..2df73e3 100644
--- a/paper2remarkable/providers/_base.py
+++ b/paper2remarkable/providers/_base.py
@@ -18,12 +18,12 @@ import time
from ..exceptions import _CalledProcessError
from ..log import Logger
from ..pdf_ops import prepare_pdf, blank_pdf, shrink_pdf
+from ..remarkable import upload_to_remarkable
from ..utils import (
assert_file_is_pdf,
check_pdftool,
download_url,
follow_redirects,
- upload_to_remarkable,
)
from ._info import Informer
diff --git a/paper2remarkable/remarkable.py b/paper2remarkable/remarkable.py
new file mode 100644
index 0000000..b9c32c2
--- /dev/null
+++ b/paper2remarkable/remarkable.py
@@ -0,0 +1,182 @@
+# -*- coding: utf-8 -*-
+
+"""Module for dealing with transfers to the reMarkable
+
+Author: G.J.J. van den Burg
+License: See LICENSE file
+Copyright: 2021, G.J.J. van den Burg
+
+
+"""
+
+import subprocess
+
+from .exceptions import RemarkableError
+from .log import Logger
+
+
+logger = Logger()
+
+
+def upload_to_remarkable_rmapi(
+ filepath, remarkable_dir="/", rmapi_path="rmapi"
+):
+ logger.info("Starting upload to reMarkable using rMapi")
+
+ # Create the reMarkable dir if it doesn't exist
+ remarkable_dir = remarkable_dir.rstrip("/")
+ if remarkable_dir:
+ parts = remarkable_dir.split("/")
+ rmdir = ""
+ while parts:
+ rmdir += "/" + parts.pop(0)
+ status = subprocess.call(
+ [rmapi_path, "mkdir", rmdir],
+ stdout=subprocess.DEVNULL,
+ )
+ if not status == 0:
+ raise RemarkableError(
+ "Creating directory %s on reMarkable failed"
+ % remarkable_dir
+ )
+
+ # Upload the file
+ status = subprocess.call(
+ [rmapi_path, "put", filepath, remarkable_dir + "/"],
+ stdout=subprocess.DEVNULL,
+ )
+ if not status == 0:
+ raise RemarkableError(
+ "Uploading file %s to reMarkable failed" % filepath
+ )
+ logger.info("Upload successful.")
+
+
+def upload_to_remarkable_rmapy(filepath, remarkable_dir="/"):
+ from rmapy.api import Client
+ from rmapy.document import ZipDocument
+ from rmapy.folder import Folder
+ from rmapy.exceptions import ApiError, AuthError
+
+ client = Client()
+ if not client.is_auth():
+ print(
+ "\nThe reMarkable needs to be authenticated before we can upload."
+ )
+ print("Please visit:\n")
+ print("\thttps://my.remarkable.com/connect/desktop")
+ print("\nand copy the one-time code for a desktop application.\n")
+ code = input("Please enter the one-time code: ")
+ code = code.strip()
+ print()
+ try:
+ client.register_device(code)
+ except AuthError:
+ raise RemarkableError(
+ "Failed to authenticate the reMarkable client"
+ )
+
+ client.renew_token()
+ if not client.is_auth():
+ raise RemarkableError("Failed to authenticate the reMarkable client")
+
+ logger.info("Starting upload to reMarkable using rmapy")
+
+ remarkable_dir = remarkable_dir.rstrip("/")
+ if remarkable_dir:
+ parts = remarkable_dir.split("/")
+ parent_id = ""
+
+ while parts:
+ rmdir = parts.pop(0)
+ if not rmdir:
+ continue
+
+ # get the folders with the desired parent
+ folders = [
+ i for i in client.get_meta_items() if isinstance(i, Folder)
+ ]
+ siblings = [f for f in folders if f.Parent == parent_id]
+
+ # if the folder already exists, record its ID and continue
+ match = next(
+ (f for f in siblings if f.VissibleName == rmdir), None
+ )
+ if not match is None:
+ parent_id = match.ID
+ continue
+
+ # create a new folder with the desired parent
+ new_folder = Folder(rmdir)
+ new_folder.Parent = parent_id
+
+ try:
+ client.create_folder(new_folder)
+ except ApiError:
+ raise RemarkableError(
+ "Creating directory %s on reMarkable failed"
+ % remarkable_dir
+ )
+ parent_id = new_folder.ID
+
+ # upload target is the folder with the last recorded parent_id
+ target = next(
+ (
+ i
+ for i in client.get_meta_items()
+ if isinstance(i, Folder) and i.ID == parent_id
+ ),
+ None,
+ )
+ if target is None:
+ raise RemarkableError(
+ "Creating directory %s on reMarkable failed" % remarkable_dir
+ )
+ else:
+ target = Folder(ID="")
+
+ doc = ZipDocument(doc=filepath)
+ try:
+ client.upload(zip_doc=doc, to=target)
+ except ApiError:
+ raise RemarkableError(
+ "Uploading file %s to reMarkable failed" % filepath
+ )
+ logger.info("Upload successful.")
+
+
+def get_remarkable_backend(rmapi_path="rmapi"):
+ try:
+ status = subprocess.call(
+ [rmapi_path, "version"],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ )
+ except FileNotFoundError:
+ pass
+
+ if status == 0:
+ return "rmapi"
+
+ try:
+ import rmapy
+
+ assert rmapy
+
+ return "rmapy"
+ except ImportError:
+ pass
+
+ return None
+
+
+def upload_to_remarkable(filepath, remarkable_dir="/", rmapi_path="rmapi"):
+ backend = get_remarkable_backend(rmapi_path=rmapi_path)
+ if backend is None:
+ raise RemarkableError("Couldn't find a suitable reMarkable client.")
+ if backend == "rmapi":
+ upload_to_remarkable_rmapi(
+ filepath, remarkable_dir=remarkable_dir, rmapi_path=rmapi_path
+ )
+ elif backend == "rmapy":
+ upload_to_remarkable_rmapy(filepath, remarkable_dir=remarkable_dir)
diff --git a/paper2remarkable/utils.py b/paper2remarkable/utils.py
index 2432916..aed390b 100644
--- a/paper2remarkable/utils.py
+++ b/paper2remarkable/utils.py
@@ -17,7 +17,7 @@ import time
import unidecode
from .log import Logger
-from .exceptions import FileTypeError, RemarkableError, NoPDFToolError
+from .exceptions import FileTypeError, NoPDFToolError
HEADERS = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) "
@@ -138,38 +138,6 @@ def follow_redirects(url):
return url, jar
-def upload_to_remarkable(filepath, remarkable_dir="/", rmapi_path="rmapi"):
- logger.info("Starting upload to reMarkable")
-
- # Create the reMarkable dir if it doesn't exist
- remarkable_dir = remarkable_dir.rstrip("/")
- if remarkable_dir:
- parts = remarkable_dir.split("/")
- rmdir = ""
- while parts:
- rmdir += "/" + parts.pop(0)
- status = subprocess.call(
- [rmapi_path, "mkdir", rmdir],
- stdout=subprocess.DEVNULL,
- )
- if not status == 0:
- raise RemarkableError(
- "Creating directory %s on reMarkable failed"
- % remarkable_dir
- )
-
- # Upload the file
- status = subprocess.call(
- [rmapi_path, "put", filepath, remarkable_dir + "/"],
- stdout=subprocess.DEVNULL,
- )
- if not status == 0:
- raise RemarkableError(
- "Uploading file %s to reMarkable failed" % filepath
- )
- logger.info("Upload successful.")
-
-
def is_url(string):
# pattern adapted from CleverCSV
pattern = "((https?|ftp):\/\/(?!\-))?(((([\p{L}\p{N}]*[\-\_]?[\p{L}\p{N}]+)+\.)+([a-z]{2,}|local)(\.[a-z]{2,3})?)|localhost|(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\:\d{1,5})?))(\/[\p{L}\p{N}_\/()~?=&%\-\#\.:+]*)?(\.[a-z]+)?"
diff --git a/setup.py b/setup.py
index e529cc2..37c5e57 100644
--- a/setup.py
+++ b/setup.py
@@ -28,6 +28,7 @@ REQUIRED = [
"readability-lxml>=0.7.1",
"regex>=2018.11",
"requests>=2.21",
+ "rmapy>=0.2.2",
"titlecase>=0.12",
"unidecode>=1.1",
"weasyprint>=51",