mirror of
https://github.com/janeczku/calibre-web
synced 2024-11-17 23:34:53 +00:00
backup metadata second step
This commit is contained in:
parent
ca0ee5d391
commit
241aa77d41
25
cps/db.py
25
cps/db.py
@ -399,8 +399,29 @@ class CustomColumns(Base):
|
|||||||
display_dict = json.loads(self.display)
|
display_dict = json.loads(self.display)
|
||||||
return display_dict
|
return display_dict
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self, value, extra):
|
||||||
pass
|
content = dict()
|
||||||
|
content['table'] = "custom_column_" + str(self.id)
|
||||||
|
content['column'] = "value"
|
||||||
|
content['datatype'] = self.datatype
|
||||||
|
content['is_multiple'] = None if not self.is_multiple else self.is_multiple
|
||||||
|
content['kind'] = "field"
|
||||||
|
content['name'] = self.name
|
||||||
|
content['search_terms'] = ['#' + self.label]
|
||||||
|
content['label'] = self.label
|
||||||
|
content['colnum'] = self.id
|
||||||
|
content['display'] = self.get_display_dict()
|
||||||
|
content['is_custom'] = True
|
||||||
|
content['is_category'] = self.datatype in ['text', 'rating', 'enumeration', 'series']
|
||||||
|
content['link_column'] = "value"
|
||||||
|
content['category_sort'] = "value"
|
||||||
|
content['is_csp'] = False
|
||||||
|
content['is_editable'] = self.editable
|
||||||
|
content['rec_index'] = self.id + 22 # toDo why ??
|
||||||
|
content['#value#'] = value
|
||||||
|
content['#extra#'] = extra
|
||||||
|
content['is_multiple2'] = {}
|
||||||
|
return json.dumps(content, ensure_ascii=False)
|
||||||
|
|
||||||
|
|
||||||
class AlchemyEncoder(json.JSONEncoder):
|
class AlchemyEncoder(json.JSONEncoder):
|
||||||
|
@ -34,7 +34,7 @@ def get_scheduled_tasks(reconnect=True):
|
|||||||
|
|
||||||
# ToDo make configurable. Generate metadata.opf file for each changed book
|
# ToDo make configurable. Generate metadata.opf file for each changed book
|
||||||
if True:
|
if True:
|
||||||
tasks.append([lambda: TaskBackupMetadata(), 'backup metadata', False])
|
tasks.append([lambda: TaskBackupMetadata(), "en", 'backup metadata', False])
|
||||||
|
|
||||||
# Generate all missing book cover thumbnails
|
# Generate all missing book cover thumbnails
|
||||||
if config.schedule_generate_book_covers:
|
if config.schedule_generate_book_covers:
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import datetime
|
|
||||||
import os
|
import os
|
||||||
import json
|
from lxml import objectify
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from html import escape
|
from html import escape
|
||||||
@ -41,33 +41,35 @@ NSMAP = {'dc': PURL_NAMESPACE, 'opf': OPF_NAMESPACE}
|
|||||||
|
|
||||||
class TaskBackupMetadata(CalibreTask):
|
class TaskBackupMetadata(CalibreTask):
|
||||||
|
|
||||||
def __init__(self, task_message=N_('Backing up Metadata')):
|
def __init__(self, export_language="en", translated_title="cover", task_message=N_('Backing up Metadata')):
|
||||||
super(TaskBackupMetadata, self).__init__(task_message)
|
super(TaskBackupMetadata, self).__init__(task_message)
|
||||||
self.log = logger.create()
|
self.log = logger.create()
|
||||||
self.db_session = db.CalibreDB(expire_on_commit=False, init=True).session
|
self.calibre_db = db.CalibreDB(expire_on_commit=False, init=True)
|
||||||
|
self.export_language = export_language
|
||||||
|
self.translated_title = translated_title
|
||||||
|
|
||||||
def run(self, worker_thread):
|
def run(self, worker_thread):
|
||||||
try:
|
try:
|
||||||
metadata_backup = self.db_session.query(db.Metadata_Dirtied).all()
|
metadata_backup = self.calibre_db.session.query(db.Metadata_Dirtied).all()
|
||||||
custom_columns = self.db_session.query(db.CustomColumns).all()
|
custom_columns = self.calibre_db.session.query(db.CustomColumns).order_by(db.CustomColumns.label).all()
|
||||||
for backup in metadata_backup:
|
for backup in metadata_backup:
|
||||||
book = self.db_session.query(db.Books).filter(db.Books.id == backup.book).one_or_none()
|
book = self.calibre_db.session.query(db.Books).filter(db.Books.id == backup.book).one_or_none()
|
||||||
# self.db_session.query(db.Metadata_Dirtied).filter(db.Metadata_Dirtied == backup.id).delete()
|
# self.calibre_db.session.query(db.Metadata_Dirtied).filter(db.Metadata_Dirtied == backup.id).delete()
|
||||||
# self.db_session.commit()
|
# self.calibre_db.session.commit()
|
||||||
if book:
|
if book:
|
||||||
metadata_file = self.open_metadata(book, custom_columns)
|
self.open_metadata(book, custom_columns)
|
||||||
self._handleSuccess()
|
self._handleSuccess()
|
||||||
self.db_session.remove()
|
self.calibre_db.session.close()
|
||||||
else:
|
else:
|
||||||
self.log.error("Book {} not found in database".format(backup.book))
|
self.log.error("Book {} not found in database".format(backup.book))
|
||||||
self._handleError("Book {} not found in database".format(backup.book))
|
self._handleError("Book {} not found in database".format(backup.book))
|
||||||
self.db_session.remove()
|
self.calibre_db.session.close()
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
self.log.debug('Error creating metadata backup: ' + str(ex))
|
self.log.debug('Error creating metadata backup: ' + str(ex))
|
||||||
self._handleError('Error creating metadata backup: ' + str(ex))
|
self._handleError('Error creating metadata backup: ' + str(ex))
|
||||||
self.db_session.rollback()
|
self.calibre_db.session.rollback()
|
||||||
self.db_session.remove()
|
self.calibre_db.session.close()
|
||||||
|
|
||||||
def open_metadata(self, book, custom_columns):
|
def open_metadata(self, book, custom_columns):
|
||||||
if config.config_use_google_drive:
|
if config.config_use_google_drive:
|
||||||
@ -89,13 +91,27 @@ class TaskBackupMetadata(CalibreTask):
|
|||||||
if stream is not None:
|
if stream is not None:
|
||||||
stream.close()
|
stream.close()
|
||||||
else:
|
else:
|
||||||
|
# ToDo: Handle book folder not found or not readable
|
||||||
book_metadata_filepath = os.path.join(config.config_calibre_dir, book.path, 'metadata.opf')
|
book_metadata_filepath = os.path.join(config.config_calibre_dir, book.path, 'metadata.opf')
|
||||||
if not os.path.isfile(book_metadata_filepath):
|
#if not os.path.isfile(book_metadata_filepath):
|
||||||
self.create_new_metadata_backup(book, custom_columns, book_metadata_filepath)
|
self.create_new_metadata_backup(book, custom_columns, book_metadata_filepath)
|
||||||
# ToDo What to do
|
# else:
|
||||||
return open(book_metadata_filepath, "w")
|
'''namespaces = {'dc': PURL_NAMESPACE, 'opf': OPF_NAMESPACE}
|
||||||
else:
|
test = etree.parse(book_metadata_filepath)
|
||||||
etree.parse(book_metadata_filepath)
|
root = test.getroot()
|
||||||
|
for i in root.iter():
|
||||||
|
self.log.info(i)
|
||||||
|
title = root.find("dc:metadata", namespaces)
|
||||||
|
pass'''
|
||||||
|
with open(book_metadata_filepath, "rb") as f:
|
||||||
|
xml = f.read()
|
||||||
|
|
||||||
|
root = objectify.fromstring(xml)
|
||||||
|
# root.metadata['{http://purl.org/dc/elements/1.1/}title']
|
||||||
|
# root.metadata[PURL + 'title']
|
||||||
|
# getattr(root.metadata, PURL +'title')
|
||||||
|
# test = objectify.parse()
|
||||||
|
pass
|
||||||
# backup not found has to be created
|
# backup not found has to be created
|
||||||
#raise Exception('Book cover file not found')
|
#raise Exception('Book cover file not found')
|
||||||
|
|
||||||
@ -124,16 +140,23 @@ class TaskBackupMetadata(CalibreTask):
|
|||||||
contributor.text = "calibre (5.7.2) [https://calibre-ebook.com]"
|
contributor.text = "calibre (5.7.2) [https://calibre-ebook.com]"
|
||||||
contributor.set(OPF + "file-as", "calibre") # ToDo Check
|
contributor.set(OPF + "file-as", "calibre") # ToDo Check
|
||||||
contributor.set(OPF + "role", "bpk")
|
contributor.set(OPF + "role", "bpk")
|
||||||
|
|
||||||
date = etree.SubElement(metadata, PURL + "date", nsmap=NSMAP)
|
date = etree.SubElement(metadata, PURL + "date", nsmap=NSMAP)
|
||||||
date.text = datetime.datetime.strftime(book.pubdate, "%Y-%m-%dT%H:%M:%S+00:00")
|
date.text = '{d.year:04}-{d.month:02}-{d.day:02}T{d.hour:02}:{d.minute:02}:{d.second:02}'.format(d=book.pubdate)
|
||||||
language = etree.SubElement(metadata, PURL + "language", nsmap=NSMAP)
|
|
||||||
if book.languages:
|
if not book.languages:
|
||||||
language.text = str(book.languages)
|
language = etree.SubElement(metadata, PURL + "language", nsmap=NSMAP)
|
||||||
|
language.text = self.export_language
|
||||||
else:
|
else:
|
||||||
language.text = "" # ToDo: insert locale (2 letter code)
|
for b in book.languages:
|
||||||
if book.tags:
|
language = etree.SubElement(metadata, PURL + "language", nsmap=NSMAP)
|
||||||
|
language.text = str(b.languages)
|
||||||
|
for b in book.tags:
|
||||||
subject = etree.SubElement(metadata, PURL + "subject", nsmap=NSMAP)
|
subject = etree.SubElement(metadata, PURL + "subject", nsmap=NSMAP)
|
||||||
subject.text = str(book.tags)
|
subject.text = str(b.tags)
|
||||||
|
if book.comments:
|
||||||
|
description = etree.SubElement(metadata, PURL + "description", nsmap=NSMAP)
|
||||||
|
description.text = escape(str(book.comments))
|
||||||
etree.SubElement(metadata, "meta", name="calibre:author_link_map",
|
etree.SubElement(metadata, "meta", name="calibre:author_link_map",
|
||||||
content="{" + escape(",".join(['"' + str(a) + '":""' for a in book.authors])) + "}",
|
content="{" + escape(",".join(['"' + str(a) + '":""' for a in book.authors])) + "}",
|
||||||
nsmap=NSMAP)
|
nsmap=NSMAP)
|
||||||
@ -144,27 +167,36 @@ class TaskBackupMetadata(CalibreTask):
|
|||||||
content=str(book.series_index),
|
content=str(book.series_index),
|
||||||
nsmap=NSMAP)
|
nsmap=NSMAP)
|
||||||
etree.SubElement(metadata, "meta", name="calibre:timestamp",
|
etree.SubElement(metadata, "meta", name="calibre:timestamp",
|
||||||
content=datetime.datetime.strftime(book.timestamp, "%Y-%m-%dT%H:%M:%S+00:00"),
|
content='{d.year:04}-{d.month:02}-{d.day:02}T{d.hour:02}:{d.minute:02}:{d.second:02}'.format(
|
||||||
|
d=book.timestamp),
|
||||||
nsmap=NSMAP)
|
nsmap=NSMAP)
|
||||||
etree.SubElement(metadata, "meta", name="calibre:title_sort",
|
etree.SubElement(metadata, "meta", name="calibre:title_sort",
|
||||||
content=book.sort,
|
content=book.sort,
|
||||||
nsmap=NSMAP)
|
nsmap=NSMAP)
|
||||||
for cc in custom_columns:
|
for cc in custom_columns:
|
||||||
|
value = None
|
||||||
|
extra = None
|
||||||
|
cc_entry = getattr(book, "custom_column_" + str(cc.id))
|
||||||
|
if cc_entry.__len__():
|
||||||
|
value = cc_entry[0].get("value")
|
||||||
|
extra = cc_entry[0].get("extra")
|
||||||
etree.SubElement(metadata, "meta", name="calibre:user_metadata:#{}".format(cc.label),
|
etree.SubElement(metadata, "meta", name="calibre:user_metadata:#{}".format(cc.label),
|
||||||
content=escape(cc.get_display_dict()),
|
content=escape(cc.to_json(value, extra)),
|
||||||
nsmap=NSMAP)
|
nsmap=NSMAP)
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
# generate guide element and all sub elements of it
|
# generate guide element and all sub elements of it
|
||||||
|
# Title is translated from default export language
|
||||||
guide = etree.SubElement(package, "guide")
|
guide = etree.SubElement(package, "guide")
|
||||||
etree.SubElement(guide, "reference", type="cover", title="Titelbild", href="cover.jpg")
|
etree.SubElement(guide, "reference", type="cover", title=self.translated_title, href="cover.jpg")
|
||||||
|
|
||||||
# prepare finalize everything and output
|
# prepare finalize everything and output
|
||||||
doc = etree.ElementTree(package)
|
doc = etree.ElementTree(package)
|
||||||
with open(book_metadata_filepath, 'wb') as f:
|
try:
|
||||||
doc.write(f, xml_declaration=True, encoding='utf-8', pretty_print=True)
|
with open(book_metadata_filepath, 'wb') as f:
|
||||||
|
doc.write(f, xml_declaration=True, encoding='utf-8', pretty_print=True)
|
||||||
|
except Exception:
|
||||||
|
# ToDo: Folder not writeable errror
|
||||||
|
pass
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return "Backing up Metadata"
|
return "Backing up Metadata"
|
||||||
|
Loading…
Reference in New Issue
Block a user