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
7c6d527a
Commit
7c6d527a
authored
Apr 02, 2017
by
OzzieIsaacs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Code cosmetics
parent
66181daf
Show whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
254 additions
and
255 deletions
+254
-255
cps.py
cps.py
+1
-1
helper.py
cps/helper.py
+1
-0
edit_books.js
cps/static/js/edit_books.js
+10
-11
get_meta.js
cps/static/js/get_meta.js
+93
-93
main.js
cps/static/js/main.js
+6
-6
book_edit.html
cps/templates/book_edit.html
+1
-1
detail.html
cps/templates/detail.html
+6
-6
discover.html
cps/templates/discover.html
+2
-2
feed.xml
cps/templates/feed.xml
+4
-4
index.html
cps/templates/index.html
+4
-4
json.txt
cps/templates/json.txt
+2
-2
list.html
cps/templates/list.html
+1
-1
search.html
cps/templates/search.html
+2
-2
shelf.html
cps/templates/shelf.html
+2
-2
user_edit.html
cps/templates/user_edit.html
+1
-1
ub.py
cps/ub.py
+2
-1
web.py
cps/web.py
+116
-118
No files found.
cps.py
View file @
7c6d527a
...
...
@@ -22,7 +22,7 @@ except ImportError:
if
__name__
==
'__main__'
:
if
web
.
ub
.
DEVELOPMENT
:
web
.
app
.
run
(
host
=
"0.0.0.0"
,
port
=
web
.
ub
.
config
.
config_port
,
debug
=
True
)
web
.
app
.
run
(
port
=
web
.
ub
.
config
.
config_port
,
debug
=
True
)
else
:
if
gevent_present
:
web
.
app
.
logger
.
info
(
'Attempting to start gevent'
)
...
...
cps/helper.py
View file @
7c6d527a
...
...
@@ -13,6 +13,7 @@ import os
import
traceback
import
re
import
unicodedata
try
:
from
StringIO
import
StringIO
from
email.MIMEBase
import
MIMEBase
...
...
cps/static/js/edit_books.js
View file @
7c6d527a
...
...
@@ -8,7 +8,7 @@
Takes a prefix, query typeahead callback, Bloodhound typeahead adapter
and returns the completions it gets from the bloodhound engine prefixed.
*/
function
prefixed
_s
ource
(
prefix
,
query
,
cb
,
bhAdapter
)
{
function
prefixed
S
ource
(
prefix
,
query
,
cb
,
bhAdapter
)
{
bhAdapter
(
query
,
function
(
retArray
){
var
matches
=
[];
for
(
var
i
=
0
;
i
<
retArray
.
length
;
i
++
)
{
...
...
@@ -18,7 +18,7 @@ function prefixed_source(prefix, query, cb, bhAdapter) {
cb
(
matches
);
});
}
function
get
_p
ath
(){
function
get
P
ath
(){
var
jsFileLocation
=
$
(
"script[src*=edit_books]"
).
attr
(
"src"
);
// the js file path
jsFileLocation
=
jsFileLocation
.
replace
(
"/static/js/edit_books.js"
,
''
);
// the js folder path
return
jsFileLocation
;
...
...
@@ -31,7 +31,7 @@ var authors = new Bloodhound({
},
queryTokenizer
:
Bloodhound
.
tokenizers
.
whitespace
,
remote
:
{
url
:
get
_p
ath
()
+
"/get_authors_json?q=%QUERY"
url
:
get
P
ath
()
+
"/get_authors_json?q=%QUERY"
}
});
...
...
@@ -44,7 +44,7 @@ var series = new Bloodhound({
return
[
query
];
},
remote
:
{
url
:
get
_p
ath
()
+
"/get_series_json?q="
,
url
:
get
P
ath
()
+
"/get_series_json?q="
,
replace
:
function
(
url
,
query
)
{
return
url
+
encodeURIComponent
(
query
);
}
...
...
@@ -63,7 +63,7 @@ var tags = new Bloodhound({
return
tokens
;
},
remote
:
{
url
:
get
_p
ath
()
+
"/get_tags_json?q=%QUERY"
url
:
get
P
ath
()
+
"/get_tags_json?q=%QUERY"
}
});
...
...
@@ -76,10 +76,9 @@ var languages = new Bloodhound({
return
[
query
];
},
remote
:
{
url
:
get
_p
ath
()
+
"/get_languages_json?q="
,
url
:
get
P
ath
()
+
"/get_languages_json?q="
,
replace
:
function
(
url
,
query
)
{
url_query
=
url
+
encodeURIComponent
(
query
);
return
url_query
;
return
url
+
encodeURIComponent
(
query
);
}
}
});
...
...
@@ -101,7 +100,7 @@ function sourceSplit(query, cb, split, source) {
for
(
var
i
=
0
;
i
<
tokens
.
length
;
i
++
)
{
prefix
+=
tokens
[
i
].
trim
()
+
newSplit
;
}
prefixed
_s
ource
(
prefix
,
currentSource
,
cb
,
bhAdapter
);
prefixed
S
ource
(
prefix
,
currentSource
,
cb
,
bhAdapter
);
}
var
promiseAuthors
=
authors
.
initialize
();
...
...
@@ -130,7 +129,7 @@ var promiseSeries = series.initialize();
displayKey
:
"name"
,
source
:
series
.
ttAdapter
()
}
)
)
;
});
var
promiseTags
=
tags
.
initialize
();
...
...
@@ -165,7 +164,7 @@ var promiseLanguages = languages.initialize();
$
(
"form"
).
on
(
"change input typeahead:selected"
,
function
(
data
){
var
form
=
$
(
"form"
).
serialize
();
$
.
getJSON
(
get
_p
ath
()
+
"/get_matching_tags"
,
form
,
function
(
data
)
{
$
.
getJSON
(
get
P
ath
()
+
"/get_matching_tags"
,
form
,
function
(
data
)
{
$
(
".tags_click"
).
each
(
function
()
{
if
(
$
.
inArray
(
parseInt
(
$
(
this
).
children
(
"input"
).
first
().
val
(),
10
),
data
.
tags
)
===
-
1
)
{
if
(
!
(
$
(
this
).
hasClass
(
"active"
)))
{
...
...
cps/static/js/get_meta.js
View file @
7c6d527a
...
...
@@ -9,36 +9,95 @@ $(document).ready(function () {
var
msg
=
i18nMsg
;
var
douban
=
"https://api.douban.com"
;
var
dbSearch
=
"/v2/book/search"
;
var
db_get_i
nfo
=
"/v2/book/"
;
var
db_get_info_by_isbn
=
"/v2/book/isbn/ "
;
// var dbGetI
nfo = "/v2/book/";
//
var db_get_info_by_isbn = "/v2/book/isbn/ ";
var
dbDone
=
false
;
var
google
=
"https://www.googleapis.com/"
;
var
gg
_s
earch
=
"/books/v1/volumes"
;
var
gg_get_info
=
"/books/v1/volumes/"
;
var
gg
_d
one
=
false
;
var
gg
S
earch
=
"/books/v1/volumes"
;
//
var gg_get_info = "/books/v1/volumes/";
var
gg
D
one
=
false
;
var
db
_r
esults
=
[];
var
gg
_r
esults
=
[];
var
show
_f
lag
=
0
;
String
.
prototype
.
replaceAll
=
function
(
s1
,
s2
)
{
var
db
R
esults
=
[];
var
gg
R
esults
=
[];
var
show
F
lag
=
0
;
String
.
prototype
.
replaceAll
=
function
(
s1
,
s2
)
{
return
this
.
replace
(
new
RegExp
(
s1
,
"gm"
),
s2
);
};
function
gg_search_book
(
title
)
{
function
showResult
()
{
showFlag
++
;
if
(
showFlag
===
1
)
{
$
(
"#meta-info"
).
html
(
'<ul id="book-list" class="media-list"></ul>'
);
}
if
(
ggDone
&&
dbDone
)
{
if
(
!
ggResults
&&
!
dbResults
)
{
$
(
"#meta-info"
).
html
(
'<p class="text-danger">'
+
msg
.
no_result
+
"</p>"
);
return
;
}
}
if
(
ggDone
&&
ggResults
.
length
>
0
)
{
for
(
var
i
=
0
;
i
<
ggResults
.
length
;
i
++
)
{
var
book
=
ggResults
[
i
];
var
bookCover
;
if
(
book
.
volumeInfo
.
imageLinks
)
{
bookCover
=
book
.
volumeInfo
.
imageLinks
.
thumbnail
;
}
else
{
bookCover
=
"/static/generic_cover.jpg"
;
}
var
bookHtml
=
'<li class="media">'
+
'<img class="pull-left img-responsive" data-toggle="modal" data-target="#metaModal" src="'
+
bookCover
+
'" alt="Cover" style="width:100px;height:150px" onclick=
\'
javascript:get_meta("google",'
+
i
+
')
\'
>'
+
'<div class="media-body">'
+
'<h4 class="media-heading"><a href="https://books.google.com/books?id='
+
book
.
id
+
'" target="_blank">'
+
book
.
volumeInfo
.
title
+
'</a></h4>'
+
"<p>"
+
msg
.
author
+
":"
+
book
.
volumeInfo
.
authors
+
"</p>"
+
"<p>"
+
msg
.
publisher
+
":"
+
book
.
volumeInfo
.
publisher
+
"</p>"
+
"<p>"
+
msg
.
description
+
":"
+
book
.
volumeInfo
.
description
+
"</p>"
+
"<p>"
+
msg
.
source
+
':<a href="https://books.google.com" target="_blank">Google Books</a></p>'
+
"</div>"
+
"</li>"
;
$
(
"#book-list"
).
append
(
bookHtml
);
}
ggDone
=
false
;
}
if
(
dbDone
&&
dbResults
.
length
>
0
)
{
for
(
var
i
=
0
;
i
<
dbResults
.
length
;
i
++
)
{
var
book
=
dbResults
[
i
];
var
bookHtml
=
'<li class="media">'
+
'<img class="pull-left img-responsive" data-toggle="modal" data-target="#metaModal" src="'
+
book
.
image
+
'" alt="Cover" style="width:100px;height: 150px" onclick=
\'
javascript:get_meta("douban",'
+
i
+
')
\'
>'
+
'<div class="media-body">'
+
'<h4 class="media-heading"><a href="https://book.douban.com/subject/'
+
book
.
id
+
'" target="_blank">'
+
book
.
title
+
"</a></h4>"
+
"<p>"
+
msg
.
author
+
":"
+
book
.
author
+
"</p>"
+
"<p>"
+
msg
.
publisher
+
":"
+
book
.
publisher
+
"</p>"
+
"<p>"
+
msg
.
description
+
":"
+
book
.
summary
+
"</p>"
+
"<p>"
+
msg
.
source
+
':<a href="https://book.douban.com" target="_blank">Douban Books</a></p>'
+
"</div>"
+
"</li>"
;
$
(
"#book-list"
).
append
(
bookHtml
);
}
dbDone
=
false
;
}
}
function
ggSearchBook
(
title
)
{
title
=
title
.
replaceAll
(
/
\s
+/
,
"+"
);
var
url
=
google
+
gg
_s
earch
+
"?q="
+
title
;
var
url
=
google
+
gg
S
earch
+
"?q="
+
title
;
$
.
ajax
({
url
,
type
:
"GET"
,
dataType
:
"jsonp"
,
jsonp
:
"callback"
,
success
:
function
(
data
)
{
gg
_r
esults
=
data
.
items
;
gg
R
esults
=
data
.
items
;
},
complete
:
function
()
{
gg
_d
one
=
true
;
show
_r
esult
();
gg
D
one
=
true
;
show
R
esult
();
}
});
}
...
...
@@ -47,7 +106,7 @@ $(document).ready(function () {
var
meta
;
var
tags
;
if
(
source
===
"google"
)
{
meta
=
gg
_r
esults
[
id
];
meta
=
gg
R
esults
[
id
];
$
(
"#description"
).
val
(
meta
.
volumeInfo
.
description
);
$
(
"#bookAuthor"
).
val
(
meta
.
volumeInfo
.
authors
.
join
(
" & "
));
$
(
"#book_title"
).
val
(
meta
.
volumeInfo
.
title
);
...
...
@@ -61,13 +120,13 @@ $(document).ready(function () {
return
;
}
if
(
source
===
"douban"
)
{
meta
=
db
_r
esults
[
id
];
meta
=
db
R
esults
[
id
];
$
(
"#description"
).
val
(
meta
.
summary
);
$
(
"#bookAuthor"
).
val
(
meta
.
author
.
join
(
" & "
));
$
(
"#book_title"
).
val
(
meta
.
title
);
tags
=
''
;
tags
=
""
;
for
(
var
i
=
0
;
i
<
meta
.
tags
.
length
;
i
++
)
{
tags
=
tags
+
meta
.
tags
[
i
].
title
+
','
;
tags
=
tags
+
meta
.
tags
[
i
].
title
+
","
;
}
$
(
"#tags"
).
val
(
tags
);
$
(
"#rating"
).
val
(
Math
.
round
(
meta
.
rating
.
average
/
2
));
...
...
@@ -75,91 +134,32 @@ $(document).ready(function () {
}
}
function
do
_s
earch
(
keyword
)
{
show
_f
lag
=
0
;
function
do
S
earch
(
keyword
)
{
show
F
lag
=
0
;
$
(
"#meta-info"
).
text
(
msg
.
loading
);
var
keyword
=
$
(
"#keyword"
).
val
();
//
var keyword = $("#keyword").val();
if
(
keyword
)
{
db_search_book
(
keyword
);
gg_search_book
(
keyword
);
}
}
function
show_result
()
{
show_flag
++
;
if
(
show_flag
==
1
)
{
$
(
'#meta-info'
).
html
(
'<ul id="book-list" class="media-list"></ul>'
);
}
if
(
gg_done
&&
dbDone
)
{
if
(
!
gg_results
&&
!
db_results
)
{
$
(
'#meta-info'
).
html
(
'<p class="text-danger">'
+
msg
.
no_result
+
'</p>'
);
return
;
}
}
if
(
gg_done
&&
gg_results
.
length
>
0
)
{
for
(
var
i
=
0
;
i
<
gg_results
.
length
;
i
++
)
{
var
book
=
gg_results
[
i
];
var
book_cover
;
if
(
book
.
volumeInfo
.
imageLinks
)
{
book_cover
=
book
.
volumeInfo
.
imageLinks
.
thumbnail
;
}
else
{
book_cover
=
'/static/generic_cover.jpg'
;
}
var
book_html
=
'<li class="media">'
+
'<img class="pull-left img-responsive" data-toggle="modal" data-target="#metaModal" src="'
+
book_cover
+
'" alt="Cover" style="width:100px;height:150px" onclick=
\'
javascript:get_meta("google",'
+
i
+
')
\'
>'
+
'<div class="media-body">'
+
'<h4 class="media-heading"><a href="https://books.google.com/books?id='
+
book
.
id
+
'" target="_blank">'
+
book
.
volumeInfo
.
title
+
'</a></h4>'
+
'<p>'
+
msg
.
author
+
':'
+
book
.
volumeInfo
.
authors
+
'</p>'
+
'<p>'
+
msg
.
publisher
+
':'
+
book
.
volumeInfo
.
publisher
+
'</p>'
+
'<p>'
+
msg
.
description
+
':'
+
book
.
volumeInfo
.
description
+
'</p>'
+
'<p>'
+
msg
.
source
+
':<a href="https://books.google.com" target="_blank">Google Books</a></p>'
+
'</div>'
+
'</li>'
;
$
(
"#book-list"
).
append
(
book_html
);
}
gg_done
=
false
;
}
if
(
dbDone
&&
db_results
.
length
>
0
)
{
for
(
var
i
=
0
;
i
<
db_results
.
length
;
i
++
)
{
var
book
=
db_results
[
i
];
var
book_html
=
'<li class="media">'
+
'<img class="pull-left img-responsive" data-toggle="modal" data-target="#metaModal" src="'
+
book
.
image
+
'" alt="Cover" style="width:100px;height: 150px" onclick=
\'
javascript:get_meta("douban",'
+
i
+
')
\'
>'
+
'<div class="media-body">'
+
'<h4 class="media-heading"><a href="https://book.douban.com/subject/'
+
book
.
id
+
'" target="_blank">'
+
book
.
title
+
'</a></h4>'
+
'<p>'
+
msg
.
author
+
':'
+
book
.
author
+
'</p>'
+
'<p>'
+
msg
.
publisher
+
':'
+
book
.
publisher
+
'</p>'
+
'<p>'
+
msg
.
description
+
':'
+
book
.
summary
+
'</p>'
+
'<p>'
+
msg
.
source
+
':<a href="https://book.douban.com" target="_blank">Douban Books</a></p>'
+
'</div>'
+
"</li>"
;
$
(
"#book-list"
).
append
(
book_html
);
}
dbDone
=
false
;
dbSearchBook
(
keyword
);
ggSearchBook
(
keyword
);
}
}
db_search_book
=
function
(
title
)
{
var
url
=
douban
+
dbSearch
+
'?q='
+
title
+
'&fields=all&count=10'
;
function
dbSearchBook
(
title
)
{
var
url
=
douban
+
dbSearch
+
"?q="
+
title
+
"&fields=all&count=10"
;
$
.
ajax
({
url
:
url
,
type
:
"GET"
,
dataType
:
"jsonp"
,
jsonp
:
'callback'
,
jsonp
:
"callback"
,
success
:
function
(
data
)
{
db
_r
esults
=
data
.
books
;
db
R
esults
=
data
.
books
;
},
error
:
function
()
{
$
(
'#meta-info'
).
html
(
'<p class="text-danger">'
+
msg
.
search_error
+
'!</p>'
);
$
(
"#meta-info"
).
html
(
'<p class="text-danger">'
+
msg
.
search_error
+
"!</p>"
);
},
complete
:
function
()
{
dbDone
=
true
;
show
_r
esult
();
show
R
esult
();
}
});
}
...
...
@@ -167,15 +167,15 @@ $(document).ready(function () {
$
(
"#do-search"
).
click
(
function
()
{
var
keyword
=
$
(
"#keyword"
).
val
();
if
(
keyword
)
{
do
_s
earch
(
keyword
);
do
S
earch
(
keyword
);
}
});
$
(
"#get_meta"
).
click
(
function
()
{
var
book
_t
itle
=
$
(
"#book_title"
).
val
();
if
(
book
_t
itle
)
{
$
(
"#keyword"
).
val
(
book
_t
itle
);
do
_search
(
book_t
itle
);
var
book
T
itle
=
$
(
"#book_title"
).
val
();
if
(
book
T
itle
)
{
$
(
"#keyword"
).
val
(
book
T
itle
);
do
Search
(
bookT
itle
);
}
});
...
...
cps/static/js/main.js
View file @
7c6d527a
...
...
@@ -49,13 +49,13 @@ $(function() {
});
});
$
(
"#check_for_update"
).
click
(
function
()
{
var
button
_t
ext
=
$
(
"#check_for_update"
).
html
();
var
button
T
ext
=
$
(
"#check_for_update"
).
html
();
$
(
"#check_for_update"
).
html
(
"..."
);
$
.
ajax
({
dataType
:
"json"
,
url
:
window
.
location
.
pathname
+
"/../../get_update_status"
,
success
:
function
(
data
)
{
$
(
"#check_for_update"
).
html
(
button
_t
ext
);
$
(
"#check_for_update"
).
html
(
button
T
ext
);
if
(
data
.
status
===
true
)
{
$
(
"#check_for_update"
).
addClass
(
"hidden"
);
$
(
"#perform_update"
).
removeClass
(
"hidden"
);
...
...
@@ -67,7 +67,7 @@ $(function() {
});
$
(
"#restart_database"
).
click
(
function
()
{
$
.
ajax
({
dataType
:
'json'
,
dataType
:
"json"
,
url
:
window
.
location
.
pathname
+
"/../../shutdown"
,
data
:
{
"parameter"
:
2
}
});
...
...
@@ -76,7 +76,7 @@ $(function() {
$
(
"#spinner2"
).
show
();
$
.
ajax
({
type
:
"POST"
,
dataType
:
'json'
,
dataType
:
"json"
,
data
:
{
start
:
"True"
},
url
:
window
.
location
.
pathname
+
"/../../get_updater_status"
,
success
:
function
(
data
)
{
...
...
@@ -94,10 +94,10 @@ $(function() {
function
updateTimer
()
{
$
.
ajax
({
dataType
:
'json'
,
dataType
:
"json"
,
url
:
window
.
location
.
pathname
+
"/../../get_updater_status"
,
success
:
function
(
data
)
{
console
.
log
(
data
.
status
);
//
console.log(data.status);
$
(
"#UpdateprogressDialog #Updatecontent"
).
html
(
updateText
[
data
.
status
]);
if
(
data
.
status
>
6
){
clearInterval
(
updateTimerID
);
...
...
cps/templates/book_edit.html
View file @
7c6d527a
...
...
@@ -106,7 +106,7 @@
</div>
<a
href=
"#"
id=
"get_meta"
class=
"btn btn-default"
data-toggle=
"modal"
data-target=
"#metaModal"
>
{{_('Get metadata')}}
</a>
<button
type=
"submit"
class=
"btn btn-default"
>
{{_('Submit')}}
</button>
<a
href=
"{{ url_for('show_book',id=book.id) }}"
class=
"btn btn-default"
>
{{_('Back')}}
</a>
<a
href=
"{{ url_for('show_book',
book_
id=book.id) }}"
class=
"btn btn-default"
>
{{_('Back')}}
</a>
</form>
</div>
{% endif %}
...
...
cps/templates/detail.html
View file @
7c6d527a
...
...
@@ -15,7 +15,7 @@
<h2>
{{entry.title}}
</h2>
<p
class=
"author"
>
{% for author in entry.authors %}
<a
href=
"{{url_for('author', id=author.id ) }}"
>
{{author.name}}
</a>
<a
href=
"{{url_for('author',
book_
id=author.id ) }}"
>
{{author.name}}
</a>
{% if not loop.last %}
&
{% endif %}
...
...
@@ -37,7 +37,7 @@
{% endif %}
{% if entry.series|length > 0 %}
<p>
{{_('Book')}} {{entry.series_index}} {{_('of')}}
<a
href=
"{{url_for('series', id=entry.series[0].id)}}"
>
{{entry.series[0].name}}
</a></p>
<p>
{{_('Book')}} {{entry.series_index}} {{_('of')}}
<a
href=
"{{url_for('series',
book_
id=entry.series[0].id)}}"
>
{{entry.series[0].name}}
</a></p>
{% endif %}
{% if entry.languages.__len__() > 0 %}
...
...
@@ -65,7 +65,7 @@
<span
class=
"glyphicon glyphicon-tags"
></span>
{% for tag in entry.tags %}
<a
href=
"{{ url_for('category', id=tag.id) }}"
class=
"btn btn-xs btn-info"
role=
"button"
>
{{tag.name}}
</a>
<a
href=
"{{ url_for('category',
book_
id=tag.id) }}"
class=
"btn btn-xs btn-info"
role=
"button"
>
{{tag.name}}
</a>
{%endfor%}
</div>
</p>
...
...
@@ -110,7 +110,7 @@
{% if not g.user.is_anonymous() %}
<p>
<div
class=
"custom_columns"
id=
"have_read_container"
>
<form
id=
"have_read_form"
action=
"{{ url_for('toggle_read', id=entry.id)}}"
method=
"POST"
)
>
<form
id=
"have_read_form"
action=
"{{ url_for('toggle_read',
book_
id=entry.id)}}"
method=
"POST"
)
>
<input
id=
"have_read_cb"
type=
"checkbox"
{%
if
have_read
%}
checked
{%
endif
%}
>
<label
for=
"have_read_cb"
>
{{_('Read')}}
</label>
</form>
...
...
@@ -136,7 +136,7 @@
</button>
<ul
class=
"dropdown-menu"
aria-labelledby=
"btnGroupDrop1"
>
{% for format in entry.data %}
<li><a
href=
"{{ url_for('get_download_link_ext', book_id=entry.id, format=format.format|lower, anyname=entry.id|string+'.'+format.format) }}"
>
{{format.format}}
</a></li>
<li><a
href=
"{{ url_for('get_download_link_ext', book_id=entry.id,
book_
format=format.format|lower, anyname=entry.id|string+'.'+format.format) }}"
>
{{format.format}}
</a></li>
{%endfor%}
</ul>
</div>
...
...
@@ -154,7 +154,7 @@
<ul
class=
"dropdown-menu"
aria-labelledby=
"btnGroupDrop2"
>
{% for format in entry.data %}
{%if format.format|lower == 'epub' or format.format|lower == 'txt' or format.format|lower == 'pdf' or format.format|lower == 'cbr' or format.format|lower == 'cbt' or format.format|lower == 'cbz' %}
<li><a
target=
"_blank"
href=
"{{ url_for('read_book', book_id=entry.id, format=format.format|lower) }}"
>
{{format.format}}
</a></li>
<li><a
target=
"_blank"
href=
"{{ url_for('read_book', book_id=entry.id,
book_
format=format.format|lower) }}"
>
{{format.format}}
</a></li>
{% endif %}
{%endfor%}
</ul>
...
...
cps/templates/discover.html
View file @
7c6d527a
...
...
@@ -8,14 +8,14 @@
<div
class=
"col-sm-3 col-lg-2 col-xs-6 book"
>
<div
class=
"cover"
>
{% if entry.has_cover is defined %}
<a
href=
"{{ url_for('show_book', id=entry.id) }}"
>
<a
href=
"{{ url_for('show_book',
book_
id=entry.id) }}"
>
<img
src=
"{{ url_for('get_cover', cover_path=entry.path.replace('\\','/')) }}"
/>
</a>
{% endif %}
</div>
<div
class=
"meta"
>
<p
class=
"title"
>
{{entry.title|shortentitle}}
</p>
<p
class=
"author"
><a
href=
"{{url_for('author', id=entry.authors[0].id) }}"
>
{{entry.authors[0].name}}
</a></p>
<p
class=
"author"
><a
href=
"{{url_for('author',
book_
id=entry.authors[0].id) }}"
>
{{entry.authors[0].name}}
</a></p>
{% if entry.ratings.__len__() > 0 %}
<div
class=
"rating"
>
{% for number in range((entry.ratings[0].rating/2)|int(2)) %}
...
...
cps/templates/feed.xml
View file @
7c6d527a
...
...
@@ -56,7 +56,7 @@
<link
type=
"image/jpeg"
href=
"{{url_for('feed_get_cover', book_id=entry.id)}}"
rel=
"http://opds-spec.org/image/thumbnail"
/>
{% endif %}
{% for format in entry.data %}
<link
rel=
"http://opds-spec.org/acquisition"
href=
"{{ url_for('get_opds_download_link', book_id=entry.id, format=format.format|lower)}}"
<link
rel=
"http://opds-spec.org/acquisition"
href=
"{{ url_for('get_opds_download_link', book_id=entry.id,
book_
format=format.format|lower)}}"
length=
"{{format.uncompressed_size}}"
mtime=
"{{entry.timestamp}}"
type=
"{{format.format|lower|mimetype}}"
/>
{% endfor %}
</entry>
...
...
@@ -65,9 +65,9 @@
{% for entry in listelements %}
<entry>
<title>
{{entry.name}}
</title>
<id>
{{ url_for(folder, id=entry.id) }}
</id>
<link
type=
"application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition"
href=
"{{url_for(folder, id=entry.id)}}"
/>
<link
type=
"application/atom+xml"
href=
"{{url_for(folder, id=entry.id)}}"
rel=
"subsection"
/>
<id>
{{ url_for(folder,
book_
id=entry.id) }}
</id>
<link
type=
"application/atom+xml;profile=opds-catalog;type=feed;kind=acquisition"
href=
"{{url_for(folder,
book_
id=entry.id)}}"
/>
<link
type=
"application/atom+xml"
href=
"{{url_for(folder,
book_
id=entry.id)}}"
rel=
"subsection"
/>
</entry>
{% endfor %}
</feed>
cps/templates/index.html
View file @
7c6d527a
...
...
@@ -8,7 +8,7 @@
{% for entry in random %}
<div
id=
"books_rand"
class=
"col-sm-3 col-lg-2 col-xs-6 book"
>
<div
class=
"cover"
>
<a
href=
"{{ url_for('show_book', id=entry.id) }}"
>
<a
href=
"{{ url_for('show_book',
book_
id=entry.id) }}"
>
{% if entry.has_cover %}
<img
src=
"{{ url_for('get_cover', cover_path=entry.path.replace('\\','/')) }}"
/>
{% else %}
...
...
@@ -18,7 +18,7 @@
</div>
<div
class=
"meta"
>
<p
class=
"title"
>
{{entry.title|shortentitle}}
</p>
<p
class=
"author"
><a
href=
"{{url_for('author', id=entry.authors[0].id) }}"
>
{{entry.authors[0].name}}
</a></p>
<p
class=
"author"
><a
href=
"{{url_for('author',
book_
id=entry.authors[0].id) }}"
>
{{entry.authors[0].name}}
</a></p>
{% if entry.ratings.__len__() > 0 %}
<div
class=
"rating"
>
{% for number in range((entry.ratings[0].rating/2)|int(2)) %}
...
...
@@ -44,7 +44,7 @@
{% for entry in entries %}
<div
id=
"books"
class=
"col-sm-3 col-lg-2 col-xs-6 book"
>
<div
class=
"cover"
>
<a
href=
"{{ url_for('show_book', id=entry.id) }}"
>
<a
href=
"{{ url_for('show_book',
book_
id=entry.id) }}"
>
{% if entry.has_cover %}
<img
src=
"{{ url_for('get_cover', cover_path=entry.path.replace('\\','/')) }}"
/>
{% else %}
...
...
@@ -56,7 +56,7 @@
<p
class=
"title"
>
{{entry.title|shortentitle}}
</p>
<p
class=
"author"
>
{% for author in entry.authors %}
<a
href=
"{{url_for('author', id=author.id) }}"
>
{{author.name}}
</a>
<a
href=
"{{url_for('author',
book_
id=author.id) }}"
>
{{author.name}}
</a>
{% if not loop.last %}
&
{% endif %}
...
...
cps/templates/json.txt
View file @
7c6d527a
...
...
@@ -36,7 +36,7 @@
"timestamp": "{{entry.timestamp}}",
"thumbnail": "{{url_for('feed_get_cover', book_id=entry.id)}}",
"main_format": {
"{{entry.data[0].format|lower}}": "{{ url_for('get_opds_download_link', book_id=entry.id, format=entry.data[0].format|lower)}}"
"{{entry.data[0].format|lower}}": "{{ url_for('get_opds_download_link', book_id=entry.id,
book_
format=entry.data[0].format|lower)}}"
},
"rating":{% if entry.ratings.__len__() > 0 %} "{{entry.ratings[0].rating}}.0"{% else %}0.0{% endif %},
"authors": [
...
...
@@ -47,7 +47,7 @@
"other_formats": {
{% if entry.data.__len__() > 1 %}
{% for format in entry.data[1:] %}
"{{format.format|lower}}": "{{ url_for('get_opds_download_link', book_id=entry.id, format=format.format|lower)}}"{% if not loop.last %},{% endif %}
"{{format.format|lower}}": "{{ url_for('get_opds_download_link', book_id=entry.id,
book_
format=format.format|lower)}}"{% if not loop.last %},{% endif %}
{% endfor %}
{% endif %} },
"title_sort": "{{entry.sort}}"
...
...
cps/templates/list.html
View file @
7c6d527a
...
...
@@ -10,7 +10,7 @@
{% endif %}
<div
class=
"row"
>
<div
class=
"col-xs-1"
align=
"left"
><span
class=
"badge"
>
{{entry.count}}
</span></div>
<div
class=
"col-xs-6"
><a
id=
"list_{{loop.index0}}"
href=
"{{url_for(folder, id=entry[0].id )}}"
>
{{entry[0].name}}
</a></div>
<div
class=
"col-xs-6"
><a
id=
"list_{{loop.index0}}"
href=
"{{url_for(folder,
book_
id=entry[0].id )}}"
>
{{entry[0].name}}
</a></div>
</div>
{% endfor %}
</div>
...
...
cps/templates/search.html
View file @
7c6d527a
...
...
@@ -15,7 +15,7 @@
<div
class=
"col-sm-3 col-lg-2 col-xs-6 book"
>
<div
class=
"cover"
>
{% if entry.has_cover is defined %}
<a
href=
"{{ url_for('show_book', id=entry.id) }}"
>
<a
href=
"{{ url_for('show_book',
book_
id=entry.id) }}"
>
<img
src=
"{{ url_for('get_cover', cover_path=entry.path.replace('\\','/')) }}"
/>
</a>
{% endif %}
...
...
@@ -24,7 +24,7 @@
<p
class=
"title"
>
{{entry.title|shortentitle}}
</p>
<p
class=
"author"
>
{% for author in entry.authors %}
<a
href=
"{{url_for('author', id=author.id ) }}"
>
{{author.name}}
</a>
<a
href=
"{{url_for('author',
book_
id=author.id ) }}"
>
{{author.name}}
</a>
{% if not loop.last %}
&
{% endif %}
...
...
cps/templates/shelf.html
View file @
7c6d527a
...
...
@@ -15,14 +15,14 @@
<div
class=
"col-sm-3 col-lg-2 col-xs-6 book"
>
<div
class=
"cover"
>
{% if entry.has_cover is defined %}
<a
href=
"{{ url_for('show_book', id=entry.id) }}"
>
<a
href=
"{{ url_for('show_book',
book_
id=entry.id) }}"
>
<img
src=
"{{ url_for('get_cover', cover_path=entry.path.replace('\\','/')) }}"
/>
</a>
{% endif %}
</div>
<div
class=
"meta"
>
<p
class=
"title"
>
{{entry.title|shortentitle}}
</p>
<p
class=
"author"
><a
href=
"{{url_for('author', id=entry.authors[0].id) }}"
>
{{entry.authors[0].name}}
</a></p>
<p
class=
"author"
><a
href=
"{{url_for('author',
book_
id=entry.authors[0].id) }}"
>
{{entry.authors[0].name}}
</a></p>
{% if entry.ratings.__len__() > 0 %}
<div
class=
"rating"
>
{% for number in range((entry.ratings[0].rating/2)|int(2)) %}
...
...
cps/templates/user_edit.html
View file @
7c6d527a
...
...
@@ -131,7 +131,7 @@
<h2>
{{_('Recent Downloads')}}
</h2>
{% for entry in downloads %}
<div
class=
"col-sm-2"
>
<a
class=
"pull-left"
href=
"{{ url_for('show_book', id=entry.id) }}"
>
<a
class=
"pull-left"
href=
"{{ url_for('show_book',
book_
id=entry.id) }}"
>
<img
class=
"media-object"
width=
"100"
src=
"{{ url_for('get_cover', cover_path=entry.path.replace('\\','/')) }}"
alt=
"..."
>
</a>
</div>
...
...
cps/ub.py
View file @
7c6d527a
...
...
@@ -93,9 +93,11 @@ class UserBase:
else
:
return
False
@
staticmethod
def
is_active
(
self
):
return
True
@
staticmethod
def
is_anonymous
(
self
):
return
False
...
...
@@ -526,7 +528,6 @@ def create_admin_user():
session
.
commit
()
except
Exception
:
session
.
rollback
()
pass
# Open session for database connection
...
...
cps/web.py
View file @
7c6d527a
...
...
@@ -403,10 +403,10 @@ def timestamptodate(date, fmt=None):
)
native
=
date
.
replace
(
tzinfo
=
None
)
if
fmt
:
format
=
fmt
time_
format
=
fmt
else
:
format
=
'
%
d
%
m
%
Y -
%
H:
%
S'
return
native
.
strftime
(
format
)
time_
format
=
'
%
d
%
m
%
Y -
%
H:
%
S'
return
native
.
strftime
(
time_
format
)
def
admin_required
(
f
):
"""
...
...
@@ -469,11 +469,11 @@ def edit_required(f):
# Fill indexpage with all requested data from database
def
fill_indexpage
(
page
,
database
,
db_filter
,
order
):
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
lang_
filter
=
True
if
current_user
.
show_detail_random
():
random
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
filter
)
.
order_by
(
func
.
random
())
.
limit
(
config
.
config_random_books
)
random
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
lang_
filter
)
.
order_by
(
func
.
random
())
.
limit
(
config
.
config_random_books
)
else
:
random
=
false
off
=
int
(
int
(
config
.
config_books_per_page
)
*
(
page
-
1
))
...
...
@@ -588,15 +588,15 @@ def feed_normal_search():
def
feed_search
(
term
):
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
lang_
filter
=
True
if
term
:
entries
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
or_
(
db
.
Books
.
tags
.
any
(
db
.
Tags
.
name
.
like
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
series
.
any
(
db
.
Series
.
name
.
like
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
authors
.
any
(
db
.
Authors
.
name
.
like
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
publishers
.
any
(
db
.
Publishers
.
name
.
like
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
title
.
like
(
"
%
"
+
term
+
"
%
"
)))
.
filter
(
filter
)
.
all
()
db
.
Books
.
title
.
like
(
"
%
"
+
term
+
"
%
"
)))
.
filter
(
lang_
filter
)
.
all
()
entriescount
=
len
(
entries
)
if
len
(
entries
)
>
0
else
1
pagination
=
Pagination
(
1
,
entriescount
,
entriescount
)
xml
=
render_title_template
(
'feed.xml'
,
searchterm
=
term
,
entries
=
entries
,
pagination
=
pagination
)
...
...
@@ -625,10 +625,10 @@ def feed_new():
@
requires_basic_auth_if_no_ano
def
feed_discover
():
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
filter
)
.
order_by
(
func
.
random
())
.
limit
(
config
.
config_books_per_page
)
lang_
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
lang_
filter
)
.
order_by
(
func
.
random
())
.
limit
(
config
.
config_books_per_page
)
pagination
=
Pagination
(
1
,
config
.
config_books_per_page
,
int
(
config
.
config_books_per_page
))
xml
=
render_title_template
(
'feed.xml'
,
entries
=
entries
,
pagination
=
pagination
)
response
=
make_response
(
xml
)
...
...
@@ -656,9 +656,9 @@ def feed_hot():
if
not
off
:
off
=
0
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
lang_
filter
=
True
all_books
=
ub
.
session
.
query
(
ub
.
Downloads
,
ub
.
func
.
count
(
ub
.
Downloads
.
book_id
))
.
order_by
(
ub
.
func
.
count
(
ub
.
Downloads
.
book_id
)
.
desc
())
.
group_by
(
ub
.
Downloads
.
book_id
)
hot_books
=
all_books
.
offset
(
off
)
.
limit
(
config
.
config_books_per_page
)
...
...
@@ -667,7 +667,7 @@ def feed_hot():
downloadBook
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
Downloads
.
book_id
)
.
first
()
if
downloadBook
:
entries
.
append
(
db
.
session
.
query
(
db
.
Books
)
.
filter
(
filter
)
.
filter
(
db
.
Books
.
id
==
book
.
Downloads
.
book_id
)
.
first
())
db
.
session
.
query
(
db
.
Books
)
.
filter
(
lang_
filter
)
.
filter
(
db
.
Books
.
id
==
book
.
Downloads
.
book_id
)
.
first
())
else
:
ub
.
session
.
query
(
ub
.
Downloads
)
.
filter
(
book
.
Downloads
.
book_id
==
ub
.
Downloads
.
book_id
)
.
delete
()
ub
.
session
.
commit
()
...
...
@@ -686,10 +686,10 @@ def feed_authorindex():
if
not
off
:
off
=
0
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Authors
)
.
join
(
db
.
books_authors_link
)
.
join
(
db
.
Books
)
.
filter
(
filter
)
\
lang_
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Authors
)
.
join
(
db
.
books_authors_link
)
.
join
(
db
.
Books
)
.
filter
(
lang_
filter
)
\
.
group_by
(
'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
()))
...
...
@@ -699,14 +699,14 @@ def feed_authorindex():
return
response
@
app
.
route
(
"/opds/author/<int:id>"
)
@
app
.
route
(
"/opds/author/<int:
book_
id>"
)
@
requires_basic_auth_if_no_ano
def
feed_author
(
id
):
def
feed_author
(
book_
id
):
off
=
request
.
args
.
get
(
"offset"
)
if
not
off
:
off
=
0
entries
,
random
,
pagination
=
fill_indexpage
((
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
),
db
.
Books
,
db
.
Books
.
authors
.
any
(
db
.
Authors
.
id
==
id
),
db
.
Books
.
timestamp
.
desc
())
db
.
Books
,
db
.
Books
.
authors
.
any
(
db
.
Authors
.
id
==
book_
id
),
db
.
Books
.
timestamp
.
desc
())
xml
=
render_title_template
(
'feed.xml'
,
entries
=
entries
,
pagination
=
pagination
)
response
=
make_response
(
xml
)
response
.
headers
[
"Content-Type"
]
=
"application/xml"
...
...
@@ -720,10 +720,10 @@ def feed_categoryindex():
if
not
off
:
off
=
0
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Tags
)
.
join
(
db
.
books_tags_link
)
.
join
(
db
.
Books
)
.
filter
(
filter
)
.
\
lang_
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Tags
)
.
join
(
db
.
books_tags_link
)
.
join
(
db
.
Books
)
.
filter
(
lang_
filter
)
.
\
group_by
(
'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
()))
...
...
@@ -733,14 +733,14 @@ def feed_categoryindex():
return
response
@
app
.
route
(
"/opds/category/<int:id>"
)
@
app
.
route
(
"/opds/category/<int:
book_
id>"
)
@
requires_basic_auth_if_no_ano
def
feed_category
(
id
):
def
feed_category
(
book_
id
):
off
=
request
.
args
.
get
(
"offset"
)
if
not
off
:
off
=
0
entries
,
random
,
pagination
=
fill_indexpage
((
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
),
db
.
Books
,
db
.
Books
.
tags
.
any
(
db
.
Tags
.
id
==
id
),
db
.
Books
.
timestamp
.
desc
())
db
.
Books
,
db
.
Books
.
tags
.
any
(
db
.
Tags
.
id
==
book_
id
),
db
.
Books
.
timestamp
.
desc
())
xml
=
render_title_template
(
'feed.xml'
,
entries
=
entries
,
pagination
=
pagination
)
response
=
make_response
(
xml
)
response
.
headers
[
"Content-Type"
]
=
"application/xml"
...
...
@@ -754,10 +754,10 @@ def feed_seriesindex():
if
not
off
:
off
=
0
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Series
)
.
join
(
db
.
books_series_link
)
.
join
(
db
.
Books
)
.
filter
(
filter
)
.
\
lang_
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Series
)
.
join
(
db
.
books_series_link
)
.
join
(
db
.
Books
)
.
filter
(
lang_
filter
)
.
\
group_by
(
'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
()))
...
...
@@ -767,14 +767,14 @@ def feed_seriesindex():
return
response
@
app
.
route
(
"/opds/series/<int:id>"
)
@
app
.
route
(
"/opds/series/<int:
book_
id>"
)
@
requires_basic_auth_if_no_ano
def
feed_series
(
id
):
def
feed_series
(
book_
id
):
off
=
request
.
args
.
get
(
"offset"
)
if
not
off
:
off
=
0
entries
,
random
,
pagination
=
fill_indexpage
((
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
),
db
.
Books
,
db
.
Books
.
series
.
any
(
db
.
Series
.
id
==
id
),
db
.
Books
.
series_index
)
db
.
Books
,
db
.
Books
.
series
.
any
(
db
.
Series
.
id
==
book_
id
),
db
.
Books
.
series_index
)
xml
=
render_title_template
(
'feed.xml'
,
entries
=
entries
,
pagination
=
pagination
)
response
=
make_response
(
xml
)
response
.
headers
[
"Content-Type"
]
=
"application/xml"
...
...
@@ -793,8 +793,8 @@ def do_gdrive_download(df, headers):
download_url
=
df
.
metadata
.
get
(
'downloadUrl'
)
s
=
partial
(
total_size
,
1024
*
1024
)
# I'm downloading BIG files, so 100M chunk size is fine for me
def
stream
():
for
byte
s
in
s
:
headers
=
{
"Range"
:
'bytes=
%
s-
%
s'
%
(
byte
s
[
0
],
bytes
[
1
])}
for
byte
in
s
:
headers
=
{
"Range"
:
'bytes=
%
s-
%
s'
%
(
byte
[
0
],
byte
[
1
])}
resp
,
content
=
df
.
auth
.
Get_Http_Object
()
.
request
(
download_url
,
headers
=
headers
)
if
resp
.
status
==
206
:
yield
content
...
...
@@ -803,14 +803,14 @@ def do_gdrive_download(df, headers):
return
return
Response
(
stream_with_context
(
stream
()),
headers
=
headers
)
@
app
.
route
(
"/opds/download/<book_id>/<format>/"
)
@
app
.
route
(
"/opds/download/<book_id>/<
book_
format>/"
)
@
requires_basic_auth_if_no_ano
@
download_required
def
get_opds_download_link
(
book_id
,
format
):
def
get_opds_download_link
(
book_id
,
book_
format
):
startTime
=
time
.
time
()
format
=
format
.
split
(
"."
)[
0
]
book_format
=
book_
format
.
split
(
"."
)[
0
]
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
==
format
.
upper
())
.
first
()
data
=
db
.
session
.
query
(
db
.
Data
)
.
filter
(
db
.
Data
.
book
==
book
.
id
)
.
filter
(
db
.
Data
.
format
==
book_
format
.
upper
())
.
first
()
app
.
logger
.
info
(
data
.
name
)
if
current_user
.
is_authenticated
:
helper
.
update_download
(
book_id
,
int
(
current_user
.
id
))
...
...
@@ -819,15 +819,15 @@ def get_opds_download_link(book_id, format):
file_name
=
book
.
authors
[
0
]
.
name
+
'_'
+
file_name
file_name
=
helper
.
get_valid_filename
(
file_name
)
headers
=
Headers
()
headers
[
"Content-Disposition"
]
=
"attachment; filename*=UTF-8''
%
s.
%
s"
%
(
quote
(
file_name
.
encode
(
'utf8'
)),
format
)
headers
[
"Content-Disposition"
]
=
"attachment; filename*=UTF-8''
%
s.
%
s"
%
(
quote
(
file_name
.
encode
(
'utf8'
)),
book_
format
)
app
.
logger
.
info
(
time
.
time
()
-
startTime
)
startTime
=
time
.
time
()
if
config
.
config_use_google_drive
:
app
.
logger
.
info
(
time
.
time
()
-
startTime
)
df
=
gdriveutils
.
getFileFromEbooksFolder
(
Gdrive
.
Instance
()
.
drive
,
book
.
path
,
data
.
name
+
"."
+
format
)
df
=
gdriveutils
.
getFileFromEbooksFolder
(
Gdrive
.
Instance
()
.
drive
,
book
.
path
,
data
.
name
+
"."
+
book_
format
)
return
do_gdrive_download
(
df
,
headers
)
else
:
response
=
make_response
(
send_from_directory
(
os
.
path
.
join
(
config
.
config_calibre_dir
,
book
.
path
),
data
.
name
+
"."
+
format
))
response
=
make_response
(
send_from_directory
(
os
.
path
.
join
(
config
.
config_calibre_dir
,
book
.
path
),
data
.
name
+
"."
+
book_
format
))
response
.
headers
=
headers
return
response
...
...
@@ -984,11 +984,11 @@ def index(page):
@
login_required_if_no_ano
def
hot_books
(
page
):
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
lang_
filter
=
True
if
current_user
.
show_detail_random
():
random
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
filter
)
.
order_by
(
func
.
random
())
.
limit
(
config
.
config_random_books
)
random
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
lang_
filter
)
.
order_by
(
func
.
random
())
.
limit
(
config
.
config_random_books
)
else
:
random
=
false
off
=
int
(
int
(
config
.
config_books_per_page
)
*
(
page
-
1
))
...
...
@@ -1000,7 +1000,7 @@ def hot_books(page):
downloadBook
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
Downloads
.
book_id
)
.
first
()
if
downloadBook
:
entries
.
append
(
db
.
session
.
query
(
db
.
Books
)
.
filter
(
filter
)
.
filter
(
db
.
Books
.
id
==
book
.
Downloads
.
book_id
)
.
first
())
db
.
session
.
query
(
db
.
Books
)
.
filter
(
lang_
filter
)
.
filter
(
db
.
Books
.
id
==
book
.
Downloads
.
book_id
)
.
first
())
else
:
ub
.
session
.
query
(
ub
.
Downloads
)
.
filter
(
book
.
Downloads
.
book_id
==
ub
.
Downloads
.
book_id
)
.
delete
()
ub
.
session
.
commit
()
...
...
@@ -1033,22 +1033,22 @@ def discover(page):
@
login_required_if_no_ano
def
author_list
():
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
lang_
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Authors
,
func
.
count
(
'books_authors_link.book'
)
.
label
(
'count'
))
.
join
(
db
.
books_authors_link
)
.
join
(
db
.
Books
)
.
filter
(
filter
)
.
group_by
(
'books_authors_link.author'
)
.
order_by
(
db
.
Authors
.
sort
)
.
all
()
lang_
filter
)
.
group_by
(
'books_authors_link.author'
)
.
order_by
(
db
.
Authors
.
sort
)
.
all
()
return
render_title_template
(
'list.html'
,
entries
=
entries
,
folder
=
'author'
,
title
=
_
(
u"Author list"
))
@
app
.
route
(
"/author/<int:id>"
,
defaults
=
{
'page'
:
1
})
@
app
.
route
(
"/author/<int:id>/<int:page>'"
)
@
app
.
route
(
"/author/<int:
book_
id>"
,
defaults
=
{
'page'
:
1
})
@
app
.
route
(
"/author/<int:
book_
id>/<int:page>'"
)
@
login_required_if_no_ano
def
author
(
id
,
page
):
entries
,
random
,
pagination
=
fill_indexpage
(
page
,
db
.
Books
,
db
.
Books
.
authors
.
any
(
db
.
Authors
.
id
==
id
),
def
author
(
book_
id
,
page
):
entries
,
random
,
pagination
=
fill_indexpage
(
page
,
db
.
Books
,
db
.
Books
.
authors
.
any
(
db
.
Authors
.
id
==
book_
id
),
db
.
Books
.
timestamp
.
desc
())
name
=
db
.
session
.
query
(
db
.
Authors
)
.
filter
(
db
.
Authors
.
id
==
id
)
.
first
()
.
name
name
=
db
.
session
.
query
(
db
.
Authors
)
.
filter
(
db
.
Authors
.
id
==
book_
id
)
.
first
()
.
name
if
entries
:
return
render_title_template
(
'index.html'
,
random
=
random
,
entries
=
entries
,
title
=
_
(
u"Author:
%(name)
s"
,
name
=
name
))
else
:
...
...
@@ -1060,22 +1060,22 @@ def author(id,page):
@
login_required_if_no_ano
def
series_list
():
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
lang_
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Series
,
func
.
count
(
'books_series_link.book'
)
.
label
(
'count'
))
.
join
(
db
.
books_series_link
)
.
join
(
db
.
Books
)
.
filter
(
filter
)
.
group_by
(
'books_series_link.series'
)
.
order_by
(
db
.
Series
.
sort
)
.
all
()
lang_
filter
)
.
group_by
(
'books_series_link.series'
)
.
order_by
(
db
.
Series
.
sort
)
.
all
()
return
render_title_template
(
'list.html'
,
entries
=
entries
,
folder
=
'series'
,
title
=
_
(
u"Series list"
))
@
app
.
route
(
"/series/<int:id>/"
,
defaults
=
{
'page'
:
1
})
@
app
.
route
(
"/series/<int:id>/<int:page>'"
)
@
app
.
route
(
"/series/<int:
book_
id>/"
,
defaults
=
{
'page'
:
1
})
@
app
.
route
(
"/series/<int:
book_
id>/<int:page>'"
)
@
login_required_if_no_ano
def
series
(
id
,
page
):
entries
,
random
,
pagination
=
fill_indexpage
(
page
,
db
.
Books
,
db
.
Books
.
series
.
any
(
db
.
Series
.
id
==
id
),
def
series
(
book_
id
,
page
):
entries
,
random
,
pagination
=
fill_indexpage
(
page
,
db
.
Books
,
db
.
Books
.
series
.
any
(
db
.
Series
.
id
==
book_
id
),
db
.
Books
.
series_index
)
name
=
db
.
session
.
query
(
db
.
Series
)
.
filter
(
db
.
Series
.
id
==
id
)
.
first
()
.
name
name
=
db
.
session
.
query
(
db
.
Series
)
.
filter
(
db
.
Series
.
id
==
book_
id
)
.
first
()
.
name
if
entries
:
return
render_title_template
(
'index.html'
,
random
=
random
,
pagination
=
pagination
,
entries
=
entries
,
title
=
_
(
u"Series:
%(serie)
s"
,
serie
=
name
))
...
...
@@ -1133,52 +1133,52 @@ def language(name, page):
@
login_required_if_no_ano
def
category_list
():
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
lang_
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Tags
,
func
.
count
(
'books_tags_link.book'
)
.
label
(
'count'
))
.
join
(
db
.
books_tags_link
)
.
join
(
db
.
Books
)
.
filter
(
filter
)
.
group_by
(
'books_tags_link.tag'
)
.
all
()
lang_
filter
)
.
group_by
(
'books_tags_link.tag'
)
.
all
()
return
render_title_template
(
'list.html'
,
entries
=
entries
,
folder
=
'category'
,
title
=
_
(
u"Category list"
))
@
app
.
route
(
"/category/<int:id>"
,
defaults
=
{
'page'
:
1
})
@
app
.
route
(
'/category/<int:id>/<int:page>'
)
@
app
.
route
(
"/category/<int:
book_
id>"
,
defaults
=
{
'page'
:
1
})
@
app
.
route
(
'/category/<int:
book_
id>/<int:page>'
)
@
login_required_if_no_ano
def
category
(
id
,
page
):
entries
,
random
,
pagination
=
fill_indexpage
(
page
,
db
.
Books
,
db
.
Books
.
tags
.
any
(
db
.
Tags
.
id
==
id
),
def
category
(
book_
id
,
page
):
entries
,
random
,
pagination
=
fill_indexpage
(
page
,
db
.
Books
,
db
.
Books
.
tags
.
any
(
db
.
Tags
.
id
==
book_
id
),
db
.
Books
.
timestamp
.
desc
())
name
=
db
.
session
.
query
(
db
.
Tags
)
.
filter
(
db
.
Tags
.
id
==
id
)
.
first
()
.
name
name
=
db
.
session
.
query
(
db
.
Tags
)
.
filter
(
db
.
Tags
.
id
==
book_
id
)
.
first
()
.
name
return
render_title_template
(
'index.html'
,
random
=
random
,
entries
=
entries
,
pagination
=
pagination
,
title
=
_
(
u"Category:
%(name)
s"
,
name
=
name
))
@
app
.
route
(
"/ajax/toggleread/<int:id>"
,
methods
=
[
'POST'
])
@
app
.
route
(
"/ajax/toggleread/<int:
book_
id>"
,
methods
=
[
'POST'
])
@
login_required
def
toggle_read
(
id
):
def
toggle_read
(
book_
id
):
book
=
ub
.
session
.
query
(
ub
.
ReadBook
)
.
filter
(
ub
.
and_
(
ub
.
ReadBook
.
user_id
==
int
(
current_user
.
id
),
ub
.
ReadBook
.
book_id
==
id
))
.
first
()
ub
.
ReadBook
.
book_id
==
book_
id
))
.
first
()
if
book
:
book
.
is_read
=
not
book
.
is_read
else
:
readBook
=
ub
.
ReadBook
()
readBook
.
user_id
=
int
(
current_user
.
id
)
readBook
.
book_id
=
id
readBook
.
book_id
=
book_
id
readBook
.
is_read
=
True
book
=
readBook
ub
.
session
.
merge
(
book
)
ub
.
session
.
commit
()
return
""
@
app
.
route
(
"/book/<int:id>"
)
@
app
.
route
(
"/book/<int:
book_
id>"
)
@
login_required_if_no_ano
def
show_book
(
id
):
def
show_book
(
book_
id
):
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
id
)
.
filter
(
filter
)
.
first
()
lang_
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
lang_
filter
)
.
first
()
if
entries
:
for
index
in
range
(
0
,
len
(
entries
.
languages
)):
try
:
...
...
@@ -1198,7 +1198,7 @@ def show_book(id):
else
:
cc
=
tmpcc
book_in_shelfs
=
[]
shelfs
=
ub
.
session
.
query
(
ub
.
BookShelf
)
.
filter
(
ub
.
BookShelf
.
book_id
==
id
)
.
all
()
shelfs
=
ub
.
session
.
query
(
ub
.
BookShelf
)
.
filter
(
ub
.
BookShelf
.
book_id
==
book_
id
)
.
all
()
for
entry
in
shelfs
:
book_in_shelfs
.
append
(
entry
.
shelf
)
...
...
@@ -1206,7 +1206,7 @@ def show_book(id):
# title=entries.title, books_shelfs=book_in_shelfs)
if
not
current_user
.
is_anonymous
():
matching_have_read_book
=
ub
.
session
.
query
(
ub
.
ReadBook
)
.
filter
(
ub
.
and_
(
ub
.
ReadBook
.
user_id
==
int
(
current_user
.
id
),
ub
.
ReadBook
.
book_id
==
id
))
.
all
()
ub
.
ReadBook
.
book_id
==
book_
id
))
.
all
()
have_read
=
len
(
matching_have_read_book
)
>
0
and
matching_have_read_book
[
0
]
.
is_read
else
:
have_read
=
None
...
...
@@ -1337,13 +1337,13 @@ def on_received_watch_confirmation():
if
not
response
[
'deleted'
]
and
response
[
'file'
][
'title'
]
==
'metadata.db'
and
response
[
'file'
][
'md5Checksum'
]
!=
md5
(
dbpath
):
tmpDir
=
tempfile
.
gettempdir
()
app
.
logger
.
info
(
'Database file updated'
)
copyfile
(
dbpath
,
tmpDir
+
"/metadata.db_"
+
str
(
current_milli_time
(
)))
copyfile
(
dbpath
,
os
.
path
.
join
(
tmpDir
,
"metadata.db_"
+
str
(
current_milli_time
()
)))
app
.
logger
.
info
(
'Backing up existing and downloading updated metadata.db'
)
gdriveutils
.
downloadFile
(
Gdrive
.
Instance
()
.
drive
,
None
,
"metadata.db"
,
tmpDir
+
"/tmp_metadata.db"
)
gdriveutils
.
downloadFile
(
Gdrive
.
Instance
()
.
drive
,
None
,
"metadata.db"
,
os
.
path
.
join
(
tmpDir
,
"tmp_metadata.db"
)
)
app
.
logger
.
info
(
'Setting up new DB'
)
os
.
rename
(
tmpDir
+
"/tmp_metadata.db"
,
dbpath
)
os
.
rename
(
os
.
path
.
join
(
tmpDir
,
"tmp_metadata.db"
)
,
dbpath
)
db
.
setup_db
()
except
Exception
,
e
:
except
Exception
as
e
:
app
.
logger
.
exception
(
e
)
updateMetaData
()
...
...
@@ -1395,14 +1395,14 @@ def search():
term
=
request
.
args
.
get
(
"query"
)
.
strip
()
if
term
:
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
lang_
filter
=
True
entries
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
or_
(
db
.
Books
.
tags
.
any
(
db
.
Tags
.
name
.
like
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
series
.
any
(
db
.
Series
.
name
.
like
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
authors
.
any
(
db
.
Authors
.
name
.
like
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
publishers
.
any
(
db
.
Publishers
.
name
.
like
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
title
.
like
(
"
%
"
+
term
+
"
%
"
)))
.
filter
(
filter
)
.
all
()
db
.
Books
.
title
.
like
(
"
%
"
+
term
+
"
%
"
)))
.
filter
(
lang_
filter
)
.
all
()
return
render_title_template
(
'search.html'
,
searchterm
=
term
,
entries
=
entries
)
else
:
return
render_title_template
(
'search.html'
,
searchterm
=
""
)
...
...
@@ -1563,15 +1563,15 @@ def feed_unread_books():
def
unread_books
(
page
):
return
render_read_books
(
page
,
False
)
@
app
.
route
(
"/read/<int:book_id>/<format>"
)
@
app
.
route
(
"/read/<int:book_id>/<
book_
format>"
)
@
login_required_if_no_ano
def
read_book
(
book_id
,
format
):
def
read_book
(
book_id
,
book_
format
):
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
first
()
if
book
:
book_dir
=
os
.
path
.
join
(
config
.
get_main_dir
,
"cps"
,
"static"
,
str
(
book_id
))
if
not
os
.
path
.
exists
(
book_dir
):
os
.
mkdir
(
book_dir
)
if
format
.
lower
()
==
"epub"
:
if
book_
format
.
lower
()
==
"epub"
:
# check if mimetype file is exists
mime_file
=
str
(
book_id
)
+
"/mimetype"
if
not
os
.
path
.
exists
(
mime_file
):
...
...
@@ -1586,9 +1586,7 @@ def read_book(book_id, format):
try
:
os
.
makedirs
(
newDir
)
except
OSError
as
exception
:
if
exception
.
errno
==
errno
.
EEXIST
:
pass
else
:
if
not
exception
.
errno
==
errno
.
EEXIST
:
raise
if
fileName
:
fd
=
open
(
os
.
path
.
join
(
newDir
,
fileName
),
"wb"
)
...
...
@@ -1596,21 +1594,21 @@ def read_book(book_id, format):
fd
.
close
()
zfile
.
close
()
return
render_title_template
(
'read.html'
,
bookid
=
book_id
,
title
=
_
(
u"Read a Book"
))
elif
format
.
lower
()
==
"pdf"
:
elif
book_
format
.
lower
()
==
"pdf"
:
all_name
=
str
(
book_id
)
+
"/"
+
book
.
data
[
0
]
.
name
+
".pdf"
tmp_file
=
os
.
path
.
join
(
book_dir
,
book
.
data
[
0
]
.
name
)
+
".pdf"
if
not
os
.
path
.
exists
(
tmp_file
):
pdf_file
=
os
.
path
.
join
(
config
.
config_calibre_dir
,
book
.
path
,
book
.
data
[
0
]
.
name
)
+
".pdf"
copyfile
(
pdf_file
,
tmp_file
)
return
render_title_template
(
'readpdf.html'
,
pdffile
=
all_name
,
title
=
_
(
u"Read a Book"
))
elif
format
.
lower
()
==
"txt"
:
elif
book_
format
.
lower
()
==
"txt"
:
all_name
=
str
(
book_id
)
+
"/"
+
book
.
data
[
0
]
.
name
+
".txt"
tmp_file
=
os
.
path
.
join
(
book_dir
,
book
.
data
[
0
]
.
name
)
+
".txt"
if
not
os
.
path
.
exists
(
all_name
):
txt_file
=
os
.
path
.
join
(
config
.
config_calibre_dir
,
book
.
path
,
book
.
data
[
0
]
.
name
)
+
".txt"
copyfile
(
txt_file
,
tmp_file
)
return
render_title_template
(
'readtxt.html'
,
txtfile
=
all_name
,
title
=
_
(
u"Read a Book"
))
elif
format
.
lower
()
==
"cbr"
:
elif
book_
format
.
lower
()
==
"cbr"
:
all_name
=
str
(
book_id
)
+
"/"
+
book
.
data
[
0
]
.
name
+
".cbr"
tmp_file
=
os
.
path
.
join
(
book_dir
,
book
.
data
[
0
]
.
name
)
+
".cbr"
if
not
os
.
path
.
exists
(
all_name
):
...
...
@@ -1622,13 +1620,13 @@ def read_book(book_id, format):
flash
(
_
(
u"Error opening eBook. File does not exist or file is not accessible:"
),
category
=
"error"
)
return
redirect
(
url_for
(
"index"
))
@
app
.
route
(
"/download/<int:book_id>/<format>"
)
@
app
.
route
(
"/download/<int:book_id>/<
book_
format>"
)
@
login_required_if_no_ano
@
download_required
def
get_download_link
(
book_id
,
format
):
format
=
format
.
split
(
"."
)[
0
]
def
get_download_link
(
book_id
,
book_
format
):
book_format
=
book_
format
.
split
(
"."
)[
0
]
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
==
format
.
upper
())
.
first
()
data
=
db
.
session
.
query
(
db
.
Data
)
.
filter
(
db
.
Data
.
book
==
book
.
id
)
.
filter
(
db
.
Data
.
format
==
book_
format
.
upper
())
.
first
()
if
data
:
# collect downloaded books only for registered user and not for anonymous user
if
current_user
.
is_authenticated
:
...
...
@@ -1639,25 +1637,25 @@ def get_download_link(book_id, format):
file_name
=
helper
.
get_valid_filename
(
file_name
)
headers
=
Headers
()
try
:
headers
[
"Content-Type"
]
=
mimetypes
.
types_map
[
'.'
+
format
]
except
:
pass
headers
[
"Content-Disposition"
]
=
"attachment; filename*=UTF-8''
%
s.
%
s"
%
(
quote
(
file_name
.
encode
(
'utf-8'
)),
format
)
headers
[
"Content-Type"
]
=
mimetypes
.
types_map
[
'.'
+
book_
format
]
except
KeyError
:
headers
[
"Content-Type"
]
=
"application/octet-stream"
headers
[
"Content-Disposition"
]
=
"attachment; filename*=UTF-8''
%
s.
%
s"
%
(
quote
(
file_name
.
encode
(
'utf-8'
)),
book_
format
)
if
config
.
config_use_google_drive
:
df
=
gdriveutils
.
getFileFromEbooksFolder
(
Gdrive
.
Instance
()
.
drive
,
book
.
path
,
'
%
s.
%
s'
%
(
data
.
name
,
format
))
df
=
gdriveutils
.
getFileFromEbooksFolder
(
Gdrive
.
Instance
()
.
drive
,
book
.
path
,
'
%
s.
%
s'
%
(
data
.
name
,
book_
format
))
return
do_gdrive_download
(
df
,
headers
)
else
:
response
=
make_response
(
send_from_directory
(
os
.
path
.
join
(
config
.
config_calibre_dir
,
book
.
path
),
data
.
name
+
"."
+
format
))
response
=
make_response
(
send_from_directory
(
os
.
path
.
join
(
config
.
config_calibre_dir
,
book
.
path
),
data
.
name
+
"."
+
book_
format
))
response
.
headers
=
headers
return
response
else
:
abort
(
404
)
@
app
.
route
(
"/download/<int:book_id>/<format>/<anyname>"
)
@
app
.
route
(
"/download/<int:book_id>/<
book_
format>/<anyname>"
)
@
login_required_if_no_ano
@
download_required
def
get_download_link_ext
(
book_id
,
format
,
anyname
):
return
get_download_link
(
book_id
,
format
)
def
get_download_link_ext
(
book_id
,
book_
format
,
anyname
):
return
get_download_link
(
book_id
,
book_
format
)
@
app
.
route
(
'/register'
,
methods
=
[
'GET'
,
'POST'
])
def
register
():
...
...
@@ -2370,10 +2368,10 @@ def edit_book(book_id):
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"title_sort"
,
1
,
db
.
title_sort
)
cc
=
db
.
session
.
query
(
db
.
Custom_Columns
)
.
filter
(
db
.
Custom_Columns
.
datatype
.
notin_
(
db
.
cc_exceptions
))
.
all
()
if
current_user
.
filter_language
()
!=
"all"
:
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
lang_
filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
filter
=
True
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
filter
)
.
first
()
lang_
filter
=
True
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
lang_
filter
)
.
first
()
author_names
=
[]
if
book
:
for
index
in
range
(
0
,
len
(
book
.
languages
)):
...
...
@@ -2575,7 +2573,7 @@ def edit_book(book_id):
if
config
.
config_use_google_drive
:
updateGdriveCalibreFromLocal
()
if
"detail_view"
in
to_save
:
return
redirect
(
url_for
(
'show_book'
,
id
=
book
.
id
))
return
redirect
(
url_for
(
'show_book'
,
book_
id
=
book
.
id
))
else
:
return
render_title_template
(
'book_edit.html'
,
book
=
book
,
authors
=
author_names
,
cc
=
cc
,
title
=
_
(
u"edit metadata"
))
...
...
@@ -2597,9 +2595,9 @@ def upload():
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"title_sort"
,
1
,
db
.
title_sort
)
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
'uuid4'
,
0
,
lambda
:
str
(
uuid4
()))
if
request
.
method
==
'POST'
and
'btn-upload'
in
request
.
files
:
file
=
request
.
files
[
'btn-upload'
]
if
'.'
in
file
.
filename
:
file_ext
=
file
.
filename
.
rsplit
(
'.'
,
1
)[
-
1
]
.
lower
()
requested_
file
=
request
.
files
[
'btn-upload'
]
if
'.'
in
requested_
file
.
filename
:
file_ext
=
requested_
file
.
filename
.
rsplit
(
'.'
,
1
)[
-
1
]
.
lower
()
if
file_ext
not
in
ALLOWED_EXTENSIONS
:
flash
(
_
(
'File extension "
%
s" is not allowed to be uploaded to this server'
%
...
...
@@ -2610,7 +2608,7 @@ def upload():
else
:
flash
(
_
(
'File to be uploaded must have an extension'
),
category
=
"error"
)
return
redirect
(
url_for
(
'index'
))
meta
=
uploader
.
upload
(
file
)
meta
=
uploader
.
upload
(
requested_
file
)
title
=
meta
.
title
author
=
meta
.
author
...
...
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