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
1a458fe3
Commit
1a458fe3
authored
May 21, 2020
by
Ozzieisaacs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix for #1407 converting books should now be possible again
parent
a4841836
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
397 additions
and
324 deletions
+397
-324
__init__.py
cps/__init__.py
+7
-1
about.py
cps/about.py
+5
-5
admin.py
cps/admin.py
+6
-6
db.py
cps/db.py
+175
-136
editbooks.py
cps/editbooks.py
+70
-69
helper.py
cps/helper.py
+21
-21
kobo.py
cps/kobo.py
+9
-9
opds.py
cps/opds.py
+17
-17
server.py
cps/server.py
+3
-0
shelf.py
cps/shelf.py
+5
-5
web.py
cps/web.py
+48
-47
worker.py
cps/worker.py
+31
-8
No files found.
cps/__init__.py
View file @
1a458fe3
...
...
@@ -37,6 +37,9 @@ from . import config_sql, logger, cache_buster, cli, ub, db
from
.reverseproxy
import
ReverseProxied
from
.server
import
WebServer
# import queue
# queue = queue.Queue()
mimetypes
.
init
()
mimetypes
.
add_type
(
'application/xhtml+xml'
,
'.xhtml'
)
mimetypes
.
add_type
(
'application/epub+zip'
,
'.epub'
)
...
...
@@ -82,6 +85,8 @@ log = logger.create()
from
.
import
services
calibre_db
=
db
.
CalibreDB
()
def
create_app
():
app
.
wsgi_app
=
ReverseProxied
(
app
.
wsgi_app
)
# For python2 convert path to unicode
...
...
@@ -98,7 +103,8 @@ def create_app():
app
.
secret_key
=
os
.
getenv
(
'SECRET_KEY'
,
config_sql
.
get_flask_session_key
(
ub
.
session
))
web_server
.
init_app
(
app
,
config
)
db
.
setup_db
(
config
,
cli
.
settingspath
)
calibre_db
.
setup_db
(
config
,
cli
.
settingspath
)
calibre_db
.
start
()
babel
.
init_app
(
app
)
_BABEL_TRANSLATIONS
.
update
(
str
(
item
)
for
item
in
babel
.
list_translations
())
...
...
cps/about.py
View file @
1a458fe3
...
...
@@ -30,7 +30,7 @@ import babel, pytz, requests, sqlalchemy
import
werkzeug
,
flask
,
flask_login
,
flask_principal
,
jinja2
from
flask_babel
import
gettext
as
_
from
.
import
db
,
converter
,
uploader
,
server
,
isoLanguages
,
constants
from
.
import
db
,
c
alibre_db
,
c
onverter
,
uploader
,
server
,
isoLanguages
,
constants
from
.web
import
render_title_template
try
:
from
flask_login
import
__version__
as
flask_loginVersion
...
...
@@ -85,10 +85,10 @@ _VERSIONS.update(uploader.get_versions())
@
about
.
route
(
"/stats"
)
@
flask_login
.
login_required
def
stats
():
counter
=
db
.
session
.
query
(
db
.
Books
)
.
count
()
authors
=
db
.
session
.
query
(
db
.
Authors
)
.
count
()
categorys
=
db
.
session
.
query
(
db
.
Tags
)
.
count
()
series
=
db
.
session
.
query
(
db
.
Series
)
.
count
()
counter
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
count
()
authors
=
calibre_
db
.
session
.
query
(
db
.
Authors
)
.
count
()
categorys
=
calibre_
db
.
session
.
query
(
db
.
Tags
)
.
count
()
series
=
calibre_
db
.
session
.
query
(
db
.
Series
)
.
count
()
_VERSIONS
[
'ebook converter'
]
=
_
(
converter
.
get_calibre_version
())
_VERSIONS
[
'unrar'
]
=
_
(
converter
.
get_unrar_version
())
_VERSIONS
[
'kepubify'
]
=
_
(
converter
.
get_kepubify_version
())
...
...
cps/admin.py
View file @
1a458fe3
...
...
@@ -38,7 +38,7 @@ from sqlalchemy.exc import IntegrityError
from
sqlalchemy.sql.expression
import
func
from
.
import
constants
,
logger
,
helper
,
services
from
.
import
db
,
ub
,
web_server
,
get_locale
,
config
,
updater_thread
,
babel
,
gdriveutils
from
.
import
db
,
calibre_db
,
ub
,
web_server
,
get_locale
,
config
,
updater_thread
,
babel
,
gdriveutils
from
.helper
import
speaking_language
,
check_valid_domain
,
send_test_mail
,
reset_password
,
generate_password_hash
from
.gdriveutils
import
is_gdrive_ready
,
gdrive_support
from
.web
import
admin_required
,
render_title_template
,
before_request
,
unconfigured
,
login_required_if_no_ano
...
...
@@ -86,7 +86,7 @@ def shutdown():
showtext
=
{}
if
task
in
(
0
,
1
):
# valid commandos received
# close all database connections
db
.
dispose
()
calibre_
db
.
dispose
()
ub
.
dispose
()
if
task
==
0
:
...
...
@@ -99,7 +99,7 @@ def shutdown():
if
task
==
2
:
log
.
warning
(
"reconnecting to calibre database"
)
db
.
setup_db
(
config
,
ub
.
app_DB_path
)
calibre_
db
.
setup_db
(
config
,
ub
.
app_DB_path
)
showtext
[
'text'
]
=
_
(
u'Reconnect successful'
)
return
json
.
dumps
(
showtext
)
...
...
@@ -148,9 +148,9 @@ def configuration():
@
login_required
@
admin_required
def
view_configuration
():
readColumn
=
db
.
session
.
query
(
db
.
Custom_Columns
)
\
readColumn
=
calibre_
db
.
session
.
query
(
db
.
Custom_Columns
)
\
.
filter
(
and_
(
db
.
Custom_Columns
.
datatype
==
'bool'
,
db
.
Custom_Columns
.
mark_for_delete
==
0
))
.
all
()
restrictColumns
=
db
.
session
.
query
(
db
.
Custom_Columns
)
\
restrictColumns
=
calibre_
db
.
session
.
query
(
db
.
Custom_Columns
)
\
.
filter
(
and_
(
db
.
Custom_Columns
.
datatype
==
'text'
,
db
.
Custom_Columns
.
mark_for_delete
==
0
))
.
all
()
return
render_title_template
(
"config_view_edit.html"
,
conf
=
config
,
readColumns
=
readColumn
,
restrictColumns
=
restrictColumns
,
...
...
@@ -944,7 +944,7 @@ def edit_user(user_id):
translations
=
babel
.
list_translations
()
+
[
LC
(
'en'
)]
kobo_support
=
feature_support
[
'kobo'
]
and
config
.
config_kobo_sync
for
book
in
content
.
downloads
:
downloadbook
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
()
downloadbook
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
()
if
downloadbook
:
downloads
.
append
(
downloadbook
)
else
:
...
...
cps/db.py
100755 → 100644
View file @
1a458fe3
This diff is collapsed.
Click to expand it.
cps/editbooks.py
View file @
1a458fe3
This diff is collapsed.
Click to expand it.
cps/helper.py
View file @
1a458fe3
...
...
@@ -23,7 +23,6 @@ import os
import
io
import
json
import
mimetypes
import
random
import
re
import
shutil
import
time
...
...
@@ -42,6 +41,7 @@ from flask_login import current_user
from
sqlalchemy.sql.expression
import
true
,
false
,
and_
,
or_
,
text
,
func
from
werkzeug.datastructures
import
Headers
from
werkzeug.security
import
generate_password_hash
from
.
import
calibre_db
try
:
from
urllib.parse
import
quote
...
...
@@ -74,8 +74,8 @@ log = logger.create()
# Convert existing book entry to new format
def
convert_book_format
(
book_id
,
calibrepath
,
old_book_format
,
new_book_format
,
user_id
,
kindle_mail
=
None
):
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
data
=
db
.
session
.
query
(
db
.
Data
)
.
filter
(
db
.
Data
.
book
==
book
.
id
)
.
filter
(
db
.
Data
.
format
==
old_book_format
)
.
first
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
data
=
calibre_
db
.
session
.
query
(
db
.
Data
)
.
filter
(
db
.
Data
.
book
==
book
.
id
)
.
filter
(
db
.
Data
.
format
==
old_book_format
)
.
first
()
if
not
data
:
error_message
=
_
(
u"
%(format)
s format not found for book id:
%(book)
d"
,
format
=
old_book_format
,
book
=
book_id
)
log
.
error
(
"convert_book_format:
%
s"
,
error_message
)
...
...
@@ -212,7 +212,7 @@ def check_read_formats(entry):
# 3: If Pdf file is existing, it's directly send to kindle email
def
send_mail
(
book_id
,
book_format
,
convert
,
kindle_mail
,
calibrepath
,
user_id
):
"""Send email with attachments"""
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
if
convert
==
1
:
# returns None if success, otherwise errormessage
...
...
@@ -324,7 +324,7 @@ def delete_book_file(book, calibrepath, book_format=None):
def
update_dir_structure_file
(
book_id
,
calibrepath
,
first_author
):
localbook
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
localbook
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
path
=
os
.
path
.
join
(
calibrepath
,
localbook
.
path
)
authordir
=
localbook
.
path
.
split
(
'/'
)[
0
]
...
...
@@ -383,7 +383,7 @@ def update_dir_structure_file(book_id, calibrepath, first_author):
def
update_dir_structure_gdrive
(
book_id
,
first_author
):
error
=
False
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
path
=
book
.
path
authordir
=
book
.
path
.
split
(
'/'
)[
0
]
...
...
@@ -494,13 +494,13 @@ def get_cover_on_failure(use_generic_cover):
def
get_book_cover
(
book_id
):
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
common_filters
(
allow_show_archived
=
True
))
.
first
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
common_filters
(
allow_show_archived
=
True
))
.
first
()
return
get_book_cover_internal
(
book
,
use_generic_cover_on_failure
=
True
)
def
get_book_cover_with_uuid
(
book_uuid
,
use_generic_cover_on_failure
=
True
):
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
book_uuid
)
.
first
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
book_uuid
)
.
first
()
return
get_book_cover_internal
(
book
,
use_generic_cover_on_failure
)
...
...
@@ -775,7 +775,7 @@ def tags_filters():
# Creates for all stored languages a translated speaking name in the array for the UI
def
speaking_language
(
languages
=
None
):
if
not
languages
:
languages
=
db
.
session
.
query
(
db
.
Languages
)
.
join
(
db
.
books_languages_link
)
.
join
(
db
.
Books
)
\
languages
=
calibre_
db
.
session
.
query
(
db
.
Languages
)
.
join
(
db
.
books_languages_link
)
.
join
(
db
.
Books
)
\
.
filter
(
common_filters
())
\
.
group_by
(
text
(
'books_languages_link.lang_code'
))
.
all
()
for
lang
in
languages
:
...
...
@@ -808,7 +808,7 @@ def order_authors(entry):
error
=
False
for
auth
in
sort_authors
:
# ToDo: How to handle not found authorname
result
=
db
.
session
.
query
(
db
.
Authors
)
.
filter
(
db
.
Authors
.
sort
==
auth
.
lstrip
()
.
strip
())
.
first
()
result
=
calibre_
db
.
session
.
query
(
db
.
Authors
)
.
filter
(
db
.
Authors
.
sort
==
auth
.
lstrip
()
.
strip
())
.
first
()
if
not
result
:
error
=
True
break
...
...
@@ -825,12 +825,12 @@ def fill_indexpage(page, database, db_filter, order, *join):
def
fill_indexpage_with_archived_books
(
page
,
database
,
db_filter
,
order
,
allow_show_archived
,
*
join
):
if
current_user
.
show_detail_random
():
randm
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
(
allow_show_archived
))
\
randm
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
(
allow_show_archived
))
\
.
order_by
(
func
.
random
())
.
limit
(
config
.
config_random_books
)
else
:
randm
=
false
()
off
=
int
(
int
(
config
.
config_books_per_page
)
*
(
page
-
1
))
query
=
db
.
session
.
query
(
database
)
.
join
(
*
join
,
isouter
=
True
)
.
\
query
=
calibre_
db
.
session
.
query
(
database
)
.
join
(
*
join
,
isouter
=
True
)
.
\
filter
(
db_filter
)
.
\
filter
(
common_filters
(
allow_show_archived
))
pagination
=
Pagination
(
page
,
config
.
config_books_per_page
,
...
...
@@ -843,8 +843,8 @@ def fill_indexpage_with_archived_books(page, database, db_filter, order, allow_s
def
get_typeahead
(
database
,
query
,
replace
=
(
''
,
''
),
tag_filter
=
true
()):
query
=
query
or
''
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"lower"
,
1
,
lcase
)
entries
=
db
.
session
.
query
(
database
)
.
filter
(
tag_filter
)
.
\
calibre_
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"lower"
,
1
,
lcase
)
entries
=
calibre_
db
.
session
.
query
(
database
)
.
filter
(
tag_filter
)
.
\
filter
(
func
.
lower
(
database
.
name
)
.
ilike
(
"
%
"
+
query
+
"
%
"
))
.
all
()
json_dumps
=
json
.
dumps
([
dict
(
name
=
r
.
name
.
replace
(
*
replace
))
for
r
in
entries
])
return
json_dumps
...
...
@@ -852,7 +852,7 @@ def get_typeahead(database, query, replace=('', ''), tag_filter=true()):
# read search results from calibre-database and return it (function is used for feed and simple search
def
get_search_results
(
term
):
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"lower"
,
1
,
lcase
)
calibre_
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"lower"
,
1
,
lcase
)
q
=
list
()
authorterms
=
re
.
split
(
"[, ]+"
,
term
)
for
authorterm
in
authorterms
:
...
...
@@ -860,7 +860,7 @@ def get_search_results(term):
db
.
Books
.
authors
.
any
(
func
.
lower
(
db
.
Authors
.
name
)
.
ilike
(
"
%
"
+
term
+
"
%
"
))
return
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
())
.
filter
(
return
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
())
.
filter
(
or_
(
db
.
Books
.
tags
.
any
(
func
.
lower
(
db
.
Tags
.
name
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
series
.
any
(
func
.
lower
(
db
.
Series
.
name
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
authors
.
any
(
and_
(
*
q
)),
...
...
@@ -870,7 +870,7 @@ def get_search_results(term):
def
get_cc_columns
(
filter_config_custom_read
=
False
):
tmpcc
=
db
.
session
.
query
(
db
.
Custom_Columns
)
.
filter
(
db
.
Custom_Columns
.
datatype
.
notin_
(
db
.
cc_exceptions
))
.
all
()
tmpcc
=
calibre_
db
.
session
.
query
(
db
.
Custom_Columns
)
.
filter
(
db
.
Custom_Columns
.
datatype
.
notin_
(
db
.
cc_exceptions
))
.
all
()
cc
=
[]
r
=
None
if
config
.
config_columns_to_ignore
:
...
...
@@ -887,9 +887,9 @@ def get_cc_columns(filter_config_custom_read=False):
def
get_download_link
(
book_id
,
book_format
,
client
):
book_format
=
book_format
.
split
(
"."
)[
0
]
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
common_filters
())
.
first
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
common_filters
())
.
first
()
if
book
:
data1
=
db
.
session
.
query
(
db
.
Data
)
.
filter
(
db
.
Data
.
book
==
book
.
id
)
\
data1
=
calibre_
db
.
session
.
query
(
db
.
Data
)
.
filter
(
db
.
Data
.
book
==
book
.
id
)
\
.
filter
(
db
.
Data
.
format
==
book_format
.
upper
())
.
first
()
else
:
abort
(
404
)
...
...
@@ -911,13 +911,13 @@ def get_download_link(book_id, book_format, client):
def
check_exists_book
(
authr
,
title
):
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"lower"
,
1
,
lcase
)
calibre_
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"lower"
,
1
,
lcase
)
q
=
list
()
authorterms
=
re
.
split
(
r'\s*&\s*'
,
authr
)
for
authorterm
in
authorterms
:
q
.
append
(
db
.
Books
.
authors
.
any
(
func
.
lower
(
db
.
Authors
.
name
)
.
ilike
(
"
%
"
+
authorterm
+
"
%
"
)))
return
db
.
session
.
query
(
db
.
Books
)
.
filter
(
return
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
and_
(
db
.
Books
.
authors
.
any
(
and_
(
*
q
)),
func
.
lower
(
db
.
Books
.
title
)
.
ilike
(
"
%
"
+
title
+
"
%
"
)
))
.
first
()
...
...
cps/kobo.py
View file @
1a458fe3
...
...
@@ -48,7 +48,7 @@ from sqlalchemy.sql.expression import and_, or_
from
sqlalchemy.exc
import
StatementError
import
requests
from
.
import
config
,
logger
,
kobo_auth
,
db
,
helper
,
shelf
as
shelf_lib
,
ub
from
.
import
config
,
logger
,
kobo_auth
,
db
,
calibre_db
,
helper
,
shelf
as
shelf_lib
,
ub
from
.services
import
SyncToken
as
SyncToken
from
.web
import
download_required
from
.kobo_auth
import
requires_kobo_auth
...
...
@@ -170,7 +170,7 @@ def HandleSyncRequest():
# It looks like it's treating the db.Books.last_modified field as a string and may fail
# the comparison because of the +00:00 suffix.
changed_entries
=
(
db
.
session
.
query
(
db
.
Books
)
calibre_
db
.
session
.
query
(
db
.
Books
)
.
join
(
db
.
Data
)
.
filter
(
or_
(
func
.
datetime
(
db
.
Books
.
last_modified
)
>
sync_token
.
books_last_modified
,
db
.
Books
.
id
.
in_
(
recently_restored_or_archived_books
)))
...
...
@@ -207,7 +207,7 @@ def HandleSyncRequest():
ub
.
KoboReadingState
.
user_id
==
current_user
.
id
,
ub
.
KoboReadingState
.
book_id
.
notin_
(
reading_states_in_new_entitlements
))))
for
kobo_reading_state
in
changed_reading_states
.
all
():
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
kobo_reading_state
.
book_id
)
.
one_or_none
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
kobo_reading_state
.
book_id
)
.
one_or_none
()
if
book
:
sync_results
.
append
({
"ChangedReadingState"
:
{
...
...
@@ -256,7 +256,7 @@ def HandleMetadataRequest(book_uuid):
if
not
current_app
.
wsgi_app
.
is_proxied
:
log
.
debug
(
'Kobo: Received unproxied request, changed request port to server port'
)
log
.
info
(
"Kobo library metadata request received for book
%
s"
%
book_uuid
)
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
book_uuid
)
.
first
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
book_uuid
)
.
first
()
if
not
book
or
not
book
.
data
:
log
.
info
(
u"Book
%
s not found in database"
,
book_uuid
)
return
redirect_or_proxy_request
()
...
...
@@ -474,7 +474,7 @@ def add_items_to_shelf(items, shelf):
items_unknown_to_calibre
.
append
(
item
)
continue
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
item
[
"RevisionId"
])
.
one_or_none
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
item
[
"RevisionId"
])
.
one_or_none
()
if
not
book
:
items_unknown_to_calibre
.
append
(
item
)
continue
...
...
@@ -545,7 +545,7 @@ def HandleTagRemoveItem(tag_id):
items_unknown_to_calibre
.
append
(
item
)
continue
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
item
[
"RevisionId"
])
.
one_or_none
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
item
[
"RevisionId"
])
.
one_or_none
()
if
not
book
:
items_unknown_to_calibre
.
append
(
item
)
continue
...
...
@@ -613,7 +613,7 @@ def create_kobo_tag(shelf):
"Type"
:
"UserTag"
}
for
book_shelf
in
shelf
.
books
:
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_shelf
.
book_id
)
.
one_or_none
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_shelf
.
book_id
)
.
one_or_none
()
if
not
book
:
log
.
info
(
u"Book (id:
%
s) in BookShelf (id:
%
s) not found in book database"
,
book_shelf
.
book_id
,
shelf
.
id
)
continue
...
...
@@ -629,7 +629,7 @@ def create_kobo_tag(shelf):
@
kobo
.
route
(
"/v1/library/<book_uuid>/state"
,
methods
=
[
"GET"
,
"PUT"
])
@
login_required
def
HandleStateRequest
(
book_uuid
):
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
book_uuid
)
.
first
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
book_uuid
)
.
first
()
if
not
book
or
not
book
.
data
:
log
.
info
(
u"Book
%
s not found in database"
,
book_uuid
)
return
redirect_or_proxy_request
()
...
...
@@ -804,7 +804,7 @@ def TopLevelEndpoint():
@
login_required
def
HandleBookDeletionRequest
(
book_uuid
):
log
.
info
(
"Kobo book deletion request received for book
%
s"
%
book_uuid
)
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
book_uuid
)
.
first
()
book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
==
book_uuid
)
.
first
()
if
not
book
:
log
.
info
(
u"Book
%
s not found in database"
,
book_uuid
)
return
redirect_or_proxy_request
()
...
...
cps/opds.py
View file @
1a458fe3
...
...
@@ -30,7 +30,7 @@ from flask_login import current_user
from
sqlalchemy.sql.expression
import
func
,
text
,
or_
,
and_
from
werkzeug.security
import
check_password_hash
from
.
import
constants
,
logger
,
config
,
db
,
ub
,
services
,
get_locale
,
isoLanguages
from
.
import
constants
,
logger
,
config
,
db
,
calibre_db
,
ub
,
services
,
get_locale
,
isoLanguages
from
.helper
import
fill_indexpage
,
get_download_link
,
get_book_cover
,
speaking_language
from
.pagination
import
Pagination
from
.web
import
common_filters
,
get_search_results
,
render_read_books
,
download_required
...
...
@@ -108,7 +108,7 @@ def feed_new():
@
opds
.
route
(
"/opds/discover"
)
@
requires_basic_auth_if_no_ano
def
feed_discover
():
entries
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
())
.
order_by
(
func
.
random
())
\
entries
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
())
.
order_by
(
func
.
random
())
\
.
limit
(
config
.
config_books_per_page
)
pagination
=
Pagination
(
1
,
config
.
config_books_per_page
,
int
(
config
.
config_books_per_page
))
return
render_xml_template
(
'feed.xml'
,
entries
=
entries
,
pagination
=
pagination
)
...
...
@@ -133,10 +133,10 @@ def feed_hot():
hot_books
=
all_books
.
offset
(
off
)
.
limit
(
config
.
config_books_per_page
)
entries
=
list
()
for
book
in
hot_books
:
downloadBook
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
Downloads
.
book_id
)
.
first
()
downloadBook
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
Downloads
.
book_id
)
.
first
()
if
downloadBook
:
entries
.
append
(
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
())
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
())
.
filter
(
db
.
Books
.
id
==
book
.
Downloads
.
book_id
)
.
first
()
)
else
:
...
...
@@ -153,11 +153,11 @@ def feed_hot():
@
requires_basic_auth_if_no_ano
def
feed_authorindex
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
entries
=
db
.
session
.
query
(
db
.
Authors
)
.
join
(
db
.
books_authors_link
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
entries
=
calibre_
db
.
session
.
query
(
db
.
Authors
)
.
join
(
db
.
books_authors_link
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
.
group_by
(
text
(
'books_authors_link.author'
))
.
order_by
(
db
.
Authors
.
sort
)
.
limit
(
config
.
config_books_per_page
)
\
.
offset
(
off
)
pagination
=
Pagination
((
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
),
config
.
config_books_per_page
,
len
(
db
.
session
.
query
(
db
.
Authors
)
.
all
()))
len
(
calibre_
db
.
session
.
query
(
db
.
Authors
)
.
all
()))
return
render_xml_template
(
'feed.xml'
,
listelements
=
entries
,
folder
=
'opds.feed_author'
,
pagination
=
pagination
)
...
...
@@ -176,11 +176,11 @@ def feed_author(book_id):
@
requires_basic_auth_if_no_ano
def
feed_publisherindex
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
entries
=
db
.
session
.
query
(
db
.
Publishers
)
.
join
(
db
.
books_publishers_link
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
entries
=
calibre_
db
.
session
.
query
(
db
.
Publishers
)
.
join
(
db
.
books_publishers_link
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
.
group_by
(
text
(
'books_publishers_link.publisher'
))
.
order_by
(
db
.
Publishers
.
sort
)
\
.
limit
(
config
.
config_books_per_page
)
.
offset
(
off
)
pagination
=
Pagination
((
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
),
config
.
config_books_per_page
,
len
(
db
.
session
.
query
(
db
.
Publishers
)
.
all
()))
len
(
calibre_
db
.
session
.
query
(
db
.
Publishers
)
.
all
()))
return
render_xml_template
(
'feed.xml'
,
listelements
=
entries
,
folder
=
'opds.feed_publisher'
,
pagination
=
pagination
)
...
...
@@ -199,10 +199,10 @@ def feed_publisher(book_id):
@
requires_basic_auth_if_no_ano
def
feed_categoryindex
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
entries
=
db
.
session
.
query
(
db
.
Tags
)
.
join
(
db
.
books_tags_link
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
entries
=
calibre_
db
.
session
.
query
(
db
.
Tags
)
.
join
(
db
.
books_tags_link
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
.
group_by
(
text
(
'books_tags_link.tag'
))
.
order_by
(
db
.
Tags
.
name
)
.
offset
(
off
)
.
limit
(
config
.
config_books_per_page
)
pagination
=
Pagination
((
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
),
config
.
config_books_per_page
,
len
(
db
.
session
.
query
(
db
.
Tags
)
.
all
()))
len
(
calibre_
db
.
session
.
query
(
db
.
Tags
)
.
all
()))
return
render_xml_template
(
'feed.xml'
,
listelements
=
entries
,
folder
=
'opds.feed_category'
,
pagination
=
pagination
)
...
...
@@ -221,10 +221,10 @@ def feed_category(book_id):
@
requires_basic_auth_if_no_ano
def
feed_seriesindex
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
entries
=
db
.
session
.
query
(
db
.
Series
)
.
join
(
db
.
books_series_link
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
entries
=
calibre_
db
.
session
.
query
(
db
.
Series
)
.
join
(
db
.
books_series_link
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
.
group_by
(
text
(
'books_series_link.series'
))
.
order_by
(
db
.
Series
.
sort
)
.
offset
(
off
)
.
all
()
pagination
=
Pagination
((
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
),
config
.
config_books_per_page
,
len
(
db
.
session
.
query
(
db
.
Series
)
.
all
()))
len
(
calibre_
db
.
session
.
query
(
db
.
Series
)
.
all
()))
return
render_xml_template
(
'feed.xml'
,
listelements
=
entries
,
folder
=
'opds.feed_series'
,
pagination
=
pagination
)
...
...
@@ -243,7 +243,7 @@ def feed_series(book_id):
@
requires_basic_auth_if_no_ano
def
feed_ratingindex
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
entries
=
db
.
session
.
query
(
db
.
Ratings
,
func
.
count
(
'books_ratings_link.book'
)
.
label
(
'count'
),
entries
=
calibre_
db
.
session
.
query
(
db
.
Ratings
,
func
.
count
(
'books_ratings_link.book'
)
.
label
(
'count'
),
(
db
.
Ratings
.
rating
/
2
)
.
label
(
'name'
))
\
.
join
(
db
.
books_ratings_link
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
.
group_by
(
text
(
'books_ratings_link.rating'
))
.
order_by
(
db
.
Ratings
.
rating
)
.
all
()
...
...
@@ -271,7 +271,7 @@ def feed_ratings(book_id):
@
requires_basic_auth_if_no_ano
def
feed_formatindex
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
entries
=
db
.
session
.
query
(
db
.
Data
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
entries
=
calibre_
db
.
session
.
query
(
db
.
Data
)
.
join
(
db
.
Books
)
.
filter
(
common_filters
())
\
.
group_by
(
db
.
Data
.
format
)
.
order_by
(
db
.
Data
.
format
)
.
all
()
pagination
=
Pagination
((
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
),
config
.
config_books_per_page
,
len
(
entries
))
...
...
@@ -305,7 +305,7 @@ def feed_languagesindex():
cur_l
=
LC
.
parse
(
current_user
.
filter_language
())
except
UnknownLocaleError
:
cur_l
=
None
languages
=
db
.
session
.
query
(
db
.
Languages
)
.
filter
(
languages
=
calibre_
db
.
session
.
query
(
db
.
Languages
)
.
filter
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
.
all
()
if
cur_l
:
languages
[
0
]
.
name
=
cur_l
.
get_language_name
(
get_locale
())
...
...
@@ -356,7 +356,7 @@ def feed_shelf(book_id):
books_in_shelf
=
ub
.
session
.
query
(
ub
.
BookShelf
)
.
filter
(
ub
.
BookShelf
.
shelf
==
book_id
)
.
order_by
(
ub
.
BookShelf
.
order
.
asc
())
.
all
()
for
book
in
books_in_shelf
:
cur_book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
()
cur_book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
()
result
.
append
(
cur_book
)
pagination
=
Pagination
((
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
),
config
.
config_books_per_page
,
len
(
result
))
...
...
@@ -378,7 +378,7 @@ def opds_download_link(book_id, book_format):
@
opds
.
route
(
"/ajax/book/<string:uuid>"
,
defaults
=
{
'library'
:
""
})
@
requires_basic_auth_if_no_ano
def
get_metadata_calibre_companion
(
uuid
,
library
):
entry
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
.
like
(
"
%
"
+
uuid
+
"
%
"
))
.
first
()
entry
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
uuid
.
like
(
"
%
"
+
uuid
+
"
%
"
))
.
first
()
if
entry
is
not
None
:
js
=
render_template
(
'json.txt'
,
entry
=
entry
)
response
=
make_response
(
js
)
...
...
cps/server.py
View file @
1a458fe3
...
...
@@ -196,6 +196,9 @@ class WebServer(object):
def
stop
(
self
,
restart
=
False
):
from
.
import
updater_thread
updater_thread
.
stop
()
from
.
import
calibre_db
calibre_db
.
stop
()
log
.
info
(
"webserver stop (restart=
%
s)"
,
restart
)
self
.
restart
=
restart
...
...
cps/shelf.py
View file @
1a458fe3
...
...
@@ -28,7 +28,7 @@ from flask_babel import gettext as _
from
flask_login
import
login_required
,
current_user
from
sqlalchemy.sql.expression
import
func
from
.
import
logger
,
ub
,
searched_ids
,
db
from
.
import
logger
,
ub
,
searched_ids
,
db
,
calibre_db
from
.web
import
render_title_template
from
.helper
import
common_filters
...
...
@@ -320,11 +320,11 @@ def show_shelf(shelf_type, shelf_id):
books_in_shelf
=
ub
.
session
.
query
(
ub
.
BookShelf
)
.
filter
(
ub
.
BookShelf
.
shelf
==
shelf_id
)
\
.
order_by
(
ub
.
BookShelf
.
order
.
asc
())
.
all
()
for
book
in
books_in_shelf
:
cur_book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
filter
(
common_filters
())
.
first
()
cur_book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
filter
(
common_filters
())
.
first
()
if
cur_book
:
result
.
append
(
cur_book
)
else
:
cur_book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
()
cur_book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
()
if
not
cur_book
:
log
.
info
(
'Not existing book
%
s in
%
s deleted'
,
book
.
book_id
,
shelf
)
ub
.
session
.
query
(
ub
.
BookShelf
)
.
filter
(
ub
.
BookShelf
.
book_id
==
book
.
book_id
)
.
delete
()
...
...
@@ -356,7 +356,7 @@ def order_shelf(shelf_id):
books_in_shelf2
=
ub
.
session
.
query
(
ub
.
BookShelf
)
.
filter
(
ub
.
BookShelf
.
shelf
==
shelf_id
)
\
.
order_by
(
ub
.
BookShelf
.
order
.
asc
())
.
all
()
for
book
in
books_in_shelf2
:
cur_book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
filter
(
common_filters
())
.
first
()
cur_book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
filter
(
common_filters
())
.
first
()
if
cur_book
:
result
.
append
({
'title'
:
cur_book
.
title
,
'id'
:
cur_book
.
id
,
...
...
@@ -364,7 +364,7 @@ def order_shelf(shelf_id):
'series'
:
cur_book
.
series
,
'series_index'
:
cur_book
.
series_index
})
else
:
cur_book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
()
cur_book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
()
result
.
append
({
'title'
:
_
(
'Hidden Book'
),
'id'
:
cur_book
.
id
,
'author'
:
[],
...
...
cps/web.py
View file @
1a458fe3
This diff is collapsed.
Click to expand it.
cps/worker.py
View file @
1a458fe3
...
...
@@ -24,10 +24,10 @@ import smtplib
import
socket
import
time
import
threading
import
queue
from
glob
import
glob
from
shutil
import
copyfile
from
datetime
import
datetime
from
sqlalchemy.exc
import
OperationalError
try
:
from
StringIO
import
StringIO
...
...
@@ -46,7 +46,8 @@ from email.utils import make_msgid
from
email.generator
import
Generator
from
flask_babel
import
gettext
as
_
from
.
import
db
,
logger
,
config
from
.
import
calibre_db
,
db
from
.
import
logger
,
config
from
.subproc_wrapper
import
process_open
from
.
import
gdriveutils
...
...
@@ -190,6 +191,8 @@ class WorkerThread(threading.Thread):
self
.
UIqueue
=
list
()
self
.
asyncSMTP
=
None
self
.
id
=
0
self
.
db_queue
=
queue
.
Queue
()
calibre_db
.
add_queue
(
self
.
db_queue
)
self
.
doLock
=
threading
.
Lock
()
# Main thread loop starting the different tasks
...
...
@@ -275,6 +278,18 @@ class WorkerThread(threading.Thread):
self
.
doLock
.
acquire
()
index
=
self
.
current
self
.
doLock
.
release
()
'''dbpath = os.path.join(config.config_calibre_dir, "metadata.db")
engine = create_engine('sqlite://',
echo=False,
isolation_level="SERIALIZABLE",
connect_args={'check_same_thread': True})
engine.execute("attach database '{}' as calibre;".format(dbpath))
conn = engine.connect()
Session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
w_session = Session()
engine.execute("attach database '{}' as calibre;".format(dbpath))'''
file_path
=
self
.
queue
[
index
][
'file_path'
]
bookid
=
self
.
queue
[
index
][
'bookid'
]
format_old_ext
=
u'.'
+
self
.
queue
[
index
][
'settings'
][
'old_book_format'
]
.
lower
()
...
...
@@ -285,7 +300,7 @@ class WorkerThread(threading.Thread):
# this will allow send to kindle workflow to continue to work
if
os
.
path
.
isfile
(
file_path
+
format_new_ext
):
log
.
info
(
"Book id
%
d already converted to
%
s"
,
bookid
,
format_new_ext
)
cur_book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
bookid
)
.
first
()
cur_book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
bookid
)
.
first
()
self
.
queue
[
index
][
'path'
]
=
file_path
self
.
queue
[
index
][
'title'
]
=
cur_book
.
title
self
.
_handleSuccess
()
...
...
@@ -309,19 +324,26 @@ class WorkerThread(threading.Thread):
check
,
error_message
=
self
.
_convert_calibre
(
file_path
,
format_old_ext
,
format_new_ext
,
index
)
if
check
==
0
:
cur_book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
bookid
)
.
first
()
cur_book
=
calibre_
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
bookid
)
.
first
()
if
os
.
path
.
isfile
(
file_path
+
format_new_ext
):
# self.db_queue.join()
new_format
=
db
.
Data
(
name
=
cur_book
.
data
[
0
]
.
name
,
book_format
=
self
.
queue
[
index
][
'settings'
][
'new_book_format'
]
.
upper
(),
book
=
bookid
,
uncompressed_size
=
os
.
path
.
getsize
(
file_path
+
format_new_ext
))
cur_book
.
data
.
append
(
new_format
)
task
=
{
'task'
:
'add_format'
,
'id'
:
bookid
,
'format'
:
new_format
}
self
.
db_queue
.
put
(
task
)
# To Do how to handle error?
print
(
'finished'
)
'''cur_book.data.append(new_format)
try:
db
.
session
.
commit
()
# db.session.merge(cur_book)
calibre_db.session.commit()
except OperationalError as e:
db
.
session
.
rollback
()
calibre_
db.session.rollback()
log.error("Database error:
%
s", e)
self._handleError(_(u"Database error:
%(error)
s.", error=e))
return
return
'''
self
.
queue
[
index
][
'path'
]
=
cur_book
.
path
self
.
queue
[
index
][
'title'
]
=
cur_book
.
title
...
...
@@ -375,6 +397,7 @@ class WorkerThread(threading.Thread):
# process returncode
check
=
p
.
returncode
calibre_traceback
=
p
.
stderr
.
readlines
()
error_message
=
""
for
ele
in
calibre_traceback
:
if
sys
.
version_info
<
(
3
,
0
):
ele
=
ele
.
decode
(
'utf-8'
)
...
...
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