PI Anthology: Reuse epub cover if there is one.

This commit is contained in:
Jim Miller 2026-04-29 13:01:22 -05:00
parent 2e25172ba3
commit 18e45a403b
2 changed files with 83 additions and 22 deletions

View file

@ -64,7 +64,7 @@ from fanficfare import adapters, exceptions
from fanficfare.epubutils import (
get_dcsource, get_dcsource_chaptercount, get_story_url_from_epub_html,
get_story_url_from_zip_html, reset_orig_chapters_epub, get_cover_data)
get_story_url_from_zip_html, reset_orig_chapters_epub, get_cover_img)
from fanficfare.geturls import (
get_urls_from_page, get_urls_from_text,get_urls_from_imap,
@ -2213,30 +2213,45 @@ class FanFicFarePlugin(InterfaceAction):
## start with None. If no subbook covers, don't force one
## here. User can configure FFF to always create/polish a
## cover if they want. This is about when we force it.
coverpath = None
coverimgpath = None
coverimgtype = None
had_cover = False
## first, look for covers inside the subbooks. Stop at the
## first one, which will be used if there isn't a pre-existing
# epubmerge wants a path to cover img on disk
def write_image(imgtype,imgdata):
tmp = PersistentTemporaryFile(prefix='cover_',
suffix='.'+imagetypes[imgtype],
dir=options['tdir'])
tmp.write(imgdata)
tmp.flush()
tmp.close()
return tmp.name
## if prior epub had a cover, we should use it again.
if mergebook['calibre_id'] and db.has_format(mergebook['calibre_id'],'EPUB',index_is_id=True):
(covertype,coverdata) = get_cover_img(db.format(mergebook['calibre_id'],'EPUB',index_is_id=True,as_file=True))
if coverdata:
had_cover = True
coverimgpath = write_image(covertype,coverdata)
coverimgtype = covertype
logger.debug("prior anthology cover found")
## look for covers inside the subbooks. Stop at the first
## one, which will be used if there isn't a pre-existing
## calibre cover.
if not coverpath:
if not coverimgpath:
for book in good_list:
coverdata = get_cover_data(book['outfile'])
(covertype,coverdata) = get_cover_img(book['outfile'])
if coverdata: # found a cover.
(coverimgtype,coverimgdata) = coverdata[4:6]
# logger.debug('coverimgtype:%s [%s]'%(coverimgtype,imagetypes[coverimgtype]))
tmpcover = PersistentTemporaryFile(suffix='.'+imagetypes[coverimgtype],
dir=options['tdir'])
tmpcover.write(coverimgdata)
tmpcover.flush()
tmpcover.close()
coverpath = tmpcover.name
coverimgpath = write_image(covertype,coverdata)
coverimgtype = covertype
logger.debug('from subbook coverimgpath:%s'%coverimgpath)
break
# logger.debug('coverpath:%s'%coverpath)
## if updating an existing book and there is at least one
## subbook cover:
if coverpath and mergebook['calibre_id']:
if not had_cover and coverimgpath and mergebook['calibre_id']:
logger.debug("anth cover: using cal cover")
# Couldn't find a better way to get the cover path.
calcoverpath = os.path.join(db.library_path,
db.path(mergebook['calibre_id'], index_is_id=True),
@ -2244,9 +2259,11 @@ class FanFicFarePlugin(InterfaceAction):
## if there's an existing cover, use it. Calibre will set
## it for us during lots of different actions anyway.
if os.path.exists(calcoverpath):
coverpath = calcoverpath
coverimgpath = calcoverpath
# logger.debug('coverpath:%s'%coverpath)
## Note that this cover will be replaced if 'inject
## generated' cover is on
logger.debug('coverimgpath:%s'%coverimgpath)
mrg_args = [tmp.name,
[ x['outfile'] for x in good_list ],]
mrg_kwargs = {
@ -2254,7 +2271,7 @@ class FanFicFarePlugin(InterfaceAction):
'titleopt':mergebook['title'],
'keepmetadatafiles':True,
'source':mergebook['url'],
'coverjpgpath':coverpath
'coverjpgpath':coverimgpath
}
logger.debug('anthology_merge_keepsingletocs:%s'%
mergebook['anthology_merge_keepsingletocs'])

View file

@ -33,9 +33,53 @@ def get_dcsource_chaptercount(inputio):
## getsoups=True to check for continue_on_chapter_error chapters.
return get_update_data(inputio,getfilecount=True,getsoups=True)[:2] # (source,filecount)
def get_cover_data(inputio):
# (oldcoverhtmlhref,oldcoverhtmltype,oldcoverhtmldata,oldcoverimghref,oldcoverimgtype,oldcoverimgdata)
return get_update_data(inputio,getfilecount=True,getsoups=False)[4]
## only finds and returns cover image type and data, not cover page.
## should work on any epub. Added for anthology cover issues.
def get_cover_img(inputio):
# (oldcoverimgtype,oldcoverimgdata)
epub = ZipFile(inputio, 'r') # works equally well with inputio as a path or a blob
## Find the .opf file.
container = epub.read("META-INF/container.xml")
containerdom = parseString(container)
rootfilenodelist = containerdom.getElementsByTagName("rootfile")
rootfilename = rootfilenodelist[0].getAttribute("full-path")
contentdom = parseString(epub.read(rootfilename))
firstmetadom = contentdom.getElementsByTagName("metadata")[0]
## Save the path to the .opf file--hrefs inside it are relative to it.
relpath = get_path_part(rootfilename)
# logger.debug("relpath:%s"%relpath)
# <meta name="cover" content="cover"/>
coverid = None
covertype = None
coverdata = None
for metatag in firstmetadom.getElementsByTagName("meta"):
if metatag.getAttribute('name') == 'cover':
coverid = metatag.getAttribute('content')
# logger.debug("coverid:%s"%coverid)
break
if coverid:
for item in contentdom.getElementsByTagName("item"):
if item.getAttribute('id') == coverid:
coverhref = relpath+item.getAttribute("href")
## remove .. and the part it obviates
coverhref = re.sub(r"([^/]+/\.\./)","",coverhref)
covertype = item.getAttribute('media-type')
# logger.debug("covertype:%s coverhref:%s"%(
covertype,coverhref))
try:
coverdata = epub.read(coverhref)
# logger.debug("coverdatalen:%s"%len(coverdata))
except Exception as e:
logger.info("Failed to read cover (%s): %s"%(coverhref,e))
covertype, coverdata = None, None
break
return covertype, coverdata
def get_oldcover(epub,relpath,contentdom,item):
href=relpath+item.getAttribute("href")