', methods=['GET'])
875 | @login_required
876 | def author(author_name):
877 | # data = get_response('http://novel.juhe.im/author-books?author=' + author_name)
878 | data = get_response('http://api.zhuishushenqi.com/book/accurate-search?author=' + author_name)
879 | lis = list()
880 | for book in data['books']:
881 | lis.append({
882 | '_id': book['_id'],
883 | 'title': book['title'],
884 | 'cover': book['cover'],
885 | 'retentionRatio': book['retentionRatio'],
886 | 'latelyFollower': book['latelyFollower'],
887 | 'author': author_name
888 | })
889 | return render_template('author.html', title=author_name, lis=lis)
890 |
--------------------------------------------------------------------------------
/app/static/read.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koala060528/LightReader/d5525e10e4b6ea211cb47e75b969bf6e5307b35f/app/static/read.ico
--------------------------------------------------------------------------------
/app/tasks.py:
--------------------------------------------------------------------------------
1 | from app import app, db, redis
2 | from rq import get_current_job
3 | from app.models import Task, Download, User
4 | from app.routes import get_response, get_content_list, reg_biquge, get_content_text
5 | import os
6 | from config import Config
7 | from hashlib import md5
8 | from datetime import datetime
9 |
10 | app.app_context().push()
11 |
12 |
13 | def _set_task_progress(progress):
14 | job = get_current_job()
15 | if job:
16 | job.meta['progress'] = progress
17 | job.save_meta()
18 | task = Task.query.get(job.get_id())
19 | # task.user.add_notification('task_progress', {'task_id': job.get_id(), 'progress': progress})
20 |
21 | if progress >= 100:
22 | task.complete = True
23 |
24 | db.session.commit()
25 |
26 |
27 | def download(user_id, source_id, book_id):
28 | try:
29 | d = Download.query.filter_by(book_id=book_id, source_id=source_id).first()
30 | # 这里必须使用id查询user而不能直接使用current_user
31 | u = User.query.get(user_id)
32 |
33 | # 获取章节信息
34 | # data = get_response('http://novel.juhe.im/book-chapters/' + source_id)
35 | data = get_response('http://api.zhuishushenqi.com/toc/{0}?view=chapters'.format(source_id))
36 | path = os.path.join(Config.UPLOADS_DEFAULT_DEST, 'downloads')
37 | if not os.path.exists(path):
38 | os.makedirs(path)
39 |
40 | # 定义文件名
41 | fileName = md5((book_id + source_id).encode("utf8")).hexdigest()[:10] + '.txt'
42 | # fileName = os.path.join(path, book_title + '.txt')
43 | # if os.path.exists(fileName):
44 | # os.remove(fileName)
45 |
46 | chapter_list = data.get('chapters')
47 | if d:
48 | # 截取需要下载的章节列表
49 | new = False
50 | download_list = chapter_list[d.chapter + 1:]
51 | book_title = d.book_name
52 | d.chapter = len(chapter_list) - 1
53 | d.time = datetime.utcnow()
54 | d.lock = True # 给下载加锁
55 | d.chapter_name = chapter_list[len(chapter_list) - 1].get('title')
56 | else:
57 | new = True
58 | # 获取书籍简介
59 | # data1 = get_response('http://novel.juhe.im/book-info/' + book_id)
60 | data1 = get_response('http://api.zhuishushenqi.com/book/' + book_id)
61 | book_title = data1.get('title')
62 | author = data1.get('author')
63 | longIntro = data1.get('longIntro')
64 | download_list = chapter_list
65 |
66 | d = Download(user=u, book_id=book_id, source_id=source_id, chapter=len(chapter_list) - 1,
67 | book_name=book_title, time=datetime.utcnow(), txt_name=fileName, lock=True,
68 | chapter_name=chapter_list[-1].get('title'))
69 | db.session.add(d)
70 | db.session.commit()
71 |
72 | with open(os.path.join(path, fileName), 'a', encoding='utf-8') as f:
73 | _set_task_progress(0)
74 | i = 0
75 | if new:
76 | f.writelines(
77 | [' ', book_title, '\n', '\n', ' ', author, '\n', '\n', ' ', longIntro, '\n', '\n'])
78 | for chapter in download_list:
79 | title = chapter.get('title')
80 | url = chapter.get('link')
81 | # 为各个源添加特殊处理
82 | if data['source'] == 'biquge':
83 | url = reg_biquge(data['link'], url)
84 |
85 | li = get_content_list(key=None, url=url)
86 | f.writelines(['\n', ' ', title, '\n', '\n'])
87 | for sentence in li:
88 | f.writelines([' ', sentence, '\n', '\n'])
89 | i += 1
90 | _set_task_progress(100 * i // len(download_list))
91 | d.lock = False # 给下载解锁
92 | db.session.add(d)
93 | db.session.commit()
94 | except Exception as e:
95 | print(e)
96 |
97 |
98 | def cache(key, url):
99 | txt = get_content_text(url)
100 | # print(txt)
101 | redis.set(key, txt, ex=86400)
102 |
--------------------------------------------------------------------------------
/app/templates/_book.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ book['title'] }}
6 |
7 | |
8 |
9 |
10 |
11 | {{ book['author'] }}
12 | |
13 |
14 |
15 | 热度:{{ book['latelyFollower'] }} 留存率:{{ book['retentionRatio'] }}
16 | |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/templates/_book_list.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ bookList['title'] }}
5 |
6 | |
7 |
8 |
9 |
10 | 书籍数量:{{ bookList['bookCount'] }} 收藏次数:{{ bookList['collectorCount'] }}
11 | |
12 |
13 |
14 |
15 | 简介:{{ bookList['desc'] }}
16 | |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/templates/_book_list_book.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ book['book']['title'] }}
6 |
7 | |
8 |
9 |
10 |
11 | {{ book['book']['author'] }}
12 | |
13 |
14 |
15 | 热度:{{ book['book']['latelyFollower'] }} 留存率:{{ '%.2f' % book['book']['retentionRatio'] }} 字数:{{ book['book']['wordCount'] }}
16 | |
17 |
18 |
19 | 评语:{{ book['comment'] }} |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/templates/_user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ u[1] }}
5 |
6 |
7 | {% if u[2] %}
8 | ★
9 | {% else %}
10 | ☆
11 | {% endif %}
12 |
13 | 上次登录:{{ moment(u[3]).fromNow() }}
14 | |
15 |
16 |
--------------------------------------------------------------------------------
/app/templates/author.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 |
4 | {% block app_content %}
5 | {% if form %}
6 | {{ wtf.quick_form(form) }}
7 | {% endif %}
8 | {% if lis %}
9 | {% for book in lis %}
10 | {% include '_book.html' %}
11 |
12 | {% endfor %}
13 | {% endif %}
14 | {% endblock %}
15 |
16 | {% block navbar %}
17 | {{ super() }}
18 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/background.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 |
5 | 用户管理
6 |
7 |
8 | 下载管理
9 |
10 |
11 | {% endblock %}
12 |
13 | {% block navbar %}
14 | {{ super() }}
15 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/base.html:
--------------------------------------------------------------------------------
1 | {% extends 'bootstrap/base.html' %}
2 |
3 | {% block title %}
4 | {% if title %}
5 | {{ title }}
6 | {% else %}
7 | Novel Reader
8 | {% endif %}
9 | {% endblock %}
10 |
11 | {% block navbar %}
12 |
25 |
56 |
57 | {% endblock %}
58 |
59 | {% block content %}
60 |
61 | {% if current_user.is_authenticated %}
62 | {% with tasks = current_user.get_tasks_in_progress() %}
63 | {% if tasks %}
64 | {% for task in tasks %}
65 |
66 | 正在生成({{ task.description }}):
67 | {{ task.get_progress() }}%
68 |
69 |
70 |
71 | {% endfor %}
72 |
73 | {% endif %}
74 | {% endwith %}
75 |
76 | {% endif %}
77 |
78 | {% with messages = get_flashed_messages() %}
79 | {% if messages %}
80 | {% for message in messages %}
81 |
{{ message }}
82 | {% endfor %}
83 | {% endif %}
84 | {% endwith %}
85 |
86 | {# application content needs to be provided in the app_content block #}
87 | {% block app_content %}{% endblock %}
88 |
89 | {% endblock %}
90 |
91 | {% block scripts %}
92 | {{ super() }}
93 | {{ moment.include_moment() }}
94 | {{ moment.lang('zh-CN') }}
95 |
96 |
144 | {% endblock %}
145 |
--------------------------------------------------------------------------------
/app/templates/book_detail.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 | {{ data.get('title') }}
5 |
6 | 作者:{{ data.get('author') }}
7 |
8 | 简介:
9 | {% for p in data.get('longIntro') %}
10 |
11 | {{ p }}
12 |
13 | {% endfor %}
14 | {% if source_type !=None %}
15 | {% if source_type == 'vip' %}
16 |
17 | (提示:当前书源失效,请 换源 )
18 |
19 | {% endif %}
20 | 最近更新:{{ moment(data.get('updated')).fromNow() }}
21 | {% if lastIndex %}
22 | 最新章节:
23 | {{ data.get('lastChapter') }}
24 |
25 | {% else %}
26 | 最新章节:{{ data.get('lastChapter') }}
27 | {% endif %}
28 |
29 |
30 | {% if is_subscribe %}
31 | 阅读进度: {{ readingChapter }}
33 | {% if next %}
34 | 下一章
36 | {% endif %}
37 |
38 | {% endif %}
39 | 阅读选项:
40 | 章节列表
41 | 换源
42 | {% if is_subscribe %}
43 | 取消订阅
44 | {% else %}
45 | 订阅
46 | {% endif %}
47 |
48 | 下载
49 |
50 |
51 | {% else %}
52 |
53 | (提示:当前书源失效,请 换源 )
54 |
55 | {% endif %}
56 |
57 |
58 | {% endblock %}
59 |
60 | {% block navbar %}
61 | {{ super() }}
62 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/book_list_detail.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 | {{ data['bookList']['title'] }}
5 |
6 | 作者:{{ data['bookList']['author']['nickname'] }}
7 |
8 | 简介:
9 |
10 |
11 | {{ data['bookList']['desc'] }}
12 |
13 |
14 | 创建时间:{{ moment(data['bookList']['created']).fromNow() }}
15 | 最近更新:{{ moment(data['bookList']['updated']).fromNow() }}
16 |
17 |
18 | {% for book in data['bookList']['books'] %}
19 | {% include '_book_list_book.html' %}
20 | {% endfor %}
21 | {% endblock %}
22 |
23 | {% block navbar %}
24 | {{ super() }}
25 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/book_list_rank.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 | {% for bookList in data['bookLists'] %}
5 | {% include '_book_list.html' %}
6 | {% endfor %}
7 |
8 |
9 |
10 |
11 |
12 | {% if start > 0 %}
13 | 上一页
14 | {% else %}
15 | 上一页
16 | {% endif %}
17 |
18 | |
19 |
20 | {% if next_page %}
21 | 下一页
22 | {% else %}
23 | 下一页
24 | {% endif %}
25 | |
26 |
27 |
28 |
29 | {% endblock %}
30 |
31 | {% block navbar %}
32 | {{ super() }}
33 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/chapter.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 |
4 | {% block app_content %}
5 |
6 | {% for c in data %}
7 | {{ c.title }}
8 | {% endfor %}
9 |
10 |
11 |
12 |
13 | {% if page != 0 %}
14 | 首页
15 | {% else %}
16 | 首页
17 | {% endif %}
18 | |
19 |
20 | {% if page != 0 %}
21 | 上一页
22 | {% else %}
23 | 上一页
24 | {% endif %}
25 | |
26 |
27 | {% if page != page_count %}
28 | 下一页
29 | {% else %}
30 | 下一页
31 | {% endif %}
32 | |
33 |
34 | {% if page != page_count %}
35 | 尾页
36 | {% else %}
37 | 尾页
38 | {% endif %}
39 | |
40 |
41 |
42 |
43 |
51 | |
52 |
53 | {% endblock %}
54 |
55 | {% block navbar %}
56 | {{ super() }}
57 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/classify.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 |
4 | {% block app_content %}
5 | {% if form %}
6 | {{ wtf.quick_form(form) }}
7 | {% endif %}
8 | {% if data %}
9 | {% for book in data %}
10 | {% include '_book.html' %}
11 |
12 | {% endfor %}
13 | {% endif %}
14 |
15 |
16 |
17 |
18 | {% if start > 0 %}
19 | 上一页
20 | {% else %}
21 | 上一页
22 | {% endif %}
23 |
24 | |
25 |
26 | {% if next %}
27 | 下一页
28 | {% else %}
29 | 下一页
30 | {% endif %}
31 | |
32 |
33 |
34 |
35 | {% endblock %}
36 |
37 | {% block navbar %}
38 | {{ super() }}
39 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/download_list.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 |
4 | {% block app_content %}
5 | 下载列表
6 |
7 | {% for d in lis %}
8 |
9 | {{ d['book_name'] }}--{{ d['source_name'] }}
10 | ·文件名:{{ d['txt_name'] }} ·{{ d['txt_size'] }}MB ·{{ d['time'] }}
11 | ·下载用户:{{ d['user_name'] }} ·{% if d['chapter_name'] %}
12 | {{ d['chapter_name'] }}
13 | {% else %}
14 | {{ d['chapter'] }} 章
15 | {% endif %}
16 |
17 | ·下载
18 | ·删除
19 |
20 |
21 |
22 |
23 | {% endfor %}
24 |
25 | {% endblock %}
26 |
27 | {% block navbar %}
28 | {{ super() }}
29 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/index.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 |
4 | {% block app_content %}
5 | {% if not current_user.is_anonymous %}
6 | 欢迎,{{ current_user.name }}
7 | {% else %}
8 | 欢迎,旅行者
9 | {% endif %}
10 |
11 | 订阅
12 |
13 | {% if not current_user.is_anonymous %}
14 |
15 |
16 |
17 | {# 订阅列表
#}
18 | {% if data.get('subscribe') %}
19 | {% for book in data.get('subscribe') %}
20 |
21 |
22 |
23 | {{ book['title'] }}
24 |
25 | |
26 |
27 |
28 |
29 | {% if book['last_chapter'] %}
30 | {{ book['last_chapter'] }}({{ moment(book['updated']).fromNow() }})
31 | {% else %}
32 | 获取更新失败,请重试
33 | {% endif %}
34 | |
35 |
36 |
37 |
38 |
39 |
40 | {% endfor %}
41 | {% else %}
42 | 你的订阅列表是空的
43 | {% endif %}
44 |
45 | {% else %}
46 |
47 |
48 | 要查看你的订阅列表,请 登录,或 注册
49 |
50 | {% endif %}
51 |
52 | {% if form %}
53 | 探索
54 | {# {{ wtf.quick_form(form) }}#}
55 |
60 |
61 | {% endif %}
62 |
63 |
64 | {% if data['classify'] %}
65 | 分类
66 |
67 | 男频
68 |
69 | {% for i in data['classify']['male'] %}
70 |
71 |
72 | {{ i['name'] }}
73 |
74 |
75 |
76 | {% endfor %}
77 |
78 |
79 |
80 |
81 | 女频
82 |
83 | {% for i in data['classify']['female'] %}
84 |
85 |
86 | {{ i['name'] }}
87 |
88 |
89 |
90 | {% endfor %}
91 |
92 |
93 |
94 |
95 | 出版
96 |
97 | {% for i in data['classify']['press'] %}
98 |
99 |
100 | {{ i['name'] }}
101 |
102 |
103 |
104 | {% endfor %}
105 |
106 |
107 | {% endif %}
108 |
109 | {% if data['rank'] %}
110 |
111 | 排行
112 |
113 | 男频
114 |
115 | {% for i in data['rank']['male'] %}
116 |
117 | {{ i['shortTitle'] }}
118 |
119 |
120 | {% endfor %}
121 |
122 |
123 |
124 |
125 | 女频
126 |
127 | {% for i in data['rank']['female'] %}
128 |
129 | {{ i['shortTitle'] }}
130 |
131 |
132 | {% endfor %}
133 |
134 |
135 | {% endif %}
136 |
137 |
138 |
139 | 书单
140 |
141 | 男频
142 |
143 | 最多收藏
144 |
145 |
146 |
147 | 本周最热
148 |
149 |
150 |
151 | 最新发布
152 |
153 |
154 |
155 |
156 | 女频
157 |
158 | 最多收藏
159 |
160 |
161 |
162 | 本周最热
163 |
164 |
165 |
166 | 最新发布
167 |
168 |
169 |
170 |
171 | {% endblock %}
172 |
173 | {% block navbar %}
174 | {{ super() }}
175 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/login.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 | {% block app_content %}
4 | 登录
5 | {{ wtf.quick_form(form) }}
6 |
7 | 如果你没有账号,请注册
8 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/permission_denied.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 | Permission Denied
5 | {{ message }}
6 |
7 |
12 | {% endblock %}
13 |
14 | {% block navbar %}
15 | {{ super() }}
16 |
25 |
26 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/rank.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 |
4 | {% block app_content %}
5 | {% for book in data['ranking']['books'] %}
6 | {% include '_book.html' %}
7 | {% endfor %}
8 | {% endblock %}
9 |
10 | {% block navbar %}
11 | {{ super() }}
12 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/read.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 | {{ title }}
5 |
6 |
7 |
8 |
9 |
10 | {% if pre is not none %}
11 | 上一章
13 | {% else %}
14 | 上一章
15 | {% endif %}
16 |
17 | |
18 |
19 |
20 | 目录
22 |
23 | |
24 |
25 |
26 | {% if next is not none %}
27 | 下一章
29 | {% else %}
30 | 下一章
31 | {% endif %}
32 | |
33 |
34 |
35 |
36 |
37 |
38 | {% for p in body %}
39 |
40 | {{ p }}
41 |
42 | {% endfor %}
43 |
44 |
45 |
46 |
47 |
48 |
49 | {% if pre is not none %}
50 | 上一章
52 | {% else %}
53 | 上一章
54 | {% endif %}
55 |
56 | |
57 |
58 |
59 | 目录
61 |
62 | |
63 |
64 |
65 | {% if next is not none %}
66 | 下一章
68 | {% else %}
69 | 下一章
70 | {% endif %}
71 | |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | 详情
80 |
81 | |
82 |
83 | 换源
85 |
86 | |
87 |
88 | 设置
90 |
91 | |
92 |
93 | 主页
94 | |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | {% endblock %}
103 |
104 | {% block navbar %}
105 | {{ super() }}
106 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/read_setting.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 |
5 |
6 |
7 |
8 |
9 | 阅读模式:
10 |
11 |
14 |
17 |
18 |
19 | 字体大小:
20 |
21 |
24 |
27 |
30 |
33 |
36 |
37 |
38 | 预览:
39 |
40 |
41 | {% for p in body %}
42 |
43 | {{ p }}
44 |
45 | {% endfor %}
46 |
47 |
48 |
95 | {% endblock %}
96 |
97 | {% block navbar %}
98 | {{ super() }}
99 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/register.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 | {% block app_content %}
4 | 注册
5 | {{ wtf.quick_form(form) }}
6 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/search_result.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 |
4 | {% block app_content %}
5 | {% if form %}
6 | {{ wtf.quick_form(form) }}
7 | {% endif %}
8 | {% if data %}
9 | {% for book in data %}
10 | {% include '_book.html' %}
11 |
12 | {% endfor %}
13 | {% endif %}
14 |
15 | {% endblock %}
16 |
17 | {% block navbar %}
18 | {{ super() }}
19 | {% endblock %}
20 |
--------------------------------------------------------------------------------
/app/templates/source.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 | {% if data %}
5 | {% for s in data %}
6 |
7 | {{ s.get('name') }}
8 | {% if s.get('current')==True %}
9 | |
10 |
11 | (当前选择)
12 |
13 | |
14 | {% endif %}
15 |
16 | |
17 |
18 |
19 | 最新章节:{{ s.get('lastChapter') }} -- 最近更新:{{ moment(s.get('updated')).fromNow() }}
20 |
21 |
22 | {% endfor %}
23 | {% endif %}
24 | {% endblock %}
25 |
26 | {% block navbar %}
27 | {{ super() }}
28 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/source_not_found.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 | Source Not Found
5 | {{ message }}
6 |
7 |
12 | {% endblock %}
13 |
14 | {% block navbar %}
15 | {{ super() }}
16 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/user_detail.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 |
5 |
6 | 用户名:{{ dic['name'] }}
7 |
8 |
9 |
10 |
11 | 序号:{{ dic['id'] }}
12 |
13 |
14 |
15 | {% if dic['is_admin'] %}
16 | 管理员:是
17 | {% else %}
18 | 管理员:否
19 | {% endif %}
20 |
21 |
22 |
23 | {% if dic['can_download'] %}
24 | 能否下载:是
25 | {% else %}
26 | 能否下载:否
27 | {% endif %}
28 |
29 | 更改
30 |
31 |
32 |
33 | 最近活动:{{ moment(dic['last_seen'] ).fromNow() }}
34 |
35 |
36 |
37 | UA:{{ dic['user_agent'] }}
38 |
39 |
40 |
41 | IP:{{ dic['user_ip'] }}
42 |
43 |
44 |
45 | 删除用户
46 |
47 |
48 |
49 | 订阅列表:
50 |
51 |
52 |
53 | {% for s in dic['subscribing'] %}
54 | {{ s['book_name'] }}
55 | ·{% if s['chapter_name'] %}
56 | {{ s['chapter_name'] }}
57 | {% else %}
58 | {{ s['chapter'] }} 章
59 | {% endif %}
60 | ·{{ moment(s['time'] ).fromNow() }}
61 |
62 |
63 | {% endfor %}
64 |
65 |
66 | {% endblock %}
67 |
68 | {% block navbar %}
69 | {{ super() }}
70 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/user_list.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% import 'bootstrap/wtf.html' as wtf %}
3 |
4 | {% block app_content %}
5 | {% if form %}
6 | {{ wtf.quick_form(form) }}
7 | {% endif %}
8 | {% if lis %}
9 | {% for u in lis %}
10 | {% include '_user.html' %}
11 |
12 | {% endfor %}
13 | {% endif %}
14 |
15 | {% endblock %}
16 |
17 | {% block navbar %}
18 | {{ super() }}
19 | {% endblock %}
--------------------------------------------------------------------------------
/app/templates/view_documents.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 |
3 | {% block app_content %}
4 | 右键另存为!请使用utf-8格式解码txt文件!
5 | {{ book_title }}
6 |
7 |
12 | {% endblock %}
13 |
14 | {% block navbar %}
15 | {{ super() }}
16 | {% endblock %}
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 |
4 | class Config(object):
5 | SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
6 | # database config
7 | D_USER = os.environ.get('D_USER') or 'koala'
8 | D_PASSWORD = os.environ.get('D_PASSWORD') or '954193221'
9 | D_HOST = '127.0.0.1'
10 | D_PORT = 3306
11 | D_DATABASE = 'lightreader'
12 | # sql连接字符串
13 | SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://%s:%s@%s:%s/%s' % (D_USER, D_PASSWORD, D_HOST, D_PORT, D_DATABASE)
14 | SQLALCHEMY_TRACK_MODIFICATIONS = False
15 |
16 | # redis设置
17 | REDIS_URL = os.environ.get('REDIS_URL') or 'redis://'
18 |
19 | # 语言设置
20 | LANGUAGES = ['zh-CN']
21 |
22 | # 每页显示的数量
23 | CHAPTER_PER_PAGE = 50
24 |
25 | # api url
26 | # 书籍详情页
27 | # BOOK_DETAIL = 'http://novel.juhe.im/book-info/{book_id}'
28 | BOOK_DETAIL = 'http://api.zhuishushenqi.com/book/{book_id}'
29 | # 章节列表
30 | # CHAPTER_LIST = 'http://novel.juhe.im/book-chapters/{book_id}'
31 | CHAPTER_LIST = 'http://api.zhuishushenqi.com/mix-atoc/{book_id}?view=chapters'
32 | # 章节详情
33 | # CHAPTER_DETAIL = 'http://novel.juhe.im/chapters/{0}'
34 | CHAPTER_DETAIL = 'http://chapter2.zhuishushenqi.com/chapter/{0}'
35 |
36 | # 文件目录
37 | UPLOADS_DEFAULT_DEST = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'files')
38 |
39 | # headers
40 | headers = {
41 | 'User-Agent': 'ZhuiShuShenQi/3.172.1 (Android 5.1.1; Meizu X86 / Meizu Mx5; China Mobile GSM)[preload=false;locale=zh_CN;clientidbase=]'
42 | }
43 |
--------------------------------------------------------------------------------
/create_db.py:
--------------------------------------------------------------------------------
1 | import pymysql
2 | from config import Config
3 | from app import db
4 |
5 | conn = pymysql.connect(host=Config.D_HOST, port=Config.D_PORT, user=Config.D_USER, passwd=Config.D_PASSWORD)
6 | cursor = conn.cursor()
7 | cursor.execute("show databases like 'lightreader'")
8 | create_db = cursor.fetchall()
9 | if not create_db:
10 | cursor.execute('create database lightreader')
11 | cursor.close()
12 | conn.close()
13 |
14 | db.create_all()
15 |
--------------------------------------------------------------------------------
/debug.py:
--------------------------------------------------------------------------------
1 | from app import app
2 |
3 | app.run(debug=True, port=5001, host='127.0.0.1')
4 |
--------------------------------------------------------------------------------
/debug_server.py:
--------------------------------------------------------------------------------
1 | from app import app
2 |
3 | app.run(debug=True, port=5001, host='0.0.0.0')
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/koala060528/LightReader/d5525e10e4b6ea211cb47e75b969bf6e5307b35f/favicon.ico
--------------------------------------------------------------------------------
/lightreader.py:
--------------------------------------------------------------------------------
1 | from app import app, db
2 | from app.models import User, Subscribe, Download, Task
3 |
4 |
5 | @app.shell_context_processor
6 | def make_shell_context():
7 | return {'db': db, 'User': User, 'Subscribe': Subscribe, 'Download': Download, 'Task': Task}
8 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | aiohttp==3.5.4
2 | alembic==1.0.10
3 | asn1crypto==0.24.0
4 | async-timeout==3.0.1
5 | asyncio==3.4.3
6 | attrs==19.1.0
7 | Babel==2.6.0
8 | certifi==2019.3.9
9 | cffi==1.12.3
10 | chardet==3.0.4
11 | Click==7.0
12 | cryptography==2.6.1
13 | dominate==2.3.5
14 | Flask==1.0.2
15 | Flask-Babel==0.12.2
16 | Flask-Bootstrap==3.3.7.1
17 | Flask-Login==0.4.1
18 | Flask-Migrate==2.4.0
19 | Flask-Moment==0.7.0
20 | Flask-SQLAlchemy==2.4.0
21 | Flask-Uploads==0.2.1
22 | Flask-WTF==0.14.2
23 | idna==2.8
24 | idna-ssl==1.1.0
25 | itsdangerous==1.1.0
26 | Jinja2==2.10.1
27 | Mako==1.0.9
28 | MarkupSafe==1.1.1
29 | multidict==4.5.2
30 | packaging==19.0
31 | pip-review==1.0
32 | pycparser==2.19
33 | PyMySQL==0.9.3
34 | pyparsing==2.4.0
35 | python-dateutil==2.8.0
36 | python-editor==1.0.4
37 | pytz==2019.1
38 | redis==3.2.1
39 | requests==2.21.0
40 | rq==1.0
41 | six==1.12.0
42 | SQLAlchemy==1.3.3
43 | urllib3==1.25.2
44 | visitor==0.1.3
45 | Werkzeug==0.14.1
46 | WTForms==2.2.1
47 | yarl==1.3.0
48 |
--------------------------------------------------------------------------------