Fix a bug and add a new thing

- Add support for logging Arcaea's errors
- Fix a bug when world maps' data don't have some unnecessary parts the client of iOS may break down
This commit is contained in:
Lost-MSth
2022-07-16 19:50:07 +08:00
parent 6801af197f
commit 47f05cdf1e
23 changed files with 549 additions and 613 deletions

View File

@@ -1,8 +1,10 @@
import functools
from functools import wraps
from traceback import format_exc
from core.api_user import APIUser
from core.error import ArcError, NoAccess, PostError
from core.sql import Connect
from flask import current_app
from setting import Config
from .api_code import error_return
@@ -11,7 +13,7 @@ from .api_code import error_return
def role_required(request, powers=[]):
'''api token验证写成了修饰器'''
def decorator(view):
@functools.wraps(view)
@wraps(view)
def wrapped_view(*args, **kwargs):
try:
request.json # 检查请求json格式
@@ -56,7 +58,7 @@ def request_json_handle(request, required_keys=[], optional_keys=[]):
'''
def decorator(view):
@functools.wraps(view)
@wraps(view)
def wrapped_view(*args, **kwargs):
data = {}
@@ -73,3 +75,21 @@ def request_json_handle(request, required_keys=[], optional_keys=[]):
return wrapped_view
return decorator
def api_try(view):
'''替代try/except记录`ArcError`为warning'''
@wraps(view)
def wrapped_view(*args, **kwargs):
try:
data = view(*args, **kwargs)
if data is None:
return error_return()
else:
return data
except ArcError as e:
if Config.ALLOW_WARNING_LOG:
current_app.logger.warning(format_exc())
return error_return(e, e.status)
return wrapped_view

View File

@@ -1,10 +1,10 @@
from core.error import ArcError, NoData
from core.error import NoData
from core.song import Song
from core.sql import Connect, Query, Sql
from flask import Blueprint, request
from .api_auth import request_json_handle, role_required
from .api_code import error_return, success_return
from .api_auth import api_try, request_json_handle, role_required
from .api_code import success_return
from .constant import Constant
bp = Blueprint('songs', __name__, url_prefix='/songs')
@@ -12,37 +12,31 @@ bp = Blueprint('songs', __name__, url_prefix='/songs')
@bp.route('/<string:song_id>', methods=['GET'])
@role_required(request, ['select', 'select_song_info'])
@api_try
def songs_song_get(user, song_id):
'''查询歌曲信息'''
with Connect() as c:
try:
s = Song(c, song_id).select()
return success_return(s.to_dict())
except ArcError as e:
return error_return(e)
return error_return()
s = Song(c, song_id).select()
return success_return(s.to_dict())
@bp.route('', methods=['GET'])
@role_required(request, ['select', 'select_song_info'])
@request_json_handle(request, optional_keys=Constant.QUERY_KEYS)
@api_try
def songs_get(data, user):
'''查询全歌曲信息'''
A = ['song_id', 'name']
B = ['song_id', 'name', 'rating_pst',
'rating_prs', 'rating_ftr', 'rating_byn']
with Connect() as c:
try:
query = Query(A, A, B).from_data(data)
x = Sql(c).select('chart', query=query)
r = []
for i in x:
r.append(Song(c).from_list(i))
query = Query(A, A, B).from_data(data)
x = Sql(c).select('chart', query=query)
r = []
for i in x:
r.append(Song(c).from_list(i))
if not r:
raise NoData(api_error_code=-2)
if not r:
raise NoData(api_error_code=-2)
return success_return([x.to_dict() for x in r])
except ArcError as e:
return error_return(e)
return error_return()
return success_return([x.to_dict() for x in r])

View File

@@ -1,11 +1,11 @@
from base64 import b64decode
from core.api_user import APIUser
from core.error import ArcError, PostError
from core.error import PostError
from core.sql import Connect
from flask import Blueprint, request
from .api_auth import request_json_handle, role_required
from .api_auth import api_try, request_json_handle, role_required
from .api_code import error_return, success_return
bp = Blueprint('token', __name__, url_prefix='/token')
@@ -13,6 +13,7 @@ bp = Blueprint('token', __name__, url_prefix='/token')
@bp.route('', methods=['POST'])
@request_json_handle(request, required_keys=['auth'])
@api_try
def token_post(data):
'''
登录获取token\
@@ -27,17 +28,14 @@ def token_post(data):
name, password = auth_decode.split(':', 1)
with Connect() as c:
try:
user = APIUser(c)
user.login(name, password, request.remote_addr)
return success_return({'token': user.token, 'user_id': user.user_id})
except ArcError as e:
return error_return(e)
return error_return()
user = APIUser(c)
user.login(name, password, request.remote_addr)
return success_return({'token': user.token, 'user_id': user.user_id})
@bp.route('', methods=['GET'])
@role_required(request, ['select_me', 'select'])
@api_try
def token_get(user):
'''判断登录有效性'''
return success_return()
@@ -45,13 +43,10 @@ def token_get(user):
@bp.route('', methods=['DELETE'])
@role_required(request, ['change_me', 'select_me', 'select'])
@api_try
def token_delete(user):
'''登出'''
with Connect() as c:
try:
user.c = c
user.logout()
return success_return()
except ArcError as e:
return error_return(e)
return error_return()
user.c = c
user.logout()
return success_return()

View File

@@ -1,10 +1,10 @@
from core.error import ArcError, InputError, NoAccess, NoData
from core.error import InputError, NoAccess, NoData
from core.score import Potential, UserScoreList
from core.sql import Connect, Query, Sql
from core.user import UserInfo, UserRegister
from flask import Blueprint, request
from .api_auth import request_json_handle, role_required
from .api_auth import api_try, request_json_handle, role_required
from .api_code import error_return, success_return
from .constant import Constant
@@ -14,59 +14,54 @@ bp = Blueprint('users', __name__, url_prefix='/users')
@bp.route('', methods=['POST'])
@role_required(request, ['change'])
@request_json_handle(request, ['name', 'password', 'email'])
@api_try
def users_post(data, _):
'''注册一个用户'''
with Connect() as c:
new_user = UserRegister(c)
try:
new_user.set_name(data['name'])
new_user.set_password(data['password'])
new_user.set_email(data['email'])
new_user.register()
return success_return({'user_id': new_user.user_id, 'user_code': new_user.user_code})
except ArcError as e:
return error_return(e)
return error_return()
new_user.set_name(data['name'])
new_user.set_password(data['password'])
new_user.set_email(data['email'])
new_user.register()
return success_return({'user_id': new_user.user_id, 'user_code': new_user.user_code})
@bp.route('', methods=['GET'])
@role_required(request, ['select'])
@request_json_handle(request, optional_keys=Constant.QUERY_KEYS)
@api_try
def users_get(data, user):
'''查询全用户信息'''
A = ['user_id', 'name', 'user_code']
B = ['user_id', 'name', 'user_code', 'join_date',
'rating_ptt', 'time_played', 'ticket', 'world_rank_score']
with Connect() as c:
try:
query = Query(A, A, B).from_data(data)
x = Sql(c).select('user', query=query)
r = []
for i in x:
r.append(UserInfo(c).from_list(i))
query = Query(A, A, B).from_data(data)
x = Sql(c).select('user', query=query)
r = []
for i in x:
r.append(UserInfo(c).from_list(i))
if not r:
raise NoData(api_error_code=-2)
if not r:
raise NoData(api_error_code=-2)
return success_return([{
'user_id': x.user_id,
'name': x.name,
'join_date': x.join_date,
'user_code': x.user_code,
'rating_ptt': x.rating_ptt/100,
'character_id': x.character.character_id,
'is_char_uncapped': x.character.is_uncapped,
'is_char_uncapped_override': x.character.is_uncapped_override,
'is_hide_rating': x.is_hide_rating,
'ticket': x.ticket
} for x in r])
except ArcError as e:
return error_return(e)
return error_return()
return success_return([{
'user_id': x.user_id,
'name': x.name,
'join_date': x.join_date,
'user_code': x.user_code,
'rating_ptt': x.rating_ptt/100,
'character_id': x.character.character_id,
'is_char_uncapped': x.character.is_uncapped,
'is_char_uncapped_override': x.character.is_uncapped_override,
'is_hide_rating': x.is_hide_rating,
'ticket': x.ticket
} for x in r])
@bp.route('/<int:user_id>', methods=['GET'])
@role_required(request, ['select', 'select_me'])
@api_try
def users_user_get(user, user_id):
'''查询用户信息'''
if user_id <= 0:
@@ -76,16 +71,13 @@ def users_user_get(user, user_id):
return error_return(NoAccess('No permission', api_error_code=-1), 403)
with Connect() as c:
try:
u = UserInfo(c, user_id)
return success_return(u.to_dict())
except ArcError as e:
return error_return(e)
return error_return()
u = UserInfo(c, user_id)
return success_return(u.to_dict())
@bp.route('/<int:user_id>/b30', methods=['GET'])
@role_required(request, ['select', 'select_me'])
@api_try
def users_user_b30_get(user, user_id):
'''查询用户b30'''
if user_id <= 0:
@@ -95,21 +87,18 @@ def users_user_b30_get(user, user_id):
return error_return(NoAccess('No permission', api_error_code=-1), 403)
with Connect() as c:
try:
x = UserScoreList(c, UserInfo(c, user_id))
x.query.limit = 30
x.select_from_user()
r = x.to_dict_list()
rating_sum = sum([i.rating for i in x.scores])
return success_return({'user_id': user_id, 'b30_ptt': rating_sum / 30, 'data': r})
except ArcError as e:
return error_return(e)
return error_return()
x = UserScoreList(c, UserInfo(c, user_id))
x.query.limit = 30
x.select_from_user()
r = x.to_dict_list()
rating_sum = sum([i.rating for i in x.scores])
return success_return({'user_id': user_id, 'b30_ptt': rating_sum / 30, 'data': r})
@bp.route('/<int:user_id>/best', methods=['GET'])
@role_required(request, ['select', 'select_me'])
@request_json_handle(request, optional_keys=Constant.QUERY_KEYS)
@api_try
def users_user_best_get(data, user, user_id):
'''查询用户所有best成绩'''
if user_id <= 0:
@@ -119,19 +108,16 @@ def users_user_best_get(data, user, user_id):
return error_return(NoAccess('No permission', api_error_code=-1), 403)
with Connect() as c:
try:
x = UserScoreList(c, UserInfo(c, user_id))
x.query.from_data(data)
x.select_from_user()
r = x.to_dict_list()
return success_return({'user_id': user_id, 'data': r})
except ArcError as e:
return error_return(e)
return error_return()
x = UserScoreList(c, UserInfo(c, user_id))
x.query.from_data(data)
x.select_from_user()
r = x.to_dict_list()
return success_return({'user_id': user_id, 'data': r})
@bp.route('/<int:user_id>/r30', methods=['GET'])
@role_required(request, ['select', 'select_me'])
@api_try
def users_user_r30_get(user, user_id):
'''查询用户r30'''
@@ -142,9 +128,5 @@ def users_user_r30_get(user, user_id):
return error_return(NoAccess('No permission', api_error_code=-1), 403)
with Connect() as c:
try:
p = Potential(c, UserInfo(c, user_id))
return success_return({'user_id': user_id, 'r10_ptt': p.recent_10 / 10, 'data': p.recent_30_to_dict_list()})
except ArcError as e:
return error_return(e)
return error_return()
p = Potential(c, UserInfo(c, user_id))
return success_return({'user_id': user_id, 'r10_ptt': p.recent_10 / 10, 'data': p.recent_30_to_dict_list()})

View File

@@ -177,10 +177,12 @@ class UserCharacter(Character):
x = self.c.fetchone()
if not x:
raise NoData('The character of the user does not exist.')
self.is_uncapped = x[0] == 1
self.is_uncapped_override = x[1] == 1
self.is_uncapped = False
self.is_uncapped_override = False
# raise NoData('The character of the user does not exist.')
else:
self.is_uncapped = x[0] == 1
self.is_uncapped_override = x[1] == 1
def select_character_info(self, user=None):
# parameter: user - User类或子类的实例

View File

@@ -1,9 +1,10 @@
class ArcError(Exception):
def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None) -> None:
def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None, status=200) -> None:
self.message = message
self.error_code = error_code
self.api_error_code = api_error_code
self.extra_data = extra_data
self.status = status
def __str__(self) -> str:
return repr(self.message)
@@ -11,8 +12,8 @@ class ArcError(Exception):
class InputError(ArcError):
# 输入类型错误
def __init__(self, message=None, error_code=108, api_error_code=-100, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=108, api_error_code=-100, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class DataExist(ArcError):
@@ -22,62 +23,62 @@ class DataExist(ArcError):
class NoData(ArcError):
# 数据不存在
def __init__(self, message=None, error_code=108, api_error_code=-2, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=108, api_error_code=-2, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class PostError(ArcError):
# 缺少输入
def __init__(self, message=None, error_code=108, api_error_code=-100, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=108, api_error_code=-100, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class UserBan(ArcError):
# 用户封禁
def __init__(self, message=None, error_code=121, api_error_code=-202, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=121, api_error_code=-202, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class ItemNotEnough(ArcError):
# 物品数量不足
def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class ItemUnavailable(ArcError):
# 物品不可用
def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class RedeemUnavailable(ArcError):
# 兑换码不可用
def __init__(self, message=None, error_code=505, api_error_code=-999, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=505, api_error_code=-999, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class MapLocked(ArcError):
# 地图锁定
def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class StaminaNotEnough(ArcError):
# 体力不足
def __init__(self, message=None, error_code=107, api_error_code=-999, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=107, api_error_code=-999, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class TicketNotEnough(ArcError):
# 记忆源点不足
def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class FriendError(ArcError):
# 好友系统出错
def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None) -> None:
super().__init__(message, error_code, api_error_code, extra_data)
def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None, status=200) -> None:
super().__init__(message, error_code, api_error_code, extra_data, status)
class NoAccess(ArcError):

View File

@@ -98,10 +98,11 @@ class LocalMultiPlayer:
if self.conn.poll(Constant.LINK_PLAY_TIMEOUT):
self.data_recv = self.conn.recv()
if self.data_recv[0] != 0:
raise ArcError('Link Play error.', self.data_recv[0])
raise ArcError('Link Play error.',
self.data_recv[0], status=400)
else:
raise Timeout(
'Timeout when waiting for data from local udp server.')
'Timeout when waiting for data from local udp server.', status=400)
def create_room(self, user: 'Player' = None) -> None:
'''创建房间'''

View File

@@ -4,7 +4,7 @@ import traceback
from flask import current_app
from .constant import Constant
from .error import InputError
from .error import ArcError, InputError
class Connect:
@@ -24,18 +24,22 @@ class Connect:
return self.c
def __exit__(self, exc_type, exc_val, exc_tb) -> bool:
flag = True
if exc_type is not None:
if self.conn:
self.conn.rollback()
if issubclass(exc_type, ArcError):
flag = False
else:
if self.conn:
self.conn.rollback()
current_app.logger.error(
traceback.format_exception(exc_type, exc_val, exc_tb))
current_app.logger.error(
traceback.format_exception(exc_type, exc_val, exc_tb))
if self.conn:
self.conn.commit()
self.conn.close()
return True
return flag
class Query:

View File

@@ -450,6 +450,10 @@ class UserInfo(User):
favorite_character_id = self.favorite_character.character_id
else:
favorite_character_id = -1
if self.character.character_id not in character_list:
self.character.character_id = 0
return {
"is_aprilfools": Config.IS_APRILFOOLS,
"curr_available_maps": self.curr_available_maps_list,
@@ -477,7 +481,7 @@ class UserInfo(User):
"world_songs": self.world_songs,
"singles": self.singles,
"packs": self.packs,
"characters": self.characters_list,
"characters": character_list,
"cores": self.cores,
"recent_score": self.recent_score_list,
"max_friend": Constant.MAX_FRIEND_COUNT,

View File

@@ -158,17 +158,17 @@ class Map:
self.is_legacy = raw_dict.get('is_legacy')
self.is_beyond = raw_dict.get('is_beyond')
self.beyond_health = raw_dict.get('beyond_health')
self.character_affinity = raw_dict.get('character_affinity')
self.affinity_multiplier = raw_dict.get('affinity_multiplier')
self.character_affinity = raw_dict.get('character_affinity', [])
self.affinity_multiplier = raw_dict.get('affinity_multiplier', [])
self.chapter = raw_dict.get('chapter')
self.available_from = raw_dict.get('available_from')
self.available_to = raw_dict.get('available_to')
self.available_from = raw_dict.get('available_from', -1)
self.available_to = raw_dict.get('available_to', 9999999999999)
self.is_repeatable = raw_dict.get('is_repeatable')
self.require_id = raw_dict.get('require_id')
self.require_type = raw_dict.get('require_type')
self.require_value = raw_dict.get('require_value')
self.require_id = raw_dict.get('require_id', '')
self.require_type = raw_dict.get('require_type', '')
self.require_value = raw_dict.get('require_value', 1)
self.coordinate = raw_dict.get('coordinate')
self.custom_bg = raw_dict.get('custom_bg')
self.custom_bg = raw_dict.get('custom_bg', '')
self.stamina_cost = raw_dict.get('stamina_cost')
self.steps = [Step().from_dict(s) for s in raw_dict.get('steps')]
return self

View File

@@ -4,6 +4,7 @@ import os
import sys
from logging.config import dictConfig
from multiprocessing import Process, set_start_method
from traceback import format_exc
from flask import Flask, request, send_from_directory
@@ -59,6 +60,7 @@ def download(file_path):
x.insert_user_download()
return send_from_directory(Constant.SONG_FILE_FOLDER_PATH, file_path, as_attachment=True)
except ArcError as e:
app.logger.warning(format_exc())
return error_return(e)
return error_return()
@@ -100,8 +102,8 @@ def main():
}
}
}
if Config.ALLOW_LOG_INFO:
log_dict['root']['handlers'] = ['wsgi', 'info_file', 'error_file']
if Config.ALLOW_INFO_LOG:
log_dict['root']['handlers'].append('info_file')
log_dict['handlers']['info_file'] = {
"class": "logging.handlers.RotatingFileHandler",
"maxBytes": 1024 * 1024,
@@ -111,6 +113,17 @@ def main():
"formatter": "default",
"filename": "./log/info.log"
}
if Config.ALLOW_WARNING_LOG:
log_dict['root']['handlers'].append('warning_file')
log_dict['handlers']['warning_file'] = {
"class": "logging.handlers.RotatingFileHandler",
"maxBytes": 1024 * 1024,
"backupCount": 1,
"encoding": "utf-8",
"level": "WARNING",
"formatter": "default",
"filename": "./log/warning.log"
}
dictConfig(log_dict)

View File

@@ -1,5 +1,5 @@
import base64
import functools
from functools import wraps
from core.error import ArcError, NoAccess
from core.sql import Connect
@@ -7,44 +7,40 @@ from core.user import UserAuth, UserLogin
from flask import Blueprint, jsonify, request
from setting import Config
from .func import error_return
from .func import arc_try, error_return
bp = Blueprint('auth', __name__, url_prefix='/auth')
@bp.route('/login', methods=['POST']) # 登录接口
@arc_try
def login():
if 'AppVersion' in request.headers: # 版本检查
if Config.ALLOW_APPVERSION:
if request.headers['AppVersion'] not in Config.ALLOW_APPVERSION:
return error_return(NoAccess('Wrong app version.', 1203))
raise NoAccess('Wrong app version.', 1203)
headers = request.headers
request.form['grant_type']
with Connect() as c:
try:
id_pwd = headers['Authorization']
id_pwd = base64.b64decode(id_pwd[6:]).decode()
name, password = id_pwd.split(':', 1)
if 'DeviceId' in headers:
device_id = headers['DeviceId']
else:
device_id = 'low_version'
id_pwd = headers['Authorization']
id_pwd = base64.b64decode(id_pwd[6:]).decode()
name, password = id_pwd.split(':', 1)
if 'DeviceId' in headers:
device_id = headers['DeviceId']
else:
device_id = 'low_version'
user = UserLogin(c)
user.login(name, password, device_id, request.remote_addr)
user = UserLogin(c)
user.login(name, password, device_id, request.remote_addr)
return jsonify({"success": True, "token_type": "Bearer", 'user_id': user.user_id, 'access_token': user.token})
except ArcError as e:
return error_return(e)
return error_return()
return jsonify({"success": True, "token_type": "Bearer", 'user_id': user.user_id, 'access_token': user.token})
def auth_required(request):
# arcaea登录验证写成了修饰器
def decorator(view):
@functools.wraps(view)
@wraps(view)
def wrapped_view(*args, **kwargs):
headers = request.headers

View File

@@ -7,27 +7,24 @@ from core.user import UserOnline
from flask import Blueprint, request
from .auth import auth_required
from .func import error_return, success_return
from .func import arc_try, success_return
bp = Blueprint('course', __name__, url_prefix='/course')
@bp.route('/me', methods=['GET'])
@auth_required(request)
@arc_try
def course_me(user_id):
with Connect() as c:
try:
user = UserOnline(c, user_id)
core = ItemCore(c)
core.item_id = 'core_course_skip_purchase'
core.select(user)
x = UserCourseList(c, user)
x.select_all()
return success_return({
'courses': x.to_dict_list(),
"stamina_cost": Constant.COURSE_STAMINA_COST,
"course_skip_purchase_ticket": core.amount
})
except ArcError as e:
return error_return(e)
return error_return()
user = UserOnline(c, user_id)
core = ItemCore(c)
core.item_id = 'core_course_skip_purchase'
core.select(user)
x = UserCourseList(c, user)
x.select_all()
return success_return({
'courses': x.to_dict_list(),
"stamina_cost": Constant.COURSE_STAMINA_COST,
"course_skip_purchase_ticket": core.amount
})

View File

@@ -1,49 +1,43 @@
from flask import Blueprint, request
from core.sql import Connect
from core.error import ArcError
from core.user import UserOnline, code_get_id
from .func import error_return, success_return
from flask import Blueprint, request
from .auth import auth_required
from .func import arc_try, success_return
bp = Blueprint('friend', __name__, url_prefix='/friend')
@bp.route('/me/add', methods=['POST']) # 加好友
@auth_required(request)
@arc_try
def add_friend(user_id):
with Connect() as c:
try:
friend_code = request.form['friend_code']
friend_id = code_get_id(c, friend_code)
user = UserOnline(c, user_id)
user.add_friend(friend_id)
friend_code = request.form['friend_code']
friend_id = code_get_id(c, friend_code)
user = UserOnline(c, user_id)
user.add_friend(friend_id)
return success_return({
"user_id": user.user_id,
"updatedAt": "2020-09-07T07:32:12.740Z",
"createdAt": "2020-09-06T10:05:18.471Z",
"friends": user.friends
})
except ArcError as e:
return error_return(e)
return error_return()
return success_return({
"user_id": user.user_id,
"updatedAt": "2020-09-07T07:32:12.740Z",
"createdAt": "2020-09-06T10:05:18.471Z",
"friends": user.friends
})
@bp.route('/me/delete', methods=['POST']) # 删好友
@auth_required(request)
@arc_try
def delete_friend(user_id):
with Connect() as c:
try:
friend_id = int(request.form['friend_id'])
user = UserOnline(c, user_id)
user.delete_friend(friend_id)
friend_id = int(request.form['friend_id'])
user = UserOnline(c, user_id)
user.delete_friend(friend_id)
return success_return({
"user_id": user.user_id,
"updatedAt": "2020-09-07T07:32:12.740Z",
"createdAt": "2020-09-06T10:05:18.471Z",
"friends": user.friends
})
except ArcError as e:
return error_return(e)
return error_return()
return success_return({
"user_id": user.user_id,
"updatedAt": "2020-09-07T07:32:12.740Z",
"createdAt": "2020-09-06T10:05:18.471Z",
"friends": user.friends
})

View File

@@ -1,5 +1,9 @@
from flask import jsonify
from functools import wraps
from traceback import format_exc
from core.error import ArcError
from flask import current_app, jsonify
from setting import Config
default_error = ArcError('Unknown Error')
@@ -56,7 +60,7 @@ def error_return(e: ArcError = default_error): # 错误返回
if e.extra_data:
r['extra'] = e.extra_data
return jsonify(r)
return jsonify(r), e.status
def success_return(value=None):
@@ -64,3 +68,21 @@ def success_return(value=None):
if value is not None:
r['value'] = value
return jsonify(r)
def arc_try(view):
'''替代try/except记录`ArcError`为warning'''
@wraps(view)
def wrapped_view(*args, **kwargs):
try:
data = view(*args, **kwargs)
if data is None:
return error_return()
else:
return data
except ArcError as e:
if Config.ALLOW_WARNING_LOG:
current_app.logger.warning(format_exc())
return error_return(e)
return wrapped_view

View File

@@ -7,7 +7,7 @@ from flask import Blueprint, request
from setting import Config
from .auth import auth_required
from .func import error_return, success_return
from .func import arc_try, success_return
bp = Blueprint('multiplayer', __name__, url_prefix='/multiplayer')
@@ -16,66 +16,57 @@ conn1, conn2 = Pipe()
@bp.route('/me/room/create', methods=['POST']) # 创建房间
@auth_required(request)
@arc_try
def room_create(user_id):
if not Config.UDP_PORT or Config.UDP_PORT == '':
return error_return(ArcError('The local udp server is down.', 151)), 404
raise ArcError('The local udp server is down.', 151, status=404)
with Connect() as c:
try:
x = LocalMultiPlayer(conn1)
user = Player(c, user_id)
user.get_song_unlock(request.json['clientSongMap'])
x.create_room(user)
r = x.to_dict()
r['endPoint'] = request.host.split(
':')[0] if Config.LINK_PLAY_HOST == '' else Config.LINK_PLAY_HOST
r['port'] = int(Config.UDP_PORT)
return success_return(r)
except ArcError as e:
return error_return(e), 400
return error_return()
x = LocalMultiPlayer(conn1)
user = Player(c, user_id)
user.get_song_unlock(request.json['clientSongMap'])
x.create_room(user)
r = x.to_dict()
r['endPoint'] = request.host.split(
':')[0] if Config.LINK_PLAY_HOST == '' else Config.LINK_PLAY_HOST
r['port'] = int(Config.UDP_PORT)
return success_return(r)
@bp.route('/me/room/join/<room_code>', methods=['POST']) # 加入房间
@auth_required(request)
@arc_try
def room_join(user_id, room_code):
if not Config.UDP_PORT or Config.UDP_PORT == '':
return error_return(ArcError('The local udp server is down.', 151)), 404
raise ArcError('The local udp server is down.', 151, status=404)
with Connect() as c:
try:
x = LocalMultiPlayer(conn1)
user = Player(c, user_id)
user.get_song_unlock(request.json['clientSongMap'])
room = Room()
room.room_code = room_code
x.join_room(room, user)
r = x.to_dict()
r['endPoint'] = request.host.split(
':')[0] if Config.LINK_PLAY_HOST == '' else Config.LINK_PLAY_HOST
r['port'] = int(Config.UDP_PORT)
return success_return(r)
except ArcError as e:
return error_return(e), 400
return error_return()
x = LocalMultiPlayer(conn1)
user = Player(c, user_id)
user.get_song_unlock(request.json['clientSongMap'])
room = Room()
room.room_code = room_code
x.join_room(room, user)
r = x.to_dict()
r['endPoint'] = request.host.split(
':')[0] if Config.LINK_PLAY_HOST == '' else Config.LINK_PLAY_HOST
r['port'] = int(Config.UDP_PORT)
return success_return(r)
@bp.route('/me/update', methods=['POST']) # 更新房间
@auth_required(request)
@arc_try
def multiplayer_update(user_id):
if not Config.UDP_PORT or Config.UDP_PORT == '':
return error_return(ArcError('The local udp server is down.', 151)), 404
raise ArcError('The local udp server is down.', 151, status=404)
with Connect() as c:
try:
x = LocalMultiPlayer(conn1)
user = Player(c, user_id)
user.token = int(request.json['token'])
x.update_room(user)
r = x.to_dict()
r['endPoint'] = request.host.split(
':')[0] if Config.LINK_PLAY_HOST == '' else Config.LINK_PLAY_HOST
r['port'] = int(Config.UDP_PORT)
return success_return(r)
except ArcError as e:
return error_return(e), 400
return error_return()
x = LocalMultiPlayer(conn1)
user = Player(c, user_id)
user.token = int(request.json['token'])
x.update_room(user)
r = x.to_dict()
r['endPoint'] = request.host.split(
':')[0] if Config.LINK_PLAY_HOST == '' else Config.LINK_PLAY_HOST
r['port'] = int(Config.UDP_PORT)
return success_return(r)

View File

@@ -10,7 +10,7 @@ from flask import Blueprint, jsonify, request
from werkzeug.datastructures import ImmutableMultiDict
from .auth import auth_required
from .func import error_return, success_return
from .func import arc_try, error_return, success_return
from .present import present_info
from .purchase import bundle_pack, bundle_bundle
from .score import song_score_friend
@@ -27,21 +27,18 @@ def game_info():
@bp.route('/serve/download/me/song', methods=['GET']) # 歌曲下载
@auth_required(request)
@arc_try
def download_song(user_id):
with Connect() as c:
try:
x = DownloadList(c, UserOnline(c, user_id))
x.song_ids = request.args.getlist('sid')
x.url_flag = json.loads(request.args.get('url', 'true'))
x.clear_user_download()
if x.is_limited and x.url_flag:
raise ArcError('You have reached the download limit.', 903)
x = DownloadList(c, UserOnline(c, user_id))
x.song_ids = request.args.getlist('sid')
x.url_flag = json.loads(request.args.get('url', 'true'))
x.clear_user_download()
if x.is_limited and x.url_flag:
raise ArcError('You have reached the download limit.', 903)
x.add_songs()
return success_return(x.urls)
except ArcError as e:
return error_return(e)
return error_return()
x.add_songs()
return success_return(x.urls)
@bp.route('/finale/progress', methods=['GET'])

View File

@@ -5,34 +5,28 @@ from core.user import UserOnline
from flask import Blueprint, request
from .auth import auth_required
from .func import error_return, success_return
from .func import arc_try, error_return, success_return
bp = Blueprint('present', __name__, url_prefix='/present')
@bp.route('/me', methods=['GET']) # 用户奖励信息
@auth_required(request)
@arc_try
def present_info(user_id):
with Connect() as c:
try:
x = UserPresentList(c, UserOnline(c, user_id))
x.select_user_presents()
x = UserPresentList(c, UserOnline(c, user_id))
x.select_user_presents()
return success_return(x.to_dict_list())
except ArcError as e:
return error_return(e)
return error_return()
return success_return(x.to_dict_list())
@bp.route('/me/claim/<present_id>', methods=['POST']) # 礼物确认
@auth_required(request)
@arc_try
def claim_present(user_id, present_id):
with Connect() as c:
try:
x = UserPresent(c, UserOnline(c, user_id))
x.claim_user_present(present_id)
x = UserPresent(c, UserOnline(c, user_id))
x.claim_user_present(present_id)
return success_return()
except ArcError as e:
return error_return(e)
return error_return()
return success_return()

View File

@@ -1,6 +1,6 @@
from time import time
from core.error import ArcError, ItemUnavailable
from core.error import InputError, ItemUnavailable, PostError
from core.item import ItemFactory, Stamina6
from core.purchase import Purchase, PurchaseList
from core.redeem import UserRedeem
@@ -9,35 +9,29 @@ from core.user import UserOnline
from flask import Blueprint, request
from .auth import auth_required
from .func import error_return, success_return
from .func import arc_try, success_return
bp = Blueprint('purchase', __name__, url_prefix='/purchase')
@bp.route('/bundle/pack', methods=['GET']) # 曲包信息
@auth_required(request)
@arc_try
def bundle_pack(user_id):
with Connect() as c:
try:
x = PurchaseList(c, UserOnline(c, user_id)
).select_from_type('pack')
return success_return(x.to_dict_list())
except ArcError as e:
return error_return(e)
return error_return()
x = PurchaseList(c, UserOnline(c, user_id)
).select_from_type('pack')
return success_return(x.to_dict_list())
@bp.route('/bundle/single', methods=['GET']) # 单曲购买信息获取
@auth_required(request)
@arc_try
def get_single(user_id):
with Connect() as c:
try:
x = PurchaseList(c, UserOnline(c, user_id)
).select_from_type('single')
return success_return(x.to_dict_list())
except ArcError as e:
return error_return(e)
return error_return()
x = PurchaseList(c, UserOnline(c, user_id)
).select_from_type('single')
return success_return(x.to_dict_list())
@bp.route('/bundle/bundle', methods=['GET']) # 捆绑包
@@ -72,99 +66,87 @@ def bundle_bundle():
@bp.route('/me/pack', methods=['POST']) # 曲包和单曲购买
@auth_required(request)
@arc_try
def buy_pack_or_single(user_id):
with Connect() as c:
try:
if 'pack_id' in request.form:
purchase_name = request.form['pack_id']
elif 'single_id' in request.form:
purchase_name = request.form['single_id']
else:
return success_return()
if 'pack_id' in request.form:
purchase_name = request.form['pack_id']
elif 'single_id' in request.form:
purchase_name = request.form['single_id']
else:
return success_return()
x = Purchase(c, UserOnline(c, user_id)).select(purchase_name)
x.buy()
x = Purchase(c, UserOnline(c, user_id)).select(purchase_name)
x.buy()
return success_return({
'user_id': x.user.user_id,
'ticket': x.user.ticket,
'packs': x.user.packs,
'singles': x.user.singles,
'characters': x.user.characters_list
})
except ArcError as e:
return error_return(e)
return error_return()
return success_return({
'user_id': x.user.user_id,
'ticket': x.user.ticket,
'packs': x.user.packs,
'singles': x.user.singles,
'characters': x.user.characters_list
})
@bp.route('/me/item', methods=['POST']) # 特殊购买world模式boost和stamina
@auth_required(request)
@arc_try
def buy_special(user_id):
with Connect() as c:
try:
if 'item_id' not in request.form:
return error_return()
item_id = request.form['item_id']
if 'item_id' not in request.form:
raise PostError('`item_id` is required')
item_id = request.form['item_id']
x = Purchase(c, UserOnline(c, user_id))
x.purchase_name = item_id
x.price = 50
x.orig_price = 50
x.discount_from = -1
x.discount_to = -1
x.items = [ItemFactory(c).get_item(item_id)]
x.buy()
x = Purchase(c, UserOnline(c, user_id))
x.purchase_name = item_id
x.price = 50
x.orig_price = 50
x.discount_from = -1
x.discount_to = -1
x.items = [ItemFactory(c).get_item(item_id)]
x.buy()
r = {'user_id': x.user.user_id, 'ticket': x.user.ticket}
if item_id == 'stamina6':
r['stamina'] = x.user.stamina.stamina
r['max_stamina_ts'] = x.user.stamina.max_stamina_ts
r['world_mode_locked_end_ts'] = -1
return success_return(r)
except ArcError as e:
return error_return(e)
return error_return()
r = {'user_id': x.user.user_id, 'ticket': x.user.ticket}
if item_id == 'stamina6':
r['stamina'] = x.user.stamina.stamina
r['max_stamina_ts'] = x.user.stamina.max_stamina_ts
r['world_mode_locked_end_ts'] = -1
return success_return(r)
@bp.route('/me/stamina/<buy_stamina_type>', methods=['POST']) # 购买体力
@auth_required(request)
@arc_try
def purchase_stamina(user_id, buy_stamina_type):
with Connect() as c:
try:
if buy_stamina_type != 'fragment':
return error_return()
if buy_stamina_type != 'fragment':
raise InputError('Invalid type of buying stamina')
user = UserOnline(c, user_id)
user.select_user_one_column('next_fragstam_ts', -1)
now = int(time()*1000)
if user.next_fragstam_ts > now:
return ItemUnavailable('Buying stamina by fragment is not available yet.', 905)
user = UserOnline(c, user_id)
user.select_user_one_column('next_fragstam_ts', -1)
now = int(time()*1000)
if user.next_fragstam_ts > now:
return ItemUnavailable('Buying stamina by fragment is not available yet.', 905)
user.update_user_one_column(
'next_fragstam_ts', now + 24 * 3600 * 1000)
s = Stamina6(c)
s.user_claim_item(user)
return success_return({
"user_id": user.user_id,
"stamina": user.stamina.stamina,
"max_stamina_ts": user.stamina.max_stamina_ts,
"next_fragstam_ts": user.next_fragstam_ts,
'world_mode_locked_end_ts': -1
})
except ArcError as e:
return error_return(e)
return error_return()
user.update_user_one_column(
'next_fragstam_ts', now + 24 * 3600 * 1000)
s = Stamina6(c)
s.user_claim_item(user)
return success_return({
"user_id": user.user_id,
"stamina": user.stamina.stamina,
"max_stamina_ts": user.stamina.max_stamina_ts,
"next_fragstam_ts": user.next_fragstam_ts,
'world_mode_locked_end_ts': -1
})
@bp.route('/me/redeem', methods=['POST']) # 兑换码
@auth_required(request)
@arc_try
def redeem(user_id):
with Connect() as c:
try:
x = UserRedeem(c, UserOnline(c, user_id))
x.claim_user_redeem(request.form['code'])
x = UserRedeem(c, UserOnline(c, user_id))
x.claim_user_redeem(request.form['code'])
return success_return({"coupon": "fragment" + str(x.fragment) if x.fragment > 0 else ""})
except ArcError as e:
return error_return(e)
return error_return()
return success_return({"coupon": "fragment" + str(x.fragment) if x.fragment > 0 else ""})

View File

@@ -1,7 +1,7 @@
from time import time
from core.course import CoursePlay
from core.error import ArcError, InputError
from core.error import InputError
from core.rank import RankList
from core.score import UserPlay
from core.sql import Connect
@@ -9,7 +9,7 @@ from core.user import UserOnline
from flask import Blueprint, request
from .auth import auth_required
from .func import error_return, success_return
from .func import arc_try, success_return
bp = Blueprint('score', __name__, url_prefix='/score')
@@ -21,6 +21,7 @@ def score_token():
@bp.route('/token/world', methods=['GET']) # 世界模式成绩上传所需的token
@auth_required(request)
@arc_try
def score_token_world(user_id):
stamina_multiply = int(
@@ -30,127 +31,108 @@ def score_token_world(user_id):
prog_boost_multiply = int(
request.args['prog_boost_multiply']) if 'prog_boost_multiply' in request.args else 0
with Connect() as c:
try:
x = UserPlay(c, UserOnline(c, user_id))
x.song.set_chart(request.args['song_id'], int(
request.args['difficulty']))
x.set_play_state_for_world(stamina_multiply,
fragment_multiply, prog_boost_multiply)
return success_return({
"stamina": x.user.stamina.stamina,
"max_stamina_ts": x.user.stamina.max_stamina_ts,
"token": x.song_token
}
)
except ArcError as e:
return error_return(e)
return error_return()
x = UserPlay(c, UserOnline(c, user_id))
x.song.set_chart(request.args['song_id'], int(
request.args['difficulty']))
x.set_play_state_for_world(stamina_multiply,
fragment_multiply, prog_boost_multiply)
return success_return({
"stamina": x.user.stamina.stamina,
"max_stamina_ts": x.user.stamina.max_stamina_ts,
"token": x.song_token
}
)
@bp.route('/token/course', methods=['GET']) # 课题模式成绩上传所需的token
@auth_required(request)
@arc_try
def score_token_course(user_id):
with Connect() as c:
try:
use_course_skip_purchase = request.args.get(
'use_course_skip_purchase', 'false') == 'true'
use_course_skip_purchase = request.args.get(
'use_course_skip_purchase', 'false') == 'true'
user = UserOnline(c, user_id)
user_play = UserPlay(c, user)
user_play.song_token = request.args.get('previous_token', None)
user_play.get_play_state()
user = UserOnline(c, user_id)
user_play = UserPlay(c, user)
user_play.song_token = request.args.get('previous_token', None)
user_play.get_play_state()
status = 'created'
if user_play.course_play_state == -1:
# 没有token课题模式刚开始
course_play = CoursePlay(c, user, user_play)
course_play.course_id = request.args['course_id']
user_play.course_play = course_play
user_play.set_play_state_for_course(
use_course_skip_purchase)
elif 0 <= user_play.course_play_state <= 3:
# 验证token
user_play.update_token_for_course()
else:
# 课题模式已经结束
user_play.clear_play_state()
user.select_user_about_stamina()
status = 'cleared' if user_play.course_play_state == 4 else 'failed'
status = 'created'
if user_play.course_play_state == -1:
# 没有token课题模式刚开始
course_play = CoursePlay(c, user, user_play)
course_play.course_id = request.args['course_id']
user_play.course_play = course_play
user_play.set_play_state_for_course(
use_course_skip_purchase)
elif 0 <= user_play.course_play_state <= 3:
# 验证token
user_play.update_token_for_course()
else:
# 课题模式已经结束
user_play.clear_play_state()
user.select_user_about_stamina()
status = 'cleared' if user_play.course_play_state == 4 else 'failed'
return success_return({
"stamina": user.stamina.stamina,
"max_stamina_ts": user.stamina.max_stamina_ts,
"token": user_play.song_token,
'status': status
})
except ArcError as e:
return error_return(e)
return error_return()
return success_return({
"stamina": user.stamina.stamina,
"max_stamina_ts": user.stamina.max_stamina_ts,
"token": user_play.song_token,
'status': status
})
@bp.route('/song', methods=['POST']) # 成绩上传
@auth_required(request)
@arc_try
def song_score_post(user_id):
with Connect() as c:
try:
x = UserPlay(c, UserOnline(c, user_id))
x.song_token = request.form['song_token']
x.song_hash = request.form['song_hash']
x.song.set_chart(
request.form['song_id'], request.form['difficulty'])
x.set_score(request.form['score'], request.form['shiny_perfect_count'], request.form['perfect_count'], request.form['near_count'],
request.form['miss_count'], request.form['health'], request.form['modifier'], int(time() * 1000), request.form['clear_type'])
x.beyond_gauge = int(request.form['beyond_gauge'])
x.submission_hash = request.form['submission_hash']
if not x.is_valid:
raise InputError('Invalid score.', 107)
x.upload_score()
return success_return(x.to_dict())
except ArcError as e:
return error_return(e)
return error_return()
x = UserPlay(c, UserOnline(c, user_id))
x.song_token = request.form['song_token']
x.song_hash = request.form['song_hash']
x.song.set_chart(
request.form['song_id'], request.form['difficulty'])
x.set_score(request.form['score'], request.form['shiny_perfect_count'], request.form['perfect_count'], request.form['near_count'],
request.form['miss_count'], request.form['health'], request.form['modifier'], int(time() * 1000), request.form['clear_type'])
x.beyond_gauge = int(request.form['beyond_gauge'])
x.submission_hash = request.form['submission_hash']
if not x.is_valid:
raise InputError('Invalid score.', 107)
x.upload_score()
return success_return(x.to_dict())
@bp.route('/song', methods=['GET']) # TOP20
@auth_required(request)
@arc_try
def song_score_top(user_id):
with Connect() as c:
try:
rank_list = RankList(c)
rank_list.song.set_chart(request.args.get(
'song_id'), request.args.get('difficulty'))
rank_list.select_top()
return success_return(rank_list.to_dict_list())
except ArcError as e:
return error_return(e)
return error_return()
rank_list = RankList(c)
rank_list.song.set_chart(request.args.get(
'song_id'), request.args.get('difficulty'))
rank_list.select_top()
return success_return(rank_list.to_dict_list())
@bp.route('/song/me', methods=['GET']) # 我的排名默认最多20
@auth_required(request)
@arc_try
def song_score_me(user_id):
with Connect() as c:
try:
rank_list = RankList(c)
rank_list.song.set_chart(request.args.get(
'song_id'), request.args.get('difficulty'))
rank_list.select_me(UserOnline(c, user_id))
return success_return(rank_list.to_dict_list())
except ArcError as e:
return error_return(e)
return error_return()
rank_list = RankList(c)
rank_list.song.set_chart(request.args.get(
'song_id'), request.args.get('difficulty'))
rank_list.select_me(UserOnline(c, user_id))
return success_return(rank_list.to_dict_list())
@bp.route('/song/friend', methods=['GET']) # 好友排名默认最多50
@auth_required(request)
@arc_try
def song_score_friend(user_id):
with Connect() as c:
try:
rank_list = RankList(c)
rank_list.song.set_chart(request.args.get(
'song_id'), request.args.get('difficulty'))
rank_list.select_friend(UserOnline(c, user_id))
return success_return(rank_list.to_dict_list())
except ArcError as e:
return error_return(e)
return error_return()
rank_list = RankList(c)
rank_list.song.set_chart(request.args.get(
'song_id'), request.args.get('difficulty'))
rank_list.select_friend(UserOnline(c, user_id))
return success_return(rank_list.to_dict_list())

View File

@@ -8,186 +8,160 @@ from flask import Blueprint, request
from setting import Config
from .auth import auth_required
from .func import error_return, success_return
from .func import arc_try, success_return
bp = Blueprint('user', __name__, url_prefix='/user')
@bp.route('', methods=['POST']) # 注册接口
@arc_try
def register():
if 'AppVersion' in request.headers: # 版本检查
if Config.ALLOW_APPVERSION:
if request.headers['AppVersion'] not in Config.ALLOW_APPVERSION:
return error_return(NoAccess('Wrong app version.', 1203))
raise NoAccess('Wrong app version.', 1203)
with Connect() as c:
try:
new_user = UserRegister(c)
new_user.set_name(request.form['name'])
new_user.set_password(request.form['password'])
new_user.set_email(request.form['email'])
if 'device_id' in request.form:
device_id = request.form['device_id']
else:
device_id = 'low_version'
new_user = UserRegister(c)
new_user.set_name(request.form['name'])
new_user.set_password(request.form['password'])
new_user.set_email(request.form['email'])
if 'device_id' in request.form:
device_id = request.form['device_id']
else:
device_id = 'low_version'
new_user.register()
new_user.register()
# 注册后自动登录
user = UserLogin(c)
user.login(new_user.name, new_user.password,
device_id, request.remote_addr)
return success_return({'user_id': user.user_id, 'access_token': user.token})
except ArcError as e:
return error_return(e)
return error_return()
# 注册后自动登录
user = UserLogin(c)
user.login(new_user.name, new_user.password,
device_id, request.remote_addr)
return success_return({'user_id': user.user_id, 'access_token': user.token})
@bp.route('/me', methods=['GET']) # 用户信息
@auth_required(request)
@arc_try
def user_me(user_id):
with Connect() as c:
try:
return success_return(UserOnline(c, user_id).to_dict())
except ArcError as e:
return error_return(e)
return error_return()
return success_return(UserOnline(c, user_id).to_dict())
@bp.route('/me/character', methods=['POST']) # 角色切换
@auth_required(request)
@arc_try
def character_change(user_id):
with Connect() as c:
try:
user = UserOnline(c, user_id)
user.change_character(
int(request.form['character']), request.form['skill_sealed'] == 'true')
user = UserOnline(c, user_id)
user.change_character(
int(request.form['character']), request.form['skill_sealed'] == 'true')
return success_return({'user_id': user.user_id, 'character': user.character.character_id})
except ArcError as e:
return error_return(e)
return error_return()
return success_return({'user_id': user.user_id, 'character': user.character.character_id})
# 角色觉醒切换
@bp.route('/me/character/<int:character_id>/toggle_uncap', methods=['POST'])
@auth_required(request)
@arc_try
def toggle_uncap(user_id, character_id):
with Connect() as c:
try:
user = User()
user.user_id = user_id
character = UserCharacter(c, character_id)
character.change_uncap_override(user)
character.select_character_info(user)
return success_return({'user_id': user.user_id, 'character': [character.to_dict()]})
except ArcError as e:
return error_return(e)
return error_return()
user = User()
user.user_id = user_id
character = UserCharacter(c, character_id)
character.change_uncap_override(user)
character.select_character_info(user)
return success_return({'user_id': user.user_id, 'character': [character.to_dict()]})
# 角色觉醒
@bp.route('/me/character/<int:character_id>/uncap', methods=['POST'])
@auth_required(request)
@arc_try
def character_first_uncap(user_id, character_id):
with Connect() as c:
try:
user = UserOnline(c, user_id)
character = UserCharacter(c, character_id)
character.select_character_info(user)
character.character_uncap(user)
return success_return({'user_id': user.user_id, 'character': [character.to_dict()], 'cores': user.cores})
except ArcError as e:
return error_return(e)
return error_return()
user = UserOnline(c, user_id)
character = UserCharacter(c, character_id)
character.select_character_info(user)
character.character_uncap(user)
return success_return({'user_id': user.user_id, 'character': [character.to_dict()], 'cores': user.cores})
# 角色使用以太之滴
@bp.route('/me/character/<int:character_id>/exp', methods=['POST'])
@auth_required(request)
@arc_try
def character_exp(user_id, character_id):
with Connect() as c:
try:
user = UserOnline(c, user_id)
character = UserCharacter(c, character_id)
character.select_character_info(user)
core = ItemCore(c)
core.amount = - int(request.form['amount'])
core.item_id = 'core_generic'
character.upgrade_by_core(user, core)
return success_return({'user_id': user.user_id, 'character': [character.to_dict], 'cores': user.cores})
except ArcError as e:
return error_return(e)
return error_return()
user = UserOnline(c, user_id)
character = UserCharacter(c, character_id)
character.select_character_info(user)
core = ItemCore(c)
core.amount = - int(request.form['amount'])
core.item_id = 'core_generic'
character.upgrade_by_core(user, core)
return success_return({'user_id': user.user_id, 'character': [character.to_dict], 'cores': user.cores})
@bp.route('/me/save', methods=['GET']) # 从云端同步
@auth_required(request)
@arc_try
def cloud_get(user_id):
with Connect() as c:
try:
user = User()
user.user_id = user_id
save = SaveData(c)
save.select_all(user)
return success_return(save.to_dict())
except ArcError as e:
return error_return(e)
return error_return()
user = User()
user.user_id = user_id
save = SaveData(c)
save.select_all(user)
return success_return(save.to_dict())
@bp.route('/me/save', methods=['POST']) # 向云端同步
@auth_required(request)
@arc_try
def cloud_post(user_id):
with Connect() as c:
try:
user = User()
user.user_id = user_id
save = SaveData(c)
save.set_value(
'scores_data', request.form['scores_data'], request.form['scores_checksum'])
save.set_value(
'clearlamps_data', request.form['clearlamps_data'], request.form['clearlamps_checksum'])
save.set_value(
'clearedsongs_data', request.form['clearedsongs_data'], request.form['clearedsongs_checksum'])
save.set_value(
'unlocklist_data', request.form['unlocklist_data'], request.form['unlocklist_checksum'])
save.set_value(
'installid_data', request.form['installid_data'], request.form['installid_checksum'])
save.set_value('devicemodelname_data',
request.form['devicemodelname_data'], request.form['devicemodelname_checksum'])
save.set_value(
'story_data', request.form['story_data'], request.form['story_checksum'])
save.set_value(
'finalestate_data', request.form['finalestate_data'], request.form['finalestate_checksum'])
user = User()
user.user_id = user_id
save = SaveData(c)
save.set_value(
'scores_data', request.form['scores_data'], request.form['scores_checksum'])
save.set_value(
'clearlamps_data', request.form['clearlamps_data'], request.form['clearlamps_checksum'])
save.set_value(
'clearedsongs_data', request.form['clearedsongs_data'], request.form['clearedsongs_checksum'])
save.set_value(
'unlocklist_data', request.form['unlocklist_data'], request.form['unlocklist_checksum'])
save.set_value(
'installid_data', request.form['installid_data'], request.form['installid_checksum'])
save.set_value('devicemodelname_data',
request.form['devicemodelname_data'], request.form['devicemodelname_checksum'])
save.set_value(
'story_data', request.form['story_data'], request.form['story_checksum'])
save.set_value(
'finalestate_data', request.form['finalestate_data'], request.form['finalestate_checksum'])
save.update_all(user)
return success_return({'user_id': user.user_id})
except ArcError as e:
return error_return(e)
return error_return()
save.update_all(user)
return success_return({'user_id': user.user_id})
@bp.route('/me/setting/<set_arg>', methods=['POST']) # 三个设置
@auth_required(request)
@arc_try
def sys_set(user_id, set_arg):
with Connect() as c:
try:
value = request.form['value']
user = UserOnline(c, user_id)
if 'favorite_character' == set_arg:
user.change_favorite_character(int(value))
else:
value = 'true' == value
if 'is_hide_rating' == set_arg or 'max_stamina_notification_enabled' == set_arg:
user.update_user_one_column(set_arg, value)
return success_return(user.to_dict())
except ArcError as e:
return error_return(e)
return error_return()
value = request.form['value']
user = UserOnline(c, user_id)
if 'favorite_character' == set_arg:
user.change_favorite_character(int(value))
else:
value = 'true' == value
if 'is_hide_rating' == set_arg or 'max_stamina_notification_enabled' == set_arg:
user.update_user_one_column(set_arg, value)
return success_return(user.to_dict())
@bp.route('/me/request_delete', methods=['POST']) # 删除账号
@auth_required(request)
@arc_try
def user_delete(user_id):
return error_return(ArcError('Cannot delete the account.', 151)), 404
raise ArcError('Cannot delete the account.', 151, status=404)

View File

@@ -1,57 +1,47 @@
from core.error import ArcError
from core.sql import Connect
from core.user import UserOnline
from core.world import UserMap, get_world_all
from flask import Blueprint, request
from .auth import auth_required
from .func import error_return, success_return
from .func import arc_try, success_return
bp = Blueprint('world', __name__, url_prefix='/world')
@bp.route('/map/me', methods=['GET']) # 获得世界模式信息,所有地图
@auth_required(request)
@arc_try
def world_all(user_id):
with Connect() as c:
try:
user = UserOnline(c, user_id)
user.select_user_about_current_map()
return success_return({
"current_map": user.current_map.map_id,
"user_id": user_id,
"maps": [x.to_dict(has_map_info=True, has_rewards=True) for x in get_world_all(c, user)]
})
except ArcError as e:
return error_return(e)
return error_return()
user = UserOnline(c, user_id)
user.select_user_about_current_map()
return success_return({
"current_map": user.current_map.map_id,
"user_id": user_id,
"maps": [x.to_dict(has_map_info=True, has_rewards=True) for x in get_world_all(c, user)]
})
@bp.route('/map/me', methods=['POST']) # 进入地图
@auth_required(request)
@arc_try
def world_in(user_id):
with Connect() as c:
try:
arcmap = UserMap(c, request.form['map_id'], UserOnline(c, user_id))
if arcmap.unlock():
return success_return(arcmap.to_dict())
except ArcError as e:
return error_return(e)
return error_return()
arcmap = UserMap(c, request.form['map_id'], UserOnline(c, user_id))
if arcmap.unlock():
return success_return(arcmap.to_dict())
@bp.route('/map/me/<map_id>', methods=['GET']) # 获得单个地图完整信息
@auth_required(request)
@arc_try
def world_one(user_id, map_id):
with Connect() as c:
try:
arcmap = UserMap(c, map_id, UserOnline(c, user_id))
arcmap.change_user_current_map()
return success_return({
"user_id": user_id,
"current_map": map_id,
"maps": [arcmap.to_dict(has_map_info=True, has_steps=True)]
})
except ArcError as e:
return error_return(e)
return error_return()
arcmap = UserMap(c, map_id, UserOnline(c, user_id))
arcmap.change_user_current_map()
return success_return({
"user_id": user_id,
"current_map": map_id,
"maps": [arcmap.to_dict(has_map_info=True, has_steps=True)]
})

View File

@@ -186,7 +186,8 @@ class Config():
是否记录详细的服务器日志
If recording detailed server logs is enabled
'''
ALLOW_LOG_INFO = False
ALLOW_INFO_LOG = False
ALLOW_WARNING_LOG = False
'''
--------------------
'''