Skip to content

Commit

Permalink
porting to python3
Browse files Browse the repository at this point in the history
  • Loading branch information
cdhigh committed Feb 18, 2024
1 parent e78bbd3 commit c6fe850
Show file tree
Hide file tree
Showing 59 changed files with 2,348 additions and 1,671 deletions.
1 change: 1 addition & 0 deletions application/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def init_app(name, debug=False):
def BeforeRequest():
g.version = __Version__
g.now = datetime.datetime.utcnow
g.allowSignup = app.config['ALLOW_SIGNUP']
connect_database()

@app.teardown_request
Expand Down
Empty file.
54 changes: 30 additions & 24 deletions application/back_end/db_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@
class KeUser(MyBaseModel): # kindleEar User
name = CharField(unique=True)
passwd = CharField()
expiration_days = IntegerField(default=0) #账号超期设置值,0为永久有效
email = CharField()
secret_key = CharField(default='')
kindle_email = CharField(default='')
email = CharField(default='') #用于重置密码之类的操作
enable_send = BooleanField(default=False)
send_days = JSONField(default=JSONField.list_default)
send_time = IntegerField(default=0)
timezone = IntegerField(default=0)
book_type = CharField(default='epub') #mobi,epub
device = CharField(default='')
expiration_days = IntegerField(default=0) #账号超期设置值,0为永久有效
expires = DateTimeField(null=True) #超过了此日期后账号自动停止推送
created_time = DateTimeField(default=datetime.datetime.utcnow)

device = CharField(default='')
book_type = CharField(default='epub') #mobi,epub
book_title = CharField(default='KindleEar')
title_fmt = CharField(default='') #在元数据标题中添加日期的格式
author_format = CharField(default='') #修正Kindle 5.9.x固件的bug【将作者显示为日期】
Expand All @@ -36,10 +37,9 @@ class KeUser(MyBaseModel): # kindleEar User
time_fmt = CharField(default='%Y-%m-%d')
oldest_article = IntegerField(default=7)
book_language = CharField(default='en') #自定义RSS的语言
enable_custom_rss = BooleanField(default=True)
enable_custom_rss = BooleanField(default=False)

share_links = JSONField(default=JSONField.dict_default) #evernote/wiz/pocket/instapaper包含子字典,微博/facebook/twitter等仅包含0/1

covers = JSONField(default=JSONField.dict_default) #保存封面图片数据库ID {'order':,'cover0':,...'cover6':}
send_mail_service = JSONField(default=JSONField.dict_default) #{'service':,...}
custom = JSONField(default=JSONField.dict_default) #留着扩展,避免后续一些小特性还需要升级数据表结构
Expand Down Expand Up @@ -219,31 +219,38 @@ class LastDelivered(MyBaseModel):
record = CharField(default='')
datetime = DateTimeField(default=datetime.datetime.utcnow)

#当前使用:
#name='dbTableVersion'.int_value 行保存数据库格式版本
#name='lastSharedRssTime'.time_value 保存共享库的最新更新日期
class AppInfo(MyBaseModel):
name = CharField()
int_value = IntegerField(default=0)
str_value = CharField(default='')
time_value = DateTimeField(default=datetime.datetime.utcnow)
name = CharField(unique=True)
value = CharField(default='')
description = CharField(default='')
comment = CharField(default='')

lastSharedRssTime = 'lastSharedRssTime'
newUserMailService = 'newUserMailService'
signupType = 'signupType'
inviteCodes = 'inviteCodes'

@classmethod
def get_value(cls, name, default):
dbItem = cls.get_or_none(AppInfo.name == name)
return dbItem.value if dbItem else default

@classmethod
def set_value(cls, name, value):
cls.replace(name=name, value=value).execute()

#创建数据库表格,一个数据库只需要创建一次
#如果是sql数据库,可以使用force=True删掉之前的数据库文件(小心)
def create_database_tables(force=False):
engine = os.getenv('DATABASE_ENGINE')
if engine == "sqlite" and dbName:
if not force and os.path.exists(dbName):
#print(f'[Error] Database "{dbName}" already exists')
return
elif os.path.exists(dbName):
try:
os.remove(dbName)
except:
pass
#if engine == "sqlite" and dbName:
# if not force and os.path.exists(dbName):
# #print(f'[Error] Database "{dbName}" already exists')
# return
# elif os.path.exists(dbName):
# try:
# os.remove(dbName)
# except:
# pass

if engine not in ["datastore", "mongodb"]:
#with dbInstance.connection_context():
Expand All @@ -252,5 +259,4 @@ def create_database_tables(force=False):
SharedRss, SharedRssCategory, LastDelivered, AppInfo], safe=True)
#close_database()

#AppInfo(name='dbTableVersion', int_value=DB_VERSION).save()
#print(f'Create database "{dbName}" finished')
11 changes: 11 additions & 0 deletions application/back_end/send_mail_adpt.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@
except ImportError:
smtp_send_mail = None

#返回当前可用的发送邮件服务列表
def avaliable_sm_services():
sm = ['local']
if gae_mail:
sm.append('gae')
if SendGridAPIClient:
sm.append('sendgrid')
if smtp_send_mail:
sm.append('smtp')
return sm

#发送邮件
#title: 邮件标题
#attachment: 附件二进制内容,或元祖 (filename, content)
Expand Down
73 changes: 70 additions & 3 deletions application/back_end/task_queue_adpt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# -*- coding:utf-8 -*-
#封装后台的任务队列,以适用不同的平台部署要求
#Author: cdhigh <https://github.com/cdhigh>
import os, json
import os, sys, json

__TASK_QUEUE_SERVICE = os.getenv('TASK_QUEUE_SERVICE')
if __TASK_QUEUE_SERVICE == "gae":
Expand Down Expand Up @@ -42,7 +42,11 @@ def create_http_task(url, payload):
#return client.create_task(tasks_v2.CreateTaskRequest(parent=taskParent, task=task))

elif __TASK_QUEUE_SERVICE == 'celery':
#启动celery
#celery -A main.celery_app worker --loglevel=info --logfile=d:\celery.log --concurrency=2 -P eventlet
#celery -A main.celery_app beat -s /home/celery/var/run/celerybeat-schedule --loglevel=info --logfile=d:\celery.log --concurrency=2 -P eventlet
from celery import Celery, Task, shared_task
from celery.schedules import crontab
from ..work.worker import WorkerImpl
from ..work.url2book import Url2BookImpl

Expand All @@ -53,17 +57,38 @@ def __call__(self, *args, **kwargs):
return self.run(*args, **kwargs)

app.config.from_mapping(
CELERY={'broker_url': app.config['CELERY_BROKER_URL'],
'result_backend': app.config['CELERY_RESULT_BACKEND'],
CELERY={'broker_url': app.config['TASK_QUEUE_BROKER_URL'],
'result_backend': app.config['TASK_QUEUE_RESULT_BACKEND'],
'task_ignore_result': True,
},)

celery_app = Celery(app.name, task_cls=FlaskTask)
celery_app.config_from_object(app.config["CELERY"])
celery_app.set_default()

celery_app.conf.beat_schedule = {
'check_deliver': {
'task': 'check_deliver',
'schedule': crontab(minute=0, hour='*/1'), #每个小时
'args': []
},
'remove_logs': {
'task': 'remove_logs', #每天凌晨
'schedule': crontab(minute=0, hour=0, day_of_month='*/1'),
'args': []
},
}
app.extensions["celery"] = celery_app
return celery_app

@shared_task(name="check_deliver", ignore_result=True)
def check_deliver():
MultiUserDelivery()

@shared_task(name="remove_logs", ignore_result=True)
def remove_logs():
RemoveLogs()

@shared_task(ignore_result=True)
def start_celery_worker_impl(**payload):
return WorkerImpl(**payload)
Expand All @@ -78,6 +103,48 @@ def create_delivery_task(payload: dict):
def create_url2book_task(payload: dict):
start_celery_url2book.delay(**payload)

elif __TASK_QUEUE_SERVICE == 'rq':
#启动rq
#set FLASK_APP=main.py
#flask rq worker

from flask_rq2 import RQ

rq = RQ()

def init_task_queue_service(app):
app.config['RQ_REDIS_URL'] = app.config['TASK_QUEUE_BROKER_URL']
rq.init_app(app)
#check_deliver.cron('0 */1 * * *', 'check_deliver') #每隔一个小时执行一次
#remove_logs.cron('0 0 */1 * *', 'check_deliver') #每隔24小时执行一次
return rq

@rq.job
def check_deliver():
from ..view.deliver import MultiUserDelivery
MultiUserDelivery()

@rq.job
def remove_logs():
from ..view.logs import RemoveLogs
RemoveLogs()

@rq.job
def start_rq_worker_impl(**payload):
from ..work.worker import WorkerImpl
return WorkerImpl(**payload)

@rq.job
def start_rq_url2book(**payload):
from ..work.url2book import Url2BookImpl
return Url2BookImpl(**payload)

def create_delivery_task(payload: dict):
start_rq_worker_impl.queue(**payload)

def create_url2book_task(payload: dict):
start_rq_url2book.queue(**payload)

elif not __TASK_QUEUE_SERVICE:
from ..work.worker import WorkerImpl
from ..work.url2book import Url2BookImpl
Expand Down
8 changes: 3 additions & 5 deletions application/base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@
#一些共同的工具函数,工具函数都是小写+下划线形式

#确认登录的装饰器
#如果提供userName,则要求登录的用户名=userName
#forAjax:是返回一个json字典
def login_required(userName=None, forAjax=False):
#forAjax:是否返回一个json字典
def login_required(forAjax=False):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
if ((session.get('login') == 1) and (not userName or (userName == session.get('userName')))
and get_login_user()):
if ((session.get('login') == 1) and get_login_user()):
return func(*args, **kwargs)
else:
return redirect(url_for("bpLogin.NeedLoginAjax") if forAjax else url_for("bpLogin.Login"))
Expand Down
1 change: 0 additions & 1 deletion application/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

@bpHome.route('/')
def Home():
#worker.WorkerImpl('admin', ['builtin:adventuregamers', 'custom:Recipe:2447:KEY', 'custom:Recipe:4964:KEY'])
return render_template('home.html')

@bpHome.route('/env')
Expand Down
30 changes: 27 additions & 3 deletions application/static/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ button {

.app-menu .pure-menu-selected a,
.app-menu .pure-menu-selected span {
color: white;
color: white !important;
text-decoration: none;
}

.app-menu .pure-menu-item a:hover,
Expand Down Expand Up @@ -609,7 +610,27 @@ select[id="shared_rss_lang_pick"] {
font-weight: bold;
}

.h3button {
background-color: rgb(0, 120, 231);
color: #fff;
border:solid 1px #ccc;
border-radius: 20px;
margin: 0px 40px;
padding: 2px 30px;
cursor: pointer;
font-size: 0.9em;
text-decoration: none;
white-space: nowrap;
}
.h3button:hover {
background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10));
color: white;
}

/* Feed列表的汉堡菜单按钮及其弹出子按钮 */
.hamburger-btn-container {
position: relative;
}
.hamburger-btn {
position: absolute;
top: 50%;
Expand Down Expand Up @@ -648,7 +669,10 @@ select[id="shared_rss_lang_pick"] {
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
transition: background-color 0.3s, box-shadow 0.3s;
}

.additional-btn-disabled {
pointer-events:none;
background: silver !important;
}
.additional-btn:hover {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}
Expand Down Expand Up @@ -788,7 +812,7 @@ div[class="schedule_daytimes"] input {
}
.imgFileUploade .imgAll li{
list-style: none;
width: 210px;height: 323px;border:solid 1px #ccc;margin:8px 5px;float: left;
width: 195px;height: 300px;border:solid 1px #ccc;margin:8px 5px;float: left;
position: relative;box-shadow: 0 0 10px #eee;
display: flex;
justify-content: center;
Expand Down
62 changes: 1 addition & 61 deletions application/static/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -968,73 +968,13 @@ var AjaxFileUpload = {
///[end] adv_uploadcss.html

///[start] admin.html
//添加一个账号
function AddAccount(name) {
var newName = $('#new_username').val();
var newPwd1 = $('#new_u_pwd1').val();
var newPwd2 = $('#new_u_pwd2').val();
var newEmail = $('#new_email').val();
var smService = $('#sm_service').val(); //send mail service
var expiration = $('#new_u_expiration').val();
if (!newName || !newPwd1 || !newPwd2) {
alert(i18n.namePwdEmpty);
return;
} else if (newPwd1 != newPwd2) {
alert(i18n.pwdDismatch);
return;
}

$.post("/admin", {actType: 'add', new_username: newName, new_u_pwd1: newPwd1, new_u_pwd2: newPwd2,
new_u_expiration: expiration, new_email: newEmail, sm_service: smService}, function (data) {
if (data.status == "ok") {
$('#new_username').val('');
$('#new_u_pwd1').val('');
$('#new_u_pwd2').val('');
$('#new_email').val('');
window.location.reload(true);
ShowSimpleModalDialog('<p>' + i18n.addAccountOk + '</p>');
} else if (data.status == i18n.loginRequired) {
window.location.href = '/login';
} else {
alert(data.status);
}
});
}

//修改账号的密码
function ChangeAccountPassword(name) {
var oldPwd = $('#orgpwd').val();
var newPwd1 = $('#newpwd1').val();
var newPwd2 = $('#newpwd2').val();
if (!oldPwd || !newPwd1 || !newPwd2) {
alert(i18n.namePwdEmpty);
return;
} else if (newPwd1 != newPwd2) {
alert(i18n.pwdDismatch);
return;
}

$.post("/admin", {actType: 'change', name: name, op: oldPwd, p1: newPwd1, p2: newPwd2}, function (data) {
if (data.status == "ok") {
$('#orgpwd').val('');
$('#newpwd1').val('');
$('#newpwd2').val('');
ShowSimpleModalDialog('<p>' + i18n.chPwdSuccess + '</p>');
} else if (data.status == i18n.loginRequired) {
window.location.href = '/login';
} else {
alert(data.status);
}
});
}

//删除一个账号
function DeleteAccount(name) {
if (!confirm(i18n.areYouSureDelete.format(name))) {
return;
}

$.post("/admin", {actType: 'delete', name: name}, function (data) {
$.post("/account/delete", {name: name}, function (data) {
if (data.status == "ok") {
ShowSimpleModalDialog('<p>' + i18n.accountDeleted + '</p>');
window.location.reload(true);
Expand Down
Loading

0 comments on commit c6fe850

Please sign in to comment.