initial commit

This commit is contained in:
daniel
2020-05-14 15:18:18 +02:00
commit 3eb4a3f443
5 changed files with 180 additions and 0 deletions

106
bin/sync_zotero_rm Normal file
View File

@@ -0,0 +1,106 @@
#!/usr/bin/env python3
from pyzotero import zotero
from webdav3.client import Client
from tempfile import TemporaryDirectory
from os.path import join
import subprocess
import zipfile
from rmapy.api import Client as RMClient
from rmapy.folder import Folder
from rmapy.document import Document
from rmapy.document import ZipDocument
from sync_zotero_rm.config import get_config
if __name__ == "__main__":
# get/create config
cfg = get_config()
# TODO init remarkabel connection
# init all services and apis we need
zot = zotero.Zotero(cfg['zot_user_id'], "user", cfg['zot_api_key'])
rmapy = RMClient()
rmapy.renew_token()
# used for zotero pdf download
webdav = Client({
"webdav_hostname": cfg['webdav_url'],
"webdav_login": cfg['webdav_user'],
"webdav_password": cfg['webdav_password']
})
# temp dir for file processing
tempdir = TemporaryDirectory()
# find the zotero collection key
print("Fetching collection from Zotero... ", end="", flush=True)
zot_collections = zot.collections()
for collection in zot_collections:
if collection['data']['name'] == cfg['zot_collection']:
zot_collection_key = collection['data']['key']
print("Done")
# get pdf items in collection
print("Fetching item list... ", end="", flush=True)
zot_items = zot.collection_items(zot_collection_key)
zot_items_pdf = [item for item in zot_items
if "contentType" in item['data']
and item['data']['contentType'] == "application/pdf"
]
print("Done")
print(f"Items to sync: {len(zot_items_pdf)}")
# get existing documents and folders on remarkable
rm_items = rmapy.get_meta_items()
rm_folders = [f for f in rm_items if isinstance(f, Folder)]
rm_documents = [f for f in rm_items if isinstance(f, Document)]
rm_existing_names = [f.VissibleName for f in rm_documents]
# find or create correct folder on remarkable
folder = [f for f in rm_folders if f.VissibleName == cfg['rm_folder']]
if len(folder) > 0:
folder = folder[0]
else: # folder does not exist yet
print(f"Creating folder {remarkable_folder}")
folder = Folder(cfg['rm_folder'])
rmapy.create_folder(folder)
# Process items
for item in zot_items_pdf:
title = item['data']['title']
print(title)
if title[:-4] in rm_existing_names:
print("skip (already exists)")
else:
# Download via webdav
print("download, ", end="", flush=True)
key = item['key']
local_path = join(tempdir.name, f"{key}.zip")
webdav.download_sync(remote_path=f"{key}.zip", local_path=local_path)
# Unpack file
print("unpack, ", end="", flush=True)
with zipfile.ZipFile(local_path, "r") as zip:
zip.extract(title, path=tempdir.name)
file_path = join(tempdir.name, title)
# Upload to RM
print("upload ", end="", flush=True)
rawDocument = ZipDocument(doc=file_path)
success = rmapy.upload(rawDocument, folder)
if success:
print("done")
else:
print("Upload failed")
exit(1)
# Delete files from zotero collection
print("Removing items from zotero collection")
for item in zot_items:
if item['data']['itemType'] == "attachment":
continue
zot.deletefrom_collection(zot_collection_key, item)

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
rmapy==0.2.1
Pyzotero==1.4.16
webdavclient3==3.14.4

14
setup.py Normal file
View File

@@ -0,0 +1,14 @@
from setuptools import setup, find_packages
install_reqs = [line.strip() for line in open("requirements.txt").readlines()]
packs = find_packages(exclude=["bin"])
setup(
name="sync_zotero_rm",
version="0.0.1",
author="Daniel Bauer",
description="Sync zotero collections to remarkable devices",
install_requires=install_reqs,
scripts=["bin/sync_zotero_rm"],
packages=packs
)

View File

57
sync_zotero_rm/config.py Normal file
View File

@@ -0,0 +1,57 @@
import yaml
from pathlib import Path
from os.path import join
CONFIG_FILE = join(str(Path.home()), ".zotero_remarkable.yaml")
def _read_config():
try:
with open(CONFIG_FILE, "r") as f:
return yaml.safe_load(f)
except:
return None
def _write_config(cfg):
with open(CONFIG_FILE, "w", encoding="utf8") as f:
yaml.dump(cfg, f, default_flow_style=False, allow_unicode=True)
def _check_config(cfg):
if not isinstance(cfg, dict):
return False
valid = True
for i in [
"zot_api_key",
"zot_user_id",
"zot_collection",
"webdav_url",
"webdav_user",
"webdav_password",
"rm_folder"]:
if i not in cfg:
valid = False
return valid
def _create_config():
cfg = {}
for i in [
"zot_api_key",
"zot_user_id",
"zot_collection",
"webdav_url",
"webdav_user",
"webdav_password",
"rm_folder"]:
answer = input(i + ": ")
cfg[i] = answer.strip()
_write_config(cfg)
return cfg
def get_config():
cfg = _read_config()
if not _check_config(cfg):
return _create_config()
else:
return cfg