From f6a32557295b9c86e446d3f08d4b333dfa9060ea Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Wed, 5 Sep 2018 15:12:27 +0400 Subject: [PATCH] Initial --- .gitignore | 178 ++++++++++++++++++++++++++++++++++++++++++ ci.sh | 10 +++ goodreads/__init__.py | 104 ++++++++++++++++++++++++ goodreads/__main__.py | 0 run | 6 ++ 5 files changed, 298 insertions(+) create mode 100644 .gitignore create mode 100755 ci.sh create mode 100644 goodreads/__init__.py create mode 100644 goodreads/__main__.py create mode 100755 run diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..236a11e --- /dev/null +++ b/.gitignore @@ -0,0 +1,178 @@ + +# Created by https://www.gitignore.io/api/python,emacs + +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +### Python Patch ### +.venv/ + +### Python.VirtualEnv Stack ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +pip-selfcheck.json + + +# End of https://www.gitignore.io/api/python,emacs diff --git a/ci.sh b/ci.sh new file mode 100755 index 0000000..0546b95 --- /dev/null +++ b/ci.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +cd "$(this_dir)" || exit + +. ~/bash_ci + +ci_run mypy goodreads +ci_run pylint -E goodreads + +ci_report_errors diff --git a/goodreads/__init__.py b/goodreads/__init__.py new file mode 100644 index 0000000..46ebfe2 --- /dev/null +++ b/goodreads/__init__.py @@ -0,0 +1,104 @@ +import os +from xml.dom.minidom import parseString # type: ignore + +BPATH = "/L/backups/goodreads" + +# TODO might be useful to keep track of updates?... +# then I need some sort of system to store diffs in generic way... +# althogh... coud use same mechanism as for filtering +def get_last() -> str: + return max(sorted([os.path.join(BPATH, f) for f in os.listdir(BPATH) if f.endswith('.xmll')])) + +_SP = '' + +def get_reviews(): + fname = get_last() + xmls = [] + with open(fname, 'r') as fo: + data = fo.read() + for xx in data.split(_SP): + if len(xx.strip()) == 0: + break + xmls.append(parseString(xx + _SP)) + return xmls + +def get_books(): + books = [] + for review in get_reviews(): + book_element = review.getElementsByTagName('book')[0] + title_element = book_element.getElementsByTagName('title')[0] + id_element = book_element.getElementsByTagName('id')[0] + isbn_element = book_element.getElementsByTagName('isbn')[0] + isbn13_element = book_element.getElementsByTagName('isbn13')[0] + date_added = review.getElementsByTagName('date_added')[0] + started_at = review.getElementsByTagName('started_at')[0] + read_at = review.getElementsByTagName('read_at')[0] + + shelves_element = review.getElementsByTagName('shelves')[0] + book_shelves = [] + for shelf in shelves_element.getElementsByTagName('shelf'): + book_shelves.append(shelf.getAttribute('name')) + + book = { + 'title': title_element.firstChild.data, + 'id': id_element.firstChild.data, + 'shelves': book_shelves + } + + if isbn_element.getAttribute('nil') != 'true': + book['isbn'] = isbn_element.firstChild.data + else: + book['isbn'] = '' + + if isbn13_element.getAttribute('nil') != 'true': + book['isbn13'] = isbn13_element.firstChild.data + else: + book['isbn13'] = '' + + if started_at.firstChild is not None: + book['started_at'] = started_at.firstChild.data + else: + book['started_at'] = '' + + if read_at.firstChild is not None: + book['read_at'] = read_at.firstChild.data + else: + book['read_at'] = '' + + book['date_added'] = None if date_added.firstChild is None else date_added.firstChild.data + + books.append(book) + return books + +from typing import List, Dict, NamedTuple +from datetime import datetime + +class Event(NamedTuple): + dt: datetime + summary: str + + +def _parse_date(s: str) -> datetime: + return datetime.strptime(s, "%a %b %d %H:%M:%S %z %Y") + + +def get_events(): + events = [] + for b in get_books(): + added = _parse_date(b['date_added']) + title = b['title'] + events.append(Event( + dt=added, + summary=f'Added book "{title}"', # TODO shelf? + )) + # TODO finished? other updates? + return sorted(events, key=lambda e: e.dt) + +def main(): + for e in get_events(): + print(e) + + +if __name__ == '__main__': + main() + diff --git a/goodreads/__main__.py b/goodreads/__main__.py new file mode 100644 index 0000000..e69de29 diff --git a/run b/run new file mode 100755 index 0000000..d610c53 --- /dev/null +++ b/run @@ -0,0 +1,6 @@ +#!/bin/bash +set -eu + +cd "$(dirname "$0")" + +python3 -m goodreads