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
24c743d2
Commit
24c743d2
authored
Apr 19, 2020
by
Ozzieisaacs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Code cosmetics
parent
7bb5afa5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
262 additions
and
192 deletions
+262
-192
cli.py
cps/cli.py
+1
-1
db.py
cps/db.py
+1
-1
helper.py
cps/helper.py
+81
-55
jinjia.py
cps/jinjia.py
+5
-1
kobo.py
cps/kobo.py
+12
-5
logger.py
cps/logger.py
+1
-1
oauth.py
cps/oauth.py
+2
-2
opds.py
cps/opds.py
+43
-21
server.py
cps/server.py
+2
-2
SyncToken.py
cps/services/SyncToken.py
+7
-5
shelf.py
cps/shelf.py
+32
-27
subproc_wrapper.py
cps/subproc_wrapper.py
+5
-5
list.html
cps/templates/list.html
+6
-6
ub.py
cps/ub.py
+59
-55
updater.py
cps/updater.py
+5
-5
No files found.
cps/cli.py
View file @
24c743d2
...
...
@@ -34,7 +34,7 @@ def version_info():
parser
=
argparse
.
ArgumentParser
(
description
=
'Calibre Web is a web app'
' providing a interface for browsing, reading and downloading eBooks
\n
'
,
prog
=
'cps.py'
)
' providing a interface for browsing, reading and downloading eBooks
\n
'
,
prog
=
'cps.py'
)
parser
.
add_argument
(
'-p'
,
metavar
=
'path'
,
help
=
'path and name to settings db, e.g. /opt/cw.db'
)
parser
.
add_argument
(
'-g'
,
metavar
=
'path'
,
help
=
'path and name to gdrive db, e.g. /opt/gd.db'
)
parser
.
add_argument
(
'-c'
,
metavar
=
'path'
,
...
...
cps/db.py
View file @
24c743d2
...
...
@@ -25,7 +25,7 @@ import ast
from
sqlalchemy
import
create_engine
from
sqlalchemy
import
Table
,
Column
,
ForeignKey
from
sqlalchemy
import
String
,
Integer
,
Boolean
,
TIMESTAMP
,
Float
from
sqlalchemy
import
String
,
Integer
,
Boolean
,
TIMESTAMP
,
Float
,
DateTime
from
sqlalchemy.orm
import
relationship
,
sessionmaker
,
scoped_session
from
sqlalchemy.ext.declarative
import
declarative_base
...
...
cps/helper.py
View file @
24c743d2
This diff is collapsed.
Click to expand it.
cps/jinjia.py
View file @
24c743d2
...
...
@@ -80,9 +80,13 @@ def formatdate_filter(val):
formatdate
=
datetime
.
datetime
.
strptime
(
conformed_timestamp
[:
15
],
"
%
Y
%
m
%
d
%
H
%
M
%
S"
)
return
format_date
(
formatdate
,
format
=
'medium'
,
locale
=
get_locale
())
except
AttributeError
as
e
:
log
.
error
(
'Babel error:
%
s, Current user locale:
%
s, Current User:
%
s'
,
e
,
current_user
.
locale
,
current_user
.
nickname
)
log
.
error
(
'Babel error:
%
s, Current user locale:
%
s, Current User:
%
s'
,
e
,
current_user
.
locale
,
current_user
.
nickname
)
return
formatdate
@
jinjia
.
app_template_filter
(
'formatdateinput'
)
def
format_date_input
(
val
):
conformed_timestamp
=
re
.
sub
(
r"[:]|([-](?!((\d{2}[:]\d{2})|(\d{4}))$))"
,
''
,
val
)
...
...
cps/kobo.py
View file @
24c743d2
...
...
@@ -385,7 +385,7 @@ def get_metadata(book):
name
=
get_series
(
book
)
metadata
[
"Series"
]
=
{
"Name"
:
get_series
(
book
),
"Number"
:
book
.
series_index
,
"Number"
:
book
.
series_index
,
# ToDo Check int() ?
"NumberFloat"
:
float
(
book
.
series_index
),
# Get a deterministic id based on the series name.
"Id"
:
uuid
.
uuid3
(
uuid
.
NAMESPACE_DNS
,
name
),
...
...
@@ -407,8 +407,10 @@ def HandleTagCreate():
log
.
debug
(
"Received malformed v1/library/tags request."
)
abort
(
400
,
description
=
"Malformed tags POST request. Data is missing 'Name' or 'Items' field"
)
# ToDO: Names are not unique ! -> filter only private shelfs
shelf
=
ub
.
session
.
query
(
ub
.
Shelf
)
.
filter
(
and_
(
ub
.
Shelf
.
name
)
==
name
,
ub
.
Shelf
.
user_id
==
current_user
.
id
)
.
one_or_none
()
current_user
.
id
)
.
one_or_none
()
# ToDO: shouldn't it ) at the end
if
shelf
and
not
shelf_lib
.
check_shelf_edit_permissions
(
shelf
):
abort
(
401
,
description
=
"User is unauthaurized to edit shelf."
)
...
...
@@ -517,6 +519,7 @@ def HandleTagRemoveItem(tag_id):
log
.
debug
(
"Received malformed v1/library/tags/<tag_id>/items/delete request."
)
abort
(
400
,
description
=
"Malformed tags POST request. Data is missing 'Items' field"
)
# insconsitent to above requests
shelf
=
ub
.
session
.
query
(
ub
.
Shelf
)
.
filter
(
ub
.
Shelf
.
uuid
==
tag_id
,
ub
.
Shelf
.
user_id
==
current_user
.
id
)
.
one_or_none
()
if
not
shelf
:
...
...
@@ -552,7 +555,8 @@ def HandleTagRemoveItem(tag_id):
def
sync_shelves
(
sync_token
,
sync_results
):
new_tags_last_modified
=
sync_token
.
tags_last_modified
for
shelf
in
ub
.
session
.
query
(
ub
.
ShelfArchive
)
.
filter
(
func
.
datetime
(
ub
.
ShelfArchive
.
last_modified
)
>
sync_token
.
tags_last_modified
,
ub
.
ShelfArchive
.
user_id
==
current_user
.
id
):
for
shelf
in
ub
.
session
.
query
(
ub
.
ShelfArchive
)
.
filter
(
func
.
datetime
(
ub
.
ShelfArchive
.
last_modified
)
>
sync_token
.
tags_last_modified
,
ub
.
ShelfArchive
.
user_id
==
current_user
.
id
):
new_tags_last_modified
=
max
(
shelf
.
last_modified
,
new_tags_last_modified
)
sync_results
.
append
({
...
...
@@ -564,7 +568,8 @@ def sync_shelves(sync_token, sync_results):
}
})
for
shelf
in
ub
.
session
.
query
(
ub
.
Shelf
)
.
filter
(
func
.
datetime
(
ub
.
Shelf
.
last_modified
)
>
sync_token
.
tags_last_modified
,
ub
.
Shelf
.
user_id
==
current_user
.
id
):
for
shelf
in
ub
.
session
.
query
(
ub
.
Shelf
)
.
filter
(
func
.
datetime
(
ub
.
Shelf
.
last_modified
)
>
sync_token
.
tags_last_modified
,
ub
.
Shelf
.
user_id
==
current_user
.
id
):
if
not
shelf_lib
.
check_shelf_view_permissions
(
shelf
):
continue
...
...
@@ -600,6 +605,7 @@ def create_kobo_tag(shelf):
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_shelf
.
book_id
)
.
one_or_none
()
if
not
book
:
log
.
info
(
u"Book (id:
%
s) in BookShelf (id:
%
s) not found in book database"
,
book_shelf
.
book_id
,
shelf
.
id
)
# ToDo shouldn't it continue?
return
None
tag
[
"Items"
]
.
append
(
{
...
...
@@ -769,7 +775,8 @@ def HandleCoverImageRequest(book_uuid, width, height,Quality, isGreyscale):
height
=
height
),
307
)
else
:
log
.
debug
(
"Cover for unknown book:
%
s requested"
%
book_uuid
)
return
redirect_or_proxy_request
()
# additional proxy request make no sense, -> direct return
return
make_response
(
jsonify
({}))
log
.
debug
(
"Cover request received for book
%
s"
%
book_uuid
)
return
book_cover
...
...
cps/logger.py
View file @
24c743d2
...
...
@@ -108,7 +108,7 @@ def setup(log_file, log_level=None):
r
.
setLevel
(
log_level
)
# Otherwise name get's destroyed on windows
if
log_file
!=
LOG_TO_STDERR
and
log_file
!=
LOG_TO_STDOUT
:
if
log_file
!=
LOG_TO_STDERR
and
log_file
!=
LOG_TO_STDOUT
:
log_file
=
_absolute_log_file
(
log_file
,
DEFAULT_LOG_FILE
)
previous_handler
=
r
.
handlers
[
0
]
if
r
.
handlers
else
None
...
...
cps/oauth.py
View file @
24c743d2
...
...
@@ -30,7 +30,7 @@ except ImportError:
from
flask_dance.consumer.storage.sqla
import
SQLAlchemyStorage
as
SQLAlchemyBackend
from
flask_dance.consumer.storage.sqla
import
first
,
_get_real_user
from
sqlalchemy.orm.exc
import
NoResultFound
backend_resultcode
=
True
# prevent storing values with this resultcode
backend_resultcode
=
True
# prevent storing values with this resultcode
except
ImportError
:
pass
...
...
@@ -97,7 +97,7 @@ try:
def
set
(
self
,
blueprint
,
token
,
user
=
None
,
user_id
=
None
):
uid
=
first
([
user_id
,
self
.
user_id
,
blueprint
.
config
.
get
(
"user_id"
)])
u
=
first
(
_get_real_user
(
ref
,
self
.
anon_user
)
for
ref
in
(
user
,
self
.
user
,
blueprint
.
config
.
get
(
"user"
)))
for
ref
in
(
user
,
self
.
user
,
blueprint
.
config
.
get
(
"user"
)))
if
self
.
user_required
and
not
u
and
not
uid
:
raise
ValueError
(
"Cannot set OAuth token without an associated user"
)
...
...
cps/opds.py
View file @
24c743d2
This diff is collapsed.
Click to expand it.
cps/server.py
View file @
24c743d2
...
...
@@ -43,7 +43,6 @@ from . import logger
log
=
logger
.
create
()
def
_readable_listen_address
(
address
,
port
):
if
':'
in
address
:
address
=
"["
+
address
+
"]"
...
...
@@ -84,7 +83,8 @@ class WebServer(object):
if
os
.
path
.
isfile
(
certfile_path
)
and
os
.
path
.
isfile
(
keyfile_path
):
self
.
ssl_args
=
dict
(
certfile
=
certfile_path
,
keyfile
=
keyfile_path
)
else
:
log
.
warning
(
'The specified paths for the ssl certificate file and/or key file seem to be broken. Ignoring ssl.'
)
log
.
warning
(
'The specified paths for the ssl certificate file and/or key file seem to be broken. '
'Ignoring ssl.'
)
log
.
warning
(
'Cert path:
%
s'
,
certfile_path
)
log
.
warning
(
'Key path:
%
s'
,
keyfile_path
)
...
...
cps/services/SyncToken.py
View file @
24c743d2
...
...
@@ -49,10 +49,11 @@ def get_datetime_from_json(json_object, field_name):
return
datetime
.
min
class
SyncToken
()
:
class
SyncToken
:
""" The SyncToken is used to persist state accross requests.
When serialized over the response headers, the Kobo device will propagate the token onto following requests to the service.
As an example use-case, the SyncToken is used to detect books that have been added to the library since the last time the device synced to the server.
When serialized over the response headers, the Kobo device will propagate the token onto following
requests to the service. As an example use-case, the SyncToken is used to detect books that have been added
to the library since the last time the device synced to the server.
Attributes:
books_last_created: Datetime representing the newest book that the device knows about.
...
...
@@ -66,10 +67,11 @@ class SyncToken():
token_schema
=
{
"type"
:
"object"
,
"properties"
:
{
"version"
:
{
"type"
:
"string"
},
"data"
:
{
"type"
:
"object"
},},
"properties"
:
{
"version"
:
{
"type"
:
"string"
},
"data"
:
{
"type"
:
"object"
},
},
}
# This Schema doesn't contain enough information to detect and propagate book deletions from Calibre to the device.
# A potential solution might be to keep a list of all known book uuids in the token, and look for any missing from the db.
# A potential solution might be to keep a list of all known book uuids in the token, and look for any missing
# from the db.
data_schema_v1
=
{
"type"
:
"object"
,
"properties"
:
{
...
...
cps/shelf.py
View file @
24c743d2
...
...
@@ -25,7 +25,7 @@ from __future__ import division, print_function, unicode_literals
from
flask
import
Blueprint
,
request
,
flash
,
redirect
,
url_for
from
flask_babel
import
gettext
as
_
from
flask_login
import
login_required
,
current_user
from
sqlalchemy.sql.expression
import
func
,
or_
,
and_
from
sqlalchemy.sql.expression
import
func
from
.
import
logger
,
ub
,
searched_ids
,
db
from
.web
import
render_title_template
...
...
@@ -35,6 +35,7 @@ from .helper import common_filters
shelf
=
Blueprint
(
'shelf'
,
__name__
)
log
=
logger
.
create
()
def
check_shelf_edit_permissions
(
cur_shelf
):
if
not
cur_shelf
.
is_public
and
not
cur_shelf
.
user_id
==
int
(
current_user
.
id
):
log
.
error
(
"User
%
s not allowed to edit shelf
%
s"
,
current_user
,
cur_shelf
)
...
...
@@ -74,7 +75,7 @@ def add_to_shelf(shelf_id, book_id):
return
"Sorry you are not allowed to add a book to the the shelf:
%
s"
%
shelf
.
name
,
403
book_in_shelf
=
ub
.
session
.
query
(
ub
.
BookShelf
)
.
filter
(
ub
.
BookShelf
.
shelf
==
shelf_id
,
ub
.
BookShelf
.
book_id
==
book_id
)
.
first
()
ub
.
BookShelf
.
book_id
==
book_id
)
.
first
()
if
book_in_shelf
:
log
.
error
(
"Book
%
s is already part of
%
s"
,
book_id
,
shelf
)
if
not
xhr
:
...
...
@@ -195,7 +196,6 @@ def remove_from_shelf(shelf_id, book_id):
return
"Sorry you are not allowed to remove a book from this shelf:
%
s"
%
shelf
.
name
,
403
@
shelf
.
route
(
"/shelf/create"
,
methods
=
[
"GET"
,
"POST"
])
@
login_required
def
create_shelf
():
...
...
@@ -214,21 +214,24 @@ def create_shelf():
.
first
()
is
None
if
not
is_shelf_name_unique
:
flash
(
_
(
u"A public shelf with the name '
%(title)
s' already exists."
,
title
=
to_save
[
"title"
]),
category
=
"error"
)
flash
(
_
(
u"A public shelf with the name '
%(title)
s' already exists."
,
title
=
to_save
[
"title"
]),
category
=
"error"
)
else
:
is_shelf_name_unique
=
ub
.
session
.
query
(
ub
.
Shelf
)
\
.
filter
((
ub
.
Shelf
.
name
==
to_save
[
"title"
])
&
(
ub
.
Shelf
.
is_public
==
0
)
&
(
ub
.
Shelf
.
user_id
==
int
(
current_user
.
id
)))
\
.
first
()
is
None
.
filter
((
ub
.
Shelf
.
name
==
to_save
[
"title"
])
&
(
ub
.
Shelf
.
is_public
==
0
)
&
(
ub
.
Shelf
.
user_id
==
int
(
current_user
.
id
)))
\
.
first
()
is
None
if
not
is_shelf_name_unique
:
flash
(
_
(
u"A private shelf with the name '
%(title)
s' already exists."
,
title
=
to_save
[
"title"
]),
category
=
"error"
)
flash
(
_
(
u"A private shelf with the name '
%(title)
s' already exists."
,
title
=
to_save
[
"title"
]),
category
=
"error"
)
if
is_shelf_name_unique
:
try
:
ub
.
session
.
add
(
shelf
)
ub
.
session
.
commit
()
flash
(
_
(
u"Shelf
%(title)
s created"
,
title
=
to_save
[
"title"
]),
category
=
"success"
)
return
redirect
(
url_for
(
'shelf.show_shelf'
,
shelf_id
=
shelf
.
id
))
return
redirect
(
url_for
(
'shelf.show_shelf'
,
shelf_id
=
shelf
.
id
))
except
Exception
:
flash
(
_
(
u"There was an error"
),
category
=
"error"
)
return
render_title_template
(
'shelf_edit.html'
,
shelf
=
shelf
,
title
=
_
(
u"Create a Shelf"
),
page
=
"shelfcreate"
)
...
...
@@ -240,7 +243,7 @@ def create_shelf():
@
login_required
def
edit_shelf
(
shelf_id
):
shelf
=
ub
.
session
.
query
(
ub
.
Shelf
)
.
filter
(
ub
.
Shelf
.
id
==
shelf_id
)
.
first
()
if
request
.
method
==
"POST"
:
if
request
.
method
==
"POST"
:
to_save
=
request
.
form
.
to_dict
()
is_shelf_name_unique
=
False
...
...
@@ -251,15 +254,18 @@ def edit_shelf(shelf_id):
.
first
()
is
None
if
not
is_shelf_name_unique
:
flash
(
_
(
u"A public shelf with the name '
%(title)
s' already exists."
,
title
=
to_save
[
"title"
]),
category
=
"error"
)
flash
(
_
(
u"A public shelf with the name '
%(title)
s' already exists."
,
title
=
to_save
[
"title"
]),
category
=
"error"
)
else
:
is_shelf_name_unique
=
ub
.
session
.
query
(
ub
.
Shelf
)
\
.
filter
((
ub
.
Shelf
.
name
==
to_save
[
"title"
])
&
(
ub
.
Shelf
.
is_public
==
0
)
&
(
ub
.
Shelf
.
user_id
==
int
(
current_user
.
id
)))
\
.
filter
(
ub
.
Shelf
.
id
!=
shelf_id
)
\
.
first
()
is
None
.
filter
((
ub
.
Shelf
.
name
==
to_save
[
"title"
])
&
(
ub
.
Shelf
.
is_public
==
0
)
&
(
ub
.
Shelf
.
user_id
==
int
(
current_user
.
id
)))
\
.
filter
(
ub
.
Shelf
.
id
!=
shelf_id
)
\
.
first
()
is
None
if
not
is_shelf_name_unique
:
flash
(
_
(
u"A private shelf with the name '
%(title)
s' already exists."
,
title
=
to_save
[
"title"
]),
category
=
"error"
)
flash
(
_
(
u"A private shelf with the name '
%(title)
s' already exists."
,
title
=
to_save
[
"title"
]),
category
=
"error"
)
if
is_shelf_name_unique
:
shelf
.
name
=
to_save
[
"title"
]
...
...
@@ -283,7 +289,7 @@ def delete_shelf_helper(cur_shelf):
shelf_id
=
cur_shelf
.
id
ub
.
session
.
delete
(
cur_shelf
)
ub
.
session
.
query
(
ub
.
BookShelf
)
.
filter
(
ub
.
BookShelf
.
shelf
==
shelf_id
)
.
delete
()
ub
.
session
.
add
(
ub
.
ShelfArchive
(
uuid
=
cur_shelf
.
uuid
,
user_id
=
cur_shelf
.
uuid
))
ub
.
session
.
add
(
ub
.
ShelfArchive
(
uuid
=
cur_shelf
.
uuid
,
user_id
=
cur_shelf
.
uuid
))
ub
.
session
.
commit
()
log
.
info
(
"successfully deleted
%
s"
,
cur_shelf
)
...
...
@@ -295,7 +301,7 @@ def delete_shelf(shelf_id):
delete_shelf_helper
(
cur_shelf
)
return
redirect
(
url_for
(
'web.index'
))
# @shelf.route("/shelfdown/<int:shelf_id>")
@
shelf
.
route
(
"/shelf/<int:shelf_id>"
,
defaults
=
{
'shelf_type'
:
1
})
@
shelf
.
route
(
"/shelf/<int:shelf_id>/<int:shelf_type>"
)
def
show_shelf
(
shelf_type
,
shelf_id
):
...
...
@@ -319,13 +325,12 @@ def show_shelf(shelf_type, shelf_id):
ub
.
session
.
query
(
ub
.
BookShelf
)
.
filter
(
ub
.
BookShelf
.
book_id
==
book
.
book_id
)
.
delete
()
ub
.
session
.
commit
()
return
render_title_template
(
page
,
entries
=
result
,
title
=
_
(
u"Shelf: '
%(name)
s'"
,
name
=
shelf
.
name
),
shelf
=
shelf
,
page
=
"shelf"
)
shelf
=
shelf
,
page
=
"shelf"
)
else
:
flash
(
_
(
u"Error opening shelf. Shelf does not exist or is not accessible"
),
category
=
"error"
)
return
redirect
(
url_for
(
"web.index"
))
@
shelf
.
route
(
"/shelf/order/<int:shelf_id>"
,
methods
=
[
"GET"
,
"POST"
])
@
login_required
def
order_shelf
(
shelf_id
):
...
...
@@ -347,17 +352,17 @@ def order_shelf(shelf_id):
for
book
in
books_in_shelf2
:
cur_book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
filter
(
common_filters
())
.
first
()
if
cur_book
:
result
.
append
({
'title'
:
cur_book
.
title
,
'id'
:
cur_book
.
id
,
'author'
:
cur_book
.
authors
,
'series'
:
cur_book
.
series
,
'series_index'
:
cur_book
.
series_index
})
result
.
append
({
'title'
:
cur_book
.
title
,
'id'
:
cur_book
.
id
,
'author'
:
cur_book
.
authors
,
'series'
:
cur_book
.
series
,
'series_index'
:
cur_book
.
series_index
})
else
:
cur_book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
()
result
.
append
({
'title'
:
_
(
'Hidden Book'
),
'id'
:
cur_book
.
id
,
'author'
:[],
'series'
:[]})
result
.
append
({
'title'
:
_
(
'Hidden Book'
),
'id'
:
cur_book
.
id
,
'author'
:
[],
'series'
:
[]})
return
render_title_template
(
'shelf_order.html'
,
entries
=
result
,
title
=
_
(
u"Change order of Shelf: '
%(name)
s'"
,
name
=
shelf
.
name
),
shelf
=
shelf
,
page
=
"shelforder"
)
cps/subproc_wrapper.py
View file @
24c743d2
...
...
@@ -45,10 +45,10 @@ def process_open(command, quotes=(), env=None, sout=subprocess.PIPE, serr=subpro
def
process_wait
(
command
,
serr
=
subprocess
.
PIPE
):
'''Run command, wait for process to terminate, and return an iterator over lines of its output.'''
# Run command, wait for process to terminate, and return an iterator over lines of its output.
p
=
process_open
(
command
,
serr
=
serr
)
p
.
wait
()
for
l
in
p
.
stdout
.
readlines
():
if
isinstance
(
l
,
bytes
):
l
=
l
.
decode
(
'utf-8'
)
yield
l
for
l
ine
in
p
.
stdout
.
readlines
():
if
isinstance
(
l
ine
,
bytes
):
l
ine
=
line
.
decode
(
'utf-8'
)
yield
l
ine
cps/templates/list.html
View file @
24c743d2
...
...
@@ -4,18 +4,18 @@
<div
class=
"filterheader hidden-xs hidden-sm"
>
{% if entries.__len__() %}
{% if
entries[0][0].sort
%}
<button
id=
"sort_name"
class=
"btn btn-
success
"
><b>
B,A
<->
A B
</b></button>
{% if
data == 'author'
%}
<button
id=
"sort_name"
class=
"btn btn-
primary
"
><b>
B,A
<->
A B
</b></button>
{% endif %}
{% endif %}
<button
id=
"desc"
class=
"btn btn-
success
"
><span
class=
"glyphicon glyphicon-sort-by-alphabet"
></span></button>
<button
id=
"asc"
class=
"btn btn-
success
"
><span
class=
"glyphicon glyphicon-sort-by-alphabet-alt"
></span></button>
<button
id=
"desc"
class=
"btn btn-
primary
"
><span
class=
"glyphicon glyphicon-sort-by-alphabet"
></span></button>
<button
id=
"asc"
class=
"btn btn-
primary
"
><span
class=
"glyphicon glyphicon-sort-by-alphabet-alt"
></span></button>
{% if charlist|length %}
<button
id=
"all"
class=
"btn btn-
success
"
>
{{_('All')}}
</button>
<button
id=
"all"
class=
"btn btn-
primary
"
>
{{_('All')}}
</button>
{% endif %}
<div
class=
"btn-group character"
role=
"group"
>
{% for char in charlist%}
<button
class=
"btn btn-
success
char"
>
{{char.char}}
</button>
<button
class=
"btn btn-
primary
char"
>
{{char.char}}
</button>
{% endfor %}
</div>
</div>
...
...
cps/ub.py
View file @
24c743d2
This diff is collapsed.
Click to expand it.
cps/updater.py
View file @
24c743d2
...
...
@@ -69,7 +69,7 @@ class Updater(threading.Thread):
def
get_available_updates
(
self
,
request_method
,
locale
):
if
config
.
config_updatechannel
==
constants
.
UPDATE_STABLE
:
return
self
.
_stable_available_updates
(
request_method
)
return
self
.
_nightly_available_updates
(
request_method
,
locale
)
return
self
.
_nightly_available_updates
(
request_method
,
locale
)
def
do_work
(
self
):
try
:
...
...
@@ -132,7 +132,7 @@ class Updater(threading.Thread):
def
pause
(
self
):
self
.
can_run
.
clear
()
#should just resume the thread
#
should just resume the thread
def
resume
(
self
):
self
.
can_run
.
set
()
...
...
@@ -268,7 +268,7 @@ class Updater(threading.Thread):
def
is_venv
(
self
):
if
(
hasattr
(
sys
,
'real_prefix'
))
or
(
hasattr
(
sys
,
'base_prefix'
)
and
sys
.
base_prefix
!=
sys
.
prefix
):
return
os
.
sep
+
os
.
path
.
relpath
(
sys
.
prefix
,
constants
.
BASE_DIR
)
return
os
.
sep
+
os
.
path
.
relpath
(
sys
.
prefix
,
constants
.
BASE_DIR
)
else
:
return
False
...
...
@@ -280,7 +280,7 @@ class Updater(threading.Thread):
@
classmethod
def
_stable_version_info
(
cls
):
return
constants
.
STABLE_VERSION
# Current version
return
constants
.
STABLE_VERSION
# Current version
def
_nightly_available_updates
(
self
,
request_method
,
locale
):
tz
=
datetime
.
timedelta
(
seconds
=
time
.
timezone
if
(
time
.
localtime
()
.
tm_isdst
==
0
)
else
time
.
altzone
)
...
...
@@ -436,7 +436,7 @@ class Updater(threading.Thread):
patch_version_update
>
current_version
[
2
])
or
\
minor_version_update
>
current_version
[
1
]:
parents
.
append
([
commit
[
i
][
'tag_name'
],
commit
[
i
][
'body'
]
.
replace
(
'
\r\n
'
,
'<p>'
)])
newer
=
True
newer
=
True
i
-=
1
continue
if
major_version_update
<
current_version
[
0
]:
...
...
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