diff --git a/app.yaml b/app.yaml index 620af95a..104c866c 100755 --- a/app.yaml +++ b/app.yaml @@ -15,7 +15,7 @@ basic_scaling: # min_idle_instances: 0 app_engine_apis: true -entrypoint: gunicorn -b :$PORT main:app +entrypoint: gunicorn -b :$PORT -w 2 main:app inbound_services: - mail diff --git a/application/back_end/db_models.py b/application/back_end/db_models.py index 93806ff9..4ffb5fa7 100644 --- a/application/back_end/db_models.py +++ b/application/back_end/db_models.py @@ -95,16 +95,10 @@ def get_cover_data(self): return data #获取用户自定义的CSS - #css为Recipe预定义的CSS - #返回两个CSS合并后的字符串 - def get_extra_css(self, css=''): + def get_extra_css(self): dbItem = UserBlob.get_or_none((UserBlob.user == self.name) & (UserBlob.name == 'css')) - if dbItem: - extra_css = dbItem.data.decode('utf-8') - return (css + '\n\n' + extra_css) if css else extra_css - else: - return css - + return dbItem.data.decode('utf-8') if dbItem else '' + #用户的一些二进制内容,比如封面之类的 class UserBlob(MyBaseModel): name = CharField() diff --git a/application/back_end/send_mail_adpt.py b/application/back_end/send_mail_adpt.py index 4fe71f86..13c3efba 100644 --- a/application/back_end/send_mail_adpt.py +++ b/application/back_end/send_mail_adpt.py @@ -29,18 +29,22 @@ #发送邮件 #title: 邮件标题 -#attachment: 附件二进制内容 +#attachment: 附件二进制内容,或元祖 (filename, content) #fileWithTime: 发送的附件文件名是否附带当前时间 def send_to_kindle(user, title, attachment, fileWithTime=True): lcTime = local_time('%Y-%m-%d_%H-%M', user.timezone) subject = f"KindleEar {lcTime}" - lcTime = "({})".format(lcTime) if fileWithTime else "" - ext = ".{}".format(user.book_type) if user.book_type else "" - fileName = f"{title}{lcTime}{ext}" - body = "Deliver from KindleEar" - attachments = [(fileName, attachment)] + + if not isinstance(attachment, tuple): + lcTime = "({})".format(lcTime) if fileWithTime else "" + fileName = f"{title}{lcTime}.{user.book_type}" + attachment = (fileName, attachment) + + if not isinstance(attachment, list): + attachments = [attachment] status = 'ok' + body = "Deliver from KindleEar" try: send_mail(user, user.kindle_email, subject, body, attachments) except Exception as e: diff --git a/application/lib/build_ebook.py b/application/lib/build_ebook.py index fdc2b163..fd02abbd 100644 --- a/application/lib/build_ebook.py +++ b/application/lib/build_ebook.py @@ -42,7 +42,8 @@ def urls_to_book(urls: list, title: str, user, options: dict=None, output_fmt: s return None #合并自定义css - ro.extra_css = user.get_extra_css(ro.extra_css) + userCss = user.get_extra_css() + ro.extra_css = f'{ro.extra_css}\n\n{userCss}' if ro.extra_css else userCss return recipes_to_ebook(ro, user, options, output_fmt) diff --git a/application/lib/calibre/customize/conversion.py b/application/lib/calibre/customize/conversion.py index 37fdb686..d3d42d09 100644 --- a/application/lib/calibre/customize/conversion.py +++ b/application/lib/calibre/customize/conversion.py @@ -173,8 +173,9 @@ class InputFormatPlugin(Plugin): 'set this option will override any encoding declared by the ' 'document itself. Particularly useful for documents that ' 'do not declare an encoding or that have erroneous ' - 'encoding declarations.') - )} + 'encoding declarations.')), + OptionRecommendation(name='user', recommended_value=None, + help='Keuser instance.'),} #: Options to customize the behavior of this plugin. Every option must be an #: instance of :class:`OptionRecommendation`. diff --git a/application/lib/calibre/ebooks/conversion/plugins/html_input.py b/application/lib/calibre/ebooks/conversion/plugins/html_input.py index 4a670448..9169d12d 100644 --- a/application/lib/calibre/ebooks/conversion/plugins/html_input.py +++ b/application/lib/calibre/ebooks/conversion/plugins/html_input.py @@ -75,10 +75,10 @@ def convert(self, input_, opts, file_ext, log, output_dir, fs): #manifest 资源列表 manifest = ['/index.html'] - for filename, content in input_.get('imgs', []): - filename = os.path.join(fs.path, filename) + for fileName, content in input_.get('imgs', []): + fileName = os.path.join(fs.path, fileName) fs.write(fileName, content) - manifest.append(filename) + manifest.append(fileName) opf.create_manifest_from_files_in(manifest) ncx_id = opf.manifest.add_item(os.path.join(fs.path, 'index.ncx'), mime_type="application/x-dtbncx+xml") opf.manifest.item(ncx_id).id = 'ncx' diff --git a/application/lib/calibre/ebooks/conversion/plugins/recipe_input.py b/application/lib/calibre/ebooks/conversion/plugins/recipe_input.py index f3432958..837ce7b9 100644 --- a/application/lib/calibre/ebooks/conversion/plugins/recipe_input.py +++ b/application/lib/calibre/ebooks/conversion/plugins/recipe_input.py @@ -57,8 +57,6 @@ class RecipeInput(InputFormatPlugin): help=_('Do not download latest version of builtin recipes from the calibre server')), OptionRecommendation(name='lrf', recommended_value=False, help='Optimize fetching for subsequent conversion to LRF.'), - OptionRecommendation(name='user', recommended_value=None, - help='Keuser instance.'), } #执行转换完成后返回生成的 opf 文件路径,只是路径,不包含文件名 diff --git a/application/lib/calibre/ebooks/conversion/plumber.py b/application/lib/calibre/ebooks/conversion/plumber.py index b91ab3dc..6069fc2e 100644 --- a/application/lib/calibre/ebooks/conversion/plumber.py +++ b/application/lib/calibre/ebooks/conversion/plumber.py @@ -384,7 +384,7 @@ def run(self): fs = FsDictStub(tdir) else: tdir = '/' - fs = FsDictStub(None) + fs = FsDictStub() #调用calibre.customize.conversion.InputFormatPlugin.__call__(),然后调用输入插件的convert()在目标目录生成一大堆文件,包含opf #__call__()返回传入的 fs 实例,其属性 opfname 保存了opf文件的路径名 @@ -551,16 +551,15 @@ def run(self): self.log.info('Processed HTML written to:{}'.format(out_dir)) self.log.info('Creating %s...'%self.output_plugin.name) - + #创建输出临时文件缓存 if system_temp_dir: prefix = self.output_plugin.commit_name or 'output_' tmpdir = PersistentTemporaryDirectory(prefix=prefix, dir=system_temp_dir) fs_out = FsDictStub(tmpdir) else: - fs_out = FsDictStub(None) - fs_out = fs - + fs_out = FsDictStub() + #这才是启动输出转换,生成电子书 with self.output_plugin: self.output_plugin.convert(self.oeb, self.output, self.input_plugin, self.opts, self.log, fs_out) diff --git a/application/lib/filedownload.py b/application/lib/filedownload.py index d8322580..8f895f6d 100644 --- a/application/lib/filedownload.py +++ b/application/lib/filedownload.py @@ -5,25 +5,25 @@ """ from collections import namedtuple from urllib.parse import urlparse -from lib.urlopener import UrlOpener +from urlopener import UrlOpener DownloadedFileTuple = namedtuple("DownloadedFileTuple", "status fileName content") #FileDownload工具函数,简化文件下载工作 #返回一个命名元祖 DownloadedFileTuple def Download(url): - fileName = lambda url: urlparse(url).path.split('/')[-1] + fileName = urlparse(url).path.split('/')[-1] opener = UrlOpener() resp = opener.open(url) content = resp.content if resp.status_code == 413: - return DownloadedFileTuple('too large', fileName, '') + return DownloadedFileTuple('too large', fileName, b'') elif resp.status_code not in (200, 206): - return DownloadedFileTuple('download failed', fileName, '') + return DownloadedFileTuple('download failed', fileName, b'') elif not content: - return DownloadedFileTuple('not resuming', fileName, '') + return DownloadedFileTuple('not resuming', fileName, b'') else: return DownloadedFileTuple('', fileName, content) diff --git a/application/lib/filesystem_dict.py b/application/lib/filesystem_dict.py index 428640aa..fbd9651f 100644 --- a/application/lib/filesystem_dict.py +++ b/application/lib/filesystem_dict.py @@ -59,7 +59,7 @@ def delete(self, path: str): #全部清除,释放内存 def clear(self): - self.dirs = None + self.dirs = set() for key in list(self.keys()): del self[key] @@ -101,7 +101,7 @@ def _update_dirs(self): #提供给OEB的文件读写桩,给外部提供一个统一的文件系统接口,内部根据情况使用模拟文件系统字典或调用系统函数 class FsDictStub(object): #path: 如果path=str,则使用操作系统文件读写,否则使用path对应的FileSystemDict读写 - def __init__(self, path, log=None, ignore_opf=False): + def __init__(self, path=None, log=None, ignore_opf=False): if path: assert(os.path.isabs(path)) self.path = path diff --git a/application/static/base.js b/application/static/base.js index 943f6bef..f67cb9ef 100644 --- a/application/static/base.js +++ b/application/static/base.js @@ -256,7 +256,6 @@ function PopulateMySubscribed() { row_str.push(title); } if (separated) { - //row_str.push(''); row_str.push(' Sep'); } row_str.push('
' + i18n.thankForShare + '
'); } else if (data.status == i18n.loginRequired) { window.location.href = '/login'; diff --git a/application/templates/admin.html b/application/templates/admin.html index 2be39773..45f303da 100644 --- a/application/templates/admin.html +++ b/application/templates/admin.html @@ -11,7 +11,7 @@