SoulBook/soulbook/views/operate_blueprint.py
2024-08-01 19:38:07 +08:00

423 lines
16 KiB
Python

#!/usr/bin/env python
import datetime
import hashlib
from jinja2 import Environment, PackageLoader, select_autoescape
from sanic import Blueprint
from sanic.response import html, json
from urllib.parse import parse_qs, unquote
from soulbook.database.mongodb import MotorBase
from soulbook.fetcher.function import get_time, get_timestamp
from soulbook.utils import get_real_answer
from soulbook.config import CONFIG, LOGGER
try:
from ujson import loads as json_loads
from ujson import dumps as json_dumps
except:
from json import loads as json_loads
from json import dumps as json_dumps
operate_bp = Blueprint('operate_blueprint', url_prefix='operate')
@operate_bp.listener('before_server_start')
def setup_db(operate_bp, loop):
global motor_base
motor_base = MotorBase()
@operate_bp.listener('after_server_stop')
def close_connection(operate_bp, loop):
motor_base = None
# jinjia2 config
env = Environment(
loader=PackageLoader('soulbook.views.operate_blueprint', '../templates/operate'),
autoescape=select_autoescape(['html', 'xml', 'tpl']))
def template(tpl, **kwargs):
template = env.get_template(tpl)
return html(template.render(kwargs))
@operate_bp.route("/author_notification", methods=['POST'])
async def author_notification(request):
"""
作者新书通知
:param request:
:return:
: -1 用户session失效 需要重新登录
: 2 无该作者信息
: 3 作者已经添加
: 4 超过添加的上限
: 0 操作失败
: 1 操作成功
"""
user = request['session'].get('user', None)
user_data = parse_qs(str(request.body, encoding='utf-8'))
if user:
try:
motor_db = motor_base.get_db()
all_authors = await motor_db.user_message.find_one({'user': user}, {'author_latest': 1, '_id': 0})
count = len(all_authors.get('author_latest', []))
if count == CONFIG.WEBSITE.get("AUTHOR_LATEST_COUNT", 5):
return json({'status': 4})
author_name = user_data.get('author_name', None)[0]
data = []
author_cursor = motor_db.all_books.find({'author': author_name}, {'name': 1, 'url': 1, '_id': 0})
async for document in author_cursor:
data.append(document)
if data:
time = get_time()
res = await motor_db.user_message.update_one({'user': user}, {'$set': {'last_update_time': time}},
upsert=True)
is_exist = await motor_db.user_message.find_one(
{'user': user, 'author_latest.author_name': author_name})
if is_exist:
return json({'status': 3})
if res:
await motor_db.user_message.update_one(
{'user': user, 'author_latest.author_name': {'$ne': author_name}},
{'$push': {
'author_latest': {'author_name': author_name, 'add_time': time,
'set_time': get_timestamp(), 'set_date': time}}})
is_author_exist = await motor_db.author_message.find_one({'name': author_name})
if not is_author_exist:
author_data = {
"author_name": author_name,
"nums": len(data),
"updated_time": get_time(),
'set_time': get_timestamp()
}
await motor_db.author_message.save(author_data)
LOGGER.info('作者添加成功')
return json({'status': 1})
else:
return json({'status': 2})
else:
return json({'status': 2})
except Exception as e:
LOGGER.exception(e)
return json({'status': 0})
else:
return json({'status': -1})
@operate_bp.route("/change_email", methods=['POST'])
async def change_email(request):
"""
修改用户邮箱
:param request:
:return:
: -1 用户session失效 需要重新登录
: 0 修改邮箱失败
: 1 添加邮箱成功
"""
user = request['session'].get('user', None)
data = parse_qs(str(request.body, encoding='utf-8'))
if user:
try:
email = data.get('email', None)[0]
motor_db = motor_base.get_db()
await motor_db.user.update_one({'user': user},
{'$set': {'email': email}})
LOGGER.info('修改邮箱成功')
return json({'status': 1})
except Exception as e:
LOGGER.exception(e)
return json({'status': 0})
else:
return json({'status': -1})
@operate_bp.route("/change_pass", methods=['POST'])
async def change_pass(request):
"""
修改用户密码
:param request:
:return:
: -1 用户session失效 需要重新登录
: 0 修改密码失败
: 1 添加密码成功
: -2 原始密码错误
"""
user = request['session'].get('user', None)
data = parse_qs(str(request.body, encoding='utf-8'))
if user:
try:
new_pass = data.get('new_pass', None)[0]
old_pass = data.get('old_pass', None)[0]
motor_db = motor_base.get_db()
user_data = await motor_db.user.find_one({'user': user})
if user_data:
pass_first = hashlib.md5((CONFIG.WEBSITE["TOKEN"] + old_pass).encode("utf-8")).hexdigest()
pass_second = hashlib.md5((CONFIG.WEBSITE["TOKEN"] + new_pass).encode("utf-8")).hexdigest()
new_password = hashlib.md5(pass_second.encode("utf-8")).hexdigest()
password = hashlib.md5(pass_first.encode("utf-8")).hexdigest()
if password == user_data.get('password'):
await motor_db.user.update_one({'user': user},
{'$set': {'password': new_password}})
LOGGER.info('修改密码成功')
return json({'status': 1})
else:
return json({'status': -2})
except Exception as e:
LOGGER.exception(e)
return json({'status': 0})
else:
return json({'status': -1})
@operate_bp.route("/add_book", methods=['POST'])
async def owllook_add_book(request):
"""
添加书架
:param request:
:return:
: -1 用户session失效 需要重新登录
: 0 添加书架失败
: 1 添加书架成功
"""
user = request['session'].get('user', None)
data = parse_qs(str(request.body, encoding='utf-8'))
novels_name = data.get('novels_name', '')
chapter_url = data.get('chapter_url', '')
last_read_url = data.get('last_read_url', '')
if user and novels_name and chapter_url:
url = "/chapter?url={chapter_url}&novels_name={novels_name}".format(chapter_url=chapter_url[0],
novels_name=novels_name[0])
time = get_time()
try:
motor_db = motor_base.get_db()
res = await motor_db.user_message.update_one({'user': user}, {'$set': {'last_update_time': time}},
upsert=True)
if res:
await motor_db.user_message.update_one(
{'user': user, 'books_url.book_url': {'$ne': url}},
{'$push': {
'books_url': {'book_url': url, 'add_time': time,
'set_time': get_timestamp(), 'set_date': time,'last_read_url':
unquote(last_read_url[0])}}})
LOGGER.info('书架添加成功')
return json({'status': 1})
except Exception as e:
LOGGER.exception(e)
return json({'status': 0})
else:
return json({'status': -1})
@operate_bp.route("/add_bookmark", methods=['POST'])
async def owllook_add_bookmark(request):
"""
添加书签
:param request:
:return:
: -1 用户session失效 需要重新登录
: 0 添加书签失败
: 1 添加书签成功
"""
user = request['session'].get('user', None)
data = parse_qs(str(request.body, encoding='utf-8'))
bookmark_url = data.get('bookmark_url', '')
if user and bookmark_url:
url = unquote(bookmark_url[0])
time = get_time()
try:
motor_db = motor_base.get_db()
res = await motor_db.user_message.update_one({'user': user}, {'$set': {'last_update_time': time}},
upsert=True)
if res:
await motor_db.user_message.update_one(
{'user': user, 'bookmarks.bookmark': {'$ne': url}},
{'$push': {'bookmarks': {'bookmark': url, 'add_time': time, 'set_time':
get_timestamp(), 'set_date': time}}})
LOGGER.info('书签添加成功')
return json({'status': 1})
except Exception as e:
LOGGER.exception(e)
return json({'status': 0})
else:
return json({'status': -1})
@operate_bp.route("/delete_book", methods=['POST'])
async def owllook_delete_book(request):
"""
删除书架
:param request:
:return:
: -1 用户session失效 需要重新登录
: 0 删除书架失败
: 1 删除书架成功
"""
user = request['session'].get('user', None)
data = parse_qs(str(request.body, encoding='utf-8'))
if user:
if data.get('book_url', None):
book_url = data.get('book_url', None)[0]
else:
novels_name = data.get('novels_name', '')
chapter_url = data.get('chapter_url', '')
book_url = "/chapter?url={chapter_url}&novels_name={novels_name}".format(chapter_url=chapter_url[0],
novels_name=novels_name[0])
try:
motor_db = motor_base.get_db()
await motor_db.user_message.update_one({'user': user},
{'$pull': {'books_url': {"book_url": unquote(book_url)}}})
LOGGER.info('删除书架成功')
return json({'status': 1})
except Exception as e:
LOGGER.exception(e)
return json({'status': 0})
else:
return json({'status': -1})
@operate_bp.route("/delete_bookmark", methods=['POST'])
async def owllook_delete_bookmark(request):
"""
删除书签
:param request:
:return:
: -1 用户session失效 需要重新登录
: 0 删除书签失败
: 1 删除书签成功
"""
user = request['session'].get('user', None)
data = parse_qs(str(request.body, encoding='utf-8'))
bookmarkurl = data.get('bookmarkurl', '')
if user and bookmarkurl:
bookmark = unquote(bookmarkurl[0])
try:
motor_db = motor_base.get_db()
await motor_db.user_message.update_one({'user': user},
{'$pull': {'bookmarks': {"bookmark": bookmark}}})
LOGGER.info('删除书签成功')
return json({'status': 1})
except Exception as e:
LOGGER.exception(e)
return json({'status': 0})
else:
return json({'status': -1})
@operate_bp.route("/login", methods=['POST'])
async def owllook_login(request):
"""
用户登录
:param request:
:return:
: -1 用户名或密码不能为空
: 0 用户名或密码错误
: 1 登陆成功
"""
login_data = parse_qs(str(request.body, encoding='utf-8'))
user = login_data.get('user', [None])[0]
pwd = login_data.get('pwd', [None])[0]
if user and pwd:
motor_db = motor_base.get_db()
data = await motor_db.user.find_one({'user': user})
if data:
pass_first = hashlib.md5((CONFIG.WEBSITE["TOKEN"] + pwd).encode("utf-8")).hexdigest()
password = hashlib.md5(pass_first.encode("utf-8")).hexdigest()
if password == data.get('password'):
response = json({'status': 1})
# 将session_id存于cokies
date = datetime.datetime.now()
response.cookies['owl_sid'] = request['session'].sid
response.cookies['owl_sid']['expires'] = date + datetime.timedelta(days=30)
response.cookies['owl_sid']['httponly'] = True
# 此处设置存于服务器session的user值
request['session']['user'] = user
# response.cookies['user'] = user
# response.cookies['user']['expires'] = date + datetime.timedelta(days=30)
# response.cookies['user']['httponly'] = True
# response = json({'status': 1})
# response.cookies['user'] = user
return response
else:
return json({'status': -2})
return json({'status': -1})
else:
return json({'status': 0})
@operate_bp.route("/logout", methods=['GET'])
async def owllook_logout(request):
"""
用户登出
:param request:
:return:
: 0 退出失败
: 1 退出成功
"""
user = request['session'].get('user', None)
if user:
response = json({'status': 1})
del response.cookies['user']
del response.cookies['owl_sid']
return response
else:
return json({'status': 0})
@operate_bp.route("/register", methods=['POST'])
async def owllook_register(request):
"""
用户注册 不允许重名
:param request:
:return:
: -1 用户名已存在
: 0 用户名或密码不能为空
: 1 注册成功
"""
register_data = parse_qs(str(request.body, encoding='utf-8'))
user = register_data.get('user', [None])[0]
pwd = register_data.get('pwd', [None])[0]
email = register_data.get('email', [None])[0]
answer = register_data.get('answer', [None])[0]
reg_index = request.cookies.get('reg_index')
if user and pwd and email and answer and reg_index and len(user) > 2 and len(pwd) > 5:
motor_db = motor_base.get_db()
is_exist = await motor_db.user.find_one({'user': user})
if not is_exist:
# 验证问题答案是否准确
real_answer = get_real_answer(str(reg_index))
if real_answer and real_answer == answer:
pass_first = hashlib.md5((CONFIG.WEBSITE["TOKEN"] + pwd).encode("utf-8")).hexdigest()
password = hashlib.md5(pass_first.encode("utf-8")).hexdigest()
time = get_time()
data = {
"user": user,
"password": password,
"email": email,
"register_time": time,
}
await motor_db.user.save(data)
return json({'status': 1})
else:
return json({'status': -2})
else:
return json({'status': -1})
else:
return json({'status': 0})
# post_data = json_loads(str(request.body, encoding='utf-8'))
# pass_first = hashlib.md5((CONFIG.WEBSITE["TOKEN"] + post_data['pwd']).encode("utf-8")).hexdigest()
# password = hashlib.md5(pass_first.encode("utf-8")).hexdigest()
# time = get_time()
# data = {
# "user": post_data['user'],
# "password": password,
# "email": post_data['email'],
# "register_time": time,
# }
# motor_db = motor_base.get_db()
# await motor_db.user.save(data)