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
ff99cd24
Commit
ff99cd24
authored
Apr 11, 2021
by
cbartondock
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://github.com/janeczku/calibre-web
parents
df91ca50
04971f86
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
137 additions
and
83 deletions
+137
-83
admin.py
cps/admin.py
+57
-27
db.py
cps/db.py
+9
-6
helper.py
cps/helper.py
+1
-1
table.js
cps/static/js/table.js
+41
-41
web.py
cps/web.py
+29
-8
No files found.
cps/admin.py
View file @
ff99cd24
...
@@ -31,13 +31,14 @@ from datetime import datetime, timedelta
...
@@ -31,13 +31,14 @@ from datetime import datetime, timedelta
from
babel
import
Locale
as
LC
from
babel
import
Locale
as
LC
from
babel.dates
import
format_datetime
from
babel.dates
import
format_datetime
from
flask
import
Blueprint
,
flash
,
redirect
,
url_for
,
abort
,
request
,
make_response
,
send_from_directory
,
g
from
flask
import
Blueprint
,
flash
,
redirect
,
url_for
,
abort
,
request
,
make_response
,
send_from_directory
,
g
,
Response
from
flask_login
import
login_required
,
current_user
,
logout_user
,
confirm_login
from
flask_login
import
login_required
,
current_user
,
logout_user
,
confirm_login
from
flask_babel
import
gettext
as
_
from
flask_babel
import
gettext
as
_
from
sqlalchemy
import
and_
from
sqlalchemy
import
and_
from
sqlalchemy.orm.attributes
import
flag_modified
from
sqlalchemy.orm.attributes
import
flag_modified
from
sqlalchemy.exc
import
IntegrityError
,
OperationalError
,
InvalidRequestError
from
sqlalchemy.exc
import
IntegrityError
,
OperationalError
,
InvalidRequestError
from
sqlalchemy.sql.expression
import
func
,
or_
,
text
from
sqlalchemy.sql.expression
import
func
,
or_
,
text
# from sqlalchemy.func import field
from
.
import
constants
,
logger
,
helper
,
services
from
.
import
constants
,
logger
,
helper
,
services
from
.cli
import
filepicker
from
.cli
import
filepicker
...
@@ -241,29 +242,44 @@ def edit_user_table():
...
@@ -241,29 +242,44 @@ def edit_user_table():
@
login_required
@
login_required
@
admin_required
@
admin_required
def
list_users
():
def
list_users
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
off
=
int
(
request
.
args
.
get
(
"offset"
)
or
0
)
limit
=
request
.
args
.
get
(
"limit"
)
or
10
limit
=
int
(
request
.
args
.
get
(
"limit"
)
or
10
)
search
=
request
.
args
.
get
(
"search"
)
search
=
request
.
args
.
get
(
"search"
)
sort
=
request
.
args
.
get
(
"sort"
)
sort
=
request
.
args
.
get
(
"sort"
,
"state"
)
order
=
request
.
args
.
get
(
"order"
)
order
=
request
.
args
.
get
(
"order"
)
if
sort
and
order
:
state
=
None
if
sort
!=
"state"
and
order
:
order
=
text
(
sort
+
" "
+
order
)
order
=
text
(
sort
+
" "
+
order
)
else
:
else
:
order
=
ub
.
User
.
name
.
desc
()
order
=
ub
.
User
.
name
.
desc
()
if
sort
==
"state"
:
state
=
json
.
loads
(
request
.
args
.
get
(
"state"
))
all_user
=
ub
.
session
.
query
(
ub
.
User
)
all_user
=
ub
.
session
.
query
(
ub
.
User
)
if
not
config
.
config_anonbrowse
:
if
not
config
.
config_anonbrowse
:
all_user
=
all_user
.
filter
(
ub
.
User
.
role
.
op
(
'&'
)(
constants
.
ROLE_ANONYMOUS
)
!=
constants
.
ROLE_ANONYMOUS
)
all_user
=
all_user
.
filter
(
ub
.
User
.
role
.
op
(
'&'
)(
constants
.
ROLE_ANONYMOUS
)
!=
constants
.
ROLE_ANONYMOUS
)
total_count
=
all_user
.
count
()
total_count
=
filtered_count
=
all_user
.
count
()
if
search
:
if
search
:
users
=
all_user
.
filter
(
or_
(
func
.
lower
(
ub
.
User
.
name
)
.
ilike
(
"
%
"
+
search
+
"
%
"
),
all_user
=
all_user
.
filter
(
or_
(
func
.
lower
(
ub
.
User
.
name
)
.
ilike
(
"
%
"
+
search
+
"
%
"
),
func
.
lower
(
ub
.
User
.
kindle_mail
)
.
ilike
(
"
%
"
+
search
+
"
%
"
),
func
.
lower
(
ub
.
User
.
kindle_mail
)
.
ilike
(
"
%
"
+
search
+
"
%
"
),
func
.
lower
(
ub
.
User
.
email
)
.
ilike
(
"
%
"
+
search
+
"
%
"
)))
\
func
.
lower
(
ub
.
User
.
email
)
.
ilike
(
"
%
"
+
search
+
"
%
"
)))
.
order_by
(
order
)
.
offset
(
off
)
.
limit
(
limit
)
.
all
()
if
state
:
filtered_count
=
len
(
users
)
outcome
=
list
()
userlist
=
{
user
.
id
:
user
for
user
in
all_user
.
all
()}
for
entry
in
state
:
outcome
.
append
(
userlist
[
entry
])
del
userlist
[
entry
]
for
entry
in
userlist
:
outcome
.
append
(
userlist
[
entry
])
if
request
.
args
.
get
(
"order"
,
""
)
.
lower
()
==
"asc"
:
outcome
.
reverse
()
users
=
outcome
[
off
:
off
+
limit
]
else
:
else
:
users
=
all_user
.
order_by
(
order
)
.
offset
(
off
)
.
limit
(
limit
)
.
all
()
users
=
all_user
.
order_by
(
order
)
.
offset
(
off
)
.
limit
(
limit
)
.
all
()
filtered_count
=
total_count
if
search
:
filtered_count
=
len
(
users
)
for
user
in
users
:
for
user
in
users
:
if
user
.
default_language
==
"all"
:
if
user
.
default_language
==
"all"
:
...
@@ -277,12 +293,19 @@ def list_users():
...
@@ -277,12 +293,19 @@ def list_users():
response
.
headers
[
"Content-Type"
]
=
"application/json; charset=utf-8"
response
.
headers
[
"Content-Type"
]
=
"application/json; charset=utf-8"
return
response
return
response
@
admi
.
route
(
"/ajax/deleteuser"
)
@
admi
.
route
(
"/ajax/deleteuser"
,
methods
=
[
'POST'
]
)
@
login_required
@
login_required
@
admin_required
@
admin_required
def
delete_user
():
def
delete_user
():
# ToDo User delete check also not last one
user_id
=
request
.
values
.
get
(
'userid'
,
-
1
)
return
""
content
=
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
ub
.
User
.
id
==
int
(
user_id
))
.
one_or_none
()
try
:
message
=
_delete_user
(
content
)
return
Response
(
json
.
dumps
({
'type'
:
"success"
,
'message'
:
message
}),
mimetype
=
'application/json'
)
except
Exception
as
ex
:
return
Response
(
json
.
dumps
({
'type'
:
"danger"
,
'message'
:
str
(
ex
)}),
mimetype
=
'application/json'
)
log
.
error
(
"User not found"
)
return
Response
(
json
.
dumps
({
'type'
:
"danger"
,
'message'
:
_
(
"User not found"
)}),
mimetype
=
'application/json'
)
@
admi
.
route
(
"/ajax/getlocale"
)
@
admi
.
route
(
"/ajax/getlocale"
)
@
login_required
@
login_required
...
@@ -1194,21 +1217,28 @@ def _handle_new_user(to_save, content, languages, translations, kobo_support):
...
@@ -1194,21 +1217,28 @@ def _handle_new_user(to_save, content, languages, translations, kobo_support):
ub
.
session
.
rollback
()
ub
.
session
.
rollback
()
flash
(
_
(
u"Settings DB is not Writeable"
),
category
=
"error"
)
flash
(
_
(
u"Settings DB is not Writeable"
),
category
=
"error"
)
def
_delete_user
(
content
):
def
_handle_edit_user
(
to_save
,
content
,
languages
,
translations
,
kobo_support
):
if
to_save
.
get
(
"delete"
):
if
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
ub
.
User
.
role
.
op
(
'&'
)(
constants
.
ROLE_ADMIN
)
==
constants
.
ROLE_ADMIN
,
if
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
ub
.
User
.
role
.
op
(
'&'
)(
constants
.
ROLE_ADMIN
)
==
constants
.
ROLE_ADMIN
,
ub
.
User
.
id
!=
content
.
id
)
.
count
():
ub
.
User
.
id
!=
content
.
id
)
.
count
():
if
content
.
name
!=
"Guest"
:
if
content
.
name
!=
"Guest"
:
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
ub
.
User
.
id
==
content
.
id
)
.
delete
()
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
ub
.
User
.
id
==
content
.
id
)
.
delete
()
ub
.
session_commit
()
ub
.
session_commit
()
flash
(
_
(
u"User '
%(nick)
s' deleted"
,
nick
=
content
.
name
),
category
=
"success"
)
log
.
info
(
u"User {} deleted"
.
format
(
content
.
name
)
)
return
redirect
(
url_for
(
'admin.admin'
))
return
(
_
(
u"User '
%(nick)
s' deleted"
,
nick
=
content
.
name
))
else
:
else
:
flash
(
_
(
u"Can't delete Guest User"
),
category
=
"error"
)
log
.
warning
(
_
(
u"Can't delete Guest User"
)
)
return
redirect
(
url_for
(
'admin.admin'
))
raise
Exception
(
_
(
u"Can't delete Guest User"
))
else
:
else
:
flash
(
_
(
u"No admin user remaining, can't delete user"
,
nick
=
content
.
name
),
category
=
"error"
)
log
.
warning
(
u"No admin user remaining, can't delete user"
)
raise
Exception
(
_
(
u"No admin user remaining, can't delete user"
))
def
_handle_edit_user
(
to_save
,
content
,
languages
,
translations
,
kobo_support
):
if
to_save
.
get
(
"delete"
):
try
:
flash
(
_delete_user
(
content
),
category
=
"success"
)
except
Exception
as
ex
:
flash
(
str
(
ex
),
category
=
"error"
)
return
redirect
(
url_for
(
'admin.admin'
))
return
redirect
(
url_for
(
'admin.admin'
))
else
:
else
:
if
not
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
ub
.
User
.
role
.
op
(
'&'
)(
constants
.
ROLE_ADMIN
)
==
constants
.
ROLE_ADMIN
,
if
not
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
ub
.
User
.
role
.
op
(
'&'
)(
constants
.
ROLE_ADMIN
)
==
constants
.
ROLE_ADMIN
,
...
...
cps/db.py
View file @
ff99cd24
...
@@ -689,23 +689,26 @@ class CalibreDB():
...
@@ -689,23 +689,26 @@ class CalibreDB():
return
self
.
session
.
query
(
Books
)
\
return
self
.
session
.
query
(
Books
)
\
.
filter
(
and_
(
Books
.
authors
.
any
(
and_
(
*
q
)),
func
.
lower
(
Books
.
title
)
.
ilike
(
"
%
"
+
title
+
"
%
"
)))
.
first
()
.
filter
(
and_
(
Books
.
authors
.
any
(
and_
(
*
q
)),
func
.
lower
(
Books
.
title
)
.
ilike
(
"
%
"
+
title
+
"
%
"
)))
.
first
()
# read search results from calibre-database and return it (function is used for feed and simple search
def
search_query
(
self
,
term
):
def
get_search_results
(
self
,
term
,
offset
=
None
,
order
=
None
,
limit
=
None
):
order
=
order
or
[
Books
.
sort
]
pagination
=
None
term
.
strip
()
.
lower
()
term
.
strip
()
.
lower
()
self
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"lower"
,
1
,
lcase
)
self
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"lower"
,
1
,
lcase
)
q
=
list
()
q
=
list
()
authorterms
=
re
.
split
(
"[, ]+"
,
term
)
authorterms
=
re
.
split
(
"[, ]+"
,
term
)
for
authorterm
in
authorterms
:
for
authorterm
in
authorterms
:
q
.
append
(
Books
.
authors
.
any
(
func
.
lower
(
Authors
.
name
)
.
ilike
(
"
%
"
+
authorterm
+
"
%
"
)))
q
.
append
(
Books
.
authors
.
any
(
func
.
lower
(
Authors
.
name
)
.
ilike
(
"
%
"
+
authorterm
+
"
%
"
)))
re
sult
=
self
.
session
.
query
(
Books
)
.
filter
(
self
.
common_filters
(
True
))
.
filter
(
re
turn
self
.
session
.
query
(
Books
)
.
filter
(
self
.
common_filters
(
True
))
.
filter
(
or_
(
Books
.
tags
.
any
(
func
.
lower
(
Tags
.
name
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
or_
(
Books
.
tags
.
any
(
func
.
lower
(
Tags
.
name
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
Books
.
series
.
any
(
func
.
lower
(
Series
.
name
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
Books
.
series
.
any
(
func
.
lower
(
Series
.
name
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
Books
.
authors
.
any
(
and_
(
*
q
)),
Books
.
authors
.
any
(
and_
(
*
q
)),
Books
.
publishers
.
any
(
func
.
lower
(
Publishers
.
name
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
Books
.
publishers
.
any
(
func
.
lower
(
Publishers
.
name
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
func
.
lower
(
Books
.
title
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)
func
.
lower
(
Books
.
title
)
.
ilike
(
"
%
"
+
term
+
"
%
"
)
))
.
order_by
(
*
order
)
.
all
()
))
# read search results from calibre-database and return it (function is used for feed and simple search
def
get_search_results
(
self
,
term
,
offset
=
None
,
order
=
None
,
limit
=
None
):
order
=
order
or
[
Books
.
sort
]
pagination
=
None
result
=
self
.
search_query
(
term
)
.
order_by
(
*
order
)
.
all
()
result_count
=
len
(
result
)
result_count
=
len
(
result
)
if
offset
!=
None
and
limit
!=
None
:
if
offset
!=
None
and
limit
!=
None
:
offset
=
int
(
offset
)
offset
=
int
(
offset
)
...
...
cps/helper.py
View file @
ff99cd24
...
@@ -795,8 +795,8 @@ def tags_filters():
...
@@ -795,8 +795,8 @@ def tags_filters():
# checks if domain is in database (including wildcards)
# checks if domain is in database (including wildcards)
# example SELECT * FROM @TABLE WHERE 'abcdefg' LIKE Name;
# example SELECT * FROM @TABLE WHERE 'abcdefg' LIKE Name;
# from https://code.luasoftware.com/tutorials/flask/execute-raw-sql-in-flask-sqlalchemy/
# from https://code.luasoftware.com/tutorials/flask/execute-raw-sql-in-flask-sqlalchemy/
# in all calls the email address is checked for validity
def
check_valid_domain
(
domain_text
):
def
check_valid_domain
(
domain_text
):
# domain_text = domain_text.split('@', 1)[-1].lower()
sql
=
"SELECT * FROM registration WHERE (:domain LIKE domain and allow = 1);"
sql
=
"SELECT * FROM registration WHERE (:domain LIKE domain and allow = 1);"
result
=
ub
.
session
.
query
(
ub
.
Registration
)
.
from_statement
(
text
(
sql
))
.
params
(
domain
=
domain_text
)
.
all
()
result
=
ub
.
session
.
query
(
ub
.
Registration
)
.
from_statement
(
text
(
sql
))
.
params
(
domain
=
domain_text
)
.
all
()
if
not
len
(
result
):
if
not
len
(
result
):
...
...
cps/static/js/table.js
View file @
ff99cd24
...
@@ -422,6 +422,7 @@ $(function() {
...
@@ -422,6 +422,7 @@ $(function() {
$
(
"#user-table"
).
bootstrapTable
({
$
(
"#user-table"
).
bootstrapTable
({
sidePagination
:
"server"
,
sidePagination
:
"server"
,
queryParams
:
queryParams
,
pagination
:
true
,
pagination
:
true
,
paginationLoop
:
false
,
paginationLoop
:
false
,
paginationDetailHAlign
:
" hidden"
,
paginationDetailHAlign
:
" hidden"
,
...
@@ -462,28 +463,10 @@ $(function() {
...
@@ -462,28 +463,10 @@ $(function() {
$
(
"input[data-name='sidebar_read_and_unread'][data-pk='"
+
guest
.
data
(
"pk"
)
+
"']"
).
prop
(
"disabled"
,
true
);
$
(
"input[data-name='sidebar_read_and_unread'][data-pk='"
+
guest
.
data
(
"pk"
)
+
"']"
).
prop
(
"disabled"
,
true
);
$
(
".user-remove[data-pk='"
+
guest
.
data
(
"pk"
)
+
"']"
).
prop
(
"disabled"
,
true
);
$
(
".user-remove[data-pk='"
+
guest
.
data
(
"pk"
)
+
"']"
).
prop
(
"disabled"
,
true
);
},
},
onSort
:
function
(
a
,
b
)
{
// eslint-disable-next-line no-unused-vars
console
.
log
(
"huh"
);
/*onEditableSave: function (field, row, oldvalue, $el) {
},
if (field === "title" || field === "authors") {
onColumnSwitch
:
function
()
{
$.ajax({
method:"get",
dataType: "json",
url: window.location.pathname + "/../../ajax/sort_value/" + field + "/" + row.id,
success: function success(data) {
var key = Object.keys(data)[0];
$("#books-table").bootstrapTable("updateCellByUniqueId", {
id: row.id,
field: key,
value: data[key]
});
// console.log(data);
}
});
}
},*/
// eslint-disable-next-line no-unused-vars
onColumnSwitch
:
function
(
field
,
checked
)
{
var
visible
=
$
(
"#user-table"
).
bootstrapTable
(
"getVisibleColumns"
);
var
visible
=
$
(
"#user-table"
).
bootstrapTable
(
"getVisibleColumns"
);
var
hidden
=
$
(
"#user-table"
).
bootstrapTable
(
"getHiddenColumns"
);
var
hidden
=
$
(
"#user-table"
).
bootstrapTable
(
"getHiddenColumns"
);
var
st
=
""
;
var
st
=
""
;
...
@@ -525,7 +508,6 @@ $(function() {
...
@@ -525,7 +508,6 @@ $(function() {
});
});
}
}
$
(
"#user-table"
).
on
(
"click-cell.bs.table"
,
function
(
field
,
value
,
row
,
$element
)
{
$
(
"#user-table"
).
on
(
"click-cell.bs.table"
,
function
(
field
,
value
,
row
,
$element
)
{
if
(
value
===
"denied_column_value"
)
{
if
(
value
===
"denied_column_value"
)
{
ConfirmDialog
(
"btndeluser"
,
"GeneralDeleteModal"
,
$element
.
id
,
user_handle
);
ConfirmDialog
(
"btndeluser"
,
"GeneralDeleteModal"
,
$element
.
id
,
user_handle
);
...
@@ -563,7 +545,6 @@ $(function() {
...
@@ -563,7 +545,6 @@ $(function() {
$
(
".button_head"
).
removeClass
(
"disabled"
);
$
(
".button_head"
).
removeClass
(
"disabled"
);
$
(
".header_select"
).
removeAttr
(
"disabled"
);
$
(
".header_select"
).
removeAttr
(
"disabled"
);
}
}
});
});
});
});
...
@@ -603,7 +584,7 @@ function EbookActions (value, row) {
...
@@ -603,7 +584,7 @@ function EbookActions (value, row) {
/* Function for deleting books */
/* Function for deleting books */
function
UserActions
(
value
,
row
)
{
function
UserActions
(
value
,
row
)
{
return
[
return
[
"<div class=
\"
user-remove
\"
data-
pk=
\"
"
+
row
.
id
+
"
\"
data-target=
\"
#GeneralDeleteModal
\"
title=
\"
Remove
\"
>"
,
"<div class=
\"
user-remove
\"
data-
value=
\"
delete
\"
onclick=
\"
deleteUser(this, '"
+
row
.
id
+
"')
\"
data-pk=
\"
"
+
row
.
id
+
"
\"
title=
\"
Remove
\"
>"
,
"<i class=
\"
glyphicon glyphicon-trash
\"
></i>"
,
"<i class=
\"
glyphicon glyphicon-trash
\"
></i>"
,
"</div>"
"</div>"
].
join
(
""
);
].
join
(
""
);
...
@@ -715,26 +696,45 @@ function checkboxHeader(CheckboxState, field, field_index) {
...
@@ -715,26 +696,45 @@ function checkboxHeader(CheckboxState, field, field_index) {
});
});
}
}
function
user_handle
(
userId
)
{
function
deleteUser
(
a
,
b
){
confirmDialog
(
"btndeluser"
,
"GeneralDeleteModal"
,
0
,
function
()
{
$
.
ajax
({
$
.
ajax
({
method
:
"post"
,
method
:
"post"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/deleteuser"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/deleteuser"
,
data
:
{
"userid"
:
userId
}
data
:
{
"userid"
:
b
},
});
success
:
function
(
data
)
{
$
(
"#flash_success"
).
remove
();
$
(
"#flash_danger"
).
remove
();
if
(
!
jQuery
.
isEmptyObject
(
data
))
{
$
(
".navbar"
).
after
(
'<div class="row-fluid text-center" style="margin-top: -20px;">'
+
'<div id="flash_'
+
data
.
type
+
'" class="alert alert-'
+
data
.
type
+
'">'
+
data
.
message
+
'</div>'
+
'</div>'
);
}
$
.
ajax
({
$
.
ajax
({
method
:
"get"
,
method
:
"get"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/listusers"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/listusers"
,
async
:
true
,
async
:
true
,
timeout
:
900
,
timeout
:
900
,
success
:
function
(
data
)
{
success
:
function
(
data
)
{
$
(
"#user-table"
).
bootstrapTable
(
"load"
,
data
);
$
(
"#user-table"
).
bootstrapTable
(
"load"
,
data
);
}
}
});
});
}
});
}
);
}
}
function
checkboxSorter
(
a
,
b
,
c
,
d
)
function
queryParams
(
params
)
{
{
return
a
-
b
params
.
state
=
JSON
.
stringify
(
selections
);
return
params
;
}
function
user_handle
(
userId
)
{
}
}
function
test
(){
function
test
(){
...
...
cps/web.py
View file @
ff99cd24
...
@@ -753,21 +753,42 @@ def books_table():
...
@@ -753,21 +753,42 @@ def books_table():
@
web
.
route
(
"/ajax/listbooks"
)
@
web
.
route
(
"/ajax/listbooks"
)
@
login_required
@
login_required
def
list_books
():
def
list_books
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
off
=
int
(
request
.
args
.
get
(
"offset"
)
or
0
)
limit
=
request
.
args
.
get
(
"limit"
)
or
config
.
config_books_per_page
limit
=
int
(
request
.
args
.
get
(
"limit"
)
or
config
.
config_books_per_page
)
sort
=
request
.
args
.
get
(
"sort"
)
search
=
request
.
args
.
get
(
"search"
)
sort
=
request
.
args
.
get
(
"sort"
,
"state"
)
order
=
request
.
args
.
get
(
"order"
)
order
=
request
.
args
.
get
(
"order"
)
if
sort
and
order
:
state
=
None
if
sort
!=
"state"
and
order
:
order
=
[
text
(
sort
+
" "
+
order
)]
order
=
[
text
(
sort
+
" "
+
order
)]
else
:
else
:
order
=
[
db
.
Books
.
timestamp
.
desc
()]
order
=
[
db
.
Books
.
timestamp
.
desc
()]
search
=
request
.
args
.
get
(
"search"
)
if
sort
==
"state"
:
total_count
=
calibre_db
.
session
.
query
(
db
.
Books
)
.
count
()
state
=
json
.
loads
(
request
.
args
.
get
(
"state"
))
total_count
=
filtered_count
=
calibre_db
.
session
.
query
(
db
.
Books
)
.
count
()
if
state
:
outcome
=
list
()
if
search
:
if
search
:
books
=
calibre_db
.
search_query
(
search
)
filtered_count
=
len
(
books
)
else
:
books
=
calibre_db
.
session
.
query
(
db
.
Books
)
.
filter
(
calibre_db
.
common_filters
())
.
all
()
booklist
=
{
book
.
id
:
book
for
book
in
books
}
for
entry
in
state
:
outcome
.
append
(
booklist
[
entry
])
del
booklist
[
entry
]
for
entry
in
booklist
:
outcome
.
append
(
booklist
[
entry
])
if
request
.
args
.
get
(
"order"
,
""
)
.
lower
()
==
"asc"
:
outcome
.
reverse
()
entries
=
outcome
[
off
:
off
+
limit
]
elif
search
:
entries
,
filtered_count
,
__
=
calibre_db
.
get_search_results
(
search
,
off
,
order
,
limit
)
entries
,
filtered_count
,
__
=
calibre_db
.
get_search_results
(
search
,
off
,
order
,
limit
)
else
:
else
:
entries
,
__
,
__
=
calibre_db
.
fill_indexpage
((
int
(
off
)
/
(
int
(
limit
))
+
1
),
limit
,
db
.
Books
,
True
,
order
)
entries
,
__
,
__
=
calibre_db
.
fill_indexpage
((
int
(
off
)
/
(
int
(
limit
))
+
1
),
limit
,
db
.
Books
,
True
,
order
)
filtered_count
=
total_count
for
entry
in
entries
:
for
entry
in
entries
:
for
index
in
range
(
0
,
len
(
entry
.
languages
)):
for
index
in
range
(
0
,
len
(
entry
.
languages
)):
try
:
try
:
...
...
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