papis: Add full code for papis-marvin plugin
This commit is contained in:
parent
fd12c2b962
commit
a7a8ebf8ed
1 changed files with 163 additions and 1 deletions
|
@ -1 +0,0 @@
|
|||
/home/marty/projects/python/papis/marvin/papis-marvin
|
163
writing/.config/papis/scripts/papis-marvin
Executable file
163
writing/.config/papis/scripts/papis-marvin
Executable file
|
@ -0,0 +1,163 @@
|
|||
#!/usr/bin/env python
|
||||
# papis-short-help: Import iOS Marvin exported csv annotations
|
||||
#
|
||||
# This script can be used to import your highlights and notes from
|
||||
# the iOS application 'Marvin Reader'. In the app, export your
|
||||
# annotations as 'csv' format and then point the script to the
|
||||
# resulting file.
|
||||
# https://git.martyoeh.me/Marty/papis-marvin
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import logging
|
||||
from typing import Dict
|
||||
import papis.api
|
||||
import papis.pick
|
||||
import papis.format
|
||||
import papis.commands.edit
|
||||
import papis.commands.list
|
||||
import papis.commands.add
|
||||
import papis.notes
|
||||
import papis.config
|
||||
import papis.database
|
||||
import isbnlib
|
||||
import papis.isbn
|
||||
|
||||
logger = logging.getLogger("marvin")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
DEFAULT_CSV_PATH = "/home/marty/Nextcloud/Personal/Backups/Journal.csv"
|
||||
|
||||
|
||||
def main(fpath, db):
|
||||
with open(fpath) as f:
|
||||
import csv
|
||||
|
||||
csv = csv.DictReader(f)
|
||||
notes = get_all_annotations(db, csv)
|
||||
|
||||
write_to_files(notes)
|
||||
|
||||
|
||||
def get_all_annotations(db, csv) -> Dict:
|
||||
notes = {}
|
||||
note_file = ""
|
||||
for row in csv:
|
||||
# switch to next book
|
||||
if not is_same_book(row["Title"]):
|
||||
doc = get_document(db, row["Author"], row["Title"])
|
||||
if not doc:
|
||||
continue
|
||||
note_file = get_notefile(db, doc)
|
||||
|
||||
text = format_entry(row)
|
||||
|
||||
if note_file and text:
|
||||
if note_file not in notes.keys():
|
||||
notes[note_file] = []
|
||||
notes[note_file].append(text)
|
||||
return notes
|
||||
|
||||
|
||||
def get_document(db, author, title):
|
||||
res = query_document(db, author, title)
|
||||
if not res:
|
||||
add_to_database(author, title)
|
||||
res = query_document(db, author, title)
|
||||
if not res:
|
||||
logger.warning(f"Nothing found for {author}: {title}.\nPlease create manually.")
|
||||
return
|
||||
return res
|
||||
|
||||
|
||||
# TODO warn user/ let him pick with picker if multiple docs found
|
||||
def query_document(db, author, title):
|
||||
title = strip_string(title)
|
||||
for query in [f"author:({author}) title:({title})"]:
|
||||
print(f"query: {query}")
|
||||
res = db.query(query)
|
||||
if len(res) >= 1:
|
||||
return res[0]
|
||||
|
||||
|
||||
def add_to_database(author, title, confirm=True, edit=False):
|
||||
logger.info(f"Searching - '{title} {author}'")
|
||||
data = None
|
||||
try:
|
||||
data = papis.isbn.get_data(f"{title}")
|
||||
except isbnlib.ISBNLibException as e:
|
||||
logger.error(e)
|
||||
else:
|
||||
logger.warning(f"Found: {data}")
|
||||
if data:
|
||||
papis_data = papis.isbn.data_to_papis(data[0])
|
||||
papis.commands.add.run([], data=papis_data, confirm=confirm, edit=edit)
|
||||
|
||||
|
||||
def get_notefile(db, document) -> str | None:
|
||||
if not document.has("notes"):
|
||||
notes_name = papis.config.getstring("notes-name")
|
||||
document["notes"] = papis.format.format(notes_name, document)
|
||||
document.save()
|
||||
db.update(document)
|
||||
|
||||
notes_path = os.path.join(str(document.get_main_folder()), document["notes"])
|
||||
|
||||
if not os.path.exists(notes_path):
|
||||
# TODO reimplement logger: logger.debug("Creating '%s'", notes_path)
|
||||
papis.notes.notes_path_ensured(document)
|
||||
return notes_path
|
||||
|
||||
|
||||
# TODO implement custom formatting (akin to pubs-extract)
|
||||
def format_entry(row) -> str:
|
||||
text = f"> {row['HighlightText']}"
|
||||
if row["EntryText"]:
|
||||
if text:
|
||||
text += "\n"
|
||||
else:
|
||||
text = "> "
|
||||
text += f"{row['EntryText']}"
|
||||
return text
|
||||
|
||||
|
||||
_old_title = ""
|
||||
|
||||
|
||||
def is_same_book(title):
|
||||
global _old_title
|
||||
|
||||
same = _old_title == title
|
||||
_old_title = title
|
||||
if same:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def write_to_files(notes: Dict):
|
||||
# write to notes
|
||||
for f, entries in notes.items():
|
||||
if f:
|
||||
with open(f, "a") as note:
|
||||
logger.info(f"Editing {f}...")
|
||||
num_added = 0
|
||||
for entry in entries:
|
||||
with open(f) as noteread:
|
||||
if entry not in noteread.read():
|
||||
note.write(f"{entry}\n\n")
|
||||
num_added += 1
|
||||
logger.info(f"Added {num_added} entries to it.")
|
||||
|
||||
|
||||
strip_pattern = re.compile(r"([^\s\w]|_)+\w*")
|
||||
|
||||
|
||||
def strip_string(title) -> str:
|
||||
return strip_pattern.sub("", title)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# use argument passed to command as file or default file here
|
||||
fpath = sys.argv[1] if len(sys.argv) > 1 else DEFAULT_CSV_PATH
|
||||
|
||||
main(fpath, papis.database.get())
|
Loading…
Reference in a new issue