Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
D
douban-api-proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
douban-api-proxy
Commits
2c615fdf
Commit
2c615fdf
authored
Jan 28, 2017
by
OzzieIsaacs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finalize graphical setup for calibre-web
parent
75c89c28
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
506 additions
and
323 deletions
+506
-323
cps.py
cps.py
+8
-10
db.py
cps/db.py
+33
-8
fb2.py
cps/fb2.py
+1
-1
helper.py
cps/helper.py
+19
-24
admin.html
cps/templates/admin.html
+1
-1
config_edit.html
cps/templates/config_edit.html
+14
-8
index.html
cps/templates/index.html
+1
-1
stats.html
cps/templates/stats.html
+4
-4
user_edit.html
cps/templates/user_edit.html
+13
-5
ub.py
cps/ub.py
+161
-83
web.py
cps/web.py
+251
-178
No files found.
cps.py
View file @
2c615fdf
...
...
@@ -3,27 +3,25 @@ import sys
import
time
base_path
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
# Insert local directories into path
sys
.
path
.
insert
(
0
,
os
.
path
.
join
(
base_path
,
'vendor'
))
from
cps
import
web
# from cps import config
from
tornado.wsgi
import
WSGIContainer
from
tornado.httpserver
import
HTTPServer
from
tornado.ioloop
import
IOLoop
if
__name__
==
'__main__'
:
'''if config
.DEVELOPMENT:
web.app.run(host="0.0.0.0", port=web.config.config_port, debug=True)
else:
'''
http_server
=
HTTPServer
(
WSGIContainer
(
web
.
app
))
http_server
.
listen
(
we
b
.
config
.
config_port
)
IOLoop
.
instance
()
.
start
()
if
web
.
ub
.
DEVELOPMENT
:
web
.
app
.
run
(
host
=
"0.0.0.0"
,
port
=
web
.
ub
.
config
.
config_port
,
debug
=
True
)
else
:
http_server
=
HTTPServer
(
WSGIContainer
(
web
.
app
))
http_server
.
listen
(
web
.
u
b
.
config
.
config_port
)
IOLoop
.
instance
()
.
start
()
if
web
.
global_task
==
0
:
print
(
"Performing restart of Calibre-web"
)
os
.
execl
(
sys
.
executable
,
sys
.
executable
,
*
sys
.
argv
)
os
.
execl
(
sys
.
executable
,
sys
.
executable
,
*
sys
.
argv
)
else
:
print
(
"Performing shutdown of Calibre-web"
)
os
.
_
exit
(
0
)
sys
.
exit
(
0
)
cps/db.py
View file @
2c615fdf
...
...
@@ -7,12 +7,21 @@ from sqlalchemy.orm import *
import
os
import
re
import
ast
from
ub
import
Config
from
ub
import
config
import
ub
session
=
None
cc_exceptions
=
None
cc_classes
=
None
cc_ids
=
None
books_custom_column_links
=
None
engine
=
None
# user defined sort function for calibre databases (Series, etc.)
def
title_sort
(
title
):
# calibre sort stuff
config
=
Config
()
#
config=Config()
title_pat
=
re
.
compile
(
config
.
config_title_regex
,
re
.
IGNORECASE
)
match
=
title_pat
.
search
(
title
)
if
match
:
...
...
@@ -216,9 +225,10 @@ class Books(Base):
series
=
relationship
(
'Series'
,
secondary
=
books_series_link
,
backref
=
'books'
)
ratings
=
relationship
(
'Ratings'
,
secondary
=
books_ratings_link
,
backref
=
'books'
)
languages
=
relationship
(
'Languages'
,
secondary
=
books_languages_link
,
backref
=
'books'
)
identifiers
=
relationship
(
'Identifiers'
,
backref
=
'books'
)
identifiers
=
relationship
(
'Identifiers'
,
backref
=
'books'
)
def
__init__
(
self
,
title
,
sort
,
author_sort
,
timestamp
,
pubdate
,
series_index
,
last_modified
,
path
,
has_cover
,
authors
,
tags
):
def
__init__
(
self
,
title
,
sort
,
author_sort
,
timestamp
,
pubdate
,
series_index
,
last_modified
,
path
,
has_cover
,
authors
,
tags
):
# ToDO check Authors and tags necessary
self
.
title
=
title
self
.
sort
=
sort
self
.
author_sort
=
author_sort
...
...
@@ -253,19 +263,33 @@ class Custom_Columns(Base):
return
display_dict
def
setup_db
(
config
):
def
setup_db
():
global
session
global
cc_exceptions
global
cc_classes
global
cc_ids
global
books_custom_column_links
global
engine
if
config
.
config_calibre_dir
is
None
:
return
if
config
.
config_calibre_dir
is
None
or
config
.
config_calibre_dir
==
u''
:
return
False
dbpath
=
os
.
path
.
join
(
config
.
config_calibre_dir
,
"metadata.db"
)
engine
=
create_engine
(
'sqlite:///{0}'
.
format
(
dbpath
.
encode
(
'utf-8'
)),
echo
=
False
)
conn
=
engine
.
connect
()
try
:
conn
=
engine
.
connect
()
except
:
content
=
ub
.
session
.
query
(
ub
.
Settings
)
.
first
()
content
.
config_calibre_dir
=
None
content
.
db_configured
=
False
ub
.
session
.
commit
()
config
.
loadSettings
()
return
False
content
=
ub
.
session
.
query
(
ub
.
Settings
)
.
first
()
content
.
db_configured
=
True
ub
.
session
.
commit
()
config
.
loadSettings
()
conn
.
connection
.
create_function
(
'title_sort'
,
1
,
title_sort
)
cc
=
conn
.
execute
(
"SELECT id, datatype FROM custom_columns"
)
...
...
@@ -310,3 +334,4 @@ def setup_db(config):
Session
=
sessionmaker
()
Session
.
configure
(
bind
=
engine
)
session
=
Session
()
return
True
\ No newline at end of file
cps/fb2.py
View file @
2c615fdf
...
...
@@ -3,7 +3,7 @@ from lxml import etree
import
os
import
uploader
# ToDo: Check usage of original_file_name
def
get_fb2_info
(
tmp_file_path
,
original_file_name
,
original_file_extension
):
ns
=
{
...
...
cps/helper.py
View file @
2c615fdf
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import
db
,
ub
# import config
import
db
import
ub
from
flask
import
current_app
as
app
import
logging
import
smtplib
...
...
@@ -33,8 +33,9 @@ def update_download(book_id, user_id):
ub
.
session
.
commit
()
def
make_mobi
(
book_id
,
calibrepath
):
vendorpath
=
os
.
path
.
join
(
os
.
path
.
normpath
(
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
+
os
.
sep
+
"../vendor"
+
os
.
sep
))
def
make_mobi
(
book_id
,
calibrepath
):
vendorpath
=
os
.
path
.
join
(
os
.
path
.
normpath
(
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
+
os
.
sep
+
"../vendor"
+
os
.
sep
))
if
sys
.
platform
==
"win32"
:
kindlegen
=
os
.
path
.
join
(
vendorpath
,
u"kindlegen.exe"
)
else
:
...
...
@@ -80,18 +81,20 @@ def make_mobi(book_id,calibrepath):
class
StderrLogger
(
object
):
buffer
=
''
buffer
=
''
def
__init__
(
self
):
self
.
logger
=
logging
.
getLogger
(
'cps.web'
)
def
write
(
self
,
message
):
if
message
==
'
\n
'
:
if
message
==
'
\n
'
:
self
.
logger
.
debug
(
self
.
buffer
)
self
.
buffer
=
''
self
.
buffer
=
''
else
:
self
.
buffer
=
self
.
buffer
+
message
self
.
buffer
+=
message
def
send_raw_email
(
kindle_mail
,
msg
):
def
send_raw_email
(
kindle_mail
,
msg
):
settings
=
ub
.
get_mail_settings
()
msg
[
'From'
]
=
settings
[
"mail_from"
]
...
...
@@ -107,7 +110,7 @@ def send_raw_email(kindle_mail,msg):
# send email
try
:
timeout
=
600
# set timeout to 5mins
timeout
=
600
# set timeout to 5mins
org_stderr
=
smtplib
.
stderr
smtplib
.
stderr
=
StderrLogger
()
...
...
@@ -140,18 +143,11 @@ def send_test_mail(kindle_mail):
msg
[
'Subject'
]
=
_
(
u'Calibre-web test email'
)
text
=
_
(
u'This email has been sent via calibre web.'
)
msg
.
attach
(
MIMEText
(
text
.
encode
(
'UTF-8'
),
'plain'
,
'UTF-8'
))
return
send_raw_email
(
kindle_mail
,
msg
)
return
send_raw_email
(
kindle_mail
,
msg
)
def
send_mail
(
book_id
,
kindle_mail
,
calibrepath
):
def
send_mail
(
book_id
,
kindle_mail
,
calibrepath
):
"""Send email with attachments"""
is_mobi
=
False
is_azw
=
False
is_azw3
=
False
is_epub
=
False
is_pdf
=
False
file_path
=
None
settings
=
ub
.
get_mail_settings
()
# create MIME message
msg
=
MIMEMultipart
()
msg
[
'Subject'
]
=
_
(
u'Send to Kindle'
)
...
...
@@ -177,7 +173,7 @@ def send_mail(book_id, kindle_mail,calibrepath):
if
'mobi'
in
formats
:
msg
.
attach
(
get_attachment
(
formats
[
'mobi'
]))
elif
'epub'
in
formats
:
filepath
=
make_mobi
(
book
.
id
,
calibrepath
)
filepath
=
make_mobi
(
book
.
id
,
calibrepath
)
if
filepath
is
not
None
:
msg
.
attach
(
get_attachment
(
filepath
))
elif
filepath
is
None
:
...
...
@@ -207,8 +203,7 @@ def get_attachment(file_path):
return
attachment
except
IOError
:
traceback
.
print_exc
()
message
=
(
_
(
'The requested file could not be read. Maybe wrong '
\
'permissions?'
))
message
=
(
_
(
'The requested file could not be read. Maybe wrong permissions?'
))
# ToDo: What is this?
return
None
...
...
@@ -218,7 +213,7 @@ def get_valid_filename(value, replace_whitespace=True):
filename. Limits num characters to 128 max.
"""
value
=
value
[:
128
]
re_slugify
=
re
.
compile
(
'[^
\
w
\
s-]'
,
re
.
UNICODE
)
#
re_slugify = re.compile('[^\w\s-]', re.UNICODE)
value
=
unicodedata
.
normalize
(
'NFKD'
,
value
)
re_slugify
=
re
.
compile
(
'[^
\
w
\
s-]'
,
re
.
UNICODE
)
value
=
unicode
(
re_slugify
.
sub
(
''
,
value
)
.
strip
())
...
...
@@ -238,7 +233,7 @@ def get_normalized_author(value):
return
value
def
update_dir_stucture
(
book_id
,
calibrepath
):
def
update_dir_stucture
(
book_id
,
calibrepath
):
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"title_sort"
,
1
,
db
.
title_sort
)
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
path
=
os
.
path
.
join
(
calibrepath
,
book
.
path
)
...
...
cps/templates/admin.html
View file @
2c615fdf
...
...
@@ -75,7 +75,7 @@
</table>
<div
class=
"btn btn-default"
><a
href=
"{{url_for('configuration')}}"
>
{{_('Configuration')}}
</a></div>
<h2>
{{_('Administration')}}
</h2>
{% if not
config.DEVELOPMENT
%}
{% if not
development
%}
<div
class=
"btn btn-default"
data-toggle=
"modal"
data-target=
"#RestartDialog"
>
{{_('Restart Calibre-web')}}
</a></div>
<div
class=
"btn btn-default"
data-toggle=
"modal"
data-target=
"#ShutdownDialog"
>
{{_('Stop Calibre-web')}}
</a></div>
{% endif %}
...
...
cps/templates/config_edit.html
View file @
2c615fdf
...
...
@@ -9,7 +9,7 @@
</div>
<div
class=
"form-group"
>
<label
for=
"config_port"
>
{{_('Server Port')}}
</label>
<input
type=
"
text
"
class=
"form-control"
name=
"config_port"
id=
"config_port"
value=
"{% if content.config_port != None %}{{ content.config_port }}{% endif %}"
autocomplete=
"off"
required
>
<input
type=
"
number"
min=
"1"
max=
"65535
"
class=
"form-control"
name=
"config_port"
id=
"config_port"
value=
"{% if content.config_port != None %}{{ content.config_port }}{% endif %}"
autocomplete=
"off"
required
>
</div>
<div
class=
"form-group"
>
<label
for=
"config_calibre_web_title"
>
{{_('Title')}}
</label>
...
...
@@ -17,11 +17,11 @@
</div>
<div
class=
"form-group"
>
<label
for=
"config_books_per_page"
>
{{_('Books per page')}}
</label>
<input
type=
"
text
"
class=
"form-control"
name=
"config_books_per_page"
id=
"config_books_per_page"
value=
"{% if content.config_books_per_page != None %}{{ content.config_books_per_page }}{% endif %}"
autocomplete=
"off"
>
<input
type=
"
number"
min=
"1"
max=
"200
"
class=
"form-control"
name=
"config_books_per_page"
id=
"config_books_per_page"
value=
"{% if content.config_books_per_page != None %}{{ content.config_books_per_page }}{% endif %}"
autocomplete=
"off"
>
</div>
<div
class=
"form-group"
>
<label
for=
"config_random_books"
>
{{_('No. of random books to show')}}
</label>
<input
type=
"
text
"
class=
"form-control"
name=
"config_random_books"
id=
"config_random_books"
value=
"{% if content.config_random_books != None %}{{ content.config_random_books }}{% endif %}"
autocomplete=
"off"
>
<input
type=
"
number"
min=
"1"
max=
"30
"
class=
"form-control"
name=
"config_random_books"
id=
"config_random_books"
value=
"{% if content.config_random_books != None %}{{ content.config_random_books }}{% endif %}"
autocomplete=
"off"
>
</div>
<div
class=
"form-group"
>
...
...
@@ -31,10 +31,10 @@
<div
class=
"form-group"
>
<label
for=
"config_log_level"
>
{{_('Log Level')}}
</label>
<select
name=
"config_log_level"
id=
"config_log_level"
class=
"form-control"
>
<option
value=
"
DEBUG"
{%
if
content
.
config_log_level =
=
'
DEBUG
'
%}
selected
{%
endif
%}
>
DEBUG
</option>
<option
value=
"
INFO"
{%
if
content
.
config_log_level =
=
'
INFO
'
or
content
.
config_log_level =
=
None
%}
selected
{%
endif
%}
>
INFO
</option>
<option
value=
"
WARNING"
{%
if
content
.
config_log_level =
=
'
WARNING
'
%}
selected
{%
endif
%}
>
WARNING
</option>
<option
value=
"
ERROR"
{%
if
content
.
config_log_level =
=
'
ERROR
'
%}
selected
{%
endif
%}
>
ERROR
</option>
<option
value=
"
10"
{%
if
content
.
config_log_level =
=
10
%}
selected
{%
endif
%}
>
DEBUG
</option>
<option
value=
"
20"
{%
if
content
.
config_log_level =
=
20
or
content
.
config_log_level =
=
None
%}
selected
{%
endif
%}
>
INFO
</option>
<option
value=
"
30"
{%
if
content
.
config_log_level =
=
30
%}
selected
{%
endif
%}
>
WARNING
</option>
<option
value=
"
40"
{%
if
content
.
config_log_level =
=
40
%}
selected
{%
endif
%}
>
ERROR
</option>
</select>
</div>
<div
class=
"form-group"
>
...
...
@@ -48,8 +48,14 @@
<div
class=
"form-group"
>
<input
type=
"checkbox"
id=
"config_public_reg"
name=
"config_public_reg"
{%
if
content
.
config_public_reg
%}
checked
{%
endif
%}
>
<label
for=
"config_public_reg"
>
{{_('Enable public registration')}}
</label>
</div>
</div>
<button
type=
"submit"
class=
"btn btn-default"
>
{{_('Submit')}}
</button>
{% if not origin %}
<a
href=
"{{ url_for('admin') }}"
class=
"btn btn-default"
>
{{_('Back')}}
</a>
{% endif %}
{% if success %}
<a
href=
"{{ url_for('login') }}"
class=
"btn btn-default"
>
{{_('Login')}}
</a>
{% endif %}
</form>
</div>
{% endblock %}
cps/templates/index.html
View file @
2c615fdf
{% extends "layout.html" %}
{% block body %}
{% if g.user.show_
random_books
() %}
{% if g.user.show_
detail_random
() %}
<div
class=
"discover"
>
<h2>
{{_('Discover (Random Books)')}}
</h2>
<div
class=
"row"
>
...
...
cps/templates/stats.html
View file @
2c615fdf
...
...
@@ -12,19 +12,19 @@
<tbody>
<tr>
<th>
Python
</th>
<td>
{{
V
ersions['PythonVersion']}}
</td>
<td>
{{
v
ersions['PythonVersion']}}
</td>
</tr>
<tr>
<th>
Kindlegen
</th>
<td>
{{
V
ersions['KindlegenVersion']}}
</td>
<td>
{{
v
ersions['KindlegenVersion']}}
</td>
</tr>
<tr>
<th>
ImageMagick
</th>
<td>
{{
V
ersions['ImageVersion']}}
</td>
<td>
{{
v
ersions['ImageVersion']}}
</td>
</tr>
<tr>
<th>
PyPDF2
</th>
<td>
{{
V
ersions['PyPdfVersion']}}
</td>
<td>
{{
v
ersions['PyPdfVersion']}}
</td>
</tr>
</tbody>
</table>
...
...
cps/templates/user_edit.html
View file @
2c615fdf
...
...
@@ -41,25 +41,33 @@
</select>
</div>
<div
class=
"form-group"
>
<input
type=
"checkbox"
name=
"show_random"
id=
"show_random"
{%
if
content
.
random_books
%}
checked
{%
endif
%}
>
<input
type=
"checkbox"
name=
"show_random"
id=
"show_random"
{%
if
content
.
show_random_books
()
%}
checked
{%
endif
%}
>
<label
for=
"show_random"
>
{{_('Show random books')}}
</label>
</div>
<div
class=
"form-group"
>
<input
type=
"checkbox"
name=
"show_hot"
id=
"show_hot"
{%
if
content
.
hot_books
%}
checked
{%
endif
%}
>
<input
type=
"checkbox"
name=
"show_hot"
id=
"show_hot"
{%
if
content
.
show_hot_books
()
%}
checked
{%
endif
%}
>
<label
for=
"show_hot"
>
{{_('Show hot books')}}
</label>
</div>
<div
class=
"form-group"
>
<input
type=
"checkbox"
name=
"show_language"
id=
"show_language"
{%
if
content
.
language_books
%}
checked
{%
endif
%}
>
<input
type=
"checkbox"
name=
"show_language"
id=
"show_language"
{%
if
content
.
show_language
()
%}
checked
{%
endif
%}
>
<label
for=
"show_language"
>
{{_('Show language selection')}}
</label>
</div>
<div
class=
"form-group"
>
<input
type=
"checkbox"
name=
"show_series"
id=
"show_series"
{%
if
content
.
s
eries_books
%}
checked
{%
endif
%}
>
<input
type=
"checkbox"
name=
"show_series"
id=
"show_series"
{%
if
content
.
s
how_series
()
%}
checked
{%
endif
%}
>
<label
for=
"show_series"
>
{{_('Show series selection')}}
</label>
</div>
<div
class=
"form-group"
>
<input
type=
"checkbox"
name=
"show_category"
id=
"show_category"
{%
if
content
.
category_books
%}
checked
{%
endif
%}
>
<input
type=
"checkbox"
name=
"show_category"
id=
"show_category"
{%
if
content
.
show_category
()
%}
checked
{%
endif
%}
>
<label
for=
"show_category"
>
{{_('Show category selection')}}
</label>
</div>
<div
class=
"form-group"
>
<input
type=
"checkbox"
name=
"show_author"
id=
"show_author"
{%
if
content
.
show_author
()
%}
checked
{%
endif
%}
>
<label
for=
"show_author"
>
{{_('Show author selection')}}
</label>
</div>
<div
class=
"form-group"
>
<input
type=
"checkbox"
name=
"show_detail_random"
id=
"show_detail_random"
{%
if
content
.
show_detail_random
()
%}
checked
{%
endif
%}
>
<label
for=
"show_detail_random"
>
{{_('Show random books in detail view')}}
</label>
</div>
{% if g.user and g.user.role_admin() and not profile %}
{% if not content.role_anonymous() %}
...
...
cps/ub.py
View file @
2c615fdf
This diff is collapsed.
Click to expand it.
cps/web.py
View file @
2c615fdf
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment