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
1b363ac7
Commit
1b363ac7
authored
Sep 30, 2018
by
bodybybuddha
Browse files
Options
Browse Files
Download
Plain Diff
Merged master into 617 - fixed import copy conflict
parents
9b1954f2
5a2ed58d
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
235 additions
and
192 deletions
+235
-192
book_formats.py
cps/book_formats.py
+4
-2
converter.py
cps/converter.py
+1
-1
gdriveutils.py
cps/gdriveutils.py
+11
-16
reverseproxy.py
cps/reverseproxy.py
+39
-0
server.py
cps/server.py
+4
-5
messages.po
cps/translations/de/LC_MESSAGES/messages.po
+1
-1
web.py
cps/web.py
+175
-167
No files found.
cps/book_formats.py
View file @
1b363ac7
...
@@ -123,9 +123,11 @@ def pdf_preview(tmp_file_path, tmp_dir):
...
@@ -123,9 +123,11 @@ def pdf_preview(tmp_file_path, tmp_dir):
def
get_versions
():
def
get_versions
():
if
not
use_generic_pdf_cover
:
if
not
use_generic_pdf_cover
:
IVersion
=
ImageVersion
.
MAGICK_VERSION
IVersion
=
ImageVersion
.
MAGICK_VERSION
WVersion
=
ImageVersion
.
VERSION
else
:
else
:
IVersion
=
_
(
u'not installed'
)
IVersion
=
_
(
u'not installed'
)
WVersion
=
_
(
u'not installed'
)
if
use_pdf_meta
:
if
use_pdf_meta
:
PVersion
=
'v'
+
PyPdfVersion
PVersion
=
'v'
+
PyPdfVersion
else
:
else
:
...
@@ -134,4 +136,4 @@ def get_versions():
...
@@ -134,4 +136,4 @@ def get_versions():
XVersion
=
'v'
+
'.'
.
join
(
map
(
str
,
lxmlversion
))
XVersion
=
'v'
+
'.'
.
join
(
map
(
str
,
lxmlversion
))
else
:
else
:
XVersion
=
_
(
u'not installed'
)
XVersion
=
_
(
u'not installed'
)
return
{
'Image Magick'
:
IVersion
,
'PyPdf'
:
PVersion
,
'lxml'
:
XVersion
}
return
{
'Image Magick'
:
IVersion
,
'PyPdf'
:
PVersion
,
'lxml'
:
XVersion
,
'Wand Version'
:
WVersion
}
cps/converter.py
View file @
1b363ac7
...
@@ -45,5 +45,5 @@ def versioncheck():
...
@@ -45,5 +45,5 @@ def versioncheck():
elif
ub
.
config
.
config_ebookconverter
==
2
:
elif
ub
.
config
.
config_ebookconverter
==
2
:
return
versionCalibre
()
return
versionCalibre
()
else
:
else
:
return
{
'ebook_converter'
:
''
}
return
{
'ebook_converter'
:
_
(
u'not configured'
)
}
cps/gdriveutils.py
View file @
1b363ac7
...
@@ -149,19 +149,19 @@ def getDrive(drive=None, gauth=None):
...
@@ -149,19 +149,19 @@ def getDrive(drive=None, gauth=None):
drive
.
auth
.
Refresh
()
drive
.
auth
.
Refresh
()
return
drive
return
drive
def
listRootFolders
(
drive
=
None
):
def
listRootFolders
():
drive
=
getDrive
(
drive
)
drive
=
getDrive
(
Gdrive
.
Instance
()
.
drive
)
folder
=
"'root' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false"
folder
=
"'root' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false"
fileList
=
drive
.
ListFile
({
'q'
:
folder
})
.
GetList
()
fileList
=
drive
.
ListFile
({
'q'
:
folder
})
.
GetList
()
return
fileList
return
fileList
def
getEbooksFolder
(
drive
=
None
):
def
getEbooksFolder
(
drive
):
return
getFolderInFolder
(
'root'
,
config
.
config_google_drive_folder
,
drive
)
return
getFolderInFolder
(
'root'
,
config
.
config_google_drive_folder
,
drive
)
def
getFolderInFolder
(
parentId
,
folderName
,
drive
=
Non
e
):
def
getFolderInFolder
(
parentId
,
folderName
,
driv
e
):
drive
=
getDrive
(
drive
)
#
drive = getDrive(drive)
query
=
""
query
=
""
if
folderName
:
if
folderName
:
query
=
"title = '
%
s' and "
%
folderName
.
replace
(
"'"
,
"
\\
'"
)
query
=
"title = '
%
s' and "
%
folderName
.
replace
(
"'"
,
"
\\
'"
)
...
@@ -190,7 +190,6 @@ def getEbooksFolderId(drive=None):
...
@@ -190,7 +190,6 @@ def getEbooksFolderId(drive=None):
def
getFile
(
pathId
,
fileName
,
drive
):
def
getFile
(
pathId
,
fileName
,
drive
):
# drive = getDrive(Gdrive.Instance().drive)
metaDataFile
=
"'
%
s' in parents and trashed = false and title = '
%
s'"
%
(
pathId
,
fileName
.
replace
(
"'"
,
"
\\
'"
))
metaDataFile
=
"'
%
s' in parents and trashed = false and title = '
%
s'"
%
(
pathId
,
fileName
.
replace
(
"'"
,
"
\\
'"
))
fileList
=
drive
.
ListFile
({
'q'
:
metaDataFile
})
.
GetList
()
fileList
=
drive
.
ListFile
({
'q'
:
metaDataFile
})
.
GetList
()
...
@@ -200,8 +199,8 @@ def getFile(pathId, fileName, drive):
...
@@ -200,8 +199,8 @@ def getFile(pathId, fileName, drive):
return
fileList
[
0
]
return
fileList
[
0
]
def
getFolderId
(
path
,
drive
=
None
):
def
getFolderId
(
path
,
drive
):
drive
=
getDrive
(
drive
)
#
drive = getDrive(drive)
currentFolderId
=
getEbooksFolderId
(
drive
)
currentFolderId
=
getEbooksFolderId
(
drive
)
sqlCheckPath
=
path
if
path
[
-
1
]
==
'/'
else
path
+
'/'
sqlCheckPath
=
path
if
path
[
-
1
]
==
'/'
else
path
+
'/'
storedPathName
=
session
.
query
(
GdriveId
)
.
filter
(
GdriveId
.
path
==
sqlCheckPath
)
.
first
()
storedPathName
=
session
.
query
(
GdriveId
)
.
filter
(
GdriveId
.
path
==
sqlCheckPath
)
.
first
()
...
@@ -249,7 +248,7 @@ def getFileFromEbooksFolder(path, fileName):
...
@@ -249,7 +248,7 @@ def getFileFromEbooksFolder(path, fileName):
return
None
return
None
def
copyDriveFileRemote
(
drive
,
origin_file_id
,
copy_title
):
'''
def copyDriveFileRemote(drive, origin_file_id, copy_title):
drive = getDrive(drive)
drive = getDrive(drive)
copied_file = {'title': copy_title}
copied_file = {'title': copy_title}
try:
try:
...
@@ -258,7 +257,7 @@ def copyDriveFileRemote(drive, origin_file_id, copy_title):
...
@@ -258,7 +257,7 @@ def copyDriveFileRemote(drive, origin_file_id, copy_title):
return drive.CreateFile({'id': file_data['id']})
return drive.CreateFile({'id': file_data['id']})
except errors.HttpError as error:
except errors.HttpError as error:
print ('An error occurred:
%
s'
%
error)
print ('An error occurred:
%
s'
%
error)
return
None
return None
'''
# Download metadata.db from gdrive
# Download metadata.db from gdrive
...
@@ -347,7 +346,6 @@ def uploadFileToEbooksFolder(destFile, f):
...
@@ -347,7 +346,6 @@ def uploadFileToEbooksFolder(destFile, f):
def
watchChange
(
drive
,
channel_id
,
channel_type
,
channel_address
,
def
watchChange
(
drive
,
channel_id
,
channel_type
,
channel_address
,
channel_token
=
None
,
expiration
=
None
):
channel_token
=
None
,
expiration
=
None
):
# drive = getDrive(drive)
# Watch for all changes to a user's Drive.
# Watch for all changes to a user's Drive.
# Args:
# Args:
# service: Drive API service instance.
# service: Drive API service instance.
...
@@ -390,8 +388,6 @@ def watchFile(drive, file_id, channel_id, channel_type, channel_address,
...
@@ -390,8 +388,6 @@ def watchFile(drive, file_id, channel_id, channel_type, channel_address,
Raises:
Raises:
apiclient.errors.HttpError: if http request to create channel fails.
apiclient.errors.HttpError: if http request to create channel fails.
"""
"""
# drive = getDrive(drive)
body
=
{
body
=
{
'id'
:
channel_id
,
'id'
:
channel_id
,
'type'
:
channel_type
,
'type'
:
channel_type
,
...
@@ -413,8 +409,6 @@ def stopChannel(drive, channel_id, resource_id):
...
@@ -413,8 +409,6 @@ def stopChannel(drive, channel_id, resource_id):
Raises:
Raises:
apiclient.errors.HttpError: if http request to create channel fails.
apiclient.errors.HttpError: if http request to create channel fails.
"""
"""
# drive = getDrive(drive)
# service=drive.auth.service
body
=
{
body
=
{
'id'
:
channel_id
,
'id'
:
channel_id
,
'resourceId'
:
resource_id
'resourceId'
:
resource_id
...
@@ -423,7 +417,6 @@ def stopChannel(drive, channel_id, resource_id):
...
@@ -423,7 +417,6 @@ def stopChannel(drive, channel_id, resource_id):
def
getChangeById
(
drive
,
change_id
):
def
getChangeById
(
drive
,
change_id
):
# drive = getDrive(drive)
# Print a single Change resource information.
# Print a single Change resource information.
#
#
# Args:
# Args:
...
@@ -454,11 +447,13 @@ def updateDatabaseOnEdit(ID,newPath):
...
@@ -454,11 +447,13 @@ def updateDatabaseOnEdit(ID,newPath):
storedPathName
.
path
=
newPath
storedPathName
.
path
=
newPath
session
.
commit
()
session
.
commit
()
# Deletes the hashes in database of deleted book
# Deletes the hashes in database of deleted book
def
deleteDatabaseEntry
(
ID
):
def
deleteDatabaseEntry
(
ID
):
session
.
query
(
GdriveId
)
.
filter
(
GdriveId
.
gdrive_id
==
ID
)
.
delete
()
session
.
query
(
GdriveId
)
.
filter
(
GdriveId
.
gdrive_id
==
ID
)
.
delete
()
session
.
commit
()
session
.
commit
()
# Gets cover file from gdrive
# Gets cover file from gdrive
def
get_cover_via_gdrive
(
cover_path
):
def
get_cover_via_gdrive
(
cover_path
):
df
=
getFileFromEbooksFolder
(
cover_path
,
'cover.jpg'
)
df
=
getFileFromEbooksFolder
(
cover_path
,
'cover.jpg'
)
...
...
cps/reverseproxy.py
0 → 100644
View file @
1b363ac7
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class
ReverseProxied
(
object
):
"""Wrap the application in this middleware and configure the
front-end server to add these headers, to let you quietly bind
this to a URL other than / and to an HTTP scheme that is
different than what is used locally.
Code courtesy of: http://flask.pocoo.org/snippets/35/
In nginx:
location /myprefix {
proxy_pass http://127.0.0.1:8083;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name /myprefix;
}
"""
def
__init__
(
self
,
application
):
self
.
app
=
application
def
__call__
(
self
,
environ
,
start_response
):
script_name
=
environ
.
get
(
'HTTP_X_SCRIPT_NAME'
,
''
)
if
script_name
:
environ
[
'SCRIPT_NAME'
]
=
script_name
path_info
=
environ
.
get
(
'PATH_INFO'
,
''
)
if
path_info
and
path_info
.
startswith
(
script_name
):
environ
[
'PATH_INFO'
]
=
path_info
[
len
(
script_name
):]
scheme
=
environ
.
get
(
'HTTP_X_SCHEME'
,
''
)
if
scheme
:
environ
[
'wsgi.url_scheme'
]
=
scheme
servr
=
environ
.
get
(
'HTTP_X_FORWARDED_SERVER'
,
''
)
if
servr
:
environ
[
'HTTP_HOST'
]
=
servr
return
self
.
app
(
environ
,
start_response
)
cps/server.py
View file @
1b363ac7
#!/usr/bin/env python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from
socket
import
error
as
SocketError
from
socket
import
error
as
SocketError
import
sys
import
sys
import
os
import
os
import
signal
import
signal
import
web
try
:
try
:
from
gevent.pywsgi
import
WSGIServer
from
gevent.pywsgi
import
WSGIServer
...
@@ -19,8 +19,6 @@ except ImportError:
...
@@ -19,8 +19,6 @@ except ImportError:
from
tornado
import
version
as
tornadoVersion
from
tornado
import
version
as
tornadoVersion
gevent_present
=
False
gevent_present
=
False
import
web
class
server
:
class
server
:
...
@@ -29,7 +27,7 @@ class server:
...
@@ -29,7 +27,7 @@ class server:
def
__init__
(
self
):
def
__init__
(
self
):
signal
.
signal
(
signal
.
SIGINT
,
self
.
killServer
)
signal
.
signal
(
signal
.
SIGINT
,
self
.
killServer
)
signal
.
signal
(
signal
.
SIGTERM
,
self
.
killServer
)
signal
.
signal
(
signal
.
SIGTERM
,
self
.
killServer
)
def
start_gevent
(
self
):
def
start_gevent
(
self
):
try
:
try
:
...
@@ -68,7 +66,8 @@ class server:
...
@@ -68,7 +66,8 @@ class server:
ssl_options
=
ssl
)
ssl_options
=
ssl
)
http_server
.
listen
(
web
.
ub
.
config
.
config_port
)
http_server
.
listen
(
web
.
ub
.
config
.
config_port
)
self
.
wsgiserver
=
IOLoop
.
instance
()
self
.
wsgiserver
=
IOLoop
.
instance
()
self
.
wsgiserver
.
start
()
# wait for stop signal
self
.
wsgiserver
.
start
()
# wait for stop signal
self
.
wsgiserver
.
close
(
True
)
self
.
wsgiserver
.
close
(
True
)
if
self
.
restart
==
True
:
if
self
.
restart
==
True
:
...
...
cps/translations/de/LC_MESSAGES/messages.po
View file @
1b363ac7
...
@@ -1173,7 +1173,7 @@ msgstr "Pfad zu Konvertertool"
...
@@ -1173,7 +1173,7 @@ msgstr "Pfad zu Konvertertool"
#: cps/templates/config_edit.html:199
#: cps/templates/config_edit.html:199
msgid "Location of Unrar binary"
msgid "Location of Unrar binary"
msgstr "
O
fad zum UnRar Programm"
msgstr "
P
fad zum UnRar Programm"
#: cps/templates/config_edit.html:215 cps/templates/layout.html:82
#: cps/templates/config_edit.html:215 cps/templates/layout.html:82
#: cps/templates/login.html:4
#: cps/templates/login.html:4
...
...
cps/web.py
View file @
1b363ac7
#!/usr/bin/env python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
try
:
from
googleapiclient.errors
import
HttpError
except
ImportError
:
pass
try
:
from
goodreads.client
import
GoodreadsClient
goodreads_support
=
True
except
ImportError
:
goodreads_support
=
False
try
:
import
Levenshtein
levenshtein_support
=
True
except
ImportError
:
levenshtein_support
=
False
try
:
from
functools
import
reduce
except
ImportError
:
pass
# We're not using Python 3
try
:
import
rarfile
rar_support
=
True
except
ImportError
:
rar_support
=
False
try
:
from
natsort
import
natsorted
as
sort
except
ImportError
:
sort
=
sorted
# Just use regular sort then
# may cause issues with badly named pages in cbz/cbr files
import
mimetypes
import
mimetypes
import
logging
import
logging
...
@@ -41,6 +8,8 @@ from flask import (Flask, render_template, request, Response, redirect,
...
@@ -41,6 +8,8 @@ from flask import (Flask, render_template, request, Response, redirect,
url_for
,
send_from_directory
,
make_response
,
g
,
flash
,
url_for
,
send_from_directory
,
make_response
,
g
,
flash
,
abort
,
Markup
)
abort
,
Markup
)
from
flask
import
__version__
as
flaskVersion
from
flask
import
__version__
as
flaskVersion
from
werkzeug
import
__version__
as
werkzeugVersion
from
jinja2
import
__version__
as
jinja2Version
import
cache_buster
import
cache_buster
import
ub
import
ub
from
ub
import
config
from
ub
import
config
...
@@ -72,6 +41,7 @@ import json
...
@@ -72,6 +41,7 @@ import json
import
datetime
import
datetime
from
iso639
import
languages
as
isoLanguages
from
iso639
import
languages
as
isoLanguages
from
iso639
import
__version__
as
iso639Version
from
iso639
import
__version__
as
iso639Version
from
pytz
import
__version__
as
pytzVersion
from
uuid
import
uuid4
from
uuid
import
uuid4
import
os.path
import
os.path
import
sys
import
sys
...
@@ -81,11 +51,44 @@ from shutil import move, copyfile
...
@@ -81,11 +51,44 @@ from shutil import move, copyfile
import
gdriveutils
import
gdriveutils
import
converter
import
converter
import
tempfile
import
tempfile
import
hashlib
from
redirect
import
redirect_back
from
redirect
import
redirect_back
import
time
import
time
import
server
import
server
import
copy
import
copy
from
reverseproxy
import
ReverseProxied
try
:
from
googleapiclient.errors
import
HttpError
except
ImportError
:
pass
try
:
from
goodreads.client
import
GoodreadsClient
goodreads_support
=
True
except
ImportError
:
goodreads_support
=
False
try
:
import
Levenshtein
levenshtein_support
=
True
except
ImportError
:
levenshtein_support
=
False
try
:
from
functools
import
reduce
except
ImportError
:
pass
# We're not using Python 3
try
:
import
rarfile
rar_support
=
True
except
ImportError
:
rar_support
=
False
try
:
from
natsort
import
natsorted
as
sort
except
ImportError
:
sort
=
sorted
# Just use regular sort then
# may cause issues with badly named pages in cbz/cbr files
try
:
try
:
import
cPickle
import
cPickle
except
ImportError
:
except
ImportError
:
...
@@ -102,12 +105,10 @@ try:
...
@@ -102,12 +105,10 @@ try:
except
ImportError
:
except
ImportError
:
from
flask_login.__about__
import
__version__
as
flask_loginVersion
from
flask_login.__about__
import
__version__
as
flask_loginVersion
current_milli_time
=
lambda
:
int
(
round
(
time
.
time
()
*
1000
))
# Global variables
# Global variables
current_milli_time
=
lambda
:
int
(
round
(
time
.
time
()
*
1000
))
gdrive_watch_callback_token
=
'target=calibreweb-watch_files'
gdrive_watch_callback_token
=
'target=calibreweb-watch_files'
EXTENSIONS_UPLOAD
=
{
'txt'
,
'pdf'
,
'epub'
,
'mobi'
,
'azw'
,
'azw3'
,
'cbr'
,
'cbz'
,
'cbt'
,
'djvu'
,
'prc'
,
'doc'
,
'docx'
,
EXTENSIONS_UPLOAD
=
{
'txt'
,
'pdf'
,
'epub'
,
'mobi'
,
'azw'
,
'azw3'
,
'cbr'
,
'cbz'
,
'cbt'
,
'djvu'
,
'prc'
,
'doc'
,
'docx'
,
'fb2'
,
'html'
,
'rtf'
,
'odt'
}
'fb2'
,
'html'
,
'rtf'
,
'odt'
}
EXTENSIONS_CONVERT
=
{
'pdf'
,
'epub'
,
'mobi'
,
'azw3'
,
'docx'
,
'rtf'
,
'fb2'
,
'lit'
,
'lrf'
,
'txt'
,
'html'
,
'rtf'
,
'odt'
}
EXTENSIONS_CONVERT
=
{
'pdf'
,
'epub'
,
'mobi'
,
'azw3'
,
'docx'
,
'rtf'
,
'fb2'
,
'lit'
,
'lrf'
,
'txt'
,
'html'
,
'rtf'
,
'odt'
}
...
@@ -115,15 +116,7 @@ EXTENSIONS_CONVERT = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit'
...
@@ -115,15 +116,7 @@ EXTENSIONS_CONVERT = {'pdf', 'epub', 'mobi', 'azw3', 'docx', 'rtf', 'fb2', 'lit'
# EXTENSIONS_READER = set(['txt', 'pdf', 'epub', 'zip', 'cbz', 'tar', 'cbt'] + (['rar','cbr'] if rar_support else []))
# EXTENSIONS_READER = set(['txt', 'pdf', 'epub', 'zip', 'cbz', 'tar', 'cbt'] + (['rar','cbr'] if rar_support else []))
def
md5
(
fname
):
'''class ReverseProxied(object):
hash_md5
=
hashlib
.
md5
()
with
open
(
fname
,
"rb"
)
as
f
:
for
chunk
in
iter
(
lambda
:
f
.
read
(
4096
),
b
""
):
hash_md5
.
update
(
chunk
)
return
hash_md5
.
hexdigest
()
class
ReverseProxied
(
object
):
"""Wrap the application in this middleware and configure the
"""Wrap the application in this middleware and configure the
front-end server to add these headers, to let you quietly bind
front-end server to add these headers, to let you quietly bind
this to a URL other than / and to an HTTP scheme that is
this to a URL other than / and to an HTTP scheme that is
...
@@ -158,7 +151,7 @@ class ReverseProxied(object):
...
@@ -158,7 +151,7 @@ class ReverseProxied(object):
servr = environ.get('HTTP_X_FORWARDED_SERVER', '')
servr = environ.get('HTTP_X_FORWARDED_SERVER', '')
if servr:
if servr:
environ['HTTP_HOST'] = servr
environ['HTTP_HOST'] = servr
return
self
.
app
(
environ
,
start_response
)
return self.app(environ, start_response)
'''
# Main code
# Main code
...
@@ -1674,15 +1667,19 @@ def stats():
...
@@ -1674,15 +1667,19 @@ def stats():
categorys
=
db
.
session
.
query
(
db
.
Tags
)
.
count
()
categorys
=
db
.
session
.
query
(
db
.
Tags
)
.
count
()
series
=
db
.
session
.
query
(
db
.
Series
)
.
count
()
series
=
db
.
session
.
query
(
db
.
Series
)
.
count
()
versions
=
uploader
.
book_formats
.
get_versions
()
versions
=
uploader
.
book_formats
.
get_versions
()
versions
[
'Babel'
]
=
'v'
+
babelVersion
versions
[
'Babel'
]
=
'v'
+
babelVersion
versions
[
'Sqlalchemy'
]
=
'v'
+
sqlalchemyVersion
versions
[
'Sqlalchemy'
]
=
'v'
+
sqlalchemyVersion
versions
[
'Flask'
]
=
'v'
+
flaskVersion
versions
[
'Werkzeug'
]
=
'v'
+
werkzeugVersion
versions
[
'Flask Login'
]
=
'v'
+
flask_loginVersion
versions
[
'Jinja2'
]
=
'v'
+
jinja2Version
versions
[
'Flask Principal'
]
=
'v'
+
flask_principalVersion
versions
[
'Flask'
]
=
'v'
+
flaskVersion
versions
[
'Iso 639'
]
=
'v'
+
iso639Version
versions
[
'Flask Login'
]
=
'v'
+
flask_loginVersion
versions
[
'Requests'
]
=
'v'
+
requests
.
__version__
versions
[
'Flask Principal'
]
=
'v'
+
flask_principalVersion
versions
[
'pySqlite'
]
=
'v'
+
db
.
engine
.
dialect
.
dbapi
.
version
versions
[
'Iso 639'
]
=
'v'
+
iso639Version
versions
[
'Sqlite'
]
=
'v'
+
db
.
engine
.
dialect
.
dbapi
.
sqlite_version
versions
[
'pytz'
]
=
'v'
+
pytzVersion
versions
[
'Requests'
]
=
'v'
+
requests
.
__version__
versions
[
'pySqlite'
]
=
'v'
+
db
.
engine
.
dialect
.
dbapi
.
version
versions
[
'Sqlite'
]
=
'v'
+
db
.
engine
.
dialect
.
dbapi
.
sqlite_version
versions
.
update
(
converter
.
versioncheck
())
versions
.
update
(
converter
.
versioncheck
())
versions
.
update
(
server
.
Server
.
getNameVersion
())
versions
.
update
(
server
.
Server
.
getNameVersion
())
versions
[
'Python'
]
=
sys
.
version
versions
[
'Python'
]
=
sys
.
version
...
@@ -3367,24 +3364,19 @@ def reset_password(user_id):
...
@@ -3367,24 +3364,19 @@ def reset_password(user_id):
return
redirect
(
url_for
(
'admin'
))
return
redirect
(
url_for
(
'admin'
))
@
app
.
route
(
"/admin/book/<int:book_id>"
,
methods
=
[
'GET'
,
'POST'
])
def
render_edit_book
(
book_id
):
@
login_required_if_no_ano
@
edit_required
def
edit_book
(
book_id
):
# create the function for sorting...
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"title_sort"
,
1
,
db
.
title_sort
)
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
()
cc
=
db
.
session
.
query
(
db
.
Custom_Columns
)
.
filter
(
db
.
Custom_Columns
.
datatype
.
notin_
(
db
.
cc_exceptions
))
.
all
()
book
=
db
.
session
.
query
(
db
.
Books
)
\
book
=
db
.
session
.
query
(
db
.
Books
)
\
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
common_filters
())
.
first
()
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
common_filters
())
.
first
()
author_names
=
[]
# Book not found
if
not
book
:
if
not
book
:
flash
(
_
(
u"Error opening eBook. File does not exist or file is not accessible"
),
category
=
"error"
)
flash
(
_
(
u"Error opening eBook. File does not exist or file is not accessible"
),
category
=
"error"
)
return
redirect
(
url_for
(
"index"
))
return
redirect
(
url_for
(
"index"
))
for
indx
in
range
(
0
,
len
(
book
.
languages
)):
for
indx
in
range
(
0
,
len
(
book
.
languages
)):
book
.
languages
[
indx
]
.
language_name
=
language_table
[
get_locale
()][
book
.
languages
[
indx
]
.
lang_code
]
book
.
languages
[
indx
]
.
language_name
=
language_table
[
get_locale
()][
book
.
languages
[
indx
]
.
lang_code
]
author_names
=
[]
for
authr
in
book
.
authors
:
for
authr
in
book
.
authors
:
author_names
.
append
(
authr
.
name
.
replace
(
'|'
,
','
))
author_names
.
append
(
authr
.
name
.
replace
(
'|'
,
','
))
...
@@ -3403,14 +3395,92 @@ def edit_book(book_id):
...
@@ -3403,14 +3395,92 @@ def edit_book(book_id):
except
Exception
:
except
Exception
:
app
.
logger
.
warning
(
file
.
format
.
lower
()
+
' already removed from list.'
)
app
.
logger
.
warning
(
file
.
format
.
lower
()
+
' already removed from list.'
)
app
.
logger
.
debug
(
'Allowed conversion formats: '
+
', '
.
join
(
allowed_conversion_formats
))
return
render_title_template
(
'book_edit.html'
,
book
=
book
,
authors
=
author_names
,
cc
=
cc
,
title
=
_
(
u"edit metadata"
),
page
=
"editbook"
,
conversion_formats
=
allowed_conversion_formats
,
source_formats
=
valid_source_formats
)
# Show form
if
request
.
method
!=
'POST'
:
def
edit_cc_data
(
book_id
,
book
,
to_save
):
return
render_title_template
(
'book_edit.html'
,
book
=
book
,
authors
=
author_names
,
cc
=
cc
,
cc
=
db
.
session
.
query
(
db
.
Custom_Columns
)
.
filter
(
db
.
Custom_Columns
.
datatype
.
notin_
(
db
.
cc_exceptions
))
.
all
()
title
=
_
(
u"edit metadata"
),
page
=
"editbook"
,
for
c
in
cc
:
conversion_formats
=
allowed_conversion_formats
,
cc_string
=
"custom_column_"
+
str
(
c
.
id
)
source_formats
=
valid_source_formats
)
if
not
c
.
is_multiple
:
if
len
(
getattr
(
book
,
cc_string
))
>
0
:
cc_db_value
=
getattr
(
book
,
cc_string
)[
0
]
.
value
else
:
cc_db_value
=
None
if
to_save
[
cc_string
]
.
strip
():
if
c
.
datatype
==
'bool'
:
if
to_save
[
cc_string
]
==
'None'
:
to_save
[
cc_string
]
=
None
else
:
to_save
[
cc_string
]
=
1
if
to_save
[
cc_string
]
==
'True'
else
0
if
to_save
[
cc_string
]
!=
cc_db_value
:
if
cc_db_value
is
not
None
:
if
to_save
[
cc_string
]
is
not
None
:
setattr
(
getattr
(
book
,
cc_string
)[
0
],
'value'
,
to_save
[
cc_string
])
else
:
del_cc
=
getattr
(
book
,
cc_string
)[
0
]
getattr
(
book
,
cc_string
)
.
remove
(
del_cc
)
db
.
session
.
delete
(
del_cc
)
else
:
cc_class
=
db
.
cc_classes
[
c
.
id
]
new_cc
=
cc_class
(
value
=
to_save
[
cc_string
],
book
=
book_id
)
db
.
session
.
add
(
new_cc
)
elif
c
.
datatype
==
'int'
:
if
to_save
[
cc_string
]
==
'None'
:
to_save
[
cc_string
]
=
None
if
to_save
[
cc_string
]
!=
cc_db_value
:
if
cc_db_value
is
not
None
:
if
to_save
[
cc_string
]
is
not
None
:
setattr
(
getattr
(
book
,
cc_string
)[
0
],
'value'
,
to_save
[
cc_string
])
else
:
del_cc
=
getattr
(
book
,
cc_string
)[
0
]
getattr
(
book
,
cc_string
)
.
remove
(
del_cc
)
db
.
session
.
delete
(
del_cc
)
else
:
cc_class
=
db
.
cc_classes
[
c
.
id
]
new_cc
=
cc_class
(
value
=
to_save
[
cc_string
],
book
=
book_id
)
db
.
session
.
add
(
new_cc
)
else
:
if
c
.
datatype
==
'rating'
:
to_save
[
cc_string
]
=
str
(
int
(
float
(
to_save
[
cc_string
])
*
2
))
if
to_save
[
cc_string
]
.
strip
()
!=
cc_db_value
:
if
cc_db_value
is
not
None
:
# remove old cc_val
del_cc
=
getattr
(
book
,
cc_string
)[
0
]
getattr
(
book
,
cc_string
)
.
remove
(
del_cc
)
if
len
(
del_cc
.
books
)
==
0
:
db
.
session
.
delete
(
del_cc
)
cc_class
=
db
.
cc_classes
[
c
.
id
]
new_cc
=
db
.
session
.
query
(
cc_class
)
.
filter
(
cc_class
.
value
==
to_save
[
cc_string
]
.
strip
())
.
first
()
# if no cc val is found add it
if
new_cc
is
None
:
new_cc
=
cc_class
(
value
=
to_save
[
cc_string
]
.
strip
())
db
.
session
.
add
(
new_cc
)
db
.
session
.
flush
()
new_cc
=
db
.
session
.
query
(
cc_class
)
.
filter
(
cc_class
.
value
==
to_save
[
cc_string
]
.
strip
())
.
first
()
# add cc value to book
getattr
(
book
,
cc_string
)
.
append
(
new_cc
)
else
:
if
cc_db_value
is
not
None
:
# remove old cc_val
del_cc
=
getattr
(
book
,
cc_string
)[
0
]
getattr
(
book
,
cc_string
)
.
remove
(
del_cc
)
if
len
(
del_cc
.
books
)
==
0
:
db
.
session
.
delete
(
del_cc
)
else
:
input_tags
=
to_save
[
cc_string
]
.
split
(
','
)
input_tags
=
list
(
map
(
lambda
it
:
it
.
strip
(),
input_tags
))
modify_database_object
(
input_tags
,
getattr
(
book
,
cc_string
),
db
.
cc_classes
[
c
.
id
],
db
.
session
,
'custom'
)
return
cc
def
upload_single_file
(
request
,
book
,
book_id
):
# Check and handle Uploaded file
# Check and handle Uploaded file
if
'btn-upload-format'
in
request
.
files
:
if
'btn-upload-format'
in
request
.
files
:
requested_file
=
request
.
files
[
'btn-upload-format'
]
requested_file
=
request
.
files
[
'btn-upload-format'
]
...
@@ -3457,9 +3527,10 @@ def edit_book(book_id):
...
@@ -3457,9 +3527,10 @@ def edit_book(book_id):
# Queue uploader info
# Queue uploader info
uploadText
=
_
(
u"File format
%(ext)
s added to
%(book)
s"
,
ext
=
file_ext
.
upper
(),
book
=
book
.
title
)
uploadText
=
_
(
u"File format
%(ext)
s added to
%(book)
s"
,
ext
=
file_ext
.
upper
(),
book
=
book
.
title
)
helper
.
global_WorkerThread
.
add_upload
(
current_user
.
nickname
,
helper
.
global_WorkerThread
.
add_upload
(
current_user
.
nickname
,
"<a href=
\"
"
+
url_for
(
'show_book'
,
book_id
=
book
.
id
)
+
"
\"
>"
+
uploadText
+
"</a>"
)
"<a href=
\"
"
+
url_for
(
'show_book'
,
book_id
=
book
.
id
)
+
"
\"
>"
+
uploadText
+
"</a>"
)
def
upload_cover
(
request
,
book
):
if
'btn-upload-cover'
in
request
.
files
:
if
'btn-upload-cover'
in
request
.
files
:
requested_file
=
request
.
files
[
'btn-upload-cover'
]
requested_file
=
request
.
files
[
'btn-upload-cover'
]
# check for empty request
# check for empty request
...
@@ -3485,15 +3556,37 @@ def edit_book(book_id):
...
@@ -3485,15 +3556,37 @@ def edit_book(book_id):
except
IOError
:
except
IOError
:
flash
(
_
(
u"Cover-file is not a valid image file"
%
saved_filename
),
category
=
"error"
)
flash
(
_
(
u"Cover-file is not a valid image file"
%
saved_filename
),
category
=
"error"
)
return
redirect
(
url_for
(
'show_book'
,
book_id
=
book
.
id
))
return
redirect
(
url_for
(
'show_book'
,
book_id
=
book
.
id
))
to_save
=
request
.
form
.
to_dict
()
@
app
.
route
(
"/admin/book/<int:book_id>"
,
methods
=
[
'GET'
,
'POST'
])
@
login_required_if_no_ano
@
edit_required
def
edit_book
(
book_id
):
# Show form
if
request
.
method
!=
'POST'
:
return
render_edit_book
(
book_id
)
# create the function for sorting...
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"title_sort"
,
1
,
db
.
title_sort
)
book
=
db
.
session
.
query
(
db
.
Books
)
\
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
common_filters
())
.
first
()
# Book not found
if
not
book
:
flash
(
_
(
u"Error opening eBook. File does not exist or file is not accessible"
),
category
=
"error"
)
return
redirect
(
url_for
(
"index"
))
upload_single_file
(
request
,
book
,
book_id
)
upload_cover
(
request
,
book
)
try
:
try
:
to_save
=
request
.
form
.
to_dict
()
# Update book
# Update book
edited_books_id
=
set
()
edited_books_id
=
None
#handle book title
#handle book title
if
book
.
title
!=
to_save
[
"book_title"
]:
if
book
.
title
!=
to_save
[
"book_title"
]:
if
to_save
[
"book_title"
]
==
''
:
to_save
[
"book_title"
]
=
_
(
u'unknown'
)
book
.
title
=
to_save
[
"book_title"
]
book
.
title
=
to_save
[
"book_title"
]
edited_books_id
.
add
(
book
.
id
)
edited_books_id
=
book
.
id
# handle author(s)
# handle author(s)
input_authors
=
to_save
[
"author_name"
]
.
split
(
'&'
)
input_authors
=
to_save
[
"author_name"
]
.
split
(
'&'
)
...
@@ -3508,18 +3601,17 @@ def edit_book(book_id):
...
@@ -3508,18 +3601,17 @@ def edit_book(book_id):
modify_database_object
(
input_authors
,
book
.
authors
,
db
.
Authors
,
db
.
session
,
'author'
)
modify_database_object
(
input_authors
,
book
.
authors
,
db
.
Authors
,
db
.
session
,
'author'
)
if
book
.
authors
:
if
book
.
authors
:
if
author0_before_edit
!=
book
.
authors
[
0
]
.
name
:
if
author0_before_edit
!=
book
.
authors
[
0
]
.
name
:
edited_books_id
.
add
(
book
.
id
)
edited_books_id
=
book
.
id
book
.
author_sort
=
helper
.
get_sorted_author
(
input_authors
[
0
])
book
.
author_sort
=
helper
.
get_sorted_author
(
input_authors
[
0
])
if
config
.
config_use_google_drive
:
if
config
.
config_use_google_drive
:
gdriveutils
.
updateGdriveCalibreFromLocal
()
gdriveutils
.
updateGdriveCalibreFromLocal
()
error
=
False
error
=
False
for
b
in
edited_books_id
:
if
edited_books_id
:
error
=
helper
.
update_dir_stucture
(
b
,
config
.
config_calibre_dir
)
error
=
helper
.
update_dir_stucture
(
edited_books_id
,
config
.
config_calibre_dir
)
if
error
:
# stop on error
if
error
:
# stop on error
flash
(
error
,
category
=
"error"
)
flash
(
error
,
category
=
"error"
)
break
if
not
error
:
if
not
error
:
if
to_save
[
"cover_url"
]:
if
to_save
[
"cover_url"
]:
...
@@ -3562,7 +3654,6 @@ def edit_book(book_id):
...
@@ -3562,7 +3654,6 @@ def edit_book(book_id):
# handle book languages
# handle book languages
input_languages
=
to_save
[
"languages"
]
.
split
(
','
)
input_languages
=
to_save
[
"languages"
]
.
split
(
','
)
# input_languages = list(map(lambda it: it.strip().lower(), input_languages))
input_languages
=
[
x
.
strip
()
.
lower
()
for
x
in
input_languages
if
x
!=
''
]
input_languages
=
[
x
.
strip
()
.
lower
()
for
x
in
input_languages
if
x
!=
''
]
input_l
=
[]
input_l
=
[]
invers_lang_table
=
[
x
.
lower
()
for
x
in
language_table
[
get_locale
()]
.
values
()]
invers_lang_table
=
[
x
.
lower
()
for
x
in
language_table
[
get_locale
()]
.
values
()]
...
@@ -3575,6 +3666,7 @@ def edit_book(book_id):
...
@@ -3575,6 +3666,7 @@ def edit_book(book_id):
flash
(
_
(
u"
%(langname)
s is not a valid language"
,
langname
=
lang
),
category
=
"error"
)
flash
(
_
(
u"
%(langname)
s is not a valid language"
,
langname
=
lang
),
category
=
"error"
)
modify_database_object
(
input_l
,
book
.
languages
,
db
.
Languages
,
db
.
session
,
'languages'
)
modify_database_object
(
input_l
,
book
.
languages
,
db
.
Languages
,
db
.
session
,
'languages'
)
# handle book ratings
if
to_save
[
"rating"
]
.
strip
():
if
to_save
[
"rating"
]
.
strip
():
old_rating
=
False
old_rating
=
False
if
len
(
book
.
ratings
)
>
0
:
if
len
(
book
.
ratings
)
>
0
:
...
@@ -3593,104 +3685,20 @@ def edit_book(book_id):
...
@@ -3593,104 +3685,20 @@ def edit_book(book_id):
if
len
(
book
.
ratings
)
>
0
:
if
len
(
book
.
ratings
)
>
0
:
book
.
ratings
.
remove
(
book
.
ratings
[
0
])
book
.
ratings
.
remove
(
book
.
ratings
[
0
])
for
c
in
cc
:
# handle cc data
cc_string
=
"custom_column_"
+
str
(
c
.
id
)
edit_cc_data
(
book_id
,
book
,
to_save
)
if
not
c
.
is_multiple
:
if
len
(
getattr
(
book
,
cc_string
))
>
0
:
cc_db_value
=
getattr
(
book
,
cc_string
)[
0
]
.
value
else
:
cc_db_value
=
None
if
to_save
[
cc_string
]
.
strip
():
if
c
.
datatype
==
'bool'
:
if
to_save
[
cc_string
]
==
'None'
:
to_save
[
cc_string
]
=
None
else
:
to_save
[
cc_string
]
=
1
if
to_save
[
cc_string
]
==
'True'
else
0
if
to_save
[
cc_string
]
!=
cc_db_value
:
if
cc_db_value
is
not
None
:
if
to_save
[
cc_string
]
is
not
None
:
setattr
(
getattr
(
book
,
cc_string
)[
0
],
'value'
,
to_save
[
cc_string
])
else
:
del_cc
=
getattr
(
book
,
cc_string
)[
0
]
getattr
(
book
,
cc_string
)
.
remove
(
del_cc
)
db
.
session
.
delete
(
del_cc
)
else
:
cc_class
=
db
.
cc_classes
[
c
.
id
]
new_cc
=
cc_class
(
value
=
to_save
[
cc_string
],
book
=
book_id
)
db
.
session
.
add
(
new_cc
)
elif
c
.
datatype
==
'int'
:
if
to_save
[
cc_string
]
==
'None'
:
to_save
[
cc_string
]
=
None
if
to_save
[
cc_string
]
!=
cc_db_value
:
if
cc_db_value
is
not
None
:
if
to_save
[
cc_string
]
is
not
None
:
setattr
(
getattr
(
book
,
cc_string
)[
0
],
'value'
,
to_save
[
cc_string
])
else
:
del_cc
=
getattr
(
book
,
cc_string
)[
0
]
getattr
(
book
,
cc_string
)
.
remove
(
del_cc
)
db
.
session
.
delete
(
del_cc
)
else
:
cc_class
=
db
.
cc_classes
[
c
.
id
]
new_cc
=
cc_class
(
value
=
to_save
[
cc_string
],
book
=
book_id
)
db
.
session
.
add
(
new_cc
)
else
:
if
c
.
datatype
==
'rating'
:
to_save
[
cc_string
]
=
str
(
int
(
float
(
to_save
[
cc_string
])
*
2
))
if
to_save
[
cc_string
]
.
strip
()
!=
cc_db_value
:
if
cc_db_value
is
not
None
:
# remove old cc_val
del_cc
=
getattr
(
book
,
cc_string
)[
0
]
getattr
(
book
,
cc_string
)
.
remove
(
del_cc
)
if
len
(
del_cc
.
books
)
==
0
:
db
.
session
.
delete
(
del_cc
)
cc_class
=
db
.
cc_classes
[
c
.
id
]
new_cc
=
db
.
session
.
query
(
cc_class
)
.
filter
(
cc_class
.
value
==
to_save
[
cc_string
]
.
strip
())
.
first
()
# if no cc val is found add it
if
new_cc
is
None
:
new_cc
=
cc_class
(
value
=
to_save
[
cc_string
]
.
strip
())
db
.
session
.
add
(
new_cc
)
db
.
session
.
flush
()
new_cc
=
db
.
session
.
query
(
cc_class
)
.
filter
(
cc_class
.
value
==
to_save
[
cc_string
]
.
strip
())
.
first
()
# add cc value to book
getattr
(
book
,
cc_string
)
.
append
(
new_cc
)
else
:
if
cc_db_value
is
not
None
:
# remove old cc_val
del_cc
=
getattr
(
book
,
cc_string
)[
0
]
getattr
(
book
,
cc_string
)
.
remove
(
del_cc
)
if
len
(
del_cc
.
books
)
==
0
:
db
.
session
.
delete
(
del_cc
)
else
:
input_tags
=
to_save
[
cc_string
]
.
split
(
','
)
input_tags
=
list
(
map
(
lambda
it
:
it
.
strip
(),
input_tags
))
modify_database_object
(
input_tags
,
getattr
(
book
,
cc_string
),
db
.
cc_classes
[
c
.
id
],
db
.
session
,
'custom'
)
db
.
session
.
commit
()
db
.
session
.
commit
()
if
config
.
config_use_google_drive
:
if
config
.
config_use_google_drive
:
gdriveutils
.
updateGdriveCalibreFromLocal
()
gdriveutils
.
updateGdriveCalibreFromLocal
()
if
"detail_view"
in
to_save
:
if
"detail_view"
in
to_save
:
return
redirect
(
url_for
(
'show_book'
,
book_id
=
book
.
id
))
return
redirect
(
url_for
(
'show_book'
,
book_id
=
book
.
id
))
else
:
else
:
for
indx
in
range
(
0
,
len
(
book
.
languages
)):
return
render_edit_book
(
book_id
)
try
:
book
.
languages
[
indx
]
.
language_name
=
LC
.
parse
(
book
.
languages
[
indx
]
.
lang_code
)
.
get_language_name
(
get_locale
())
except
UnknownLocaleError
:
book
.
languages
[
indx
]
.
language_name
=
_
(
isoLanguages
.
get
(
part3
=
book
.
languages
[
indx
]
.
lang_code
)
.
name
)
author_names
=
[]
for
authr
in
book
.
authors
:
author_names
.
append
(
authr
.
name
)
return
render_title_template
(
'book_edit.html'
,
book
=
book
,
authors
=
author_names
,
cc
=
cc
,
title
=
_
(
u"edit metadata"
),
page
=
"editbook"
)
else
:
else
:
db
.
session
.
rollback
()
db
.
session
.
rollback
()
flash
(
error
,
category
=
"error"
)
flash
(
error
,
category
=
"error"
)
return
render_title_template
(
'book_edit.html'
,
book
=
book
,
authors
=
author_names
,
cc
=
cc
,
return
render_edit_book
(
book_id
)
title
=
_
(
u"edit metadata"
),
page
=
"editbook"
)
except
Exception
as
e
:
except
Exception
as
e
:
app
.
logger
.
exception
(
e
)
app
.
logger
.
exception
(
e
)
db
.
session
.
rollback
()
db
.
session
.
rollback
()
...
...
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