def deliver_issue(self, absolute_path: str):
        """Deliver issues to the ReMarkable.

        :param absolute_path: An absolute path for the epub file.
        """
        # Ensure a "News Assistant" folder exists
        collection = self.client.get_meta_items()
        root_folders = [
            f for f in collection if isinstance(f, Folder) and f.Parent == ""
        ]

        delivery_folder_filter = [
            f for f in root_folders if f.VissibleName == DELIVERY_FOLDER
        ]
        if len(delivery_folder_filter) == 0:
            folder = Folder(DELIVERY_FOLDER)
            self.client.create_folder(folder)
            delivery_folder_filter.append(folder)

        delivery_folder = delivery_folder_filter[0]

        # Upload the issue
        pdf_path = RemarkableDelivery.convert_issue_to_pdf(absolute_path)
        document = ZipDocument(doc=pdf_path)
        now = datetime.now()
        document.metadata["VissibleName"] = now.strftime("%d %B, %Y")
        self.client.upload(document, delivery_folder)
    def upload_document(self, local_id, local_version, cloud_id, cloud_version, path):
        content_dir = (
            self.sync_manager.push_dir(Remarkable) 
            + f'/{local_id}/{local_version}'
        )
        content_path = f'{content_dir}/{local_id}.pdf'
        
        if cloud_version:
            # reMarkable won't sync updates, need to delete 
            # and re-add
            to_delete = Document(ID=cloud_id, Version=cloud_version)
            self.rm_api.delete(to_delete)

        doc = ZipDocument(doc=content_path)
    
        folder = self.get_or_create_folder(path)
        doc.metadata['VissibleName'] = get_pdf_title(content_path) 
        doc.metadata['version'] = 1
        mapping_info = SyncMapping(
            remote_id=doc.ID,
            remote_version = 1,
            remote_path=path
        )
        print(f"push: document '{doc.metadata['VissibleName']}' {local_id} to {mapping_info.remote_path})")
        self.rm_api.upload(doc, folder)
        return mapping_info
Example #3
0
def transfer_file_to_remarkable(fname: str, config_dict: dict = None):
    from rmapy.document import ZipDocument
    from rmapy.api import Client

    rm = Client(config_dict=config_dict)
    rm.renew_token()
    doc = ZipDocument(doc=fname)
    rm.upload(doc)
    return True
Example #4
0
def transfer_file_to_remarkable(user_email: str, fname, fbytes):
    # logging.info(f"Asking for {user_email} credentials...")
    cfg = get_config_for_user(user_email)
    rm = Client(config_dict=cfg)
    # Annoychops; gotta save to disk. Bummski!
    tfile = tempfile.NamedTemporaryFile(prefix=fname, suffix=".pdf")
    tfile.write(fbytes)
    tfile.seek(0)

    doc = ZipDocument(doc=tfile.name)
    rm.upload(doc)
Example #5
0
def upload(filepath=None, replace=False):

    if not filepath:
        parser = argparse.ArgumentParser(
            "Upload Goosepaper to reMarkable tablet")
        parser.add_argument(
            "file",
            default=None,
            help="The file to upload",
        )
        args = parser.parse_args()
        filepath = args.file

    filepath = Path(filepath)

    client = Client()

    try:
        client.renew_token()
    except AuthError:
        print(
            "Looks like this if the first time you've uploaded, need to register the device"
        )
        print(
            "Get the code from here: https://my.remarkable.com/connect/remarkable"
        )
        code = input()
        print("registering")
        client.register_device(code)
        if not client.renew_token():
            print("registration failed D:")
        else:
            print("registration successful")

    for item in client.get_meta_items():
        if item.VissibleName == filepath.stem:
            if replace:
                client.delete(item)
            else:
                print("Honk! Paper already exists!")
                return False

    doc = ZipDocument(doc=str(filepath.resolve()))
    if client.upload(doc):
        print("Honk! Upload successful!")
    else:
        print("Honk! Error with upload!")

    return True
Example #6
0
def main():
    todo_manager = TodoManager()
    today = date.today()
    pdf_path = '/tmp/Today-{}.pdf'.format(today.strftime("%b-%d-%Y"))
    todo_string = todo_manager.getToDoListString()
    f = open(MARKDOWN_PATH, "w")
    f.write(todo_string)
    f.close()
    r = subprocess.run(['pandoc', '-s', MARKDOWN_PATH, '-o', pdf_path],
                       stdout=subprocess.PIPE,
                       universal_newlines=True)
    rm = Client()
    rm.renew_token()
    rawDocument = ZipDocument(doc=pdf_path)
    rm.upload(rawDocument)
    print(todo_string)
Example #7
0
def upload_rm_doc(name, rms):

    empty_jpg = Path(__file__).parent / "empty.jpg"
    empty_jpg_bytes = empty_jpg.read_bytes()

    rmapy = Client()
    if not rmapy.is_auth():
        raise Exception("Not authenticated")
    rmapy.renew_token()

    rmps = []
    for rm in rms:

        layer_counter = count(1)

        buffer = BytesIO()
        rm.to_bytes(buffer)
        buffer.seek(0)

        uuid = str(uuid4())

        rmp = RmPage(
            buffer,
            metadata={
                "layers": [{
                    "name":
                    layer.name
                    if layer.name else f"Layer {next(layer_counter)}"
                } for layer in rm.objects]
            },
            thumbnail=BytesIO(empty_jpg_bytes),
            order=uuid,
        )

        rmps.append(rmp)

    zd = ZipDocument()
    zd.content["fileType"] = "notebook"
    zd.content["pages"] = [rmp.order for rmp in rmps]
    zd.content["pageCount"] = len(rmps)
    zd.metadata["VissibleName"] = name
    zd.pagedata = "\n".join(["Blank"] * len(rmps))
    zd.rm.extend(rmps)

    rmapy.upload(zd)
Example #8
0
def transfer_file_to_remarkable(user_email: str, fname, fbytes):
    plog(f"* Asking for {user_email} credentials...")
    cfg = renew_user_token(user_email)
    rm = Client(config_dict=cfg)
    # Annoychops; gotta save to disk. Bummski!
    tfile = tempfile.NamedTemporaryFile(prefix=fname, suffix=".pdf")
    tfile.write(fbytes)
    tfile.seek(0)

    plog(f"* Generating zip...")
    doc = ZipDocument(doc=tfile.name)
    plog(f"* Uploading to device.")
    rm.upload(doc)
    plog("Success.")
    send_email_if_enabled(
        user_email,
        subject="Your document is on the way!",
        message=
        f"Your document, '{fname}', has been successfully sent to your reMarkable.",
    )
Example #9
0
def main():
    wallabag = Wallabag()
    wallabag.wallabagLogin()
    rmapy = Remarkable()
    rmapy.renew_token()
    collection = rmapy.get_meta_items()
    unread = [
        f for f in collection
        if isinstance(f, Folder) and f.VissibleName == UNREAD_FOLDER
    ][0]
    favourites = [
        f for f in collection
        if isinstance(f, Folder) and f.VissibleName == FAVOURITES_FOLDER
    ][0]
    archive = [
        f for f in collection
        if isinstance(f, Folder) and f.VissibleName == ARCHIVE_FOLDER
    ][0]
    titles = set(f.VissibleName for f in collection
                 if f.Parent in [unread.ID, archive.ID, favourites.ID])
    for w in wallabag.getEntries()[:50]:
        title = f"{w['title']} - {w['id']}"
        w_modifiedtime = datetime.strptime(w["updated_at"],
                                           "%Y-%m-%dT%H:%M:%S%z")
        if w["is_archived"] == 0:
            target = unread
        elif w["is_starred"] == 1:
            target = favourites
        else:
            target = archive
        if title not in titles:
            with tempfile.NamedTemporaryFile(suffix=".epub") as f:
                wallabag.export(w["id"], f.file)
                rawDocument = ZipDocument(doc=f.name)
                rawDocument.metadata["VissibleName"] = title
                rawDocument.metadata[
                    "ModifiedClient"] = w_modifiedtime.astimezone(
                        tz=timezone.utc).strftime(RFC3339Nano)
                rmapy.upload(rawDocument, target)
                print(f"Uploaded {title} to {target.VissibleName}")
        else:
            rm_doc = [f for f in collection if f.VissibleName == title][0]
            try:
                rm_mod_time = datetime.strptime(
                    rm_doc.ModifiedClient,
                    "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc)
            except ValueError:
                rm_mod_time = datetime.strptime(
                    rm_doc.ModifiedClient,
                    "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=timezone.utc)
            if rm_doc.Parent == target.ID:
                continue
            elif w_modifiedtime >= rm_mod_time:
                print(
                    f"{title} in wrong folder and more recent in Wallabag, moving to {target.VissibleName}..."
                )
                rm_doc.Parent = target.ID
                rm_doc.ModifiedClient = w_modifiedtime.astimezone(
                    tz=timezone.utc).strftime(RFC3339Nano)
                rmapy.update_metadata(rm_doc)
            else:
                # Wrong message, should be parents "vissiblename"
                print(
                    f"{title} moved to {target.VissibleName}, updating Wallabag..."
                )
                if rm_doc.Parent == archive.ID:
                    wallabag.updateEntry(w, archive=True, starred=False)
                elif rm_doc.Parent == favourites.ID:
                    wallabag.updateEntry(w, archive=True, starred=True)
                elif rm_doc.Parent == unread.ID:
                    wallabag.updateEntry(w, archive=False)
                else:
                    print(
                        "Found some edge case when searching for Wallabag location."
                    )
Example #10
0
def do_upload(filepath, multiparser):

    filepath = Path(filepath)
    replace = (False if multiparser.argumentOrConfig("noreplace") else
               multiparser.argumentOrConfig("replace"))
    folder = multiparser.argumentOrConfig("folder")
    cleanup = multiparser.argumentOrConfig("cleanup")
    strictlysane = multiparser.argumentOrConfig("strictlysane")
    nocase = multiparser.argumentOrConfig("nocase")

    if strictlysane:
        nocase = True

    if multiparser.argumentOrConfig("showconfig"):
        print("\nParameters passed to do_upload\n----------------\n")
        print(
            "Replace:\t{0}\nFolder:\t\t{1}\nCleanup:\t{2}\nStrictlysane:\t{3}\nNocase:\t\t{4}\nFilepath:\t{5}\n"
            .format(replace, folder, cleanup, strictlysane, nocase, filepath))

    client = auth_client()

    if not client:
        print("Honk Honk! Couldn't auth! Is your rmapy configured?")
        return False

    if not validateFolder(folder):
        return False

    # Added error handling to deal with possible race condition where the file is mangled
    # or not written out before the upload actually occurs such as an AV false positive.
    # 'pdf' is a simple throwaway file handle to make sure that we retain control of the
    # file while it's being imported.

    try:
        with open(filepath.resolve()) as pdf:
            doc = ZipDocument(doc=str(filepath.resolve()))
    except IOError as err:
        print(f"Error locating or opening {filepath}")
        return False

    paperCandidates = []
    paperFolder = None

    for item in getallitems(client):

        # is it the folder we are looking for?
        if (folder and item.Type == "CollectionType"  # is a folder
                and item.VissibleName.lower()
                == folder.lower()  # has the name we're looking for
                and (item.Parent == None
                     or item.Parent == "")):  # is not in another folder
            paperFolder = item

        # is it possibly the file we are looking for?
        elif (item.Type == "DocumentType" and item.VissibleName.lower() == str(
                doc.metadata["VissibleName"]).lower()):
            paperCandidates.append(item)

    for paper in paperCandidates:
        parent = client.get_doc(paper.Parent)

        # if the folder was found, check if a paper candidate is in it
    paper = None
    if len(paperCandidates) > 0:
        if folder:
            filtered = list(
                filter(lambda item: item.Parent == paperFolder.ID,
                       paperCandidates))
        else:
            filtered = list(
                filter(
                    lambda item: item.Parent != "trash" and client.get_doc(
                        item.Parent) == None,
                    paperCandidates,
                ))

        if len(filtered) > 1 and replace:
            print(
                f"multiple candidate papers with the same name {filtered[0].VissibleName}, don't know which to delete"
            )
            return False
        if len(filtered) == 1:  # found the outdated paper
            paper = filtered[0]

    if paper is not None:
        if replace:
            result = client.delete(paper)
        else:
            print("Honk! The paper already exists!")
            return False

    if folder and not paperFolder:
        paperFolder = Folder(folder)
        if not client.create_folder(paperFolder):
            print("Honk! Failed to create the folder!")
            return False

    # workarround rmapy bug: client.upload(doc) would set a non-existing parent
    # ID to the document
    if not paperFolder:
        paperFolder = Folder()
        paperFolder.ID = ""
    if isinstance(paperFolder, Folder):
        result = client.upload(doc, paperFolder)
        if result:
            print("Honk! Upload successful!")
            if cleanup:
                try:
                    os.remove(filepath.resolve())
                except:
                    print(
                        "Honk! Honk! Failed to remove file after upload: {0}".
                        format(filepath.resolve()))
                    return False
        else:
            print("Honk! Error with upload!")
        return result
    else:
        print("Honk! Could not upload: Document already exists.")
    return False
Example #11
0
from rmapy.api import Client
from rmapy.document import ZipDocument, Document

FILENAME = 'notes.pdf'

rmapy = Client()

# This registers the client as a new device. The received device token is
# stored in the users directory in the file ~/.rmapi, the same as with the
# go rmapi client.
# rmapy.register_device("kmdfhcsf")

rmapy.renew_token()

rawDocument = ZipDocument(doc=FILENAME)

collection = rmapy.get_meta_items()

# Gather old versions to delete
old = [
    f for f in collection
    if isinstance(f, Document) and f.VissibleName == 'notes'
]

rmapy.upload(rawDocument)

for f in old:
    rmapy.delete(f)
Example #12
0
def upload(filepath, replace=False, folder=None):

    client = auth_client()

    if not client:
        print("Honk Honk! Couldn't auth! Is your rmapy configured?")
        return False

    if not validateFolder(folder):
        return False

    filepath = Path(filepath)

    # Added error handling to deal with possible race condition where the file is mangled
    # or not written out before the upload actually occurs such as an AV false positive.
    # 'pdf' is a simple throwaway file handle to make sure that we retain control of the
    # file while it's being imported.

    try:
        with open(filepath.resolve()) as pdf:
            doc = ZipDocument(doc=str(filepath.resolve()))
    except IOError as err:
        print(f"Error locating or opening {filepath}")
        return False

    paperCandidates = []
    paperFolder = None

    for item in getallitems(client):

        # is it the folder we are looking for?
        if (folder and item.Type == "CollectionType"  # is a folder
                and item.VissibleName.lower()
                == folder.lower()  # has the name we're looking for
                and (item.Parent == None
                     or item.Parent == "")):  # is not in another folder
            paperFolder = item

        # is it possibly the file we are looking for?
        elif item.Type == "DocumentType" and item.VissibleName.lower() == str(
                doc.metadata["VissibleName"]).lower():
            paperCandidates.append(item)

    for paper in paperCandidates:
        if paper.Parent == "trash":
            continue
        parent = client.get_doc(paper.Parent)

    # if the folder was found, check if a paper candidate is in it
    paper = None
    if len(paperCandidates) > 0:
        if folder:
            filtered = list(
                filter(lambda item: item.Parent == paperFolder.ID,
                       paperCandidates))
        else:
            filtered = list(
                filter(
                    lambda item: item.Parent != "trash" and client.get_doc(
                        item.Parent) == None, paperCandidates))

        if len(filtered) > 1 and replace:
            print(
                f"multiple candidate papers with the same name {filtered[0].VissibleName}, don't know which to delete"
            )
            return False
        if len(filtered) == 1:  # found the outdated paper
            paper = filtered[0]

    if paper is not None:
        if replace:
            result = client.delete(paper)
        else:
            print("Honk! The paper already exists!")
            return False

    if folder and not paperFolder:
        paperFolder = Folder(folder)
        if not client.create_folder(paperFolder):
            print("Honk! Failed to create the folder!")
            return False

    # workarround rmapy bug: client.upload(doc) would set a non-existing parent ID to the document
    if not paperFolder:
        paperFolder = Folder()
        paperFolder.ID = ""
    if isinstance(paperFolder, Folder):
        result = client.upload(doc, paperFolder)
        if result:
            print("Honk! Upload successful!")
        else:
            print("Honk! Error with upload!")
        return result
    else:
        print("Honk! Could not upload: Document already exists.")
    return False
Example #13
0
#!/usr/bin/python3.7
from rmapy.document import ZipDocument
from rmapy.api import Client
from os import listdir

rmapy = Client()
# This registers the client as a new device. The received device token is
# stored in the users directory in the file ~/.rmapi, the same as with the
# go rmapi client.
# rmapy.register_device("ayvnpfoc")
# It's always a good idea to refresh the user token every time you start
# a new session.
rmapy.renew_token()
# Should return True

# delete the old one
collection = rmapy.get_meta_items()
oldWapo = [d for d in collection if d.VissibleName == 'The Washington Post']
if len(oldWapo) > 0:
    rmapy.delete(oldWapo[0])

# rawDocument = ZipDocument(doc="wapo.pdf")
# rawDocument.metadata["VissibleName"]="The Washington Post"
uuid = listdir("ZipDocument")[0].split('.')[0]
rawDocument = ZipDocument(uuid, file="wapo.zip")
rawDocument.metadata["VissibleName"] = "The Washington Post"

rmapy.upload(rawDocument)
Example #14
0
 def upload_file_to_folder(self, file: str, folder_name: str):
     folder = self._find_folder(folder_name)
     document = ZipDocument(doc=file)
     document.metadata["VissibleName"] = Path(file).stem
     self._rmapy.upload(document, folder)
import sys
from rmapy.document import ZipDocument
from rmapy.api import Client

rmapy_client = Client()
rmapy_client.renew_token()
doc = ZipDocument(doc=sys.argv[1])
rmapy_client.upload(doc)