Waiting for updating

+ new character
+ new byd map
+ new items
+ some new configs
+ two new operations in background
+ record email while registering
+ record ip while logging in
+ checking something before running and updating database automatically

building something about API

fix bugs:
about purchasing system
about hiding ptt
about login different accounts with same device
about some details

This is only a pre updating. Many things have been changed. It takes time to find some ways.
This commit is contained in:
Lost-MSth
2021-05-12 00:45:13 +08:00
parent 941a79ccc7
commit e3d81436d0
24 changed files with 1770 additions and 798 deletions

View File

@@ -0,0 +1,119 @@
import hashlib
import time
from server.sql import Connect
import functools
from setting import Config
from flask import jsonify
class User():
# 用户类,当数据类型用
def __init__(self, user_id=None, role='', power=[]):
self.user_id = user_id
self.role = role
self.power = power
def login():
# 登录接口
return {'token': 1}, 0
def logout():
# 登出接口
pass
def id_get_role_id(c, user_id):
# user_id获取role_id
role_id = 1
c.execute('''select role_id from user_role where user_id = :a''',
{'a': user_id})
x = c.fetchone()
if x is not None:
role_id = int(x[0])
return role_id
def role_id_get_role(c, role_id):
# role_id获取role
role = ''
c.execute('''select role_name from role where role_id = :a''',
{'a': role_id})
x = c.fetchone()
if x is not None:
role = x[0]
return role
def api_token_get_id(c, token):
# api的token获取user_id
user_id = None
c.execute('''select user_id from api_login where token = :token''', {
'token': token})
x = c.fetchone()
if x is not None:
user_id = x[0]
return user_id
def get_role_power(c, role_id):
# 获取role_id对应power返回列表
role_power = []
c.execute('''select power_name from power where power_id in (select power_id from role_power where role_id=:a)''', {
'a': role_id})
x = c.fetchall()
for i in x:
role_power.append(i[0])
return role_power
def role_required(request, power=[]):
# api token验证写成了修饰器
def decorator(view):
@functools.wraps(view)
def wrapped_view(*args, **kwargs):
try:
request.json # 检查请求json格式
except:
return jsonify({'status': 400, 'code': -1, 'data': {}, 'msg': 'Payload must be a valid json'})
if not 'Token' in request.headers:
return jsonify({'status': 401, 'code': -1, 'data': {}, 'msg': 'No Token'})
user = User()
if power == []:
if Config.API_TOKEN == request.headers['Token'] and Config.API_TOKEN != '':
user.user_id = 0
else:
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
else:
with Connect() as c:
user.user_id = api_token_get_id(
c, request.headers['Token'])
if user.user_id is None:
return jsonify({'status': 404, 'code': -1, 'data': {}, 'msg': ''})
role_id = id_get_role_id(c, user.user_id)
user.role = role_id_get_role(c, role_id)
user.role_power = get_role_power(c, role_id)
f = False
for i in power:
if i in user.role_power:
f = True
break
if not f:
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
return view(user, *args, **kwargs)
return wrapped_view
return decorator

View File

@@ -0,0 +1,15 @@
def code_get_msg(code):
# api接口code获取msg返回字符串
msg = {
'0': '',
'-1': 'See status code',
'-2': 'No data',
'-3': 'No data or user',
'-4': 'No user_id',
'-101': 'Wrong data type',
'-102': 'Wrong query parameter',
'-103': 'Wrong sort parameter',
'-104': 'Wrong sort order parameter'
}
return msg[str(code)]

View File

@@ -0,0 +1,223 @@
from flask import (
Blueprint, request, jsonify
)
import api.api_auth
import api.users
import api.songs
from api.api_code import code_get_msg
bp = Blueprint('api', __name__, url_prefix='/api/v1')
def get_query_parameter(request, query_able=[], sort_able=[]):
# 提取查询请求参数返回四个参数和code
limit = -1
offset = 0
query = {} # {'name': 'admin'}
sort = [] # [{'column': 'user_id', 'order': 'ASC'}, ...]
if 'limit' in request.json:
try:
limit = int(request.json['limit'])
except:
return -1, 0, {}, {}, -101
if 'offset' in request.json:
try:
offset = int(request.json['offset'])
except:
return -1, 0, {}, {}, -101
if 'query' in request.json:
query = request.json['query']
for i in query:
if i not in query_able:
return -1, 0, {}, {}, -102
if 'sort' in request.json:
sort = request.json['sort']
for i in sort:
if 'column' not in i or i['column'] not in sort_able:
return -1, 0, {}, {}, -103
if not 'order' in i:
i['order'] = 'ASC'
else:
if i['order'] not in ['ASC', 'DESC']:
return -1, 0, {}, {}, -104
return limit, offset, query, sort, 0
@bp.route('/')
def ping():
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
@bp.route('/token', methods=['POST'])
def token_post():
# 登录获取token
if 'auth' in request.json:
data, code = api.api_auth.login(
request.json['auth'], request.remote_addr)
if code < 0:
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
else:
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
else:
return jsonify({'status': 401, 'code': -1, 'data': {}, 'msg': 'No authentication'})
@bp.route('/token', methods=['GET'])
@api.api_auth.role_required(request, ['select_me', 'select'])
def token_get(user):
# 判断登录有效性
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
@bp.route('/token', methods=['DELETE'])
@api.api_auth.role_required(request, ['change_me', 'select_me', 'select'])
def token_delete(user):
# 登出
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
@bp.route('/users', methods=['GET'])
@api.api_auth.role_required(request, ['select'])
def users_get(user):
# 查询全用户信息
limit, offset, query, sort, code = get_query_parameter(request, ['user_id', 'name', 'user_code'], [
'user_id', 'name', 'user_code', 'join_date', 'rating_ptt', 'time_played', 'ticket'])
if code < 0:
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
data = api.users.get_users(limit, offset, query, sort)
if not data:
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
@bp.route('/users/<int:user_id>', methods=['GET'])
@api.api_auth.role_required(request, ['select', 'select_me'])
def users_user_get(user, user_id):
# 查询用户信息
if user_id == 'me':
user_id = user.user_id
if user_id <= 0:
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
data = api.users.get_user_info(user_id)
if not data:
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
@bp.route('/users/<int:user_id>/b30', methods=['GET'])
@api.api_auth.role_required(request, ['select', 'select_me'])
def users_user_b30_get(user, user_id):
# 查询用户b30
if user_id == 'me':
user_id = user.user_id
if user_id <= 0:
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
data = api.users.get_user_b30(user_id)
if data['data'] == []:
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
@bp.route('/users/<int:user_id>/best', methods=['GET'])
@api.api_auth.role_required(request, ['select', 'select_me'])
def users_user_best_get(user, user_id):
# 查询用户所有best成绩
if user_id == 'me':
user_id = user.user_id
if user_id <= 0:
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
limit, offset, query, sort, code = get_query_parameter(request, ['song_id', 'difficulty'], [
'song_id', 'difficulty', 'score', 'time_played', 'rating'])
if code < 0:
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
data = api.users.get_user_best(user_id, limit, offset, query, sort)
if data['data'] == []:
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
@bp.route('/users/<int:user_id>/r30', methods=['GET'])
@api.api_auth.role_required(request, ['select', 'select_me'])
def users_user_r30_get(user, user_id):
# 查询用户r30
if user_id == 'me':
user_id = user.user_id
if user_id <= 0:
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
data = api.users.get_user_r30(user_id)
if data['data'] == []:
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
@bp.route('/songs/<string:song_id>', methods=['GET'])
@api.api_auth.role_required(request, ['select', 'select_song_info'])
def songs_song_get(user, song_id):
# 查询歌曲信息
data = api.songs.get_song_info(song_id)
if not data:
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
@bp.route('/songs', methods=['GET'])
@api.api_auth.role_required(request, ['select', 'select_song_info'])
def songs_get(user):
# 查询全歌曲信息
limit, offset, query, sort, code = get_query_parameter(request, ['sid', 'name_en', 'name_jp', 'pakset', 'artist'], [
'sid', 'name_en', 'name_jp', 'pakset', 'artist', 'date', 'rating_pst', 'rating_prs', 'rating_ftr', 'rating_byn'])
if code < 0:
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
data = api.songs.get_songs(limit, offset, query, sort)
if not data:
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})

View File

@@ -0,0 +1,58 @@
from server.sql import Connect
from server.sql import Sql
import time
def get_song_info(song_id):
# 查询指定歌曲信息,返回字典
r = {}
with Connect('./database/arcsong.db') as c:
c.execute('''select * from songs where sid=:a''', {'a': song_id})
x = c.fetchone()
if x:
r = {'song_id': x[0],
'name': {'name_en': x[1],
'name_jp': x[2]},
'pakset': x[5],
'artist': x[6],
'date': x[9],
'rating_pst': x[12]/10,
'rating_prs': x[13]/10,
'rating_ftr': x[14]/10,
'rating_byn': x[15]/10,
'difficultly_pst': x[16]/2,
'difficultly_prs': x[17]/2,
'difficultly_ftr': x[18]/2,
'difficultly_byn': x[19]/2
}
return r
def get_songs(limit=-1, offset=0, query={}, sort=[]):
# 查询全部歌曲信息,返回字典列表
r = []
with Connect('./database/arcsong.db') as c:
x = Sql.select(c, 'songs', [], limit, offset, query, sort)
if x:
for i in x:
r.append({'sid': i[0],
'name': {'name_en': i[1],
'name_jp': i[2]},
'pakset': i[5],
'artist': i[6],
'date': i[9],
'rating_pst': i[12]/10,
'rating_prs': i[13]/10,
'rating_ftr': i[14]/10,
'rating_byn': i[15]/10,
'difficultly_pst': i[16]/2,
'difficultly_prs': i[17]/2,
'difficultly_ftr': i[18]/2,
'difficultly_byn': i[19]/2
})
return r

View File

@@ -0,0 +1,99 @@
from server.sql import Connect
from server.sql import Sql
import time
import web.webscore
import server.info
def get_users(limit=-1, offset=0, query={}, sort=[]):
# 获取全用户信息,返回字典列表
r = []
with Connect() as c:
x = Sql.select(c, 'user', [], limit, offset, query, sort)
if x:
for i in x:
if i[23] != -1:
character_id = i[23]
else:
character_id = i[6]
r.append({
'user_id': i[0],
'name': i[1],
'join_date': i[3],
'user_code': i[4],
'rating_ptt': i[5]/100,
'character_id': character_id,
'is_char_uncapped': i[8] == 1,
'is_char_uncapped_override': i[9] == 1,
'is_hide_rating': i[10],
'ticket': i[26]
})
return r
def get_user_info(user_id):
# 获取用户信息返回字典其实就是调用user/me信息
r = {}
with Connect() as c:
r = server.info.get_user_me(c, user_id)
return r
def get_user_b30(user_id):
# 获取用户b30信息返回字典
r = []
with Connect() as c:
r = web.webscore.get_user_score(c, user_id, 30)
bestptt = 0
for i in r:
if i['rating']:
bestptt += i['rating']
if 'time_played' in i:
i['time_played'] = int(time.mktime(time.strptime(
i['time_played'], '%Y-%m-%d %H:%M:%S')))
return {'user_id': user_id, 'b30_ptt': bestptt / 30, 'data': r}
def get_user_best(user_id, limit=-1, offset=0, query={}, sort=[]):
# 获取用户b30信息返回字典
r = []
with Connect() as c:
x = Sql.select(c, 'best_score', [], limit, offset, query, sort)
if x:
for i in x:
r.append({
"song_id": i[1],
"difficulty": i[2],
"score": i[3],
"shiny_perfect_count": i[4],
"perfect_count": i[5],
"near_count": i[6],
"miss_count": i[7],
"health": i[8],
"modifier": i[9],
"time_played": i[10],
"best_clear_type": i[11],
"clear_type": i[12],
"rating": i[13]
})
return {'user_id': user_id, 'data': r}
def get_user_r30(user_id):
# 获取用户r30信息返回字典
r = []
with Connect() as c:
r, r10_ptt = web.webscore.get_user_recent30(c, user_id)
return {'user_id': user_id, 'r10_ptt': r10_ptt, 'data': r}