Skip to content

Commit

Permalink
add trim builtin recipe feature
Browse files Browse the repository at this point in the history
  • Loading branch information
cdhigh committed May 19, 2024
1 parent 5bce05b commit 93a2ee7
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 10 deletions.
7 changes: 5 additions & 2 deletions application/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# KindleEar web application
# 创建app对象
# Author: cdhigh <https://github.com/cdhigh>
__Author__ = "cdhigh"

import os, builtins, datetime
from flask import Flask, render_template, session, request, g
from flask import Flask, session, g
from flask_babel import Babel, gettext
builtins.__dict__['_'] = gettext

Expand Down Expand Up @@ -41,9 +41,12 @@ def init_app(name, cfgMap, set_env, debug=False):

@app.before_request
def BeforeRequest():
session.permanent = True
app.permanent_session_lifetime = datetime.timedelta(days=31)
g.version = appVer
g.now = datetime.datetime.utcnow
g.allowSignup = (app.config['ALLOW_SIGNUP'] == 'yes')

connect_database()

@app.teardown_request
Expand Down
8 changes: 3 additions & 5 deletions application/lib/calibre/web/feeds/news.py
Original file line number Diff line number Diff line change
Expand Up @@ -2191,17 +2191,15 @@ def parse_feeds(self):
(LastDelivered.bookname==self.title) & (LastDelivered.url==url))
delta = (now - timeItem.datetime) if timeItem else None
#这里oldest_article和其他的recipe不一样,这个参数表示在这个区间内不会重复推送
if (not timeItem) or (not self.oldest_article) or (self.delivery_reason == 'manual'):
if (not timeItem or not self.oldest_article or self.delivery_reason == 'manual' or
(delta and delta.total_seconds() > 24 * 3600 * self.oldest_article)):
id_counter += 1
feed.articles.append(Article(f'internal id#{id_counter}', title, url, 'KindleEar', '', structNow, ''))

#如果是手动推送,不单不记录已推送日期,还将已有的上次推送日期数据删除
if (not self.oldest_article) or (self.delivery_reason == 'manual'):
if (self.delivery_reason == 'manual') or (not self.oldest_article):
if timeItem:
timeItem.delete_instance()
elif timeItem:
timeItem.datetime = now
timeItem.save()
else:
LastDelivered.create(user=self.user.name, bookname=self.title, url=url)
else:
Expand Down
2 changes: 1 addition & 1 deletion application/view/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def LoginPost():
elif not user.cfg('kindle_email'):
url = url_for("bpSetting.Setting")
else:
url = next_url if next_url else url_for("bpSubscribe.MySubscription")
url = next_url if next_url else url_for("bpLogs.Mylogs")
default_log.info(f"Login event: {name}")
return redirect(url)
else: #账号或密码错
Expand Down
8 changes: 7 additions & 1 deletion docs/Chinese/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ chmod +x kindleear/tools/gae_deploy.sh && \
kindleear/tools/gae_deploy.sh
```

注:默认配置为B2实例,1个工作进程,2个工作线程,20分钟超时,如果需要其他配置,可以修改最后一行代码,比如:
**注1:** 默认配置为B2实例,1个工作进程,2个工作线程,20分钟超时,如果需要其他配置,可以修改最后一行代码

```bash
#instance_class: B1 (384MB/600MHz)
Expand All @@ -35,6 +35,12 @@ kindleear/tools/gae_deploy.sh
kindleear/tools/gae_deploy.sh B1,1,t2,15m
```

**注2:** 如果想精简内置Recipe文件,仅保留你需要的语种,可以在 `kindleear/tools/gae_deploy.sh` 命令前增加一行

```bash
# parameter is a list of language code you want to keep
python kindleear/tools/trim_recipes.py en,zh,es
```

3. 如需要GAE部署的更多信息,请参考 [其他说明](#gae_other_instructions) 章节,比如怎么解决 "Unauthorized sender" 错误等。

Expand Down
9 changes: 8 additions & 1 deletion docs/English/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ chmod +x kindleear/tools/gae_deploy.sh && \
kindleear/tools/gae_deploy.sh
```

Note: The default configuration is B2 instance, 1 worker process, 2 worker threads, and a 20-minute timeout. If you need a different configuration, you can modify the last line of code, for example:
**Note 1:** The default configuration is B2 instance, 1 worker process, 2 worker threads, and a 20-minute timeout. If you need a different configuration, you can modify the last line of code, for example:

```bash
#instance_class: B1 (384MB/600MHz)
Expand All @@ -36,6 +36,13 @@ Note: The default configuration is B2 instance, 1 worker process, 2 worker threa
kindleear/tools/gae_deploy.sh B1,1,t2,15m
```

**Note 2:** If you want to trim the built-in Recipe file to keep only the languages you need, you can add a line before the `kindleear/tools/gae_deploy.sh` command.

```bash
# parameter is a list of language code you want to keep
python kindleear/tools/trim_recipes.py en,zh,es
```

3. Refer to the [Other Instructions](#gae_other_instructions) section for additional information, such as troubleshooting the 'Unauthorized sender' issue.


Expand Down
94 changes: 94 additions & 0 deletions tools/trim_recipes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
"""Trim builtin_recipes.zip/builtin_recipes.xml for KindleEar
Due to being a utility script, all file read/write exceptions are ignored.
Usage: python trim_recipes.py en zh es
"""
import re, os, sys, zipfile
import xml.etree.ElementTree as ET

def main():
if len(sys.argv) <= 1:
print('Trim builtin_recipes.zip/builtin_recipes.xml')
print('Usage: python trim_recipes.py en zh es')
print('')
return

langList = []
for item in ','.join(sys.argv[1:]).replace(';', ',').replace(' ', '').split(','):
langList.append(item.replace('_', '-').split('-')[0].lower())

thisDir = os.path.abspath(os.path.dirname(__file__))
xmlFile = os.path.normpath(os.path.join(thisDir, '../application/recipes/builtin_recipes.xml'))
reciZipFile = os.path.normpath(os.path.join(thisDir, '../application/recipes/builtin_recipes.zip'))
if not os.path.exists(xmlFile) or not os.path.exists(reciZipFile):
print('Cannot found builtin_recipes.xml/builtin_recipes.zip')
return

print(f'Triming xml file using language list: {langList}')
size0 = os.path.getsize(xmlFile)
recipeFiles = trimXml(xmlFile, langList)
size1 = os.path.getsize(xmlFile)
if not recipeFiles: #we should continue, somebody might want to remove all of them.
print('All recipes were removed! Please check your language list.')


print(f'The builtin_recipes.xml file was reduced from {filesizeformat(size0)} to {filesizeformat(size1)}.')

size0 = os.path.getsize(reciZipFile)
trimZip(reciZipFile, recipeFiles)
size1 = os.path.getsize(reciZipFile)
print(f'The builtin_recipes.zip file was reduced from {filesizeformat(size0)} to {filesizeformat(size1)}.')

#Trim xml file using language list, return a list of recipe file
def trimXml(xmlFile: str, langList: list):
namespace = 'http://calibre-ebook.com/recipe_collection'
ET.register_namespace('', namespace)
tree = ET.parse(xmlFile)
root = tree.getroot()
recipeFiles = []
toRemove = []
for recipe in root.findall(f'{{{namespace}}}recipe'):
id_ = recipe.get('id', '')
language = recipe.get('language', '').replace('_', '-').split('-')[0].lower()
if id_.startswith('builtin:') and language in langList:
recipeFiles.append(f'{id_[8:]}.recipe')
else:
toRemove.append(recipe)
for recipe in toRemove:
root.remove(recipe)

root.set('count', str(len(root.findall(f'{{{namespace}}}recipe'))))
tree.write(xmlFile, encoding='utf-8', xml_declaration=True)
return recipeFiles


#Trim recipe zip file using recipe file list
def trimZip(reciZipFile: str, recipeFiles: list):
tmpFile = reciZipFile + '.zip'
zin = zipfile.ZipFile(reciZipFile, 'r')
zout = zipfile.ZipFile(tmpFile, 'w')
for item in [e for e in zin.infolist() if e.filename in recipeFiles]:
zout.writestr(item, zin.read(item.filename))
zout.close()
zin.close()
os.remove(reciZipFile)
os.rename(tmpFile, reciZipFile)

def filesizeformat(value, binary=False, suffix='B'):
value = abs(float(value))
if binary:
base = 1024
prefixes = ('', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi')
else:
base = 1000
prefixes = ('', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')

for unit in prefixes:
if value < base:
return f"{value:3.1f} {unit}{suffix}" if unit else f"{int(value)} {suffix}"
value /= base
return f"{value:.1f} {unit}{suffix}" #type:ignore

if __name__ == '__main__':
main()

0 comments on commit 93a2ee7

Please sign in to comment.