mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Kobo driver: Add management of the I'm Reading list on Kobo via an Im_Reading tag in calibre
This commit is contained in:
commit
e77eafa751
@ -5,15 +5,16 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2010, Timothy Legge <timlegge at gmail.com> and Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2010, Timothy Legge <timlegge at gmail.com> and Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import os
|
import os, time
|
||||||
import sqlite3 as sqlite
|
import sqlite3 as sqlite
|
||||||
|
|
||||||
from calibre.devices.usbms.books import BookList
|
from calibre.devices.usbms.books import BookList
|
||||||
from calibre.devices.kobo.books import Book
|
from calibre.devices.kobo.books import Book
|
||||||
from calibre.devices.kobo.books import ImageWrapper
|
from calibre.devices.kobo.books import ImageWrapper
|
||||||
from calibre.devices.mime import mime_type_ext
|
from calibre.devices.mime import mime_type_ext
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS, debug_print
|
||||||
from calibre import prints
|
from calibre import prints
|
||||||
|
from calibre.devices.usbms.books import CollectionsBookList
|
||||||
|
|
||||||
class KOBO(USBMS):
|
class KOBO(USBMS):
|
||||||
|
|
||||||
@ -21,12 +22,15 @@ class KOBO(USBMS):
|
|||||||
gui_name = 'Kobo Reader'
|
gui_name = 'Kobo Reader'
|
||||||
description = _('Communicate with the Kobo Reader')
|
description = _('Communicate with the Kobo Reader')
|
||||||
author = 'Timothy Legge and Kovid Goyal'
|
author = 'Timothy Legge and Kovid Goyal'
|
||||||
version = (1, 0, 4)
|
version = (1, 0, 6)
|
||||||
|
|
||||||
supported_platforms = ['windows', 'osx', 'linux']
|
supported_platforms = ['windows', 'osx', 'linux']
|
||||||
|
|
||||||
|
booklist_class = CollectionsBookList
|
||||||
|
|
||||||
# Ordered list of supported formats
|
# Ordered list of supported formats
|
||||||
FORMATS = ['epub', 'pdf']
|
FORMATS = ['epub', 'pdf']
|
||||||
|
CAN_SET_METADATA = True
|
||||||
|
|
||||||
VENDOR_ID = [0x2237]
|
VENDOR_ID = [0x2237]
|
||||||
PRODUCT_ID = [0x4161]
|
PRODUCT_ID = [0x4161]
|
||||||
@ -40,6 +44,12 @@ class KOBO(USBMS):
|
|||||||
|
|
||||||
VIRTUAL_BOOK_EXTENSIONS = frozenset(['kobo'])
|
VIRTUAL_BOOK_EXTENSIONS = frozenset(['kobo'])
|
||||||
|
|
||||||
|
EXTRA_CUSTOMIZATION_MESSAGE = _('The Kobo supports only one collection '
|
||||||
|
'currently: the \"Im_Reading\" list. Create a tag called \"Im_Reading\" ')+\
|
||||||
|
'for automatic management'
|
||||||
|
|
||||||
|
EXTRA_CUSTOMIZATION_DEFAULT = ', '.join(['tags'])
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
USBMS.initialize(self)
|
USBMS.initialize(self)
|
||||||
self.book_class = Book
|
self.book_class = Book
|
||||||
@ -63,6 +73,8 @@ class KOBO(USBMS):
|
|||||||
self._card_b_prefix if oncard == 'cardb' \
|
self._card_b_prefix if oncard == 'cardb' \
|
||||||
else self._main_prefix
|
else self._main_prefix
|
||||||
|
|
||||||
|
self.booklist_class.rebuild_collections = self.rebuild_collections
|
||||||
|
|
||||||
# get the metadata cache
|
# get the metadata cache
|
||||||
bl = self.booklist_class(oncard, prefix, self.settings)
|
bl = self.booklist_class(oncard, prefix, self.settings)
|
||||||
need_sync = self.parse_metadata_cache(bl, prefix, self.METADATA_CACHE)
|
need_sync = self.parse_metadata_cache(bl, prefix, self.METADATA_CACHE)
|
||||||
@ -85,9 +97,7 @@ class KOBO(USBMS):
|
|||||||
playlist_map = {}
|
playlist_map = {}
|
||||||
|
|
||||||
if readstatus == 1:
|
if readstatus == 1:
|
||||||
if lpath not in playlist_map:
|
playlist_map[lpath]= "Im_Reading"
|
||||||
playlist_map[lpath] = []
|
|
||||||
playlist_map[lpath].append("I\'m Reading")
|
|
||||||
|
|
||||||
path = self.normalize_path(path)
|
path = self.normalize_path(path)
|
||||||
# print "Normalized FileName: " + path
|
# print "Normalized FileName: " + path
|
||||||
@ -104,14 +114,17 @@ class KOBO(USBMS):
|
|||||||
if self.update_metadata_item(bl[idx]):
|
if self.update_metadata_item(bl[idx]):
|
||||||
# print 'update_metadata_item returned true'
|
# print 'update_metadata_item returned true'
|
||||||
changed = True
|
changed = True
|
||||||
bl[idx].device_collections = playlist_map.get(lpath, [])
|
if lpath in playlist_map and \
|
||||||
|
playlist_map[lpath] not in bl[idx].device_collections:
|
||||||
|
bl[idx].device_collections.append(playlist_map[lpath])
|
||||||
else:
|
else:
|
||||||
if ContentType == '6':
|
if ContentType == '6':
|
||||||
book = Book(prefix, lpath, title, authors, mime, date, ContentType, ImageID, size=1048576)
|
book = Book(prefix, lpath, title, authors, mime, date, ContentType, ImageID, size=1048576)
|
||||||
else:
|
else:
|
||||||
book = self.book_from_path(prefix, lpath, title, authors, mime, date, ContentType, ImageID)
|
book = self.book_from_path(prefix, lpath, title, authors, mime, date, ContentType, ImageID)
|
||||||
# print 'Update booklist'
|
# print 'Update booklist'
|
||||||
book.device_collections = playlist_map.get(book.lpath, [])
|
book.device_collections = [playlist_map[lpath]] if lpath in playlist_map else []
|
||||||
|
|
||||||
if bl.add_book(book, replace_metadata=False):
|
if bl.add_book(book, replace_metadata=False):
|
||||||
changed = True
|
changed = True
|
||||||
except: # Probably a path encoding error
|
except: # Probably a path encoding error
|
||||||
@ -398,3 +411,95 @@ class KOBO(USBMS):
|
|||||||
size = os.stat(cls.normalize_path(os.path.join(prefix, lpath))).st_size
|
size = os.stat(cls.normalize_path(os.path.join(prefix, lpath))).st_size
|
||||||
book = Book(prefix, lpath, title, authors, mime, date, ContentType, ImageID, size=size, other=mi)
|
book = Book(prefix, lpath, title, authors, mime, date, ContentType, ImageID, size=size, other=mi)
|
||||||
return book
|
return book
|
||||||
|
|
||||||
|
def get_device_paths(self):
|
||||||
|
paths, prefixes = {}, {}
|
||||||
|
for prefix, path, source_id in [
|
||||||
|
('main', 'metadata.calibre', 0),
|
||||||
|
('card_a', 'metadata.calibre', 1),
|
||||||
|
('card_b', 'metadata.calibre', 2)
|
||||||
|
]:
|
||||||
|
prefix = getattr(self, '_%s_prefix'%prefix)
|
||||||
|
if prefix is not None and os.path.exists(prefix):
|
||||||
|
paths[source_id] = os.path.join(prefix, *(path.split('/')))
|
||||||
|
return paths
|
||||||
|
|
||||||
|
def update_device_database_collections(self, booklists, collections_attributes):
|
||||||
|
# debug_print('Starting update_device_database_collections', collections_attributes)
|
||||||
|
|
||||||
|
# Force collections_attributes to be 'tags' as no other is currently supported
|
||||||
|
# debug_print('KOBO: overriding the provided collections_attributes:', collections_attributes)
|
||||||
|
collections_attributes = ['tags']
|
||||||
|
|
||||||
|
collections = booklists.get_collections(collections_attributes)
|
||||||
|
# debug_print('Collections', collections)
|
||||||
|
for category, books in collections.items():
|
||||||
|
if category == 'Im_Reading':
|
||||||
|
# Create a connection to the sqlite database
|
||||||
|
connection = sqlite.connect(self._main_prefix + '.kobo/KoboReader.sqlite')
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
# Reset Im_Reading list in the database
|
||||||
|
query= 'update content set ReadStatus=0, FirstTimeReading = \'true\' where BookID is Null'
|
||||||
|
try:
|
||||||
|
cursor.execute (query)
|
||||||
|
except:
|
||||||
|
debug_print('Database Exception: Unable to reset Im_Reading list')
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
# debug_print('Commit: Reset Im_Reading list')
|
||||||
|
connection.commit()
|
||||||
|
|
||||||
|
for book in books:
|
||||||
|
# debug_print('Title:', book.title, 'lpath:', book.path)
|
||||||
|
book.device_collections = ['Im_Reading']
|
||||||
|
|
||||||
|
extension = os.path.splitext(book.path)[1]
|
||||||
|
ContentType = self.get_content_type_from_extension(extension)
|
||||||
|
|
||||||
|
ContentID = self.contentid_from_path(book.path, ContentType)
|
||||||
|
datelastread = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime())
|
||||||
|
|
||||||
|
t = (datelastread,ContentID,)
|
||||||
|
|
||||||
|
try:
|
||||||
|
cursor.execute('update content set ReadStatus=1,FirstTimeReading=\'false\',DateLastRead=? where BookID is Null and ContentID = ?', t)
|
||||||
|
except:
|
||||||
|
debug_print('Database Exception: Unable create Im_Reading list')
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
connection.commit()
|
||||||
|
# debug_print('Database: Commit create Im_Reading list')
|
||||||
|
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
# debug_print('Finished update_device_database_collections', collections_attributes)
|
||||||
|
|
||||||
|
def sync_booklists(self, booklists, end_session=True):
|
||||||
|
# debug_print('KOBO: started sync_booklists')
|
||||||
|
paths = self.get_device_paths()
|
||||||
|
|
||||||
|
blists = {}
|
||||||
|
for i in paths:
|
||||||
|
if booklists[i] is not None:
|
||||||
|
#debug_print('Booklist: ', i)
|
||||||
|
blists[i] = booklists[i]
|
||||||
|
opts = self.settings()
|
||||||
|
if opts.extra_customization:
|
||||||
|
collections = [x.lower().strip() for x in
|
||||||
|
opts.extra_customization.split(',')]
|
||||||
|
else:
|
||||||
|
collections = []
|
||||||
|
|
||||||
|
#debug_print('KOBO: collection fields:', collections)
|
||||||
|
for i, blist in blists.items():
|
||||||
|
self.update_device_database_collections(blist, collections)
|
||||||
|
|
||||||
|
USBMS.sync_booklists(self, booklists, end_session=end_session)
|
||||||
|
#debug_print('KOBO: finished sync_booklists')
|
||||||
|
|
||||||
|
def rebuild_collections(self, booklist, oncard):
|
||||||
|
collections_attributes = []
|
||||||
|
self.update_device_database_collections(booklist, collections_attributes)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user