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
9c1b3f13
Commit
9c1b3f13
authored
Mar 16, 2019
by
Ozzieisaacs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improved sorting for rated,random, hot books, read/unread book
parent
a66873a9
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
445 additions
and
426 deletions
+445
-426
admin.py
cps/admin.py
+3
-2
editbooks.py
cps/editbooks.py
+2
-1
helper.py
cps/helper.py
+112
-0
opds.py
cps/opds.py
+2
-2
discover.html
cps/templates/discover.html
+0
-1
index.html
cps/templates/index.html
+7
-7
layout.html
cps/templates/layout.html
+1
-13
ub.py
cps/ub.py
+6
-6
web.py
cps/web.py
+312
-394
No files found.
cps/admin.py
View file @
9c1b3f13
...
@@ -25,8 +25,8 @@ import os
...
@@ -25,8 +25,8 @@ import os
from
flask
import
Blueprint
,
flash
,
redirect
,
url_for
from
flask
import
Blueprint
,
flash
,
redirect
,
url_for
from
flask
import
abort
,
request
,
make_response
from
flask
import
abort
,
request
,
make_response
from
flask_login
import
login_required
,
current_user
,
logout_user
from
flask_login
import
login_required
,
current_user
,
logout_user
from
web
import
admin_required
,
render_title_template
,
before_request
,
speaking_language
,
unconfigured
,
\
from
web
import
admin_required
,
render_title_template
,
before_request
,
unconfigured
,
\
login_required_if_no_ano
,
check_valid_domain
login_required_if_no_ano
from
cps
import
db
,
ub
,
Server
,
get_locale
,
config
,
app
,
updater_thread
,
babel
from
cps
import
db
,
ub
,
Server
,
get_locale
,
config
,
app
,
updater_thread
,
babel
import
json
import
json
from
datetime
import
datetime
,
timedelta
from
datetime
import
datetime
,
timedelta
...
@@ -37,6 +37,7 @@ from babel import Locale as LC
...
@@ -37,6 +37,7 @@ from babel import Locale as LC
from
sqlalchemy.exc
import
IntegrityError
from
sqlalchemy.exc
import
IntegrityError
from
gdriveutils
import
is_gdrive_ready
,
gdrive_support
,
downloadFile
,
deleteDatabaseOnChange
,
listRootFolders
from
gdriveutils
import
is_gdrive_ready
,
gdrive_support
,
downloadFile
,
deleteDatabaseOnChange
,
listRootFolders
import
helper
import
helper
from
helper
import
speaking_language
,
check_valid_domain
from
werkzeug.security
import
generate_password_hash
from
werkzeug.security
import
generate_password_hash
try
:
try
:
from
imp
import
reload
from
imp
import
reload
...
...
cps/editbooks.py
View file @
9c1b3f13
...
@@ -31,8 +31,9 @@ import json
...
@@ -31,8 +31,9 @@ import json
from
flask_babel
import
gettext
as
_
from
flask_babel
import
gettext
as
_
from
uuid
import
uuid4
from
uuid
import
uuid4
import
helper
import
helper
from
helper
import
order_authors
,
common_filters
from
flask_login
import
current_user
from
flask_login
import
current_user
from
web
import
login_required_if_no_ano
,
common_filters
,
order_authors
,
render_title_template
,
edit_required
,
\
from
web
import
login_required_if_no_ano
,
render_title_template
,
edit_required
,
\
upload_required
,
login_required
,
EXTENSIONS_UPLOAD
upload_required
,
login_required
,
EXTENSIONS_UPLOAD
import
gdriveutils
import
gdriveutils
from
shutil
import
move
,
copyfile
from
shutil
import
move
,
copyfile
...
...
cps/helper.py
View file @
9c1b3f13
...
@@ -32,9 +32,15 @@ from flask import send_from_directory, make_response, redirect, abort
...
@@ -32,9 +32,15 @@ from flask import send_from_directory, make_response, redirect, abort
from
flask_babel
import
gettext
as
_
from
flask_babel
import
gettext
as
_
from
flask_login
import
current_user
from
flask_login
import
current_user
from
babel.dates
import
format_datetime
from
babel.dates
import
format_datetime
from
babel.core
import
UnknownLocaleError
from
datetime
import
datetime
from
datetime
import
datetime
from
babel
import
Locale
as
LC
import
shutil
import
shutil
import
requests
import
requests
from
sqlalchemy.sql.expression
import
true
,
and_
,
false
,
text
,
func
from
iso639
import
languages
as
isoLanguages
from
pagination
import
Pagination
try
:
try
:
import
gdriveutils
as
gd
import
gdriveutils
as
gd
except
ImportError
:
except
ImportError
:
...
@@ -558,3 +564,109 @@ def render_task_status(tasklist):
...
@@ -558,3 +564,109 @@ def render_task_status(tasklist):
renderedtasklist
.
append
(
task
)
renderedtasklist
.
append
(
task
)
return
renderedtasklist
return
renderedtasklist
# Language and content filters for displaying in the UI
def
common_filters
():
if
current_user
.
filter_language
()
!=
"all"
:
lang_filter
=
db
.
Books
.
languages
.
any
(
db
.
Languages
.
lang_code
==
current_user
.
filter_language
())
else
:
lang_filter
=
true
()
content_rating_filter
=
false
()
if
current_user
.
mature_content
else
\
db
.
Books
.
tags
.
any
(
db
.
Tags
.
name
.
in_
(
config
.
mature_content_tags
()))
return
and_
(
lang_filter
,
~
content_rating_filter
)
# Creates for all stored languages a translated speaking name in the array for the UI
def
speaking_language
(
languages
=
None
):
if
not
languages
:
languages
=
db
.
session
.
query
(
db
.
Languages
)
.
all
()
for
lang
in
languages
:
try
:
cur_l
=
LC
.
parse
(
lang
.
lang_code
)
lang
.
name
=
cur_l
.
get_language_name
(
get_locale
())
except
UnknownLocaleError
:
lang
.
name
=
_
(
isoLanguages
.
get
(
part3
=
lang
.
lang_code
)
.
name
)
return
languages
# checks if domain is in database (including wildcards)
# example SELECT * FROM @TABLE WHERE 'abcdefg' LIKE Name;
# from https://code.luasoftware.com/tutorials/flask/execute-raw-sql-in-flask-sqlalchemy/
def
check_valid_domain
(
domain_text
):
domain_text
=
domain_text
.
split
(
'@'
,
1
)[
-
1
]
.
lower
()
sql
=
"SELECT * FROM registration WHERE :domain LIKE domain;"
result
=
ub
.
session
.
query
(
ub
.
Registration
)
.
from_statement
(
text
(
sql
))
.
params
(
domain
=
domain_text
)
.
all
()
return
len
(
result
)
# Orders all Authors in the list according to authors sort
def
order_authors
(
entry
):
sort_authors
=
entry
.
author_sort
.
split
(
'&'
)
authors_ordered
=
list
()
error
=
False
for
auth
in
sort_authors
:
# ToDo: How to handle not found authorname
result
=
db
.
session
.
query
(
db
.
Authors
)
.
filter
(
db
.
Authors
.
sort
==
auth
.
lstrip
()
.
strip
())
.
first
()
if
not
result
:
error
=
True
break
authors_ordered
.
append
(
result
)
if
not
error
:
entry
.
authors
=
authors_ordered
return
entry
# Fill indexpage with all requested data from database
def
fill_indexpage
(
page
,
database
,
db_filter
,
order
,
*
join
):
if
current_user
.
show_detail_random
():
randm
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
())
\
.
order_by
(
func
.
random
())
.
limit
(
config
.
config_random_books
)
else
:
randm
=
false
()
off
=
int
(
int
(
config
.
config_books_per_page
)
*
(
page
-
1
))
pagination
=
Pagination
(
page
,
config
.
config_books_per_page
,
len
(
db
.
session
.
query
(
database
)
.
filter
(
db_filter
)
.
filter
(
common_filters
())
.
all
()))
entries
=
db
.
session
.
query
(
database
)
.
join
(
*
join
,
isouter
=
True
)
.
filter
(
db_filter
)
.
filter
(
common_filters
())
.
\
order_by
(
*
order
)
.
offset
(
off
)
.
limit
(
config
.
config_books_per_page
)
.
all
()
for
book
in
entries
:
book
=
order_authors
(
book
)
return
entries
,
randm
,
pagination
# read search results from calibre-database and return it (function is used for feed and simple search
def
get_search_results
(
term
):
q
=
list
()
authorterms
=
re
.
split
(
"[, ]+"
,
term
)
for
authorterm
in
authorterms
:
q
.
append
(
db
.
Books
.
authors
.
any
(
db
.
Authors
.
name
.
ilike
(
"
%
"
+
authorterm
+
"
%
"
)))
db
.
session
.
connection
()
.
connection
.
connection
.
create_function
(
"lower"
,
1
,
db
.
lcase
)
db
.
Books
.
authors
.
any
(
db
.
Authors
.
name
.
ilike
(
"
%
"
+
term
+
"
%
"
))
return
db
.
session
.
query
(
db
.
Books
)
.
filter
(
common_filters
())
.
filter
(
db
.
or_
(
db
.
Books
.
tags
.
any
(
db
.
Tags
.
name
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
series
.
any
(
db
.
Series
.
name
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
authors
.
any
(
and_
(
*
q
)),
db
.
Books
.
publishers
.
any
(
db
.
Publishers
.
name
.
ilike
(
"
%
"
+
term
+
"
%
"
)),
db
.
Books
.
title
.
ilike
(
"
%
"
+
term
+
"
%
"
)))
.
all
()
def
get_unique_other_books
(
library_books
,
author_books
):
# Get all identifiers (ISBN, Goodreads, etc) and filter author's books by that list so we show fewer duplicates
# Note: Not all images will be shown, even though they're available on Goodreads.com.
# See https://www.goodreads.com/topic/show/18213769-goodreads-book-images
identifiers
=
reduce
(
lambda
acc
,
book
:
acc
+
map
(
lambda
identifier
:
identifier
.
val
,
book
.
identifiers
),
library_books
,
[])
other_books
=
filter
(
lambda
book
:
book
.
isbn
not
in
identifiers
and
book
.
gid
[
"#text"
]
not
in
identifiers
,
author_books
)
# Fuzzy match book titles
if
feature_support
[
'levenshtein'
]:
library_titles
=
reduce
(
lambda
acc
,
book
:
acc
+
[
book
.
title
],
library_books
,
[])
other_books
=
filter
(
lambda
author_book
:
not
filter
(
lambda
library_book
:
# Remove items in parentheses before comparing
Levenshtein
.
ratio
(
re
.
sub
(
r"\(.*\)"
,
""
,
author_book
.
title
),
library_book
)
>
0.7
,
library_titles
),
other_books
)
return
other_books
cps/opds.py
View file @
9c1b3f13
...
@@ -30,12 +30,12 @@ import datetime
...
@@ -30,12 +30,12 @@ import datetime
import
ub
import
ub
from
flask_login
import
current_user
from
flask_login
import
current_user
from
functools
import
wraps
from
functools
import
wraps
from
web
import
login_required_if_no_ano
,
fill_indexpage
,
common_filters
,
get_search_results
,
render_read_books
from
web
import
login_required_if_no_ano
,
common_filters
,
get_search_results
,
render_read_books
,
download_required
from
sqlalchemy.sql.expression
import
func
,
text
from
sqlalchemy.sql.expression
import
func
,
text
import
helper
import
helper
from
werkzeug.security
import
check_password_hash
from
werkzeug.security
import
check_password_hash
from
werkzeug.datastructures
import
Headers
from
werkzeug.datastructures
import
Headers
from
web
import
download_required
from
helper
import
fill_indexpage
import
sys
import
sys
try
:
try
:
...
...
cps/templates/discover.html
View file @
9c1b3f13
...
@@ -3,7 +3,6 @@
...
@@ -3,7 +3,6 @@
<div
class=
"discover load-more"
>
<div
class=
"discover load-more"
>
<h2>
{{title}}
</h2>
<h2>
{{title}}
</h2>
<div
class=
"row"
>
<div
class=
"row"
>
{% for entry in entries %}
{% for entry in entries %}
<div
class=
"col-sm-3 col-lg-2 col-xs-6 book"
>
<div
class=
"col-sm-3 col-lg-2 col-xs-6 book"
>
<div
class=
"cover"
>
<div
class=
"cover"
>
...
...
cps/templates/index.html
View file @
9c1b3f13
...
@@ -58,14 +58,14 @@ web. {% for entry in random %}
...
@@ -58,14 +58,14 @@ web. {% for entry in random %}
<div
class=
"discover load-more"
>
<div
class=
"discover load-more"
>
<h2
class=
"{{title}}"
>
{{_(title)}}
</h2>
<h2
class=
"{{title}}"
>
{{_(title)}}
</h2>
<div
class=
"filterheader hidden-xs hidden-sm"
>
<div
class=
"filterheader hidden-xs hidden-sm"
>
<a
id=
"new"
class=
"btn btn-primary"
href=
"{{url_for('web.
newest_books
')}}"
><span
class=
"glyphicon glyphicon-sort-by-order"
></span></a>
<a
id=
"new"
class=
"btn btn-primary"
href=
"{{url_for('web.
books_list', data=page, sort='new
')}}"
><span
class=
"glyphicon glyphicon-sort-by-order"
></span></a>
<a
id=
"old"
class=
"btn btn-primary"
href=
"{{url_for('web.
oldest_books
')}}"
><span
class=
"glyphicon glyphicon-sort-by-order-alt"
></span></a>
<a
id=
"old"
class=
"btn btn-primary"
href=
"{{url_for('web.
books_list', data=page, sort='old
')}}"
><span
class=
"glyphicon glyphicon-sort-by-order-alt"
></span></a>
<a
id=
"asc"
class=
"btn btn-primary"
href=
"{{url_for('web.
titles_ascending
')}}"
><span
class=
"glyphicon glyphicon-font"
></span><span
class=
"glyphicon glyphicon-sort-by-alphabet"
></span></a>
<a
id=
"asc"
class=
"btn btn-primary"
href=
"{{url_for('web.
books_list', data=page, sort='abc
')}}"
><span
class=
"glyphicon glyphicon-font"
></span><span
class=
"glyphicon glyphicon-sort-by-alphabet"
></span></a>
<a
id=
"desc"
class=
"btn btn-primary"
href=
"{{url_for('web.
titles_descending
')}}"
><span
class=
"glyphicon glyphicon-font"
></span><span
class=
"glyphicon glyphicon-sort-by-alphabet-alt"
></span></a>
<a
id=
"desc"
class=
"btn btn-primary"
href=
"{{url_for('web.
books_list', data=page, sort='zyx
')}}"
><span
class=
"glyphicon glyphicon-font"
></span><span
class=
"glyphicon glyphicon-sort-by-alphabet-alt"
></span></a>
<a
id=
"pub_new"
class=
"btn btn-primary"
href=
"{{url_for('web.
titles_descending')}}"
><span
class=
"glyphicon glyphicon-calendar"
></span><span
class=
"glyphicon glyphicon-sort-by-order"
></a>
<a
id=
"pub_new"
class=
"btn btn-primary"
href=
"{{url_for('web.
books_list', data=page, sort='pubnew')}}"
><span
class=
"glyphicon glyphicon-calendar"
></span><span
class=
"glyphicon glyphicon-sort-by-order"
></span
></a>
<a
id=
"pub_old"
class=
"btn btn-primary"
href=
"{{url_for('web.
titles_descending')}}"
><span
class=
"glyphicon glyphicon-calendar"
></span><span
class=
"glyphicon glyphicon-sort-by-order-alt"
></a>
<a
id=
"pub_old"
class=
"btn btn-primary"
href=
"{{url_for('web.
books_list', data=page, sort='pubold')}}"
><span
class=
"glyphicon glyphicon-calendar"
></span><span
class=
"glyphicon glyphicon-sort-by-order-alt"
></span
></a>
<div
class=
"btn-group character"
role=
"group"
>
<div
class=
"btn-group character"
role=
"group"
>
<a
id=
"no_shelf"
class=
"btn btn-primary"
href=
"{{url_for('web.
titles_descending
')}}"
><span
class=
"glyphicon glyphicon-list"
></span><b>
?
</b></a>
<a
id=
"no_shelf"
class=
"btn btn-primary"
href=
"{{url_for('web.
books_list', data=page, sort='pubold
')}}"
><span
class=
"glyphicon glyphicon-list"
></span><b>
?
</b></a>
<div
id=
"all"
class=
"btn btn-primary"
>
{{_('All')}}
</div>
<div
id=
"all"
class=
"btn btn-primary"
>
{{_('All')}}
</div>
</div>
</div>
</div>
</div>
...
...
cps/templates/layout.html
View file @
9c1b3f13
...
@@ -121,22 +121,10 @@
...
@@ -121,22 +121,10 @@
<ul
class=
"list-unstyled"
id=
"scnd-nav"
intent
in-standard-append=
"nav.navigation"
in-mobile-after=
"#main-nav"
in-mobile-class=
"nav navbar-nav"
>
<ul
class=
"list-unstyled"
id=
"scnd-nav"
intent
in-standard-append=
"nav.navigation"
in-mobile-after=
"#main-nav"
in-mobile-class=
"nav navbar-nav"
>
<li
class=
"nav-head hidden-xs"
>
{{_('Browse')}}
</li>
<li
class=
"nav-head hidden-xs"
>
{{_('Browse')}}
</li>
{% if g.user.check_visibility(1024) %}
<!-- ToDo: eliminate -->
{% if g.user.check_visibility(1024) %}
<!-- ToDo: eliminate -->
<!--li id="nav_sort" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-sort-by-attributes"></span>{{_('Sorted Books')}}
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li id="nav_sort_old" {% if page == 'newest' %}class="active"{% endif %}><a href="{{url_for('web.newest_books')}}">{{_('Sort By')}} {{_('Newest')}}</a></li>
<li id="nav_sort_new" {% if page == 'oldest' %}class="active"{% endif %}><a href="{{url_for('web.oldest_books')}}">{{_('Sort By')}} {{_('Oldest')}}</a></li>
<li id="nav_sort_asc" {% if page == 'a-z' %}class="active"{% endif %}><a href="{{url_for('web.titles_ascending')}}">{{_('Sort By')}} {{_('Title')}} ({{_('Ascending')}})</a></li>
<li id="nav_sort_desc" {% if page == 'z-a' %}class="active"{% endif %}><a href="{{url_for('web.titles_descending')}}">{{_('Sort By')}} {{_('Title')}} ({{_('Descending')}})</a></li>
</ul>
</li-->
{%endif%}
{%endif%}
{% for element in sidebar %}
{% for element in sidebar %}
{% if g.user.check_visibility(element['visibility']) and element['public'] %}
{% if g.user.check_visibility(element['visibility']) and element['public'] %}
<li
id=
"nav_{{element['id']}}"
{%
if
page =
=
element
['
page
']
%}
class=
"active"
{%
endif
%}
><a
href=
"{{url_for(element['link'])}}"
><span
class=
"glyphicon {{element['glyph']}}"
></span>
{{_(element['text'])}}
</a></li>
<li
id=
"nav_{{element['id']}}"
{%
if
page =
=
element
['
page
']
%}
class=
"active"
{%
endif
%}
><a
href=
"{{url_for(element['link']
, data=element['page'], sort='new'
)}}"
><span
class=
"glyphicon {{element['glyph']}}"
></span>
{{_(element['text'])}}
</a></li>
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
...
...
cps/ub.py
View file @
9c1b3f13
...
@@ -107,21 +107,21 @@ def get_sidebar_config(kwargs=[]):
...
@@ -107,21 +107,21 @@ def get_sidebar_config(kwargs=[]):
sidebar
.
append
({
"glyph"
:
"glyphicon-book"
,
"text"
:
_
(
'Recently Added'
),
"link"
:
'web.index'
,
"id"
:
"new"
,
sidebar
.
append
({
"glyph"
:
"glyphicon-book"
,
"text"
:
_
(
'Recently Added'
),
"link"
:
'web.index'
,
"id"
:
"new"
,
"visibility"
:
SIDEBAR_RECENT
,
'public'
:
True
,
"page"
:
"root"
,
"visibility"
:
SIDEBAR_RECENT
,
'public'
:
True
,
"page"
:
"root"
,
"show_text"
:
_
(
'Show recent books'
),
"config_show"
:
True
})
"show_text"
:
_
(
'Show recent books'
),
"config_show"
:
True
})
sidebar
.
append
({
"glyph"
:
"glyphicon-fire"
,
"text"
:
_
(
'Hot Books'
),
"link"
:
'web.
hot_books
'
,
"id"
:
"hot"
,
sidebar
.
append
({
"glyph"
:
"glyphicon-fire"
,
"text"
:
_
(
'Hot Books'
),
"link"
:
'web.
books_list
'
,
"id"
:
"hot"
,
"visibility"
:
SIDEBAR_HOT
,
'public'
:
True
,
"page"
:
"hot"
,
"show_text"
:
_
(
'Show hot books'
),
"visibility"
:
SIDEBAR_HOT
,
'public'
:
True
,
"page"
:
"hot"
,
"show_text"
:
_
(
'Show hot books'
),
"config_show"
:
True
})
"config_show"
:
True
})
sidebar
.
append
(
sidebar
.
append
(
{
"glyph"
:
"glyphicon-star"
,
"text"
:
_
(
'Best rated Books'
),
"link"
:
'web.b
est_rated_books
'
,
"id"
:
"rated"
,
{
"glyph"
:
"glyphicon-star"
,
"text"
:
_
(
'Best rated Books'
),
"link"
:
'web.b
ooks_list
'
,
"id"
:
"rated"
,
"visibility"
:
SIDEBAR_BEST_RATED
,
'public'
:
True
,
"page"
:
"rated"
,
"visibility"
:
SIDEBAR_BEST_RATED
,
'public'
:
True
,
"page"
:
"rated"
,
"show_text"
:
_
(
'Show best rated books'
),
"config_show"
:
True
})
"show_text"
:
_
(
'Show best rated books'
),
"config_show"
:
True
})
sidebar
.
append
({
"glyph"
:
"glyphicon-eye-open"
,
"text"
:
_
(
'Read Books'
),
"link"
:
'web.
read_books
'
,
"id"
:
"read"
,
sidebar
.
append
({
"glyph"
:
"glyphicon-eye-open"
,
"text"
:
_
(
'Read Books'
),
"link"
:
'web.
books_list
'
,
"id"
:
"read"
,
"visibility"
:
SIDEBAR_READ_AND_UNREAD
,
'public'
:
(
not
g
.
user
.
is_anonymous
),
"page"
:
"read"
,
"visibility"
:
SIDEBAR_READ_AND_UNREAD
,
'public'
:
(
not
g
.
user
.
is_anonymous
),
"page"
:
"read"
,
"show_text"
:
_
(
'Show read and unread'
),
"config_show"
:
content
})
"show_text"
:
_
(
'Show read and unread'
),
"config_show"
:
content
})
sidebar
.
append
(
sidebar
.
append
(
{
"glyph"
:
"glyphicon-eye-close"
,
"text"
:
_
(
'Unread Books'
),
"link"
:
'web.
unread_books
'
,
"id"
:
"unread"
,
{
"glyph"
:
"glyphicon-eye-close"
,
"text"
:
_
(
'Unread Books'
),
"link"
:
'web.
books_list
'
,
"id"
:
"unread"
,
"visibility"
:
SIDEBAR_READ_AND_UNREAD
,
'public'
:
(
not
g
.
user
.
is_anonymous
),
"page"
:
"read"
,
"visibility"
:
SIDEBAR_READ_AND_UNREAD
,
'public'
:
(
not
g
.
user
.
is_anonymous
),
"page"
:
"
un
read"
,
"show_text"
:
_
(
'Show unread'
),
"config_show"
:
False
})
"show_text"
:
_
(
'Show unread'
),
"config_show"
:
False
})
sidebar
.
append
({
"glyph"
:
"glyphicon-random"
,
"text"
:
_
(
'Discover'
),
"link"
:
'web.
discover
'
,
"id"
:
"rand"
,
sidebar
.
append
({
"glyph"
:
"glyphicon-random"
,
"text"
:
_
(
'Discover'
),
"link"
:
'web.
books_list
'
,
"id"
:
"rand"
,
"visibility"
:
SIDEBAR_RANDOM
,
'public'
:
True
,
"page"
:
"discover"
,
"visibility"
:
SIDEBAR_RANDOM
,
'public'
:
True
,
"page"
:
"discover"
,
"show_text"
:
_
(
'Show random books'
),
"config_show"
:
True
})
"show_text"
:
_
(
'Show random books'
),
"config_show"
:
True
})
sidebar
.
append
({
"glyph"
:
"glyphicon-inbox"
,
"text"
:
_
(
'Categories'
),
"link"
:
'web.category_list'
,
"id"
:
"cat"
,
sidebar
.
append
({
"glyph"
:
"glyphicon-inbox"
,
"text"
:
_
(
'Categories'
),
"link"
:
'web.category_list'
,
"id"
:
"cat"
,
...
...
cps/web.py
View file @
9c1b3f13
This diff is collapsed.
Click to expand it.
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