#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import json import shutil import tempfile import subprocess from .common import isRoot from .common import rootPath from .common import saveFile from .common import projectUrl from .common import projectDesc from .common import releaseInfo from .common import createFolder from .common import resourceInfo from .sequence import txtSerialize from .sequence import jsonSerialize from .sequence import htmlSerialize from .sequence import gitbookSummary from .sequence import gitbookChapters from .sequence import gitbookMetadata def txtRelease(metadata: dict, content: dict) -> None: saveFile(releaseInfo['txt'], txtSerialize(metadata, content)) def jsonRelease(metadata: dict, content: dict) -> None: saveFile(releaseInfo['json'], jsonSerialize(metadata, content)) def gitbookRelease(metadata: dict, content: dict) -> None: createFolder(releaseInfo['gitbook']) createFolder(os.path.join(releaseInfo['gitbook'], './assets/')) createFolder(os.path.join(releaseInfo['gitbook'], './chapter/')) cover = gitbookMetadata(metadata) for (resName, resUrls) in resourceInfo.items(): cover += '{% hint style="success" %}\n' \ + '### >>> [%s](%s) <<<\n' % (resName, resUrls[0]) \ + '{% endhint %}\n\n' cover += '{%% embed url="%s" %%}\n项目地址\n{%% endembed %%}\n' % projectUrl saveFile(os.path.join(releaseInfo['gitbook'], 'README.md'), cover) saveFile(os.path.join(releaseInfo['gitbook'], 'SUMMARY.md'), gitbookSummary(content)) for (chapterPath, chapterContent) in gitbookChapters(content).items(): saveFile(os.path.join(releaseInfo['gitbook'], chapterPath), chapterContent) shutil.copy( # gitbook cover os.path.join(rootPath, './assets/cover.jpg'), os.path.join(releaseInfo['gitbook'], './assets/cover.jpg') ) def staticDepends(workDir: str, metadata: dict, content: dict) -> None: createFolder(os.path.join(workDir, './assets/')) createFolder(os.path.join(workDir, './chapter/')) cover = gitbookMetadata(metadata) + '
\n' for (resName, resUrls) in resourceInfo.items(): cover += '\n{% hint style="tip" %}\n' \ + '#### [%s](%s)([备用地址](%s))\n' % (resName, resUrls[0], resUrls[1]) \ + '{% endhint %}\n' bookInfo = json.dumps({ 'title': metadata['name'], 'author': metadata['author'], 'description': projectDesc, "language": "zh-hans", 'plugins': [ '-lunr', '-search', '-sharing', 'hints', 'github', 'hide-element', 'fontsettings', 'image-captions', 'back-to-top-button' ], 'pluginsConfig': { 'github': {'url': projectUrl}, 'hide-element': { 'elements': ['.gitbook-link'] } } }) saveFile(os.path.join(workDir, 'README.md'), cover) saveFile(os.path.join(workDir, 'book.json'), bookInfo) saveFile(os.path.join(workDir, 'SUMMARY.md'), gitbookSummary(content)) for (chapterPath, chapterContent) in gitbookChapters(content).items(): saveFile(os.path.join(workDir, chapterPath), chapterContent) shutil.copy( # gitbook cover os.path.join(rootPath, './assets/cover.jpg'), os.path.join(workDir, './assets/cover.jpg') ) def htmlCompress(file: str) -> None: rawHtml = open(file).read().split('\n') with open(file, 'w') as fileObj: fileObj.write('\n'.join([x.strip() for x in rawHtml if x.strip() != '']) + '\n') def staticBuild(workDir: str) -> None: buildDir = '/xxrs/' nodeImage = 'node:10-alpine' buildCommand = 'docker run --rm -v %s:%s --entrypoint sh %s -c "%s"' % ( workDir, buildDir, nodeImage, 'npm install gitbook-cli -g && gitbook install %s && gitbook build %s --log=debug' % ( buildDir, buildDir ) ) print('Gitbook Build -> %s' % workDir) subprocess.Popen(buildCommand, shell = True).wait() # blocking wait os.rename(os.path.join(workDir, '_book'), os.path.join(workDir, 'XXRS')) htmlCompress(os.path.join(workDir, './XXRS/index.html')) chapterFolder = os.path.join(workDir, './XXRS/chapter/') for file in os.listdir(chapterFolder): # compress html content htmlCompress(os.path.join(chapterFolder, file)) os.system('cd %s && tar cJf %s XXRS' % (workDir, releaseInfo['static'])) def staticRelease(metadata: dict, content: dict) -> None: if not isRoot(): print('\033[0;33mDue to the permission problems, it is recommended to run under root user.\033[0m') return tempDir = tempfile.TemporaryDirectory() # access temporary directory staticDepends(tempDir.name, metadata, content) staticBuild(tempDir.name) tempDir.cleanup() def calibreDepends(workDir: str, metadata: dict, content: dict) -> None: metaInfo = [ '', '', '', '', '', '', ] opfInfo = [ '', '', '', '%s' % metadata['name'], 'zho', 'Dnomd343', '%(aut)s' % {'aut': metadata['author']}, '%s' % projectUrl, '%s' % '<div>%s</div>' % ( ''.join(['<p>%s</p>' % x for x in metadata['desc']]) ), '' % metadata['author'], '' % metadata['name'], '', '', '', '', '', '', '', '', '', ] createFolder(os.path.join(workDir, 'META-INF')) saveFile(os.path.join(workDir, 'mimetype'), 'application/epub+zip') saveFile(os.path.join(workDir, 'content.opf'), '\n'.join(opfInfo) + '\n') saveFile(os.path.join(workDir, 'xxrs.html'), htmlSerialize(metadata, content)) saveFile(os.path.join(workDir, 'META-INF', 'container.xml'), '\n'.join(metaInfo) + '\n') def calibreRelease(metadata: dict, content: dict) -> None: tempDir = tempfile.TemporaryDirectory() # access temporary directory calibreDepends(tempDir.name, metadata, content) os.system('cd %s && zip -r xxrs.zip *' % tempDir.name) shutil.move(os.path.join(tempDir.name, 'xxrs.zip'), releaseInfo['calibre']) tempDir.cleanup() def calibreBuild(workDir: str, suffix: str, extOption: list, metadata: dict, content: dict) -> None: buildDir = '/xxrs/' calibreImage = 'linuxserver/calibre' calibreCommand = [ 'ebook-convert', 'xxrs.zip', 'xxrs%s' % suffix, '--output-profile=generic_eink', '--level1-toc=\'//h:h2\'', '--cover=cover.jpg', '--toc-title=目录', '--remove-paragraph-spacing', '--remove-paragraph-spacing-indent-size=2', '--verbose', ] buildCommand = 'docker run --rm -t -v %s:%s --workdir %s --entrypoint bash %s -c "%s"' % ( workDir, buildDir, buildDir, calibreImage, ' '.join(calibreCommand + extOption) ) calibreDepends(workDir, metadata, content) # generate calibre input os.system('cd %s && zip -r xxrs.zip *' % workDir) # compress as zip file shutil.copy( os.path.join(rootPath, './assets/cover.jpg'), os.path.join(workDir, './cover.jpg') # load ebook cover ) subprocess.Popen(buildCommand, shell = True).wait() # blocking wait def epubRelease(metadata: dict, content: dict) -> None: tempDir = tempfile.TemporaryDirectory() # access temporary directory print('Calibre EPUB Build -> %s' % tempDir.name) calibreBuild(tempDir.name, '.epub', [], metadata, content) shutil.copy(os.path.join(tempDir.name, './xxrs.epub'), releaseInfo['epub']) tempDir.cleanup() # MOBI Type: KF7 = 0 (old) / KF7 + KF8 = 1 (both) / KF8 = 2 (new) def mobiRelease(metadata: dict, content: dict, mobiType: int = 1) -> None: mobiOption = ['--mobi-toc-at-start'] if mobiType == 0: mobiOption.append('--mobi-file-type=old') elif mobiType == 1: mobiOption.append('--mobi-file-type=both') elif mobiType == 2: mobiOption.append('--mobi-file-type=new') else: print('Unknown MOBI type') return tempDir = tempfile.TemporaryDirectory() # access temporary directory print('Calibre MOBI Build -> %s' % tempDir.name) calibreBuild(tempDir.name, '.mobi', mobiOption, metadata, content) shutil.copy(os.path.join(tempDir.name, './xxrs.mobi'), releaseInfo['mobi']) tempDir.cleanup() def setPdocMark(originFile: str, targetFile: str) -> None: jdkImage = 'openjdk:17-alpine' tempDir = tempfile.TemporaryDirectory() # access temporary directory suffix = os.path.splitext(originFile)[-1] shutil.copy(originFile, os.path.join(tempDir.name, 'xxrs%s' % suffix)) shutil.copy( os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mobi-meta.jar'), # script folder os.path.join(tempDir.name, 'mobi-meta.jar') ) dockerCommand = 'docker run --rm -v %(src)s:%(tmp)s --workdir %(tmp)s --entrypoint sh %(img)s -c "%(cmd)s"' % { 'src': tempDir.name, 'tmp': '/xxrs/', 'img': jdkImage, 'cmd': 'java -jar mobi-meta.jar edit xxrs%s xxrs_mod%s --pdoc' % (suffix, suffix), } subprocess.Popen(dockerCommand, shell = True).wait() # blocking wait shutil.copy(os.path.join(tempDir.name, 'xxrs_mod%s' % suffix), targetFile) tempDir.cleanup() def azw3Release(metadata: dict, content: dict) -> None: tempDir = tempfile.TemporaryDirectory() # access temporary directory print('Calibre AZW3 Build -> %s' % tempDir.name) calibreBuild(tempDir.name, '.azw3', ['--mobi-toc-at-start'], metadata, content) setPdocMark(os.path.join(tempDir.name, './xxrs.azw3'), releaseInfo['azw3']) tempDir.cleanup()