Skip to content

Commit

Permalink
3.1.0
Browse files Browse the repository at this point in the history
add online reading
  • Loading branch information
cdhigh committed Jun 2, 2024
1 parent d7169e7 commit dcf100b
Show file tree
Hide file tree
Showing 22 changed files with 597 additions and 305 deletions.
5 changes: 3 additions & 2 deletions application/back_end/db_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class KeUser(MyBaseModel): # kindleEar User
created_time = DateTimeField(default=datetime.datetime.utcnow)

#email,sender,kindle_email,secret_key,enable_send,timezone,inbound_email,
#keep_in_email_days,delivery_mode,webshelf_days
#keep_in_email_days,delivery_mode,webshelf_days,reader_params
#sender: 可能等于自己的email,也可能是管理员的email
#delivery_mode: 推送模式:['email' | 'local' | 'email,local']
base_config = JSONField(default=JSONField.dict_default)
Expand All @@ -43,7 +43,8 @@ def cfg(self, item, default=None):
if value is None:
return {'email': '', 'kindle_email': '', 'secret_key': '', 'timezone': 0,
'inbound_email': 'save,forward', 'keep_in_email_days': 1,
'delivery_mode': 'email,local', 'webshelf_days': 7}.get(item, value)
'delivery_mode': 'email,local', 'webshelf_days': 7,
'reader_params': {}}.get(item, value)
else:
return value
def set_cfg(self, item, value):
Expand Down
18 changes: 9 additions & 9 deletions application/lib/build_ebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ def recipes_to_ebook(recipes: list, user, options=None, output_fmt=''):
recipes = [recipes]
output = io.BytesIO()
output_fmt=output_fmt if output_fmt else user.book_cfg('type')
plumber = Plumber(recipes, output, input_fmt='recipe', output_fmt=output_fmt)
plumber.merge_ui_recommendations(ke_opts(user, options))
options = ke_opts(user, options)
plumber = Plumber(recipes, output, input_fmt='recipe', output_fmt=output_fmt, options=options)
plumber.run()
return output.getvalue()

Expand Down Expand Up @@ -98,25 +98,25 @@ def clearPrevDownloads(): #退出时清理临时文件
def html_to_book(html: str, title: str, user, imgs=None, options=None, output_fmt='', language=''):
input_ = {'html': html, 'imgs': imgs, 'title': title, 'language': language}
output = io.BytesIO()
output_fmt=output_fmt if output_fmt else user.book_cfg('type')
plumber = Plumber(input_, output, input_fmt='html', output_fmt=output_fmt)
plumber.merge_ui_recommendations(ke_opts(user, options))
output_fmt = output_fmt if output_fmt else user.book_cfg('type')
options = ke_opts(user, options)
plumber = Plumber(input_, output, input_fmt='html', output_fmt=output_fmt, options=options)
plumber.run()
return output.getvalue()

#获取KindleEar定制的电子书转换参数
def ke_opts(user, options=None):
opt = user.custom.get('calibre_options', {})
if not isinstance(opt, dict):
opt = {}
opt = opt.copy()
opt = user.custom.get('calibre_options')
opt = opt.copy() if isinstance(opt, dict) else {}
opt.update(options or {})
opt.setdefault('output_profile', user.book_cfg('device'))
opt.setdefault('input_profile', 'kindle')
opt.setdefault('no_inline_toc', False)
opt.setdefault('epub_inline_toc', True)
opt.setdefault('dont_compress', True)
opt.setdefault('dont_split_on_page_breaks', True)
opt.setdefault('dont_save_webshelf', False)
opt.setdefault('keep_images', True)
opt['user'] = user

#opt.setdefault('debug_pipeline', os.getenv('KE_TEMP_DIR'))
Expand Down
4 changes: 0 additions & 4 deletions application/lib/calibre/customize/conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,6 @@ class InputFormatPlugin(Plugin):
'document itself. Particularly useful for documents that '
'do not declare an encoding or that have erroneous '
'encoding declarations.')),
OptionRecommendation(name='user', recommended_value=None,
help='Keuser instance.'),
OptionRecommendation(name='keep_images', recommended_value=True,
help='If keep the images.'),
}

#: Options to customize the behavior of this plugin. Every option must be an
Expand Down
60 changes: 35 additions & 25 deletions application/lib/calibre/ebooks/conversion/plumber.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.utils.date import parse_date
from calibre.utils.zipfile import ZipFile
from calibre.utils.filenames import ascii_filename
from calibre import (extract, walk, isbytestring, filesystem_encoding,
get_types_map)
from calibre.constants import __version__
from polyglot.builtins import string_or_bytes

from filesystem_dict import FsDictStub
from application.utils import sanitize_filename, get_directory_size
from application.utils import get_directory_size
from application.base_handler import save_delivery_log

DEBUG_README=b'''
Expand Down Expand Up @@ -90,10 +91,11 @@ class Plumber:

#input_: 输入,编译好的recipes列表或包含html和相关图像的一个字典
#output: 输出文件绝对路径名,也可能是一个BytesIO
def __init__(self, input_, output, input_fmt, output_fmt=None, abort_after_input_dump=False):
def __init__(self, input_, output, input_fmt, output_fmt=None, options=None, abort_after_input_dump=False):
self.input_ = input_
self.output = output
self.log = default_log
self.user_options = options or {}
self.abort_after_input_dump = abort_after_input_dump
self.pipeline_options = _pipeline_options

Expand Down Expand Up @@ -190,8 +192,6 @@ def merge_plugin_recommendations(self):
for source in (self.input_plugin, self.output_plugin):
self.merge_plugin_recs(source)

#在外面设置电子书生成的参数
# {'name1': value1, 'name2': value2}
def merge_ui_recommendations(self, recommendations: dict):
'''
Merge recommendations from the UI. As long as the UI recommendation
Expand All @@ -213,10 +213,10 @@ def eq(name, a, b):
if rec is not None:
rec.recommended_value = val

def opts_to_mi(self, mi):
def opts_to_mi(self, opts, mi):
from calibre.ebooks.metadata import string_to_authors
for x in self.metadata_option_names:
val = getattr(self.opts, x, None)
val = getattr(opts, x, None)
if val is not None:
if x == 'authors':
val = string_to_authors(val)
Expand Down Expand Up @@ -252,7 +252,7 @@ def download_cover(self, url):
img.convert('RGB').save(pt.name)
return pt.name

def read_user_metadata(self):
def read_user_metadata(self, opts):
'''
Read all metadata specified by the user. Command line options override
metadata from a specified OPF file.
Expand All @@ -266,7 +266,7 @@ def read_user_metadata(self):
# with open(self.opts.read_metadata_from_opf, 'rb') as stream:
# opf = OPF(stream, os.path.dirname(self.opts.read_metadata_from_opf))
# mi = opf.to_book_metadata()
self.opts_to_mi(mi)
self.opts_to_mi(opts, mi)
#if mi.cover:
# if mi.cover.startswith('http:') or mi.cover.startswith('https:'):
# mi.cover = self.download_cover(mi.cover)
Expand All @@ -282,44 +282,49 @@ def setup_options(self):
'''
Setup the `self.opts` object.
'''
self.opts = OptionValues()
opts = OptionValues()
for group in (self.input_options, self.pipeline_options, self.output_options):
for rec in group:
setattr(self.opts, rec.option.name, rec.recommended_value)
setattr(opts, rec.option.name, rec.recommended_value)

for name, val in self.user_options.items():
setattr(opts, name, val)

def set_profile(profiles, which):
attr = which + '_profile'
sval = getattr(self.opts, attr)
sval = getattr(opts, attr)
for x in profiles():
if x.short_name == sval:
setattr(self.opts, attr, x)
setattr(opts, attr, x)
return
self.log.warn(
'Profile (%s) %r is no longer available, using default'%(which, sval))
for x in profiles():
if x.short_name == 'default':
setattr(self.opts, attr, x)
setattr(opts, attr, x)
break

set_profile(input_profiles, 'input')
set_profile(output_profiles, 'output')

self.read_user_metadata()
self.read_user_metadata(opts)

self.opts.no_inline_navbars = self.opts.output_profile.supports_mobi_indexing \
opts.no_inline_navbars = opts.output_profile.supports_mobi_indexing \
and self.output_fmt == 'mobi'

if self.opts.verbose > 1:
if opts.verbose > 1:
self.log.debug('Resolved conversion options')
try:
self.log.debug('calibre version:', __version__)
odict = dict(self.opts.__dict__)
odict = dict(opts.__dict__)
for x in ('username', 'password'):
odict.pop(x, None)
self.log.debug(pprint.pformat(odict))
except:
self.log.exception('Failed to get resolved conversion options')

self.opts = opts

def flush(self):
try:
sys.stdout.flush()
Expand Down Expand Up @@ -409,7 +414,7 @@ def run(self):
# self.dump_input(self.oeb, tdir)
# if self.abort_after_input_dump:
# return
self.opts_to_mi(self.user_metadata)
self.opts_to_mi(self.opts, self.user_metadata)
if not hasattr(self.oeb, 'manifest'): #从一堆文件里面创建OEBBook实例
try:
self.oeb = create_oebbook(self.log, self.oeb, self.opts, encoding=self.input_plugin.output_encoding,
Expand Down Expand Up @@ -579,15 +584,20 @@ def run(self):
def save_oeb_if_need(self, oeb):
user = self.opts.user #type:ignore
oebDir = os.environ.get('EBOOK_SAVE_DIR')
if not (oebDir and ('local' in user.cfg('delivery_mode'))):
if getattr(self.opts, 'dont_save_webshelf') or not (oebDir and ('local' in user.cfg('delivery_mode'))):
return

title = sanitize_filename(oeb.metadata.title[0].value or 'Untitled')
bookDir = _bookDir = os.path.join(oebDir, user.name, user.local_time('%Y-%m-%d'), title)
cnt = 0
while os.path.exists(bookDir): #一天可以保存多个同名推送
cnt += 1
bookDir = f'{_bookDir} [{cnt}]'
#提取字符串开头的数字
def prefixNum(txt):
match = re.search(r'^(\d+)', txt)
return int(match.group(1)) if match else 0

dateDir = os.path.join(oebDir, user.name, user.local_time('%Y-%m-%d'))
maxIdx = max([prefixNum(item) for item in os.listdir(dateDir)]) if os.path.exists(dateDir) else 0
title = oeb.metadata.title[0].value or 'Untitled'
title = ascii_filename(title).replace(' ', '_')
bookDir = os.path.join(dateDir, f'{maxIdx + 1:03}_{title}')

try:
os.makedirs(bookDir)
except Exception as e:
Expand Down
4 changes: 2 additions & 2 deletions application/static/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -1150,7 +1150,7 @@ var AjaxFileUpload = {
}
},
error: function(xhr, status, error) {
alert(status);
alert(status + '\n' + error);
}
});
},
Expand Down Expand Up @@ -1312,7 +1312,7 @@ function startUploadCoversToServer(url) {
$("#up_cover_progress").hide();
$("#up_cover_progress_bar").css("width", "0px");
$("#up_cover_progress_bar").html('');
alert(status);
alert(status + '\n' + error);
}
});
}
Expand Down
73 changes: 42 additions & 31 deletions application/static/reader.css
Original file line number Diff line number Diff line change
@@ -1,48 +1,61 @@
body {
* {
padding: 0px;
margin: 0px;
font-family: Arial, sans-serif;
overflow: hidden;
}
html, body {
padding: 0px;
margin: 0px;
height: 100%;
scrollbar-width: none;
-ms-overflow-style: none;
}
::-webkit-scrollbar {
body::-webkit-scrollbar {
display: none;
width: 0px;
height: 0px;
background: transparent;
}
::-webkit-scrollbar-thumb {
body::-webkit-scrollbar-thumb {
background: transparent;
display: none;
}

.container {
margin: 0px;
padding: 5px;
padding: 0px;
position: relative;
height: 100%;
width: 100%;
box-sizing: border-box;
}
.content {
margin-right: 10px;
padding: 15px;
margin: 0px;
padding: 0px;
overflow-y: auto;
height: 100%;
width: 100%;
scrollbar-width: none;
box-sizing: border-box;
/*-webkit-overflow-scrolling: touch;*/
}
.content::-webkit-scrollbar {
display: none;
.embedded-iframe {
padding: 10px 20px 10px 10px;
margin: 0px;
width: 100%;
height: 100%;
border: none;
white-space: normal;
word-wrap: break-word;
overflow-wrap: break-word;
overflow: hidden;
hyphens: auto;
box-sizing: border-box;
scrollbar-width: none;
-ms-overflow-style: none;
}
.pos-indicator {
position: absolute;
right: 15px;
right: 5px;
top: 5px;
width: 10px;
width: 15px;
height: 50px;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 5px;
Expand All @@ -52,6 +65,7 @@ body {
position: fixed;
left: 0px;
top: 0px;
margin: 0px;
padding: 5px 10px 5px 5px;
background-color: white;
overflow-x: hidden;
Expand All @@ -62,13 +76,22 @@ body {

/* small screen, ink mode, pw3/voyage=1448x1072 */
@media (max-width: 1072px) {
::-webkit-scrollbar {
display: none;
width: 0px;
height: 0px;
background: transparent;
}
::-webkit-scrollbar-thumb {
background: transparent;
display: none;
}
.navbar {
display: none;
right: 20px;
bottom: 10px;
bottom: 0px;
}
.container {
width: 100%;
margin: 0px 10px 0px 0px;
overflow: hidden;
-webkit-overflow-scrolling: touch;
Expand All @@ -90,13 +113,10 @@ body {
}
.container {
width: auto;
overflow-y: scroll;
margin-left: 400px; /* width of .navbar */
margin-left: 410px; /* width of .navbar */
}
.pos-indicator {
display: none;
}
button#closeNavBtn {

.pos-indicator, .nav-indicator, button#closeNavBtn {
display: none;
}
.nav-footer button {
Expand Down Expand Up @@ -264,12 +284,3 @@ body {
text-align: center;
font-size: 0.9em;
}
.embedded-iframe {
padding: 0px;
margin: 0px;
width: 100%;
height: 100%;
border: none;
scrollbar-width: none;
-ms-overflow-style: none;
}
Loading

0 comments on commit dcf100b

Please sign in to comment.