mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-08 16:57:26 +08:00
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:
119
latest version/api/api_auth.py
Normal file
119
latest version/api/api_auth.py
Normal 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
|
||||
15
latest version/api/api_code.py
Normal file
15
latest version/api/api_code.py
Normal 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)]
|
||||
223
latest version/api/api_main.py
Normal file
223
latest version/api/api_main.py
Normal 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': ''})
|
||||
58
latest version/api/songs.py
Normal file
58
latest version/api/songs.py
Normal 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
|
||||
99
latest version/api/users.py
Normal file
99
latest version/api/users.py
Normal 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}
|
||||
Reference in New Issue
Block a user