Update to v2.6.2

This commit is contained in:
Lost-MSth
2021-08-11 18:45:32 +08:00
parent 168e5f0b12
commit 7c3bc99570
16 changed files with 1158 additions and 839 deletions

View File

@@ -62,12 +62,13 @@ It is just so interesting. What it can do is under exploration.
>
> Tips: When updating, please keep the original database in case of data loss.
### Version 2.6.1
- 适用于Arcaea 3.7.0版本 For Arcaea 3.7.0
### Version 2.6.2
- 适用于Arcaea 3.8.0版本 For Arcaea 3.8.0
- 更新了歌曲数据库 Update the song database.
-增活动图设置 Add available event maps setting.
-搭档 **咲弥 & 伊丽莎白** 已解锁 Unlock the new character **Saya & Elizabeth**.
- 新搭档 **莉莉** 已解锁 Unlock the new character **Lily**.
- 修复了一个Bug Fix a bug.
- 添加了`user/me`接口 Add `user/me` interface.
- 链接重定向导致无法切换地图的问题 Link redirection caused the problem that players are unable to switch maps.
## 运行环境与依赖 Running environment and requirements

View File

@@ -1,5 +1,7 @@
import hashlib
import base64
import time
import random
from server.sql import Connect
import functools
from setting import Config
@@ -14,9 +16,40 @@ class User():
self.power = power
def login():
# 登录接口
return {'token': 1}, 0
def login(auth: str, ip: str):
# 登录接口,返回字典和错误码
try:
auth_decode = bytes.decode(base64.b64decode(auth))
except:
return {}, -100
if not ':' in auth_decode:
return {}, -100
name, password = auth_decode.split(':', 1)
with Connect() as c:
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
c.execute('''select user_id, password from user where name = :name''', {
'name': name})
x = c.fetchone()
if x is None:
return {}, -201
if x[1] == '':
return {}, -202
if hash_pwd != x[1]:
return {}, -201
user_id = str(x[0])
now = int(time.time() * 1000)
token = hashlib.sha256(
(user_id + str(random.randint(10000, 99999)) + str(now)).encode("utf8")).hexdigest()
c.execute('''delete from api_login where user_id=?''', (user_id,))
c.execute('''insert into api_login values(?,?,?,?)''',
(user_id, token, now, ip))
return {'token': token, 'user_id': user_id}, 0
def logout():

View File

@@ -6,10 +6,13 @@ def code_get_msg(code):
'-2': 'No data',
'-3': 'No data or user',
'-4': 'No user_id',
'-100': 'Wrong post data',
'-101': 'Wrong data type',
'-102': 'Wrong query parameter',
'-103': 'Wrong sort parameter',
'-104': 'Wrong sort order parameter'
'-104': 'Wrong sort order parameter',
'-201': 'Wrong username or password',
'-202': 'User is banned'
}
return msg[str(code)]

View File

@@ -1,6 +1,7 @@
from flask import (
Blueprint, request, jsonify
)
import functools
import api.api_auth
import api.users
import api.songs
@@ -10,93 +11,112 @@ from api.api_code import code_get_msg
bp = Blueprint('api', __name__, url_prefix='/api/v1')
class Query():
# 查询类,当查询附加参数的数据类型用
def __init__(self, limit=-1, offset=0, query={}, sort=[]) -> None:
self.limit = limit
self.offset = offset
self.query = query # {'name': 'admin'}
self.sort = sort # [{'column': 'user_id', 'order': 'ASC'}, ...]
def get_query_parameter(request, query_able=[], sort_able=[]):
# 提取查询请求参数,返回四个参数和code
# 提取查询请求参数,返回Query类查询参数写成修饰器
limit = -1
offset = 0
query = {} # {'name': 'admin'}
sort = [] # [{'column': 'user_id', 'order': 'ASC'}, ...]
def decorator(view):
@functools.wraps(view)
def wrapped_view(*args, **kwargs):
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
re = Query()
return limit, offset, query, sort, 0
if 'limit' in request.json:
try:
re.limit = int(request.json['limit'])
except:
return jsonify({'status': 200, 'code': -101, 'data': {}, 'msg': code_get_msg(-101)})
if 'offset' in request.json:
try:
re.offset = int(request.json['offset'])
except:
return jsonify({'status': 200, 'code': -101, 'data': {}, 'msg': code_get_msg(-101)})
if 'query' in request.json:
re.query = request.json['query']
for i in re.query:
if i not in query_able:
return jsonify({'status': 200, 'code': -102, 'data': {}, 'msg': code_get_msg(-102)})
if 'sort' in request.json:
re.sort = request.json['sort']
for i in re.sort:
if 'column' not in i or i['column'] not in sort_able:
return jsonify({'status': 200, 'code': -103, 'data': {}, 'msg': code_get_msg(-103)})
if not 'order' in i:
i['order'] = 'ASC'
else:
if i['order'] not in ['ASC', 'DESC']:
return jsonify({'status': 200, 'code': -104, 'data': {}, 'msg': code_get_msg(-104)})
return view(re, *args, **kwargs)
return wrapped_view
return decorator
def return_encode(code: int = 0, data: dict = {}, status: int = 200, msg: str = ''):
# 构造返回返回jsonify处理过后的response_class
if msg == '':
msg = code_get_msg(code)
if code < 0:
return jsonify({'status': status, 'code': code, 'data': {}, 'msg': msg})
else:
return jsonify({'status': status, 'code': code, 'data': data, 'msg': msg})
@bp.route('/')
def ping():
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
return return_encode()
@bp.route('/token', methods=['POST'])
def token_post():
# 登录获取token
# {'auth': `base64(user_id:password)`}
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': ''})
str(request.json['auth']), request.remote_addr)
return return_encode(code, data)
else:
return jsonify({'status': 401, 'code': -1, 'data': {}, 'msg': 'No authentication'})
return return_encode(-1, {}, 401, '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': ''})
return return_encode()
@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': ''})
return return_encode()
@bp.route('/users', methods=['GET'])
@api.api_auth.role_required(request, ['select'])
def users_get(user):
@get_query_parameter(request, ['user_id', 'name', 'user_code'], [
'user_id', 'name', 'user_code', 'join_date', 'rating_ptt', 'time_played', 'ticket', 'world_rank_score'])
def users_get(query, 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', 'world_rank_score'])
if code < 0:
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
data = api.users.get_users(limit, offset, query, sort)
data = api.users.get_users(query)
if not data:
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
return return_encode(-2)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/users/<int:user_id>', methods=['GET'])
@@ -108,17 +128,17 @@ def users_user_get(user, user_id):
user_id = user.user_id
if user_id <= 0:
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
return return_encode(-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'})
return return_encode(-1, {}, 403, '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 return_encode(-3)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/users/<int:user_id>/b30', methods=['GET'])
@@ -126,48 +146,39 @@ def users_user_get(user, user_id):
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)})
return return_encode(-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'})
return return_encode(-1, {}, 403, '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 return_encode(-3)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@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):
@get_query_parameter(request, ['song_id', 'difficulty'], [
'song_id', 'difficulty', 'score', 'time_played', 'rating'])
def users_user_best_get(query, 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)})
return return_encode(-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'})
return return_encode(-1, {}, 403, '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)
data = api.users.get_user_best(user_id, query)
if data['data'] == []:
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
return return_encode(-3)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/users/<int:user_id>/r30', methods=['GET'])
@@ -175,21 +186,18 @@ def users_user_best_get(user, user_id):
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)})
return return_encode(-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'})
return return_encode(-1, {}, 403, '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 return_encode(-3)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/songs/<string:song_id>', methods=['GET'])
@@ -200,24 +208,21 @@ 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 return_encode(-2)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)
@bp.route('/songs', methods=['GET'])
@api.api_auth.role_required(request, ['select', 'select_song_info'])
def songs_get(user):
@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'])
def songs_get(query, 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)
data = api.songs.get_songs(query)
if not data:
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
return return_encode(-2)
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
return return_encode(0, data)

View File

@@ -30,12 +30,12 @@ def get_song_info(song_id):
return r
def get_songs(limit=-1, offset=0, query={}, sort=[]):
def get_songs(query=None):
# 查询全部歌曲信息,返回字典列表
r = []
with Connect('./database/arcsong.db') as c:
x = Sql.select(c, 'songs', [], limit, offset, query, sort)
x = Sql.select(c, 'songs', [], query)
if x:
for i in x:

View File

@@ -5,12 +5,12 @@ import web.webscore
import server.info
def get_users(limit=-1, offset=0, query={}, sort=[]):
def get_users(query=None):
# 获取全用户信息,返回字典列表
r = []
with Connect() as c:
x = Sql.select(c, 'user', [], limit, offset, query, sort)
x = Sql.select(c, 'user', [], query)
if x:
for i in x:
@@ -62,12 +62,12 @@ def get_user_b30(user_id):
return {'user_id': user_id, 'b30_ptt': bestptt / 30, 'data': r}
def get_user_best(user_id, limit=-1, offset=0, query={}, sort=[]):
def get_user_best(user_id, query=None):
# 获取用户b30信息返回字典
r = []
with Connect() as c:
x = Sql.select(c, 'best_score', [], limit, offset, query, sort)
x = Sql.select(c, 'best_score', [], query)
if x:
for i in x:
r.append({

Binary file not shown.

View File

@@ -4,7 +4,7 @@ import json
# 数据库初始化文件删掉arcaea_database.db文件后运行即可谨慎使用
ARCAEA_SERVER_VERSION = 'v2.6.1'
ARCAEA_SERVER_VERSION = 'v2.6.2'
def main(path='./'):
@@ -298,46 +298,46 @@ def main(path='./'):
# 搭档初始化
char = ['hikari', 'tairitsu', 'kou', 'sapphire', 'lethe', '', 'Tairitsu(Axium)', 'Tairitsu(Grievous Lady)', 'stella', 'Hikari & Fisica', 'ilith', 'eto', 'luna', 'shirabe', 'Hikari(Zero)', 'Hikari(Fracture)', 'Hikari(Summer)', 'Tairitsu(Summer)', 'Tairitsu & Trin',
'ayu', 'Eto & Luna', 'yume', 'Seine & Hikari', 'saya', 'Tairitsu & Chuni Penguin', 'Chuni Penguin', 'haruna', 'nono', 'MTA-XXX', 'MDA-21', 'kanae', 'Hikari(Fantasia)', 'Tairitsu(Sonata)', 'sia', 'DORO*C', 'Tairitsu(Tempest)', 'brillante', 'Ilith(Summer)', 'etude', 'Alice & Tenniel', 'Luna & Mia', 'areus', 'seele', 'isabelle', 'mir', 'lagrange', '???', 'nami']
'ayu', 'Eto & Luna', 'yume', 'Seine & Hikari', 'saya', 'Tairitsu & Chuni Penguin', 'Chuni Penguin', 'haruna', 'nono', 'MTA-XXX', 'MDA-21', 'kanae', 'Hikari(Fantasia)', 'Tairitsu(Sonata)', 'sia', 'DORO*C', 'Tairitsu(Tempest)', 'brillante', 'Ilith(Summer)', 'etude', 'Alice & Tenniel', 'Luna & Mia', 'areus', 'seele', 'isabelle', 'mir', 'lagrange', 'linka', 'nami', 'Saya & Elizabeth', 'lily']
skill_id = ['gauge_easy', '', '', '', 'note_mirror', '', '', 'gauge_hard', 'frag_plus_10_pack_stellights', 'gauge_easy|frag_plus_15_pst&prs', 'gauge_hard|fail_frag_minus_100', 'frag_plus_5_side_light', 'visual_hide_hp', 'frag_plus_5_side_conflict', 'challenge_fullcombo_0gauge', 'gauge_overflow', 'gauge_easy|note_mirror', 'note_mirror', 'visual_tomato_pack_tonesphere',
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', '', '', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', '', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami']
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', '', '', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', '', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami', 'skill_elizabeth', 'skill_lily']
skill_id_uncap = ['', '', 'frags_kou', '', 'visual_ink', '', '', '', '', '', '', '', '', 'shirabe_entry_fee',
'', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
'', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
skill_unlock_level = [0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 0, 0, 0, 0, 0,
0, 0, 0, 8, 0, 14, 0, 0, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0]
0, 0, 0, 8, 0, 14, 0, 0, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0]
frag1 = [55, 55, 60, 50, 47, 0, 47, 57, 41, 22, 50, 54, 60, 56, 78, 42, 41, 61, 52, 50, 52, 32,
42, 55, 45, 58, 43, 0.5, 68, 50, 62, 45, 45, 52, 44, 27, 59, 0, 45, 50, 50, 47, 47, 61, 43, 42, 50, 25]
42, 55, 45, 58, 43, 0.5, 68, 50, 62, 45, 45, 52, 44, 27, 59, 0, 45, 50, 50, 47, 47, 61, 43, 42, 50, 25, 58, 50]
prog1 = [35, 55, 47, 50, 60, 0, 60, 70, 58, 45, 70, 45, 42, 46, 61, 67, 49, 44, 28, 45, 24, 46, 52,
59, 62, 33, 58, 25, 63, 69, 50, 45, 45, 51, 34, 70, 62, 70, 45, 32, 32, 61, 47, 47, 37, 42, 50, 50]
59, 62, 33, 58, 25, 63, 69, 50, 45, 45, 51, 34, 70, 62, 70, 45, 32, 32, 61, 47, 47, 37, 42, 50, 50, 45, 41]
overdrive1 = [35, 55, 25, 50, 47, 0, 72, 57, 41, 7, 10, 32, 65, 31, 61, 53, 31, 47, 38, 12, 39, 18,
48, 65, 45, 55, 44, 25, 46, 44, 33, 45, 45, 37, 25, 27, 50, 20, 45, 63, 21, 47, 61, 47, 65, 80, 50, 30]
48, 65, 45, 55, 44, 25, 46, 44, 33, 45, 45, 37, 25, 27, 50, 20, 45, 63, 21, 47, 61, 47, 65, 80, 50, 30, 49, 15]
frag20 = [78, 80, 90, 75, 70, 0, 70, 79, 65, 40, 50, 80, 90, 82, 0, 61, 67, 92, 85, 50, 86, 52,
65, 85, 67, 88, 64, 0.5, 95, 70, 95, 50, 80, 87, 71, 50, 85, 0, 80, 75, 50, 70, 70, 90, 65, 80, 100, 50]
65, 85, 67, 88, 64, 0.5, 95, 70, 95, 50, 80, 87, 71, 50, 85, 0, 80, 75, 50, 70, 70, 90, 65, 80, 100, 50, 68, 60]
prog20 = [61, 80, 70, 75, 90, 0, 90, 102, 84, 78, 105, 67, 63, 68, 0, 99, 80, 66, 46, 83, 40, 73,
80, 90, 93, 50, 86, 78, 89, 98, 75, 80, 50, 64, 55, 100, 90, 110, 80, 50, 74, 90, 70, 70, 56, 80, 100, 55]
80, 90, 93, 50, 86, 78, 89, 98, 75, 80, 50, 64, 55, 100, 90, 110, 80, 50, 74, 90, 70, 70, 56, 80, 100, 55, 65, 60]
overdrive20 = [61, 80, 47, 75, 70, 0, 95, 79, 65, 31, 50, 59, 90, 58, 0, 78, 50, 70, 62, 49, 64,
46, 73, 95, 67, 84, 70, 78, 69, 70, 50, 80, 80, 63, 25, 50, 72, 55, 50, 95, 55, 70, 90, 70, 99, 80, 100, 40]
46, 73, 95, 67, 84, 70, 78, 69, 70, 50, 80, 80, 63, 25, 50, 72, 55, 50, 95, 55, 70, 90, 70, 99, 80, 100, 40, 69, 60]
frag30 = [88, 90, 100, 75, 80, 0, 70, 79, 65, 40, 50, 80, 90, 92, 0, 61, 67, 92, 85, 50, 86, 62,
65, 85, 67, 88, 74, 0.5, 105, 80, 95, 50, 80, 87, 71, 50, 95, 0, 80, 75, 50, 70, 80, 100, 65, 80, 100, 50]
65, 85, 67, 88, 74, 0.5, 105, 80, 95, 50, 80, 87, 71, 50, 95, 0, 80, 75, 50, 70, 80, 100, 65, 80, 100, 50, 68, 60]
prog30 = [71, 90, 80, 75, 100, 0, 90, 102, 84, 78, 105, 67, 63, 78, 0, 99, 80, 66, 46, 83, 40, 83,
80, 90, 93, 50, 96, 88, 99, 108, 75, 80, 50, 64, 55, 100, 100, 110, 80, 50, 74, 90, 80, 80, 56, 80, 100, 55]
80, 90, 93, 50, 96, 88, 99, 108, 75, 80, 50, 64, 55, 100, 100, 110, 80, 50, 74, 90, 80, 80, 56, 80, 100, 55, 65, 60]
overdrive30 = [71, 90, 57, 75, 80, 0, 95, 79, 65, 31, 50, 59, 90, 68, 0, 78, 50, 70, 62, 49, 64,
56, 73, 95, 67, 84, 80, 88, 79, 80, 50, 80, 80, 63, 25, 50, 82, 55, 50, 95, 55, 70, 100, 80, 99, 80, 100, 40]
56, 73, 95, 67, 84, 80, 88, 79, 80, 50, 80, 80, 63, 25, 50, 82, 55, 50, 95, 55, 70, 100, 80, 99, 80, 100, 40, 69, 60]
char_type = [1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 2, 0, 0, 0, 2, 3, 1, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 1, 0, 0, 0]
0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 1, 0, 0, 0, 0, 0]
char_core = {
0: [{'core_id': 'core_hollow', 'amount': 25}, {'core_id': 'core_desolate', 'amount': 5}],
@@ -355,7 +355,7 @@ def main(path='./'):
43: [{'core_id': 'core_chunithm', 'amount': 15}]
}
for i in range(0, 48):
for i in range(0, 50):
skill_requires_uncap = 1 if i == 2 else 0
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21, 42, 43]:
@@ -379,7 +379,7 @@ def main(path='./'):
c.execute('''insert into item values(?,"core",1,'')''', (i,))
world_songs = ["babaroque", "shadesoflight", "kanagawa", "lucifer", "anokumene", "ignotus", "rabbitintheblackroom", "qualia", "redandblue", "bookmaker", "darakunosono", "espebranch", "blacklotus", "givemeanightmare", "vividtheory", "onefr", "gekka", "vexaria3", "infinityheaven3", "fairytale3", "goodtek3", "suomi", "rugie", "faintlight", "harutopia", "goodtek", "dreaminattraction", "syro", "diode", "freefall", "grimheart", "blaster",
"cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight", "lapis", "solitarydream", "lumia3", "purpleverse", "moonheart3", "glow", "enchantedlove", "take", "lifeispiano", "vandalism", "nexttoyou3", "lostcivilization3", "turbocharger", "bookmaker3", "laqryma3", "kyogenkigo", "hivemind", "seclusion"]
"cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight", "lapis", "solitarydream", "lumia3", "purpleverse", "moonheart3", "glow", "enchantedlove", "take", "lifeispiano", "vandalism", "nexttoyou3", "lostcivilization3", "turbocharger", "bookmaker3", "laqryma3", "kyogenkigo", "hivemind", "seclusion", "quonwacca3"]
for i in world_songs:
c.execute('''insert into item values(?,"world_song",1,'')''', (i,))

View File

@@ -0,0 +1,376 @@
{
"map_id": "byd_bookmaker",
"is_legacy": false,
"chapter": 1001,
"available_from": -1,
"available_to": 9999999999999,
"is_repeatable": false,
"require_id": "bookmaker2",
"require_type": "chart_unlock",
"coordinate": "-650,-650",
"is_beyond": true,
"stamina_cost": 3,
"beyond_health": 300,
"character_affinity": [
23,
34,
47
],
"affinity_multiplier": [
1.3,
5,
3.8
],
"step_count": 31,
"custom_bg": "",
"curr_position": 3,
"curr_capture": 35.81730523472207,
"is_locked": false,
"steps": [
{
"map_id": "byd_bookmaker",
"position": 0,
"capture": 10
},
{
"map_id": "byd_bookmaker",
"position": 1,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 2,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 3,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
],
"restrict_ids": [
"bookmaker",
"viciousheroism",
"battlenoone",
"galaxyfriends",
"rekkaresonance"
],
"restrict_type": "song_id"
},
{
"map_id": "byd_bookmaker",
"position": 4,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 5,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 6,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 7,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 8,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 9,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 10,
"capture": 10,
"items": [
{
"type": "core",
"id": "core_generic",
"amount": 1
}
]
},
{
"map_id": "byd_bookmaker",
"position": 11,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 12,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 13,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 14,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 15,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 16,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 17,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 18,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 19,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 20,
"capture": 10,
"items": [
{
"type": "core",
"id": "core_generic",
"amount": 1
}
]
},
{
"map_id": "byd_bookmaker",
"position": 21,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 22,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 23,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 24,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 25,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 26,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 27,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 28,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 29,
"capture": 10,
"items": [
{
"type": "fragment",
"amount": 30
}
]
},
{
"map_id": "byd_bookmaker",
"position": 30,
"capture": 0,
"items": [
{
"id": "bookmaker3",
"type": "world_song"
}
]
}
]
}

View File

@@ -256,4 +256,13 @@
}],
"orig_price": 300,
"price": 300
}, {
"name": "wacca",
"items": [{
"type": "pack",
"id": "wacca",
"is_available": true
}],
"orig_price": 500,
"price": 500
}]

File diff suppressed because it is too large Load Diff

View File

@@ -632,7 +632,7 @@ def world_all(user_id):
})
@app.route(add_url_prefix('/world/map/me/'), methods=['POST']) # 进入地图
@app.route(add_url_prefix('/world/map/me'), methods=['POST']) # 进入地图
@server.auth.auth_required(request)
def world_in(user_id):
map_id = request.form['map_id']

View File

@@ -1005,12 +1005,12 @@ def arc_all_get(user_id):
"complete": 1
},
{
"unlock_key": "ouroboros|2|0",
"unlock_key": "tiemedowngently|2|0",
"complete": 1
},
{
"unlock_key": "tiemedowngently|1|0",
"complete": 1
"unlock_key": "tempestissimo|2|101",
"complete": 100
},
{
"unlock_key": "aegleseeker|2|3|crystalgravity|2",
@@ -1165,7 +1165,11 @@ def arc_all_get(user_id):
"complete": 1
},
{
"unlock_key": "pragmatism|2|0",
"unlock_key": "tiemedowngently|1|0",
"complete": 1
},
{
"unlock_key": "ouroboros|2|0",
"complete": 1
},
{
@@ -1232,6 +1236,10 @@ def arc_all_get(user_id):
"unlock_key": "melodyoflove|1|0",
"complete": 1
},
{
"unlock_key": "mazymetroplex|2|0",
"complete": 1
},
{
"unlock_key": "seclusion|2|0",
"complete": 1
@@ -1256,10 +1264,6 @@ def arc_all_get(user_id):
"unlock_key": "lostdesire|2|0",
"complete": 1
},
{
"unlock_key": "tiemedowngently|2|0",
"complete": 1
},
{
"unlock_key": "solitarydream|1|0",
"complete": 1
@@ -1296,14 +1300,6 @@ def arc_all_get(user_id):
"unlock_key": "jump|1|0",
"complete": 1
},
{
"unlock_key": "dandelion|2|0",
"complete": 1
},
{
"unlock_key": "infinityheaven|2|0",
"complete": 1
},
{
"unlock_key": "grievouslady|1|101",
"complete": 100
@@ -1324,6 +1320,10 @@ def arc_all_get(user_id):
"unlock_key": "ignotus|2|0",
"complete": 1
},
{
"unlock_key": "ignotus|1|0",
"complete": 1
},
{
"unlock_key": "nhelv|1|0",
"complete": 1
@@ -1336,10 +1336,6 @@ def arc_all_get(user_id):
"unlock_key": "guardina|2|0",
"complete": 1
},
{
"unlock_key": "guardina|1|0",
"complete": 1
},
{
"unlock_key": "lethaeus|1|0",
"complete": 1
@@ -1404,6 +1400,22 @@ def arc_all_get(user_id):
"unlock_key": "gloryroad|0|0",
"complete": 1
},
{
"unlock_key": "guardina|1|0",
"complete": 1
},
{
"unlock_key": "pragmatism|2|0",
"complete": 1
},
{
"unlock_key": "oracle|2|0",
"complete": 1
},
{
"unlock_key": "genocider|2|0",
"complete": 1
},
{
"unlock_key": "buchigireberserker|2|3|gothiveofra|2",
"complete": 1
@@ -1444,10 +1456,6 @@ def arc_all_get(user_id):
"unlock_key": "flyburg|2|0",
"complete": 1
},
{
"unlock_key": "oracle|2|0",
"complete": 1
},
{
"unlock_key": "clotho|2|0",
"complete": 1
@@ -1502,16 +1510,8 @@ def arc_all_get(user_id):
},
{
"unlock_key": "equilibrium_challenge|2|102",
"complete": -1
},
{
"unlock_key": "cyanine|1|0",
"complete": 1
},
{
"unlock_key": "tempestissimo|3|101",
"complete": 100
},
{
"unlock_key": "overwhelm|2|0",
"complete": 1
@@ -1526,7 +1526,7 @@ def arc_all_get(user_id):
},
{
"unlock_key": "equilibrium_challenge|1|102",
"complete": -1
"complete": 1
},
{
"unlock_key": "aterlbus|2|0",
@@ -1548,6 +1548,14 @@ def arc_all_get(user_id):
"unlock_key": "goodtek|2|0",
"complete": 1
},
{
"unlock_key": "infinityheaven|2|0",
"complete": 1
},
{
"unlock_key": "dandelion|2|0",
"complete": 1
},
{
"unlock_key": "blrink|2|0",
"complete": 1
@@ -1580,10 +1588,6 @@ def arc_all_get(user_id):
"unlock_key": "conflict|2|0",
"complete": 1
},
{
"unlock_key": "ignotus|1|0",
"complete": 1
},
{
"unlock_key": "monochromeprincess|1|0",
"complete": 1
@@ -1652,18 +1656,26 @@ def arc_all_get(user_id):
"unlock_key": "blaster|1|0",
"complete": 1
},
{
"unlock_key": "genocider|1|0",
"complete": 1
},
{
"unlock_key": "rise|1|0",
"complete": 1
},
{
"unlock_key": "tempestissimo|3|101",
"complete": 100
},
{
"unlock_key": "cyanine|1|0",
"complete": 1
},
{
"unlock_key": "axiumcrisis|2|0",
"complete": 1
},
{
"unlock_key": "tempestissimo|2|101",
"complete": 100
},
{
"unlock_key": "solitarydream|2|0",
"complete": 1
@@ -1692,6 +1704,30 @@ def arc_all_get(user_id):
"unlock_key": "corpssansorganes|2|0",
"complete": 1
},
{
"unlock_key": "tempestissimo|1|101",
"complete": 100
},
{
"unlock_key": "conflict|1|0",
"complete": 1
},
{
"unlock_key": "mazymetroplex|1|0",
"complete": 1
},
{
"unlock_key": "viyellastears|2|0",
"complete": 1
},
{
"unlock_key": "equilibrium_challenge|0|102",
"complete": 1
},
{
"unlock_key": "grievouslady|0|101",
"complete": 100
},
{
"unlock_key": "snowwhite|1|0",
"complete": 1
@@ -1704,26 +1740,6 @@ def arc_all_get(user_id):
"unlock_key": "jump|2|0",
"complete": 1
},
{
"unlock_key": "tempestissimo|1|101",
"complete": 100
},
{
"unlock_key": "conflict|1|0",
"complete": 1
},
{
"unlock_key": "viyellastears|2|0",
"complete": 1
},
{
"unlock_key": "equilibrium_challenge|0|102",
"complete": -1
},
{
"unlock_key": "grievouslady|0|101",
"complete": 100
},
{
"unlock_key": "saikyostronger|2|3|izana|2",
"complete": 1

View File

@@ -30,10 +30,11 @@ class Connect():
return True
class Sql():
@staticmethod
def select(c, table_name, target_column=[], limit=-1, offset=0, query={}, sort=[]):
def select(c, table_name, target_column=[], query=None):
# 执行查询单句sql语句返回fetchall数据
# 使用准确查询,且在单表内
@@ -51,9 +52,10 @@ class Sql():
where_field = []
where_value = []
for i in query:
where_field.append(i)
where_value.append(query[i])
if query:
for i in query.query:
where_field.append(i)
where_value.append(query.query[i])
if where_field and where_value:
sql += ' where '
@@ -64,16 +66,17 @@ class Sql():
sql_dict[where_field[i]] = where_value[i]
sql += ' and ' + where_field[i] + '=:' + where_field[i]
if sort:
sql += ' order by ' + sort[0]['column'] + ' ' + sort[0]['order']
if len(sort) >= 2:
for i in range(1, len(sort)):
sql += ', ' + sort[i]['column'] + ' ' + sort[i]['order']
if query and query.sort:
sql += ' order by ' + \
query.sort[0]['column'] + ' ' + query.sort[0]['order']
for i in range(1, len(query.sort)):
sql += ', ' + query.sort[i]['column'] + \
' ' + query.sort[i]['order']
if limit >= 0:
if query and query.limit >= 0:
sql += ' limit :limit offset :offset'
sql_dict['limit'] = limit
sql_dict['offset'] = offset
sql_dict['limit'] = query.limit
sql_dict['offset'] = query.offset
c.execute(sql, sql_dict)

View File

@@ -8,7 +8,7 @@ class Config():
主机的地址和端口号
Host and port of your server
'''
HOST = '192.168.1.101'
HOST = '0.0.0.0'
PORT = '80'
'''
--------------------
@@ -30,7 +30,7 @@ class Config():
Allowed game versions
If it is blank, all are allowed.
'''
ALLOW_APPVERSION = ['3.5.3', '3.5.3c', '3.7.0', '3.7.0c']
ALLOW_APPVERSION = ['3.5.3', '3.5.3c', '3.8.0', '3.8.0c']
'''
--------------------
'''
@@ -106,7 +106,7 @@ class Config():
API interface full control permission Token
If you don't want to use it, leave it blank.
'''
API_TOKEN = '123'
API_TOKEN = ''
'''
--------------------
'''

View File

@@ -418,7 +418,7 @@ def all_character():
def change_character():
# 修改角色数据
skill_ids = ['No_skill', 'gauge_easy', 'note_mirror', 'gauge_hard', 'frag_plus_10_pack_stellights', 'gauge_easy|frag_plus_15_pst&prs', 'gauge_hard|fail_frag_minus_100', 'frag_plus_5_side_light', 'visual_hide_hp', 'frag_plus_5_side_conflict', 'challenge_fullcombo_0gauge', 'gauge_overflow', 'gauge_easy|note_mirror', 'note_mirror', 'visual_tomato_pack_tonesphere',
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', 'frags_kou', 'visual_ink', 'shirabe_entry_fee', 'frags_yume', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami']
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', 'frags_kou', 'visual_ink', 'shirabe_entry_fee', 'frags_yume', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion', 'skill_lagrange', 'gauge_safe_10', 'frags_nami', 'skill_elizabeth', 'skill_lily']
return render_template('web/changechar.html', skill_ids=skill_ids)