Skip to content

Commit

Permalink
Merge pull request #15 from codycodes/dev
Browse files Browse the repository at this point in the history
Sort books by most recent access
  • Loading branch information
codycodes authored Sep 19, 2020
2 parents 53202bc + 49eac31 commit f602bdb
Show file tree
Hide file tree
Showing 12 changed files with 233 additions and 86 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,7 @@ testbook.py
test.py
*alfred4*
.DS_Store

# custom
alfred_books.py
book.py
31 changes: 12 additions & 19 deletions src/alfred_books.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# encoding: utf-8
from __future__ import unicode_literals

import sys
import book
from workflow import Workflow, ICON_WARNING, ICON_INFO, MATCH_ALL, \
Expand All @@ -9,8 +11,6 @@

def main(wf):

log.debug('Started')

if wf.update_available:
# Adds a notification to top of Script Filter results
wf.add_item('New version available',
Expand All @@ -20,22 +20,20 @@ def main(wf):
icon=ICON_INFO)

args = len(wf.args)
log.debug('ARGS: ' + str(wf.args))

option = None
if args and wf.args[0]:
switch = wf.args[0].split()[0]
switches = [u'-a', u'-t', u'-g', u'-h', u'-n']
if any([switch in switches]):
switch = switch[:2]
log.debug('SWITCH: ' + switch)
query, option = wf.args[0].split(switch)[1], switch
else:
query, option = wf.args[0], None
query = wf.decode(query)

else:
query = None
books = wf.cached_data('books', book.get_books, max_age=20)
books = wf.cached_data('books', book.get_books, max_age=5)

# Don't do anything else if there are no books
if not books:
Expand All @@ -48,27 +46,24 @@ def main(wf):
if query or option == '-h':
if option:
if option == '-a':
log.debug('-a input')
books = wf.filter(
query,
books,
key=lambda book: ' '.join(book.author),
key=lambda book: book.author,
match_on=MATCH_ALL ^ MATCH_ALLCHARS, min_score=30
)
elif option == '-t':
log.debug('-t input')
books = wf.filter(
query,
books,
key=lambda book: ' '.join(book.title),
key=lambda book: book.title,
match_on=MATCH_ALL ^ MATCH_ALLCHARS, min_score=30
)
elif option == '-g':
log.debug('-g input')
books = wf.filter(
query,
books,
key=lambda book: ' '.join(book.genre),
key=lambda book: book.genre,
match_on=MATCH_ALL ^ MATCH_ALLCHARS, min_score=30
)
elif option == '-h':
Expand All @@ -86,22 +81,21 @@ def main(wf):
'no option(s) search by title and author'
)
elif option == '-n':
log.debug('-n input')
books = wf.filter(
query,
books,
key=lambda book: ' '.join(book.is_new),
key=lambda book: book.is_new,
match_on=MATCH_ALL ^ MATCH_ALLCHARS, min_score=30
)
else:
books = wf.filter(
query,
books,
key=lambda book: ' '.join(book.title) + ' ' +
' '.join(book.author),
key=lambda book: book.title + book.author,
match_on=MATCH_ALL ^ MATCH_ALLCHARS, min_score=30
)

books.sort(key=lambda book: book.last_accessed, reverse=True)
for b in books:
wf.add_item(type='file',
title=b.title,
Expand All @@ -121,9 +115,8 @@ def main(wf):
wf.send_feedback()


if __name__ == u"__main__":
if __name__ == "__main__":
wf = Workflow(help_url='https://github.com/codycodes/alfred-books/issues',
update_settings={'github_slug': 'codycodes/alfred-books'},
normalization='NFD')
update_settings={'github_slug': 'codycodes/alfred-books'})
log = wf.logger
sys.exit(wf.run(main))
22 changes: 18 additions & 4 deletions src/book.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# encoding: utf-8
from __future__ import unicode_literals
import sqlite3
import os

BOOKS_PATH = os.path.expanduser('~'
'/Library/Containers/'
'com.apple.iBooksX/Data/Documents/BKLibrary/')
BOOKS_PATH = os.path.expanduser(
'~/Library/Containers/com.apple.iBooksX/Data/Documents/BKLibrary/')


class Book:
Expand All @@ -12,7 +13,7 @@ class Book:
books = 0

def __init__(self, title, path, author, book_desc, is_new, genre,
read_pct):
read_pct, last_accessed):
self.title = title
self.path = path
self.author = author
Expand All @@ -21,6 +22,7 @@ def __init__(self, title, path, author, book_desc, is_new, genre,
self.is_new = "True" if is_new else "False"
self.genre = genre if genre else 'No genre for this title available in Books'
self.read_pct = '0%' if not read_pct else str(read_pct * 100)[:4] + '%'
self.last_accessed = last_accessed
Book.books += 1

def display_book(self):
Expand Down Expand Up @@ -55,6 +57,17 @@ def get_books():
row = dict(row)
# check if path exists
if row['ZPATH'] is not None:
if os.path.exists(row['ZPATH']):
try:
# grab last metadata change
last_accessed = float(os.stat(row['ZPATH']).st_ctime)
except OSError:
# inaccessible path
last_accessed = -1
else:
# book not downloaded
last_accessed = -1

book = Book(
title=row['ZTITLE'],
path=row['ZPATH'] if os.path.exists(row['ZPATH']) else None,
Expand All @@ -63,6 +76,7 @@ def get_books():
is_new=row['ZISNEW'],
genre=row['ZGENRE'],
read_pct=row['ZREADINGPROGRESS'],
last_accessed=last_accessed,
)
books.append(book)
conn.close()
Expand Down
Empty file removed src/workflow/.alfredversionchecked
Empty file.
5 changes: 1 addition & 4 deletions src/workflow/background.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,7 @@ def _job_pid(name):
if _process_exists(pid):
return pid

try:
os.unlink(pidfile)
except Exception: # pragma: no cover
pass
os.unlink(pidfile)


def is_running(name):
Expand Down
18 changes: 10 additions & 8 deletions src/workflow/notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ def install_notifier():
# z.extractall(destdir)
tgz = tarfile.open(archive, 'r:gz')
tgz.extractall(destdir)
assert os.path.exists(n), \
'Notify.app could not be installed in %s' % destdir
if not os.path.exists(n): # pragma: nocover
raise RuntimeError('Notify.app could not be installed in ' + destdir)

# Replace applet icon
icon = notifier_icon_path()
Expand Down Expand Up @@ -253,8 +253,9 @@ def png_to_icns(png_path, icns_path):
try:
iconset = os.path.join(tempdir, 'Icon.iconset')

assert not os.path.exists(iconset), \
'iconset already exists: ' + iconset
if os.path.exists(iconset): # pragma: nocover
raise RuntimeError('iconset already exists: ' + iconset)

os.makedirs(iconset)

# Copy source icon to icon set and generate all the other
Expand Down Expand Up @@ -283,8 +284,9 @@ def png_to_icns(png_path, icns_path):
if retcode != 0:
raise RuntimeError('iconset exited with %d' % retcode)

assert os.path.exists(icns_path), \
'generated ICNS file not found: ' + repr(icns_path)
if not os.path.exists(icns_path): # pragma: nocover
raise ValueError(
'generated ICNS file not found: ' + repr(icns_path))
finally:
try:
shutil.rmtree(tempdir)
Expand Down Expand Up @@ -332,8 +334,8 @@ def ustr(s):
print('converting {0!r} to {1!r} ...'.format(o.png, icns),
file=sys.stderr)

assert not os.path.exists(icns), \
'destination file already exists: ' + icns
if os.path.exists(icns):
raise ValueError('destination file already exists: ' + icns)

png_to_icns(o.png, icns)
sys.exit(0)
Expand Down
12 changes: 5 additions & 7 deletions src/workflow/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ class Version(object):
"""

#: Match version and pre-release/build information in version strings
match_version = re.compile(r'([0-9\.]+)(.+)?').match
match_version = re.compile(r'([0-9][0-9\.]*)(.+)?').match

def __init__(self, vstr):
"""Create new `Version` object.
Expand All @@ -247,7 +247,7 @@ def _parse(self, vstr):
else:
m = self.match_version(vstr)
if not m:
raise ValueError('invalid version number: {!r}'.format(vstr))
raise ValueError('invalid version number: ' + vstr)

version, suffix = m.groups()
parts = self._parse_dotted_string(version)
Expand All @@ -257,7 +257,7 @@ def _parse(self, vstr):
if len(parts):
self.patch = parts.pop(0)
if not len(parts) == 0:
raise ValueError('version number too long: {!r}'.format(vstr))
raise ValueError('version number too long: ' + vstr)

if suffix:
# Build info
Expand All @@ -268,11 +268,9 @@ def _parse(self, vstr):
if suffix:
if not suffix.startswith('-'):
raise ValueError(
'suffix must start with - : {0}'.format(suffix))
'suffix must start with - : ' + suffix)
self.suffix = suffix[1:]

# wf().logger.debug('version str `{}` -> {}'.format(vstr, repr(self)))

def _parse_dotted_string(self, s):
"""Parse string ``s`` into list of ints and strings."""
parsed = []
Expand Down Expand Up @@ -521,7 +519,7 @@ def install_update():
path = retrieve_download(Download.from_dict(dl))

wf().logger.info('installing updated workflow ...')
subprocess.call(['open', path])
subprocess.call(['open', path]) # nosec

wf().cache_data(key, no_update)
return True
Expand Down
Loading

0 comments on commit f602bdb

Please sign in to comment.