mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-09 01:07:27 +08:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14b685850c | ||
|
|
3fbf473de2 | ||
|
|
8a3cec05b7 | ||
|
|
e3d81436d0 | ||
|
|
941a79ccc7 | ||
|
|
62902a561c | ||
|
|
1660bc5899 | ||
|
|
d577246d28 | ||
|
|
9fd626468e | ||
|
|
c51a1b4e85 | ||
|
|
0e42123417 | ||
|
|
e216e6144b | ||
|
|
b70c435a4a | ||
|
|
eb03d2be93 | ||
|
|
fcb5d264ef | ||
|
|
d617951e1f | ||
|
|
febf931f1a | ||
|
|
981961d6a1 | ||
|
|
a90380df4c | ||
|
|
4f66f492fc |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.log
|
||||||
44
README.md
44
README.md
@@ -19,6 +19,7 @@ This procedure is mainly used for study and research, and shall not be used for
|
|||||||
- 多设备登录 Multi device login
|
- 多设备登录 Multi device login
|
||||||
- 成绩上传 Score upload
|
- 成绩上传 Score upload
|
||||||
- PTT
|
- PTT
|
||||||
|
- 世界排名 Global rank
|
||||||
- 排名 Rank
|
- 排名 Rank
|
||||||
- 好友系统 Friends
|
- 好友系统 Friends
|
||||||
- 数据同步 Data synchronization
|
- 数据同步 Data synchronization
|
||||||
@@ -28,17 +29,15 @@ This procedure is mainly used for study and research, and shall not be used for
|
|||||||
- 单曲和曲包购买(没啥用) Single songs and song packs purchase(useless)
|
- 单曲和曲包购买(没啥用) Single songs and song packs purchase(useless)
|
||||||
- 奖励系统 Present system
|
- 奖励系统 Present system
|
||||||
- 兑换码系统 Redeem code system
|
- 兑换码系统 Redeem code system
|
||||||
- 全角色立绘 All character drawings
|
- 角色系统 Character system
|
||||||
- 角色技能 Character skills
|
|
||||||
- 自定义角色属性 Customizable characters attributes
|
|
||||||
- 全剧情解锁 Unlock all the stories
|
- 全剧情解锁 Unlock all the stories
|
||||||
- 后台查询 Background search
|
- 后台查询 Background search
|
||||||
- 后台自定义信息 Customize some things in the background
|
- 后台自定义信息 Customize some things in the background
|
||||||
- 成绩校验 Score check
|
- 成绩校验 Score check
|
||||||
- 下载校验 Download check
|
- 下载校验 Download check
|
||||||
|
- 服务器日志 Server log
|
||||||
|
|
||||||
没有以下 We don't have:
|
没有以下 We don't have:
|
||||||
- 角色数值 Character characteristic value
|
|
||||||
- 服务器安全性保证 Server security assurance
|
- 服务器安全性保证 Server security assurance
|
||||||
|
|
||||||
可能有问题 There may be problems:
|
可能有问题 There may be problems:
|
||||||
@@ -59,29 +58,38 @@ It is just so interesting. What it can do is under exploration.
|
|||||||
## 更新日志 Update log
|
## 更新日志 Update log
|
||||||
只保留最新版本 Only keep the latest version.
|
只保留最新版本 Only keep the latest version.
|
||||||
|
|
||||||
> 提醒:更新时请注意保留原先的数据库,以防数据丢失
|
> 提醒:更新时请注意保留原先的数据库,以防数据丢失。
|
||||||
>
|
>
|
||||||
> Tips: When updating, please keep the original database in case of data loss.
|
> Tips: When updating, please keep the original database in case of data loss.
|
||||||
|
|
||||||
### Version 2.2
|
### Version 2.5
|
||||||
- 适用于Arcaea 3.5.1版本 For Arcaea 3.5.1
|
- 适用于Arcaea 3.6.2版本 For Arcaea 3.6.2
|
||||||
- 更新了歌曲数据库 Update the song database.
|
- 更新了歌曲数据库 Update the song database.
|
||||||
- 新增多设备登录 Add multi device login.
|
- 新增世界排名 Add global rank.
|
||||||
- 修改了配置文件结构 The configuration file structure has been modified.
|
- 新增世界模式的奖励获取 Add reward acquisition of new world mode.
|
||||||
- 优化了代码结构 Optimize the code structure.
|
- 完善角色系统,包括: Improve the character system, including
|
||||||
- 修复了一堆Bug Fix many bugs.
|
- 角色升级 Level up
|
||||||
|
- 角色觉醒 Upcapping
|
||||||
|
- 角色核心 Character cores
|
||||||
|
- 世界模式下的数值计算 Numerical calculation in world mode
|
||||||
|
- 某些场景下的角色解锁 Character unlocking in some cases
|
||||||
|
|
||||||
> 提醒:本次更新需重新登录
|
- 新增了一些设置选项和后台功能 Add some setting options and background functions.
|
||||||
>
|
- 正在构建API接口 Building API interface.
|
||||||
> Tip: You need to log in Arcaea again in this update.
|
- 打算重新写后台界面 Plan to rewrite the background interface.
|
||||||
|
- 修复了一些Bug Fix some bugs.
|
||||||
|
- 登录时获取信息的并行计算导致的数据库锁错误 Database lock error caused by parallel computing of getting information during login
|
||||||
|
|
||||||
|
> 提醒:由于时间仓促,本版本可能存在较多问题与漏洞,请谨慎使用
|
||||||
|
> Tips: Due to lack of time, this version may have many bugs, please use it with caution.
|
||||||
|
|
||||||
## 运行环境与依赖 Running environment and requirements
|
## 运行环境与依赖 Running environment and requirements
|
||||||
- Windows操作系统 Windows operating system
|
- Windows/Linux/Mac OS/Android
|
||||||
- Python 3
|
- Python 3
|
||||||
- Flask模块 Flask module
|
- Flask module
|
||||||
- Charles
|
- Charles, IDA, proxy app... (optional)
|
||||||
|
|
||||||
|
<!--
|
||||||
## 环境搭建 Environment construction
|
## 环境搭建 Environment construction
|
||||||
[中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
|
[中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
|
||||||
[English](https://github.com/Lost-MSth/Arcaea-server/wiki/Environment-construction)
|
[English](https://github.com/Lost-MSth/Arcaea-server/wiki/Environment-construction)
|
||||||
@@ -89,11 +97,13 @@ It is just so interesting. What it can do is under exploration.
|
|||||||
## 使用说明 Instruction for use
|
## 使用说明 Instruction for use
|
||||||
[中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E)
|
[中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E)
|
||||||
[English](https://github.com/Lost-MSth/Arcaea-server/wiki/Instruction-for-use)
|
[English](https://github.com/Lost-MSth/Arcaea-server/wiki/Instruction-for-use)
|
||||||
|
-->
|
||||||
|
|
||||||
## 注意 Attentions
|
## 注意 Attentions
|
||||||
[中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E6%B3%A8%E6%84%8F)
|
[中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E6%B3%A8%E6%84%8F)
|
||||||
[English](https://github.com/Lost-MSth/Arcaea-server/wiki/Attentions)
|
[English](https://github.com/Lost-MSth/Arcaea-server/wiki/Attentions)
|
||||||
|
|
||||||
|
|
||||||
## 鸣谢 Thanks
|
## 鸣谢 Thanks
|
||||||
歌曲数据库来自 Using song database from
|
歌曲数据库来自 Using song database from
|
||||||
[BotArcAPI releases](https://github.com/TheSnowfield/BotArcAPI/releases)
|
[BotArcAPI releases](https://github.com/TheSnowfield/BotArcAPI/releases)
|
||||||
|
|||||||
118
latest version/api/api_auth.py
Normal file
118
latest version/api/api_auth.py
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
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 Config.API_TOKEN == request.headers['Token'] and Config.API_TOKEN != '':
|
||||||
|
user.user_id = 0
|
||||||
|
elif power == []:
|
||||||
|
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', '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)
|
||||||
|
|
||||||
|
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[13]/10,
|
||||||
|
'rating_prs': x[14]/10,
|
||||||
|
'rating_ftr': x[15]/10,
|
||||||
|
'rating_byn': x[16]/10,
|
||||||
|
'difficultly_pst': x[17]/2,
|
||||||
|
'difficultly_prs': x[18]/2,
|
||||||
|
'difficultly_ftr': x[19]/2,
|
||||||
|
'difficultly_byn': x[20]/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[13]/10,
|
||||||
|
'rating_prs': i[14]/10,
|
||||||
|
'rating_ftr': i[15]/10,
|
||||||
|
'rating_byn': i[16]/10,
|
||||||
|
'difficultly_pst': i[17]/2,
|
||||||
|
'difficultly_prs': i[18]/2,
|
||||||
|
'difficultly_ftr': i[19]/2,
|
||||||
|
'difficultly_byn': i[20]/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}
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,270 +1,380 @@
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
import hashlib
|
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
|
||||||
# 数据库初始化文件,删掉arcaea_database.db文件后运行即可,谨慎使用
|
# 数据库初始化文件,删掉arcaea_database.db文件后运行即可,谨慎使用
|
||||||
|
|
||||||
conn = sqlite3.connect('arcaea_database.db')
|
ARCAEA_SERVER_VERSION = 'v2.5'
|
||||||
c = conn.cursor()
|
|
||||||
c.execute('''create table if not exists user(user_id int primary key,
|
|
||||||
name text unique,
|
|
||||||
password text not null,
|
|
||||||
join_date char(20),
|
|
||||||
user_code char(10),
|
|
||||||
rating_ptt int,
|
|
||||||
character_id int,
|
|
||||||
is_skill_sealed int,
|
|
||||||
is_char_uncapped int,
|
|
||||||
is_char_uncapped_override int,
|
|
||||||
is_hide_rating int,
|
|
||||||
song_id text,
|
|
||||||
difficulty int,
|
|
||||||
score int,
|
|
||||||
shiny_perfect_count int,
|
|
||||||
perfect_count int,
|
|
||||||
near_count int,
|
|
||||||
miss_count int,
|
|
||||||
health int,
|
|
||||||
modifier int,
|
|
||||||
time_played int,
|
|
||||||
clear_type int,
|
|
||||||
rating real,
|
|
||||||
favorite_character int,
|
|
||||||
max_stamina_notification_enabled int,
|
|
||||||
current_map text,
|
|
||||||
ticket int,
|
|
||||||
prog_boost int
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists login(access_token text,
|
|
||||||
user_id int,
|
|
||||||
login_time int,
|
|
||||||
login_ip text,
|
|
||||||
login_device text,
|
|
||||||
primary key(access_token, user_id)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists friend(user_id_me int,
|
|
||||||
user_id_other int,
|
|
||||||
primary key (user_id_me, user_id_other)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists best_score(user_id int,
|
|
||||||
song_id text,
|
|
||||||
difficulty int,
|
|
||||||
score int,
|
|
||||||
shiny_perfect_count int,
|
|
||||||
perfect_count int,
|
|
||||||
near_count int,
|
|
||||||
miss_count int,
|
|
||||||
health int,
|
|
||||||
modifier int,
|
|
||||||
time_played int,
|
|
||||||
best_clear_type int,
|
|
||||||
clear_type int,
|
|
||||||
rating real,
|
|
||||||
primary key(user_id, song_id, difficulty)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists user_char(user_id int,
|
|
||||||
character_id int,
|
|
||||||
level int,
|
|
||||||
exp real,
|
|
||||||
level_exp real,
|
|
||||||
frag real,
|
|
||||||
prog real,
|
|
||||||
overdrive real,
|
|
||||||
skill_id text,
|
|
||||||
skill_unlock_level int,
|
|
||||||
skill_requires_uncap int,
|
|
||||||
skill_id_uncap text,
|
|
||||||
char_type int,
|
|
||||||
is_uncapped int,
|
|
||||||
is_uncapped_override int,
|
|
||||||
primary key(user_id, character_id)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists character(character_id int primary key,
|
|
||||||
name text,
|
|
||||||
level int,
|
|
||||||
exp real,
|
|
||||||
level_exp real,
|
|
||||||
frag real,
|
|
||||||
prog real,
|
|
||||||
overdrive real,
|
|
||||||
skill_id text,
|
|
||||||
skill_unlock_level int,
|
|
||||||
skill_requires_uncap int,
|
|
||||||
skill_id_uncap text,
|
|
||||||
char_type int,
|
|
||||||
uncap_cores text,
|
|
||||||
is_uncapped int,
|
|
||||||
is_uncapped_override int
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists recent30(user_id int primary key,
|
|
||||||
r0 real,
|
|
||||||
song_id0 text,
|
|
||||||
r1 real,
|
|
||||||
song_id1 text,
|
|
||||||
r2 real,
|
|
||||||
song_id2 text,
|
|
||||||
r3 real,
|
|
||||||
song_id3 text,
|
|
||||||
r4 real,
|
|
||||||
song_id4 text,
|
|
||||||
r5 real,
|
|
||||||
song_id5 text,
|
|
||||||
r6 real,
|
|
||||||
song_id6 text,
|
|
||||||
r7 real,
|
|
||||||
song_id7 text,
|
|
||||||
r8 real,
|
|
||||||
song_id8 text,
|
|
||||||
r9 real,
|
|
||||||
song_id9 text,
|
|
||||||
r10 real,
|
|
||||||
song_id10 text,
|
|
||||||
r11 real,
|
|
||||||
song_id11 text,
|
|
||||||
r12 real,
|
|
||||||
song_id12 text,
|
|
||||||
r13 real,
|
|
||||||
song_id13 text,
|
|
||||||
r14 real,
|
|
||||||
song_id14 text,
|
|
||||||
r15 real,
|
|
||||||
song_id15 text,
|
|
||||||
r16 real,
|
|
||||||
song_id16 text,
|
|
||||||
r17 real,
|
|
||||||
song_id17 text,
|
|
||||||
r18 real,
|
|
||||||
song_id18 text,
|
|
||||||
r19 real,
|
|
||||||
song_id19 text,
|
|
||||||
r20 real,
|
|
||||||
song_id20 text,
|
|
||||||
r21 real,
|
|
||||||
song_id21 text,
|
|
||||||
r22 real,
|
|
||||||
song_id22 text,
|
|
||||||
r23 real,
|
|
||||||
song_id23 text,
|
|
||||||
r24 real,
|
|
||||||
song_id24 text,
|
|
||||||
r25 real,
|
|
||||||
song_id25 text,
|
|
||||||
r26 real,
|
|
||||||
song_id26 text,
|
|
||||||
r27 real,
|
|
||||||
song_id27 text,
|
|
||||||
r28 real,
|
|
||||||
song_id28 text,
|
|
||||||
r29 real,
|
|
||||||
song_id29 text
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists user_world(user_id int,
|
|
||||||
map_id text,
|
|
||||||
curr_position int,
|
|
||||||
curr_capture real,
|
|
||||||
is_locked int,
|
|
||||||
primary key(user_id, map_id)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists world_songplay(user_id int,
|
|
||||||
song_id text,
|
|
||||||
difficulty int,
|
|
||||||
stamina_multiply int,
|
|
||||||
fragment_multiply int,
|
|
||||||
prog_boost_multiply int,
|
|
||||||
primary key(user_id, song_id, difficulty)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists download_token(user_id int,
|
|
||||||
song_id text,
|
|
||||||
file_name text,
|
|
||||||
token text,
|
|
||||||
time int,
|
|
||||||
primary key(user_id, song_id, file_name)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists user_download(user_id int,
|
|
||||||
token text,
|
|
||||||
time int,
|
|
||||||
primary key(user_id, token, time)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists item(item_id text,
|
|
||||||
type text,
|
|
||||||
is_available int,
|
|
||||||
price int,
|
|
||||||
orig_price int,
|
|
||||||
discount_from int,
|
|
||||||
discount_to int,
|
|
||||||
_id text,
|
|
||||||
primary key(item_id, type)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists user_item(user_id int,
|
|
||||||
item_id text,
|
|
||||||
type text,
|
|
||||||
primary key(user_id, item_id, type)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists user_save(user_id int primary key,
|
|
||||||
scores_data text,
|
|
||||||
clearlamps_data text,
|
|
||||||
clearedsongs_data text,
|
|
||||||
unlocklist_data text,
|
|
||||||
installid_data text,
|
|
||||||
devicemodelname_data text,
|
|
||||||
story_data text,
|
|
||||||
createdAt int
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists present(present_id text primary key,
|
|
||||||
expire_ts int,
|
|
||||||
items text,
|
|
||||||
description text
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists user_present(user_id int,
|
|
||||||
present_id text,
|
|
||||||
primary key(user_id, present_id)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists songfile(song_id text,
|
|
||||||
file_type int,
|
|
||||||
md5 text,
|
|
||||||
primary key(song_id, file_type)
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists redeem(code text primary key,
|
|
||||||
items text,
|
|
||||||
type int
|
|
||||||
);''')
|
|
||||||
c.execute('''create table if not exists user_redeem(user_id int,
|
|
||||||
code text,
|
|
||||||
primary key(user_id, code)
|
|
||||||
);''')
|
|
||||||
|
|
||||||
|
|
||||||
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',
|
def main(path='./'):
|
||||||
'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']
|
conn = sqlite3.connect(path+'arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''create table if not exists config(id text primary key,
|
||||||
|
value text
|
||||||
|
);''')
|
||||||
|
c.execute('''insert into config values("version", :a);''',
|
||||||
|
{'a': ARCAEA_SERVER_VERSION})
|
||||||
|
c.execute('''create table if not exists user(user_id int primary key,
|
||||||
|
name text unique,
|
||||||
|
password text not null,
|
||||||
|
join_date char(20),
|
||||||
|
user_code char(10),
|
||||||
|
rating_ptt int,
|
||||||
|
character_id int,
|
||||||
|
is_skill_sealed int,
|
||||||
|
is_char_uncapped int,
|
||||||
|
is_char_uncapped_override int,
|
||||||
|
is_hide_rating int,
|
||||||
|
song_id text,
|
||||||
|
difficulty int,
|
||||||
|
score int,
|
||||||
|
shiny_perfect_count int,
|
||||||
|
perfect_count int,
|
||||||
|
near_count int,
|
||||||
|
miss_count int,
|
||||||
|
health int,
|
||||||
|
modifier int,
|
||||||
|
time_played int,
|
||||||
|
clear_type int,
|
||||||
|
rating real,
|
||||||
|
favorite_character int,
|
||||||
|
max_stamina_notification_enabled int,
|
||||||
|
current_map text,
|
||||||
|
ticket int,
|
||||||
|
prog_boost int,
|
||||||
|
email text,
|
||||||
|
world_rank_score int
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists login(access_token text,
|
||||||
|
user_id int,
|
||||||
|
login_time int,
|
||||||
|
login_ip text,
|
||||||
|
login_device text,
|
||||||
|
primary key(access_token, user_id)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists friend(user_id_me int,
|
||||||
|
user_id_other int,
|
||||||
|
primary key (user_id_me, user_id_other)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists best_score(user_id int,
|
||||||
|
song_id text,
|
||||||
|
difficulty int,
|
||||||
|
score int,
|
||||||
|
shiny_perfect_count int,
|
||||||
|
perfect_count int,
|
||||||
|
near_count int,
|
||||||
|
miss_count int,
|
||||||
|
health int,
|
||||||
|
modifier int,
|
||||||
|
time_played int,
|
||||||
|
best_clear_type int,
|
||||||
|
clear_type int,
|
||||||
|
rating real,
|
||||||
|
primary key(user_id, song_id, difficulty)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_char(user_id int,
|
||||||
|
character_id int,
|
||||||
|
level int,
|
||||||
|
exp real,
|
||||||
|
is_uncapped int,
|
||||||
|
is_uncapped_override int,
|
||||||
|
primary key(user_id, character_id)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_char_full(user_id int,
|
||||||
|
character_id int,
|
||||||
|
level int,
|
||||||
|
exp real,
|
||||||
|
is_uncapped int,
|
||||||
|
is_uncapped_override int,
|
||||||
|
primary key(user_id, character_id)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists character(character_id int primary key,
|
||||||
|
name text,
|
||||||
|
max_level int,
|
||||||
|
frag1 real,
|
||||||
|
prog1 real,
|
||||||
|
overdrive1 real,
|
||||||
|
frag20 real,
|
||||||
|
prog20 real,
|
||||||
|
overdrive20 real,
|
||||||
|
frag30 real,
|
||||||
|
prog30 real,
|
||||||
|
overdrive30 real,
|
||||||
|
skill_id text,
|
||||||
|
skill_unlock_level int,
|
||||||
|
skill_requires_uncap int,
|
||||||
|
skill_id_uncap text,
|
||||||
|
char_type int,
|
||||||
|
is_uncapped int
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists char_item(character_id int,
|
||||||
|
item_id text,
|
||||||
|
type text,
|
||||||
|
amount int,
|
||||||
|
primary key(character_id, item_id, type)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists recent30(user_id int primary key,
|
||||||
|
r0 real,
|
||||||
|
song_id0 text,
|
||||||
|
r1 real,
|
||||||
|
song_id1 text,
|
||||||
|
r2 real,
|
||||||
|
song_id2 text,
|
||||||
|
r3 real,
|
||||||
|
song_id3 text,
|
||||||
|
r4 real,
|
||||||
|
song_id4 text,
|
||||||
|
r5 real,
|
||||||
|
song_id5 text,
|
||||||
|
r6 real,
|
||||||
|
song_id6 text,
|
||||||
|
r7 real,
|
||||||
|
song_id7 text,
|
||||||
|
r8 real,
|
||||||
|
song_id8 text,
|
||||||
|
r9 real,
|
||||||
|
song_id9 text,
|
||||||
|
r10 real,
|
||||||
|
song_id10 text,
|
||||||
|
r11 real,
|
||||||
|
song_id11 text,
|
||||||
|
r12 real,
|
||||||
|
song_id12 text,
|
||||||
|
r13 real,
|
||||||
|
song_id13 text,
|
||||||
|
r14 real,
|
||||||
|
song_id14 text,
|
||||||
|
r15 real,
|
||||||
|
song_id15 text,
|
||||||
|
r16 real,
|
||||||
|
song_id16 text,
|
||||||
|
r17 real,
|
||||||
|
song_id17 text,
|
||||||
|
r18 real,
|
||||||
|
song_id18 text,
|
||||||
|
r19 real,
|
||||||
|
song_id19 text,
|
||||||
|
r20 real,
|
||||||
|
song_id20 text,
|
||||||
|
r21 real,
|
||||||
|
song_id21 text,
|
||||||
|
r22 real,
|
||||||
|
song_id22 text,
|
||||||
|
r23 real,
|
||||||
|
song_id23 text,
|
||||||
|
r24 real,
|
||||||
|
song_id24 text,
|
||||||
|
r25 real,
|
||||||
|
song_id25 text,
|
||||||
|
r26 real,
|
||||||
|
song_id26 text,
|
||||||
|
r27 real,
|
||||||
|
song_id27 text,
|
||||||
|
r28 real,
|
||||||
|
song_id28 text,
|
||||||
|
r29 real,
|
||||||
|
song_id29 text
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_world(user_id int,
|
||||||
|
map_id text,
|
||||||
|
curr_position int,
|
||||||
|
curr_capture real,
|
||||||
|
is_locked int,
|
||||||
|
primary key(user_id, map_id)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists world_songplay(user_id int,
|
||||||
|
song_id text,
|
||||||
|
difficulty int,
|
||||||
|
stamina_multiply int,
|
||||||
|
fragment_multiply int,
|
||||||
|
prog_boost_multiply int,
|
||||||
|
primary key(user_id, song_id, difficulty)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists download_token(user_id int,
|
||||||
|
song_id text,
|
||||||
|
file_name text,
|
||||||
|
token text,
|
||||||
|
time int,
|
||||||
|
primary key(user_id, song_id, file_name)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_download(user_id int,
|
||||||
|
token text,
|
||||||
|
time int,
|
||||||
|
primary key(user_id, token, time)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists item(item_id text,
|
||||||
|
type text,
|
||||||
|
is_available int,
|
||||||
|
_id text,
|
||||||
|
primary key(item_id, type)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_item(user_id int,
|
||||||
|
item_id text,
|
||||||
|
type text,
|
||||||
|
amount int,
|
||||||
|
primary key(user_id, item_id, type)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists purchase(purchase_name text primary key,
|
||||||
|
price int,
|
||||||
|
orig_price int,
|
||||||
|
discount_from int,
|
||||||
|
discount_to int
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists purchase_item(purchase_name text,
|
||||||
|
item_id text,
|
||||||
|
type text,
|
||||||
|
primary key(purchase_name, item_id, type)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_save(user_id int primary key,
|
||||||
|
scores_data text,
|
||||||
|
clearlamps_data text,
|
||||||
|
clearedsongs_data text,
|
||||||
|
unlocklist_data text,
|
||||||
|
installid_data text,
|
||||||
|
devicemodelname_data text,
|
||||||
|
story_data text,
|
||||||
|
createdAt int
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists present(present_id text primary key,
|
||||||
|
expire_ts int,
|
||||||
|
items text,
|
||||||
|
description text
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_present(user_id int,
|
||||||
|
present_id text,
|
||||||
|
primary key(user_id, present_id)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists songfile(song_id text,
|
||||||
|
file_type int,
|
||||||
|
md5 text,
|
||||||
|
primary key(song_id, file_type)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists redeem(code text primary key,
|
||||||
|
items text,
|
||||||
|
type int
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_redeem(user_id int,
|
||||||
|
code text,
|
||||||
|
primary key(user_id, code)
|
||||||
|
);''')
|
||||||
|
|
||||||
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',
|
c.execute('''create table if not exists role(role_id int primary key,
|
||||||
'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']
|
role_name text,
|
||||||
|
caption text
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_role(user_id int,
|
||||||
|
role_id int,
|
||||||
|
primary key(user_id, role_id)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists power(power_id int primary key,
|
||||||
|
power_name text,
|
||||||
|
caption text
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists role_power(role_id int,
|
||||||
|
power_id int,
|
||||||
|
primary key(role_id, power_id)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists api_login(user_id int,
|
||||||
|
token text,
|
||||||
|
login_time int,
|
||||||
|
login_ip text,
|
||||||
|
primary key(user_id, token)
|
||||||
|
);''')
|
||||||
|
|
||||||
skill_id_uncap = ['', '', 'frags_kou', '', 'visual_ink', '', '', '', '', '', '', '', '', 'shirabe_entry_fee',
|
# 搭档初始化
|
||||||
'', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
|
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']
|
||||||
|
|
||||||
|
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']
|
||||||
|
|
||||||
|
skill_id_uncap = ['', '', 'frags_kou', '', 'visual_ink', '', '', '', '', '', '', '', '', 'shirabe_entry_fee',
|
||||||
|
'', '', '', '', '', '', '', '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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
char_core = {
|
||||||
|
0: [{'core_id': 'core_hollow', 'amount': 25}, {'core_id': 'core_desolate', 'amount': 5}],
|
||||||
|
1: [{'core_id': 'core_hollow', 'amount': 5}, {'core_id': 'core_desolate', 'amount': 25}],
|
||||||
|
2: [{'core_id': 'core_hollow', 'amount': 5}, {'core_id': 'core_crimson', 'amount': 25}],
|
||||||
|
4: [{'core_id': 'core_ambivalent', 'amount': 25}, {'core_id': 'core_desolate', 'amount': 5}],
|
||||||
|
13: [{'core_id': 'core_scarlet', 'amount': 30}],
|
||||||
|
21: [{'core_id': 'core_scarlet', 'amount': 30}],
|
||||||
|
26: [{'core_id': 'core_chunithm', 'amount': 15}],
|
||||||
|
27: [{'core_id': 'core_chunithm', 'amount': 15}],
|
||||||
|
28: [{'core_id': 'core_chunithm', 'amount': 15}],
|
||||||
|
29: [{'core_id': 'core_chunithm', 'amount': 15}],
|
||||||
|
36: [{'core_id': 'core_chunithm', 'amount': 15}],
|
||||||
|
42: [{'core_id': 'core_chunithm', 'amount': 15}],
|
||||||
|
43: [{'core_id': 'core_chunithm', 'amount': 15}]
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in range(0, 46):
|
||||||
|
skill_requires_uncap = 1 if i == 2 else 0
|
||||||
|
|
||||||
for i in range(0, 44):
|
|
||||||
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21, 42, 43]:
|
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21, 42, 43]:
|
||||||
sql = 'insert into character values('+str(
|
sql = '''insert into character values(?,?,30,?,?,?,?,?,?,?,?,?,?,?,?,?,?,1)'''
|
||||||
i)+',"'+char[i]+'''",30,25000,25000,90,90,90,"'''+skill_id[i]+'''",0,0,"'''+skill_id_uncap[i]+'''",0,'',1,1)'''
|
c.execute(sql, (i, char[i], frag1[i], prog1[i], overdrive1[i], frag20[i], prog20[i], overdrive20[i],
|
||||||
c.execute(sql)
|
frag30[i], prog30[i], overdrive30[i], skill_id[i], skill_unlock_level[i], skill_requires_uncap, skill_id_uncap[i], char_type[i]))
|
||||||
else:
|
else:
|
||||||
if i != 5:
|
if i != 5:
|
||||||
sql = 'insert into character values('+str(
|
sql = '''insert into character values(?,?,20,?,?,?,?,?,?,?,?,?,?,?,?,?,?,0)'''
|
||||||
i)+',"'+char[i]+'''",30,25000,25000,90,90,90,"'''+skill_id[i]+'''",0,0,"'''+skill_id_uncap[i]+'''",0,'',0,0)'''
|
c.execute(sql, (i, char[i], frag1[i], prog1[i], overdrive1[i], frag20[i], prog20[i], overdrive20[i],
|
||||||
c.execute(sql)
|
frag30[i], prog30[i], overdrive30[i], skill_id[i], skill_unlock_level[i], skill_requires_uncap, skill_id_uncap[i], char_type[i]))
|
||||||
|
|
||||||
|
for i in char_core:
|
||||||
|
for j in char_core[i]:
|
||||||
|
c.execute('''insert into char_item values(?,?,'core',?)''',
|
||||||
|
(i, j['core_id'], j['amount']))
|
||||||
|
cores = ['core_hollow', 'core_desolate', 'core_chunithm', 'core_crimson',
|
||||||
|
'core_ambivalent', 'core_scarlet', 'core_groove', 'core_generic']
|
||||||
|
|
||||||
def b2int(x):
|
for i in cores:
|
||||||
# int与布尔值转换
|
c.execute('''insert into item values(?,"core",1,'')''', (i,))
|
||||||
if x:
|
|
||||||
return 1
|
|
||||||
else:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
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"]
|
||||||
|
for i in world_songs:
|
||||||
|
c.execute('''insert into item values(?,"world_song",1,'')''', (i,))
|
||||||
|
|
||||||
def insert_items(c, items):
|
world_unlocks = ["scenery_chap1", "scenery_chap2",
|
||||||
|
"scenery_chap3", "scenery_chap4", "scenery_chap5"]
|
||||||
|
for i in world_unlocks:
|
||||||
|
c.execute('''insert into item values(?,"world_unlock",1,'')''', (i,))
|
||||||
|
|
||||||
|
def insert_items(c, items):
|
||||||
# 物品数据导入
|
# 物品数据导入
|
||||||
for i in items:
|
for i in items:
|
||||||
if 'discount_from' not in i:
|
if 'discount_from' not in i:
|
||||||
@@ -275,60 +385,83 @@ def insert_items(c, items):
|
|||||||
discount_to = -1
|
discount_to = -1
|
||||||
else:
|
else:
|
||||||
discount_to = i['discount_to']
|
discount_to = i['discount_to']
|
||||||
|
c.execute('''insert into purchase values(?,?,?,?,?)''',
|
||||||
|
(i['name'], i['price'], i['orig_price'], discount_from, discount_to))
|
||||||
for j in i['items']:
|
for j in i['items']:
|
||||||
if "_id" not in j:
|
if "_id" not in j:
|
||||||
_id = ''
|
_id = ''
|
||||||
else:
|
else:
|
||||||
_id = j['_id']
|
_id = j['_id']
|
||||||
if j['type'] != 'character':
|
c.execute('''insert into item values(?,?,?,?)''',
|
||||||
c.execute('''insert into item(item_id, type, is_available, price, orig_price, discount_from, discount_to, _id) values(:a,:b,:c,:d,:e,:f,:g,:h)''', {
|
(j['id'], j['type'], j['is_available'], _id))
|
||||||
'a': j['id'], 'b': j['type'], 'c': b2int(j['is_available']), 'd': i['price'], 'e': i['orig_price'], 'f': discount_from, 'g': discount_to, 'h': _id})
|
c.execute('''insert into purchase_item values(?,?,?)''',
|
||||||
|
(i['name'], j['id'], j['type']))
|
||||||
|
|
||||||
|
# item初始化
|
||||||
|
f = open(path+'singles.json', 'r')
|
||||||
|
singles = json.load(f)
|
||||||
|
f.close()
|
||||||
|
insert_items(c, singles)
|
||||||
|
|
||||||
f = open('singles.json', 'r')
|
f = open(path+'packs.json', 'r')
|
||||||
singles = json.load(f)
|
packs = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
insert_items(c, singles)
|
insert_items(c, packs)
|
||||||
|
|
||||||
f = open('packs.json', 'r')
|
# api权限与权限组初始化
|
||||||
packs = json.load(f)
|
role = ['admin', 'user', 'selecter']
|
||||||
f.close()
|
role_caption = ['管理员', '用户', '查询接口']
|
||||||
insert_items(c, packs)
|
|
||||||
|
|
||||||
conn.commit()
|
power = ['select', 'select_me', 'change', 'change_me', 'grant',
|
||||||
conn.close()
|
'grant_inf', 'select_song_rank', 'select_song_info']
|
||||||
|
power_caption = ['总体查询权限', '自我查询权限', '总体修改权限',
|
||||||
|
'自我修改权限', '授权权限', '下级授权权限', '歌曲排行榜查询权限', '歌曲信息查询权限']
|
||||||
|
|
||||||
|
role_power = {'0': [0, 1, 3, 5, 6, 7],
|
||||||
|
'1': [1, 3, 6, 7],
|
||||||
|
'2': [0]
|
||||||
|
}
|
||||||
|
|
||||||
def arc_register(name: str, password: str):
|
for i in range(0, len(role)):
|
||||||
|
c.execute('''insert into role values(:a,:b,:c)''', {
|
||||||
|
'a': i, 'b': role[i], 'c': role_caption[i]})
|
||||||
|
for i in range(0, len(power)):
|
||||||
|
c.execute('''insert into power values(:a,:b,:c)''', {
|
||||||
|
'a': i, 'b': power[i], 'c': power_caption[i]})
|
||||||
|
for i in role_power:
|
||||||
|
for j in role_power[i]:
|
||||||
|
c.execute('''insert into role_power values(:a,:b)''',
|
||||||
|
{'a': int(i), 'b': j})
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def arc_register(name: str):
|
||||||
def build_user_code(c):
|
def build_user_code(c):
|
||||||
return '123456789'
|
return '123456789'
|
||||||
|
|
||||||
def build_user_id(c):
|
def build_user_id(c):
|
||||||
return 2000000
|
return 2000000
|
||||||
|
|
||||||
# def insert_user_char(c, user_id):
|
|
||||||
# for i in range(0, 38):
|
|
||||||
# if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
|
|
||||||
# sql = 'insert into user_char values('+str(user_id)+','+str(
|
|
||||||
# i)+''',30,25000,25000,90,90,90,'',0,0,'',0,1,1)'''
|
|
||||||
# c.execute(sql)
|
|
||||||
# else:
|
|
||||||
# if i != 5:
|
|
||||||
# sql = 'insert into user_char values('+str(user_id)+','+str(
|
|
||||||
# i)+''',30,25000,25000,90,90,90,'',0,0,'',0,0,0)'''
|
|
||||||
# c.execute(sql)
|
|
||||||
def insert_user_char(c, user_id):
|
def insert_user_char(c, user_id):
|
||||||
# 为用户添加所有可用角色
|
# 为用户添加可用角色
|
||||||
c.execute('''select * from character''')
|
c.execute('''insert into user_char values(?,?,?,?,?,?)''',
|
||||||
x = c.fetchall()
|
(user_id, 0, 30, 25000, 1, 0))
|
||||||
if x != []:
|
c.execute('''insert into user_char values(?,?,?,?,?,?)''',
|
||||||
for i in x:
|
(user_id, 1, 30, 25000, 1, 0))
|
||||||
c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', {
|
|
||||||
'a': user_id, 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]})
|
|
||||||
|
|
||||||
conn = sqlite3.connect('arcaea_database.db')
|
c.execute(
|
||||||
|
'''select character_id, max_level, is_uncapped from character''')
|
||||||
|
x = c.fetchall()
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
exp = 25000 if i[1] == 30 else 10000
|
||||||
|
c.execute('''insert into user_char_full values(?,?,?,?,?,?)''',
|
||||||
|
(user_id, i[0], i[1], exp, i[2], 0))
|
||||||
|
|
||||||
|
conn = sqlite3.connect(path+'arcaea_database.db')
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
|
hash_pwd = '41e5653fc7aeb894026d6bb7b2db7f65902b454945fa8fd65a6327047b5277fb'
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from user where name = :name)''', {'name': name})
|
'''select exists(select * from user where name = :name)''', {'name': name})
|
||||||
if c.fetchone() == (0,):
|
if c.fetchone() == (0,):
|
||||||
@@ -352,5 +485,8 @@ def arc_register(name: str, password: str):
|
|||||||
conn.close()
|
conn.close()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
arc_register('admin')
|
||||||
|
|
||||||
arc_register('admin', 'admin123')
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|||||||
78
latest version/database/map/byd_lostcivilization.json
Normal file
78
latest version/database/map/byd_lostcivilization.json
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"map_id": "byd_lostcivilization",
|
||||||
|
"is_legacy": false,
|
||||||
|
"chapter": 1001,
|
||||||
|
"available_from": -1,
|
||||||
|
"available_to": 9999999999999,
|
||||||
|
"is_repeatable": false,
|
||||||
|
"require_id": "lostcivilization2",
|
||||||
|
"require_type": "chart_unlock",
|
||||||
|
"coordinate": "-650,-900",
|
||||||
|
"is_beyond": true,
|
||||||
|
"stamina_cost": 3,
|
||||||
|
"beyond_health": 250,
|
||||||
|
"character_affinity": [0, 1],
|
||||||
|
"affinity_multiplier": [1.9, 1.9],
|
||||||
|
"step_count": 7,
|
||||||
|
"custom_bg": "",
|
||||||
|
"curr_position": 0,
|
||||||
|
"curr_capture": 0,
|
||||||
|
"is_locked": false,
|
||||||
|
"steps": [{
|
||||||
|
"map_id": "byd_lostcivilization",
|
||||||
|
"position": 0,
|
||||||
|
"capture": 85
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lostcivilization",
|
||||||
|
"position": 1,
|
||||||
|
"capture": 5,
|
||||||
|
"items": [{
|
||||||
|
"type": "core",
|
||||||
|
"id": "core_generic",
|
||||||
|
"amount": 1
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lostcivilization",
|
||||||
|
"position": 2,
|
||||||
|
"capture": 5,
|
||||||
|
"items": [{
|
||||||
|
"type": "core",
|
||||||
|
"id": "core_generic",
|
||||||
|
"amount": 1
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lostcivilization",
|
||||||
|
"position": 3,
|
||||||
|
"capture": 5,
|
||||||
|
"items": [{
|
||||||
|
"type": "core",
|
||||||
|
"id": "core_generic",
|
||||||
|
"amount": 1
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lostcivilization",
|
||||||
|
"position": 4,
|
||||||
|
"capture": 100,
|
||||||
|
"items": [{
|
||||||
|
"type": "core",
|
||||||
|
"id": "core_generic",
|
||||||
|
"amount": 1
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lostcivilization",
|
||||||
|
"position": 5,
|
||||||
|
"capture": 50,
|
||||||
|
"items": [{
|
||||||
|
"type": "fragment",
|
||||||
|
"amount": 525
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lostcivilization",
|
||||||
|
"position": 6,
|
||||||
|
"capture": 0,
|
||||||
|
"items": [{
|
||||||
|
"id": "lostcivilization3",
|
||||||
|
"type": "world_song"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
114
latest version/database/map/test3.json
Normal file
114
latest version/database/map/test3.json
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
{
|
||||||
|
"map_id": "test3",
|
||||||
|
"is_legacy": true,
|
||||||
|
"is_beyond": false,
|
||||||
|
"beyond_health": 100,
|
||||||
|
"character_affinity": [],
|
||||||
|
"affinity_multiplier": [],
|
||||||
|
"chapter": 0,
|
||||||
|
"available_from": -1,
|
||||||
|
"available_to": 2106124800000,
|
||||||
|
"is_repeatable": false,
|
||||||
|
"require_id": "",
|
||||||
|
"require_type": "",
|
||||||
|
"require_value": 0,
|
||||||
|
"coordinate": "300,200",
|
||||||
|
"step_count": 12,
|
||||||
|
"custom_bg": "",
|
||||||
|
"stamina_cost": 1,
|
||||||
|
"curr_position": 0,
|
||||||
|
"curr_capture": 0,
|
||||||
|
"is_locked": false,
|
||||||
|
"steps": [{
|
||||||
|
"position": 0,
|
||||||
|
"capture": 10
|
||||||
|
}, {
|
||||||
|
"position": 1,
|
||||||
|
"capture": 10,
|
||||||
|
"items": [{
|
||||||
|
"type": "fragment",
|
||||||
|
"amount": 1000
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"position": 2,
|
||||||
|
"capture": 10,
|
||||||
|
"restrict_id": "base",
|
||||||
|
"restrict_type": "pack_id",
|
||||||
|
"items": [{
|
||||||
|
"type": "memory",
|
||||||
|
"amount": 150
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"position": 3,
|
||||||
|
"capture": 10,
|
||||||
|
"restrict_id": "base",
|
||||||
|
"restrict_type": "pack_id",
|
||||||
|
"step_type": ["randomsong"],
|
||||||
|
"items": [{
|
||||||
|
"id": "supernova",
|
||||||
|
"type": "world_song"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"position": 4,
|
||||||
|
"capture": 10,
|
||||||
|
"items": [{
|
||||||
|
"type": "core",
|
||||||
|
"id": "core_generic",
|
||||||
|
"amount": 1
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"position": 5,
|
||||||
|
"capture": 10,
|
||||||
|
"step_type": ["speedlimit"],
|
||||||
|
"speed_limit_value": 60,
|
||||||
|
"items": [{
|
||||||
|
"id": "scenery_chap4",
|
||||||
|
"type": "world_unlock"
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"position": 6,
|
||||||
|
"capture": 10,
|
||||||
|
"items": [{
|
||||||
|
"type": "fragment",
|
||||||
|
"amount": 1250
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"position": 7,
|
||||||
|
"capture": 10,
|
||||||
|
"step_type": ["plusstamina"],
|
||||||
|
"plus_stamina_value": 2,
|
||||||
|
"items": [{
|
||||||
|
"type": "fragment",
|
||||||
|
"amount": 125
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"position": 8,
|
||||||
|
"capture": 10,
|
||||||
|
"items": [{
|
||||||
|
"type": "fragment",
|
||||||
|
"amount": 125
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"position": 9,
|
||||||
|
"capture": 10,
|
||||||
|
"items": [{
|
||||||
|
"type": "memory",
|
||||||
|
"amount": 150
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"position": 10,
|
||||||
|
"capture": 10,
|
||||||
|
"items": [{"id": "2", "type": "character"}]
|
||||||
|
}, {
|
||||||
|
"position": 11,
|
||||||
|
"capture": 0,
|
||||||
|
"items": [{
|
||||||
|
"type": "core",
|
||||||
|
"id": "core_crimson",
|
||||||
|
"amount": 50
|
||||||
|
}, {
|
||||||
|
"type": "fragment",
|
||||||
|
"amount": 125
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
@@ -3,154 +3,139 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "core",
|
"id": "core",
|
||||||
"_id": "6008c2ff36651a07ebc52ca9",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "shiawase",
|
"name": "shiawase",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "shiawase",
|
"id": "shiawase",
|
||||||
"_id": "6008c2ff36651a07ebc52ce0",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}, {
|
}, {
|
||||||
"type": "character",
|
"type": "character",
|
||||||
"id": "kou",
|
"id": "kou",
|
||||||
"_id": "6008c2ff36651a07ebc52cdf",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1552089600000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1552694399000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "dynamix",
|
"name": "dynamix",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "dynamix",
|
"id": "dynamix",
|
||||||
"_id": "6008c2ff36651a07ebc52ce4",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}, {
|
}, {
|
||||||
"type": "character",
|
"type": "character",
|
||||||
"id": "sapphire",
|
"id": "sapphire",
|
||||||
"_id": "6008c2ff36651a07ebc52ce3",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "mirai",
|
"name": "mirai",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "mirai",
|
"id": "mirai",
|
||||||
"_id": "6008c2ff36651a07ebc52cdc",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}, {
|
}, {
|
||||||
"type": "character",
|
"type": "character",
|
||||||
"id": "lethe",
|
"id": "lethe",
|
||||||
"_id": "6008c2ff36651a07ebc52cdb",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1552089600000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1552694399000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "yugamu",
|
"name": "yugamu",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "yugamu",
|
"id": "yugamu",
|
||||||
"_id": "6008c2ff36651a07ebc52caa",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "lanota",
|
"name": "lanota",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "lanota",
|
"id": "lanota",
|
||||||
"_id": "6008c2ff36651a07ebc52cd0",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "nijuusei",
|
"name": "nijuusei",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "nijuusei",
|
"id": "nijuusei",
|
||||||
"_id": "6008c2ff36651a07ebc52cab",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "rei",
|
"name": "rei",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "rei",
|
"id": "rei",
|
||||||
"_id": "6008c2ff36651a07ebc52cc5",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "tonesphere",
|
"name": "tonesphere",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "tonesphere",
|
"id": "tonesphere",
|
||||||
"_id": "6008c2ff36651a07ebc52cd2",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "groovecoaster",
|
"name": "groovecoaster",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "groovecoaster",
|
"id": "groovecoaster",
|
||||||
"_id": "6008c2ff36651a07ebc52ca1",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "zettai",
|
"name": "zettai",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "zettai",
|
"id": "zettai",
|
||||||
"_id": "6008c2ff36651a07ebc52cc7",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "chunithm",
|
"name": "chunithm",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "chunithm",
|
"id": "chunithm",
|
||||||
"_id": "6008c2ff36651a07ebc52cbb",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 300,
|
"price": 300,
|
||||||
@@ -160,47 +145,50 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "prelude",
|
"id": "prelude",
|
||||||
"_id": "6008c2ff36651a07ebc52ca2",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 400,
|
"price": 400,
|
||||||
"orig_price": 400
|
"orig_price": 400,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "omatsuri",
|
"name": "omatsuri",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "omatsuri",
|
"id": "omatsuri",
|
||||||
"_id": "6008c2ff36651a07ebc52cc8",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500
|
"orig_price": 500,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "vs",
|
"name": "vs",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "vs",
|
"id": "vs",
|
||||||
"_id": "6008c2ff36651a07ebc52cbe",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 500,
|
"price": 500,
|
||||||
"orig_price": 500
|
"orig_price": 500,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "extend",
|
"name": "extend",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "extend",
|
"id": "extend",
|
||||||
"_id": "6008c2ff36651a07ebc52ca5",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 700,
|
"price": 700,
|
||||||
"orig_price": 700
|
"orig_price": 700,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "alice",
|
"name": "alice",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "alice",
|
"id": "alice",
|
||||||
"_id": "6008c2ff36651a07ebc52ccd",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 500,
|
"orig_price": 500,
|
||||||
@@ -210,7 +198,6 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "alice_append_1",
|
"id": "alice_append_1",
|
||||||
"_id": "6008c2ff36651a07ebc52cb4",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 300,
|
"orig_price": 300,
|
||||||
@@ -220,7 +207,6 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "ongeki",
|
"id": "ongeki",
|
||||||
"_id": "6008c2ff36651a07ebc52cc1",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 400,
|
"orig_price": 400,
|
||||||
@@ -230,7 +216,6 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "maimai",
|
"id": "maimai",
|
||||||
"_id": "6008c2ff36651a07ebc52ca8",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 400,
|
"orig_price": 400,
|
||||||
@@ -240,9 +225,26 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "chunithm_append_1",
|
"id": "chunithm_append_1",
|
||||||
"_id": "6008c2ff36651a07ebc52cda",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 300,
|
"orig_price": 300,
|
||||||
"price": 300
|
"price": 300
|
||||||
|
}, {
|
||||||
|
"name": "observer_append_1",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "observer_append_1",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"orig_price": 300,
|
||||||
|
"price": 300
|
||||||
|
}, {
|
||||||
|
"name": "observer",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "observer",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"orig_price": 500,
|
||||||
|
"price": 500
|
||||||
}]
|
}]
|
||||||
@@ -12,55 +12,50 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"id": "dataerror",
|
"id": "dataerror",
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"_id": "6008c2ff36651a07ebc52cb5",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "yourvoiceso",
|
"name": "yourvoiceso",
|
||||||
"items": [{
|
"items": [{
|
||||||
"id": "yourvoiceso",
|
"id": "yourvoiceso",
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"_id": "6008c2ff36651a07ebc52cc2",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "crosssoul",
|
"name": "crosssoul",
|
||||||
"items": [{
|
"items": [{
|
||||||
"id": "crosssoul",
|
"id": "crosssoul",
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"_id": "6008c2ff36651a07ebc52ccf",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "impurebird",
|
"name": "impurebird",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "impurebird",
|
"id": "impurebird",
|
||||||
"_id": "6008c2ff36651a07ebc52cb6",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "auxesia",
|
"name": "auxesia",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "auxesia",
|
"id": "auxesia",
|
||||||
"_id": "6008c2ff36651a07ebc52c9d",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -72,43 +67,39 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "modelista",
|
"id": "modelista",
|
||||||
"_id": "6008c2ff36651a07ebc52cc3",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "yozakurafubuki",
|
"name": "yozakurafubuki",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "yozakurafubuki",
|
"id": "yozakurafubuki",
|
||||||
"_id": "6008c2ff36651a07ebc52cb7",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "surrender",
|
"name": "surrender",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "surrender",
|
"id": "surrender",
|
||||||
"_id": "6008c2ff36651a07ebc52c9e",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "metallicpunisher",
|
"name": "metallicpunisher",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "metallicpunisher",
|
"id": "metallicpunisher",
|
||||||
"_id": "6008c2ff36651a07ebc52cc4",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -118,7 +109,6 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "carminescythe",
|
"id": "carminescythe",
|
||||||
"_id": "6008c2ff36651a07ebc52cb8",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -128,79 +118,72 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "bethere",
|
"id": "bethere",
|
||||||
"_id": "6008c2ff36651a07ebc52c9f",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "callmyname",
|
"name": "callmyname",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "callmyname",
|
"id": "callmyname",
|
||||||
"_id": "6008c2ff36651a07ebc52cd1",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "fallensquare",
|
"name": "fallensquare",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "fallensquare",
|
"id": "fallensquare",
|
||||||
"_id": "6008c2ff36651a07ebc52cac",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "dropdead",
|
"name": "dropdead",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "dropdead",
|
"id": "dropdead",
|
||||||
"_id": "6008c2ff36651a07ebc52cb9",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "alexandrite",
|
"name": "alexandrite",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "alexandrite",
|
"id": "alexandrite",
|
||||||
"_id": "6008c2ff36651a07ebc52ca0",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "astraltale",
|
"name": "astraltale",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "astraltale",
|
"id": "astraltale",
|
||||||
"_id": "6008c2ff36651a07ebc52cc6",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "phantasia",
|
"name": "phantasia",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "phantasia",
|
"id": "phantasia",
|
||||||
"_id": "6008c2ff36651a07ebc52cad",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -210,7 +193,6 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "empireofwinter",
|
"id": "empireofwinter",
|
||||||
"_id": "6008c2ff36651a07ebc52cba",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -220,75 +202,72 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "libertas",
|
"id": "libertas",
|
||||||
"_id": "6008c2ff36651a07ebc52cd3",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "dottodot",
|
"name": "dottodot",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "dottodot",
|
"id": "dottodot",
|
||||||
"_id": "6008c2ff36651a07ebc52cae",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "dreadnought",
|
"name": "dreadnought",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "dreadnought",
|
"id": "dreadnought",
|
||||||
"_id": "6008c2ff36651a07ebc52cd4",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "mirzam",
|
"name": "mirzam",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "mirzam",
|
"id": "mirzam",
|
||||||
"_id": "6008c2ff36651a07ebc52caf",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
"discount_from": 1583712000000,
|
"discount_from": 1615248000000,
|
||||||
"discount_to": 1584316799000
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "heavenlycaress",
|
"name": "heavenlycaress",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "heavenlycaress",
|
"id": "heavenlycaress",
|
||||||
"_id": "6008c2ff36651a07ebc52cbc",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "filament",
|
"name": "filament",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "filament",
|
"id": "filament",
|
||||||
"_id": "6008c2ff36651a07ebc52ca3",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "avantraze",
|
"name": "avantraze",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "avantraze",
|
"id": "avantraze",
|
||||||
"_id": "6008c2ff36651a07ebc52cd5",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -298,17 +277,17 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "battlenoone",
|
"id": "battlenoone",
|
||||||
"_id": "6008c2ff36651a07ebc52cc9",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "saikyostronger",
|
"name": "saikyostronger",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "saikyostronger",
|
"id": "saikyostronger",
|
||||||
"_id": "6008c2ff36651a07ebc52cb0",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -318,67 +297,72 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "izana",
|
"id": "izana",
|
||||||
"_id": "6008c2ff36651a07ebc52cbd",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "einherjar",
|
"name": "einherjar",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "einherjar",
|
"id": "einherjar",
|
||||||
"_id": "6008c2ff36651a07ebc52ca4",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "laqryma",
|
"name": "laqryma",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "laqryma",
|
"id": "laqryma",
|
||||||
"_id": "6008c2ff36651a07ebc52cd6",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "amygdata",
|
"name": "amygdata",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "amygdata",
|
"id": "amygdata",
|
||||||
"_id": "6008c2ff36651a07ebc52cca",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "altale",
|
"name": "altale",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "altale",
|
"id": "altale",
|
||||||
"_id": "6008c2ff36651a07ebc52cb1",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "feelssoright",
|
"name": "feelssoright",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "feelssoright",
|
"id": "feelssoright",
|
||||||
"_id": "6008c2ff36651a07ebc52cd7",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "scarletcage",
|
"name": "scarletcage",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "scarletcage",
|
"id": "scarletcage",
|
||||||
"_id": "6008c2ff36651a07ebc52ccb",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -388,7 +372,6 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "teriqma",
|
"id": "teriqma",
|
||||||
"_id": "6008c2ff36651a07ebc52cb2",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -398,27 +381,28 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "mahoroba",
|
"id": "mahoroba",
|
||||||
"_id": "6008c2ff36651a07ebc52cbf",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "badtek",
|
"name": "badtek",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "badtek",
|
"id": "badtek",
|
||||||
"_id": "6008c2ff36651a07ebc52cd8",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "maliciousmischance",
|
"name": "maliciousmischance",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "maliciousmischance",
|
"id": "maliciousmischance",
|
||||||
"_id": "6008c2ff36651a07ebc52ccc",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -428,7 +412,6 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "buchigireberserker",
|
"id": "buchigireberserker",
|
||||||
"_id": "6008c2ff36651a07ebc52cb3",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -438,17 +421,17 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "galaxyfriends",
|
"id": "galaxyfriends",
|
||||||
"_id": "6008c2ff36651a07ebc52cc0",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100,
|
||||||
|
"discount_from": 1615248000000,
|
||||||
|
"discount_to": 1615852799000
|
||||||
}, {
|
}, {
|
||||||
"name": "xeraphinite",
|
"name": "xeraphinite",
|
||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "xeraphinite",
|
"id": "xeraphinite",
|
||||||
"_id": "6008c2ff36651a07ebc52ca7",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
@@ -458,7 +441,6 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "xanatos",
|
"id": "xanatos",
|
||||||
"_id": "6008c2ff36651a07ebc52cd9",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
@@ -468,7 +450,24 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "attraqtia",
|
"id": "attraqtia",
|
||||||
"_id": "6008c2ff36651a07ebc52cce",
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"orig_price": 100,
|
||||||
|
"price": 100
|
||||||
|
}, {
|
||||||
|
"name": "gimmedablood",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "gimmedablood",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"orig_price": 100,
|
||||||
|
"price": 100
|
||||||
|
}, {
|
||||||
|
"name": "bassline",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "bassline",
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
|
|||||||
0
latest version/log/error.log
Normal file
0
latest version/log/error.log
Normal file
@@ -10,15 +10,108 @@ import server.setme
|
|||||||
import server.arcscore
|
import server.arcscore
|
||||||
import web.login
|
import web.login
|
||||||
import web.index
|
import web.index
|
||||||
|
import api.api_main
|
||||||
import server.arcworld
|
import server.arcworld
|
||||||
import server.arcdownload
|
import server.arcdownload
|
||||||
import server.arcpurchase
|
import server.arcpurchase
|
||||||
|
import server.init
|
||||||
|
import server.character
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
wsgi_app = app.wsgi_app
|
wsgi_app = app.wsgi_app
|
||||||
|
|
||||||
|
os.chdir(sys.path[0]) # 更改工作路径,以便于愉快使用相对路径
|
||||||
|
|
||||||
|
app.config.from_mapping(SECRET_KEY=Config.SECRET_KEY)
|
||||||
|
app.config['SESSION_TYPE'] = 'filesystem'
|
||||||
|
app.register_blueprint(web.login.bp)
|
||||||
|
app.register_blueprint(web.index.bp)
|
||||||
|
app.register_blueprint(api.api_main.bp)
|
||||||
|
|
||||||
|
log_dict = {
|
||||||
|
'version': 1,
|
||||||
|
'root': {
|
||||||
|
'level': 'INFO',
|
||||||
|
'handlers': ['wsgi', 'error_file']
|
||||||
|
},
|
||||||
|
'handlers': {
|
||||||
|
'wsgi': {
|
||||||
|
'class': 'logging.StreamHandler',
|
||||||
|
'stream': 'ext://flask.logging.wsgi_errors_stream',
|
||||||
|
'formatter': 'default'
|
||||||
|
},
|
||||||
|
"error_file": {
|
||||||
|
"class": "logging.handlers.RotatingFileHandler",
|
||||||
|
"maxBytes": 1024 * 1024,
|
||||||
|
"backupCount": 1,
|
||||||
|
"encoding": "utf-8",
|
||||||
|
"level": "ERROR",
|
||||||
|
"formatter": "default",
|
||||||
|
"filename": "./log/error.log"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'formatters': {
|
||||||
|
'default': {
|
||||||
|
'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if Config.ALLOW_LOG_INFO:
|
||||||
|
log_dict['root']['handlers'] = ['wsgi', 'info_file', 'error_file']
|
||||||
|
log_dict['handlers']['info_file'] = {
|
||||||
|
"class": "logging.handlers.RotatingFileHandler",
|
||||||
|
"maxBytes": 1024 * 1024,
|
||||||
|
"backupCount": 1,
|
||||||
|
"encoding": "utf-8",
|
||||||
|
"level": "INFO",
|
||||||
|
"formatter": "default",
|
||||||
|
"filename": "./log/info.log"
|
||||||
|
}
|
||||||
|
|
||||||
|
dictConfig(log_dict)
|
||||||
|
|
||||||
|
if not server.init.check_before_run(app):
|
||||||
|
app.logger.error('Something wrong. The server will not run.')
|
||||||
|
input('Press ENTER key to exit.')
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
app.logger.info("Start to initialize data in 'songfile' table...")
|
||||||
|
try:
|
||||||
|
error = server.arcdownload.initialize_songfile()
|
||||||
|
except:
|
||||||
|
error = 'Something wrong.'
|
||||||
|
if error:
|
||||||
|
app.logger.warning(error)
|
||||||
|
else:
|
||||||
|
app.logger.info('Complete!')
|
||||||
|
|
||||||
|
|
||||||
|
def add_url_prefix(url, strange_flag=False):
|
||||||
|
# 给url加前缀,返回字符串
|
||||||
|
if not url or not Config.GAME_API_PREFIX:
|
||||||
|
return Config.GAME_API_PREFIX + url
|
||||||
|
|
||||||
|
prefix = Config.GAME_API_PREFIX
|
||||||
|
if prefix[0] != '/':
|
||||||
|
prefix = '/' + prefix
|
||||||
|
if prefix[-1] == '/':
|
||||||
|
prefix = prefix[:-1]
|
||||||
|
|
||||||
|
if url[0] != '/':
|
||||||
|
r = '/' + url
|
||||||
|
else:
|
||||||
|
r = url
|
||||||
|
|
||||||
|
if strange_flag and prefix.count('/') >= 1: # 为了方便处理双斜杠
|
||||||
|
t = prefix[::-1]
|
||||||
|
t = t[t.find('/')+1:]
|
||||||
|
prefix = t[::-1]
|
||||||
|
|
||||||
|
return prefix + r
|
||||||
|
|
||||||
|
|
||||||
def error_return(error_code): # 错误返回
|
def error_return(error_code): # 错误返回
|
||||||
# -7 处理交易时发生了错误
|
# -7 处理交易时发生了错误
|
||||||
@@ -72,6 +165,7 @@ def error_return(error_code): # 错误返回
|
|||||||
@app.route('/')
|
@app.route('/')
|
||||||
def hello():
|
def hello():
|
||||||
return "Hello World!"
|
return "Hello World!"
|
||||||
|
# 自定义路径
|
||||||
|
|
||||||
|
|
||||||
@app.route('/favicon.ico', methods=['GET']) # 图标
|
@app.route('/favicon.ico', methods=['GET']) # 图标
|
||||||
@@ -83,14 +177,24 @@ def favicon():
|
|||||||
return app.send_static_file('favicon.ico')
|
return app.send_static_file('favicon.ico')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/auth/login', methods=['POST']) # 登录接口
|
@app.route(add_url_prefix('/auth/login'), methods=['POST']) # 登录接口
|
||||||
def login():
|
def login():
|
||||||
|
if 'AppVersion' in request.headers: # 版本检查
|
||||||
|
if Config.ALLOW_APPVERSION:
|
||||||
|
if request.headers['AppVersion'] not in Config.ALLOW_APPVERSION:
|
||||||
|
return jsonify({"success": False, "error_code": 5})
|
||||||
|
|
||||||
headers = request.headers
|
headers = request.headers
|
||||||
id_pwd = headers['Authorization']
|
id_pwd = headers['Authorization']
|
||||||
id_pwd = base64.b64decode(id_pwd[6:]).decode()
|
id_pwd = base64.b64decode(id_pwd[6:]).decode()
|
||||||
name, password = id_pwd.split(':', 1)
|
name, password = id_pwd.split(':', 1)
|
||||||
|
if 'DeviceId' in headers:
|
||||||
device_id = headers['DeviceId']
|
device_id = headers['DeviceId']
|
||||||
token, error_code = server.auth.arc_login(name, password, device_id)
|
else:
|
||||||
|
device_id = 'low_version'
|
||||||
|
|
||||||
|
token, error_code = server.auth.arc_login(
|
||||||
|
name, password, device_id, request.remote_addr)
|
||||||
if not error_code:
|
if not error_code:
|
||||||
r = {"success": True, "token_type": "Bearer"}
|
r = {"success": True, "token_type": "Bearer"}
|
||||||
r['access_token'] = token
|
r['access_token'] = token
|
||||||
@@ -99,23 +203,33 @@ def login():
|
|||||||
return error_return(error_code)
|
return error_return(error_code)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/user/', methods=['POST']) # 注册接口
|
@app.route(add_url_prefix('/user/'), methods=['POST']) # 注册接口
|
||||||
def register():
|
def register():
|
||||||
|
if 'AppVersion' in request.headers: # 版本检查
|
||||||
|
if Config.ALLOW_APPVERSION:
|
||||||
|
if request.headers['AppVersion'] not in Config.ALLOW_APPVERSION:
|
||||||
|
return jsonify({"success": False, "error_code": 5})
|
||||||
|
|
||||||
name = request.form['name']
|
name = request.form['name']
|
||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
|
email = request.form['email']
|
||||||
|
if 'device_id' in request.form:
|
||||||
device_id = request.form['device_id']
|
device_id = request.form['device_id']
|
||||||
|
else:
|
||||||
|
device_id = 'low_version'
|
||||||
|
|
||||||
user_id, token, error_code = server.auth.arc_register(
|
user_id, token, error_code = server.auth.arc_register(
|
||||||
name, password, device_id)
|
name, password, device_id, email, request.remote_addr)
|
||||||
if user_id is not None:
|
if user_id is not None:
|
||||||
r = {"success": True, "value": {
|
r = {"success": True, "value": {
|
||||||
'user_id': user_id, 'access_token': token}}
|
'user_id': user_id, 'access_token': token}}
|
||||||
return jsonify(r)
|
return jsonify(r)
|
||||||
else:
|
else:
|
||||||
return error_return(error_code) # 应该是101,用户名被占用,毕竟电子邮箱没记录
|
return error_return(error_code)
|
||||||
|
|
||||||
|
|
||||||
# 集成式请求,没想到什么好办法处理,就先这样写着
|
# 集成式请求,没想到什么好办法处理,就先这样写着
|
||||||
@app.route('/latte/13/compose/aggregate', methods=['GET'])
|
@app.route(add_url_prefix('/compose/aggregate'), methods=['GET'])
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def aggregate(user_id):
|
def aggregate(user_id):
|
||||||
calls = request.args.get('calls')
|
calls = request.args.get('calls')
|
||||||
@@ -126,7 +240,7 @@ def aggregate(user_id):
|
|||||||
return jsonify(r)
|
return jsonify(r)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/user/me/character', methods=['POST']) # 角色切换
|
@app.route(add_url_prefix('/user/me/character'), methods=['POST']) # 角色切换
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def character_change(user_id):
|
def character_change(user_id):
|
||||||
character_id = request.form['character']
|
character_id = request.form['character']
|
||||||
@@ -145,7 +259,8 @@ def character_change(user_id):
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/<path:path>/toggle_uncap', methods=['POST']) # 角色觉醒切换
|
# 角色觉醒切换
|
||||||
|
@app.route(add_url_prefix('/<path:path>/toggle_uncap', True), methods=['POST'])
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def character_uncap(user_id, path):
|
def character_uncap(user_id, path):
|
||||||
while '//' in path:
|
while '//' in path:
|
||||||
@@ -164,7 +279,42 @@ def character_uncap(user_id, path):
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/friend/me/add', methods=['POST']) # 加好友
|
# 角色觉醒
|
||||||
|
@app.route(add_url_prefix('/<path:path>/uncap', True), methods=['POST'])
|
||||||
|
@server.auth.auth_required(request)
|
||||||
|
def character_first_uncap(user_id, path):
|
||||||
|
while '//' in path:
|
||||||
|
path = path.replace('//', '/')
|
||||||
|
character_id = int(path[21:])
|
||||||
|
r = server.character.char_uncap(user_id, character_id)
|
||||||
|
if r is not None:
|
||||||
|
return jsonify({
|
||||||
|
"success": True,
|
||||||
|
"value": r
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
|
# 角色使用以太之滴
|
||||||
|
@app.route(add_url_prefix('/<path:path>/exp', True), methods=['POST'])
|
||||||
|
@server.auth.auth_required(request)
|
||||||
|
def character_exp(user_id, path):
|
||||||
|
while '//' in path:
|
||||||
|
path = path.replace('//', '/')
|
||||||
|
character_id = int(path[21:])
|
||||||
|
amount = int(request.form['amount'])
|
||||||
|
r = server.character.char_use_core(user_id, character_id, amount)
|
||||||
|
if r is not None:
|
||||||
|
return jsonify({
|
||||||
|
"success": True,
|
||||||
|
"value": r
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route(add_url_prefix('/friend/me/add'), methods=['POST']) # 加好友
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def add_friend(user_id):
|
def add_friend(user_id):
|
||||||
friend_code = request.form['friend_code']
|
friend_code = request.form['friend_code']
|
||||||
@@ -190,7 +340,7 @@ def add_friend(user_id):
|
|||||||
return error_return(401)
|
return error_return(401)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/friend/me/delete', methods=['POST']) # 删好友
|
@app.route(add_url_prefix('/friend/me/delete'), methods=['POST']) # 删好友
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def delete_friend(user_id):
|
def delete_friend(user_id):
|
||||||
friend_id = int(request.form['friend_id'])
|
friend_id = int(request.form['friend_id'])
|
||||||
@@ -212,7 +362,8 @@ def delete_friend(user_id):
|
|||||||
return error_return(401)
|
return error_return(401)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/score/song/friend', methods=['GET']) # 好友排名,默认最多50
|
# 好友排名,默认最多50
|
||||||
|
@app.route(add_url_prefix('/score/song/friend'), methods=['GET'])
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def song_score_friend(user_id):
|
def song_score_friend(user_id):
|
||||||
song_id = request.args.get('song_id')
|
song_id = request.args.get('song_id')
|
||||||
@@ -227,7 +378,7 @@ def song_score_friend(user_id):
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/score/song/me', methods=['GET']) # 我的排名,默认最多20
|
@app.route(add_url_prefix('/score/song/me'), methods=['GET']) # 我的排名,默认最多20
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def song_score_me(user_id):
|
def song_score_me(user_id):
|
||||||
song_id = request.args.get('song_id')
|
song_id = request.args.get('song_id')
|
||||||
@@ -242,7 +393,7 @@ def song_score_me(user_id):
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/score/song', methods=['GET']) # TOP20
|
@app.route(add_url_prefix('/score/song'), methods=['GET']) # TOP20
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def song_score_top(user_id):
|
def song_score_top(user_id):
|
||||||
song_id = request.args.get('song_id')
|
song_id = request.args.get('song_id')
|
||||||
@@ -257,7 +408,7 @@ def song_score_top(user_id):
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/score/song', methods=['POST']) # 成绩上传
|
@app.route(add_url_prefix('/score/song'), methods=['POST']) # 成绩上传
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def song_score_post(user_id):
|
def song_score_post(user_id):
|
||||||
song_token = request.form['song_token']
|
song_token = request.form['song_token']
|
||||||
@@ -281,22 +432,17 @@ def song_score_post(user_id):
|
|||||||
|
|
||||||
r, re = server.arcscore.arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count,
|
r, re = server.arcscore.arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count,
|
||||||
perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type)
|
perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type)
|
||||||
if r is not None:
|
|
||||||
if re:
|
if re:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
"value": re
|
"value": re
|
||||||
})
|
})
|
||||||
else:
|
|
||||||
return jsonify({
|
|
||||||
"success": True,
|
|
||||||
"value": {"user_rating": r}
|
|
||||||
})
|
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/score/token', methods=['GET']) # 成绩上传所需的token,显然我不想验证
|
# 成绩上传所需的token,显然我不想验证
|
||||||
|
@app.route(add_url_prefix('/score/token'), methods=['GET'])
|
||||||
def score_token():
|
def score_token():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
@@ -307,7 +453,7 @@ def score_token():
|
|||||||
|
|
||||||
|
|
||||||
# 世界模式成绩上传所需的token,无验证
|
# 世界模式成绩上传所需的token,无验证
|
||||||
@app.route('/latte/13/score/token/world', methods=['GET'])
|
@app.route(add_url_prefix('/score/token/world'), methods=['GET'])
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def score_token_world(user_id):
|
def score_token_world(user_id):
|
||||||
args = request.args
|
args = request.args
|
||||||
@@ -322,7 +468,7 @@ def score_token_world(user_id):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/user/me/save', methods=['GET']) # 从云端同步
|
@app.route(add_url_prefix('/user/me/save'), methods=['GET']) # 从云端同步
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def cloud_get(user_id):
|
def cloud_get(user_id):
|
||||||
r = server.arcscore.arc_all_get(user_id)
|
r = server.arcscore.arc_all_get(user_id)
|
||||||
@@ -335,7 +481,7 @@ def cloud_get(user_id):
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/user/me/save', methods=['POST']) # 向云端同步
|
@app.route(add_url_prefix('/user/me/save'), methods=['POST']) # 向云端同步
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def cloud_post(user_id):
|
def cloud_post(user_id):
|
||||||
scores_data = request.form['scores_data']
|
scores_data = request.form['scores_data']
|
||||||
@@ -356,7 +502,7 @@ def cloud_post(user_id):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/purchase/me/redeem', methods=['POST']) # 兑换码
|
@app.route(add_url_prefix('/purchase/me/redeem'), methods=['POST']) # 兑换码
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def redeem(user_id):
|
def redeem(user_id):
|
||||||
code = request.form['code']
|
code = request.form['code']
|
||||||
@@ -378,7 +524,7 @@ def redeem(user_id):
|
|||||||
|
|
||||||
|
|
||||||
# 礼物确认
|
# 礼物确认
|
||||||
@app.route('/latte/13/present/me/claim/<present_id>', methods=['POST'])
|
@app.route(add_url_prefix('/present/me/claim/<present_id>'), methods=['POST'])
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def claim_present(user_id, present_id):
|
def claim_present(user_id, present_id):
|
||||||
flag = server.arcpurchase.claim_user_present(user_id, present_id)
|
flag = server.arcpurchase.claim_user_present(user_id, present_id)
|
||||||
@@ -390,7 +536,8 @@ def claim_present(user_id, present_id):
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/purchase/me/item', methods=['POST']) # 购买,world模式boost
|
# 购买,world模式boost
|
||||||
|
@app.route(add_url_prefix('/purchase/me/item'), methods=['POST'])
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def prog_boost(user_id):
|
def prog_boost(user_id):
|
||||||
re = {"success": False}
|
re = {"success": False}
|
||||||
@@ -407,20 +554,19 @@ def prog_boost(user_id):
|
|||||||
return jsonify(re)
|
return jsonify(re)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/purchase/me/pack', methods=['POST']) # 曲包和单曲购买
|
@app.route(add_url_prefix('/purchase/me/pack'), methods=['POST']) # 曲包和单曲购买
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def pack(user_id):
|
def pack(user_id):
|
||||||
if 'pack_id' in request.form:
|
if 'pack_id' in request.form:
|
||||||
return jsonify(server.arcpurchase.buy_pack(user_id, request.form['pack_id']))
|
return jsonify(server.arcpurchase.buy_thing(user_id, request.form['pack_id']))
|
||||||
if 'single_id' in request.form:
|
if 'single_id' in request.form:
|
||||||
return jsonify(server.arcpurchase.buy_single(user_id, request.form['single_id']))
|
return jsonify(server.arcpurchase.buy_thing(user_id, request.form['single_id']))
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({"success": True})
|
||||||
"success": True
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/purchase/bundle/single', methods=['GET']) # 单曲购买信息获取
|
# 单曲购买信息获取
|
||||||
|
@app.route(add_url_prefix('/purchase/bundle/single'), methods=['GET'])
|
||||||
def single():
|
def single():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
@@ -428,7 +574,7 @@ def single():
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/world/map/me', methods=['GET']) # 获得世界模式信息,所有地图
|
@app.route(add_url_prefix('/world/map/me'), methods=['GET']) # 获得世界模式信息,所有地图
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def world_all(user_id):
|
def world_all(user_id):
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -441,7 +587,7 @@ def world_all(user_id):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/world/map/me/', methods=['POST']) # 进入地图
|
@app.route(add_url_prefix('/world/map/me/'), methods=['POST']) # 进入地图
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def world_in(user_id):
|
def world_in(user_id):
|
||||||
map_id = request.form['map_id']
|
map_id = request.form['map_id']
|
||||||
@@ -451,7 +597,8 @@ def world_in(user_id):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/world/map/me/<map_id>', methods=['GET']) # 获得单个地图完整信息
|
# 获得单个地图完整信息
|
||||||
|
@app.route(add_url_prefix('/world/map/me/<map_id>'), methods=['GET'])
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def world_one(user_id, map_id):
|
def world_one(user_id, map_id):
|
||||||
server.arcworld.change_user_current_map(user_id, map_id)
|
server.arcworld.change_user_current_map(user_id, map_id)
|
||||||
@@ -465,7 +612,7 @@ def world_one(user_id, map_id):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/serve/download/me/song', methods=['GET']) # 歌曲下载
|
@app.route(add_url_prefix('/serve/download/me/song'), methods=['GET']) # 歌曲下载
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def download_song(user_id):
|
def download_song(user_id):
|
||||||
song_ids = request.args.getlist('sid')
|
song_ids = request.args.getlist('sid')
|
||||||
@@ -501,7 +648,8 @@ def download(file_path):
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/<path:path>', methods=['POST']) # 三个设置,写在最后降低优先级
|
# 三个设置,写在最后降低优先级
|
||||||
|
@app.route(add_url_prefix('/<path:path>', True), methods=['POST'])
|
||||||
@server.auth.auth_required(request)
|
@server.auth.auth_required(request)
|
||||||
def sys_set(user_id, path):
|
def sys_set(user_id, path):
|
||||||
set_arg = path[10:]
|
set_arg = path[10:]
|
||||||
@@ -513,30 +661,10 @@ def sys_set(user_id, path):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
app.config.from_mapping(SECRET_KEY=Config.SECRET_KEY)
|
if Config.SSL_CERT and Config.SSL_KEY:
|
||||||
app.register_blueprint(web.login.bp)
|
app.run(Config.HOST, Config.PORT, ssl_context=(
|
||||||
app.register_blueprint(web.index.bp)
|
Config.SSL_CERT, Config.SSL_KEY))
|
||||||
|
|
||||||
dictConfig({
|
|
||||||
'version': 1,
|
|
||||||
'formatters': {'default': {
|
|
||||||
'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
|
|
||||||
}},
|
|
||||||
'root': {
|
|
||||||
'level': 'INFO'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.logger.info("Start to initialize data in 'songfile' table...")
|
|
||||||
try:
|
|
||||||
error = server.arcdownload.initialize_songfile()
|
|
||||||
except:
|
|
||||||
error = 'Something wrong.'
|
|
||||||
if error:
|
|
||||||
app.logger.warning(error)
|
|
||||||
else:
|
else:
|
||||||
app.logger.info('Complete!')
|
|
||||||
|
|
||||||
app.run(Config.HOST, Config.PORT)
|
app.run(Config.HOST, Config.PORT)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,24 @@ def get_file_md5(file_path):
|
|||||||
return myhash.hexdigest()
|
return myhash.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def get_one_song(c, user_id, song_id, file_dir='./database/songs'):
|
def get_url(file_path, **kwargs):
|
||||||
|
# 获取下载地址
|
||||||
|
|
||||||
|
t = ''
|
||||||
|
if 't' in kwargs:
|
||||||
|
t = kwargs['t']
|
||||||
|
|
||||||
|
if Config.DOWNLOAD_LINK_PREFIX:
|
||||||
|
prefix = Config.DOWNLOAD_LINK_PREFIX
|
||||||
|
if prefix[-1] != '/':
|
||||||
|
prefix += '/'
|
||||||
|
|
||||||
|
return prefix + file_path + '?t=' + t
|
||||||
|
else:
|
||||||
|
return url_for('download', file_path=file_path, t=t, _external=True)
|
||||||
|
|
||||||
|
|
||||||
|
def get_one_song(c, user_id, song_id, file_dir='./database/songs', url_flag=True):
|
||||||
# 获取一首歌的下载链接,返回字典
|
# 获取一首歌的下载链接,返回字典
|
||||||
dir_list = os.listdir(os.path.join(file_dir, song_id))
|
dir_list = os.listdir(os.path.join(file_dir, song_id))
|
||||||
re = {}
|
re = {}
|
||||||
@@ -37,7 +54,6 @@ def get_one_song(c, user_id, song_id, file_dir='./database/songs'):
|
|||||||
if os.path.isfile(os.path.join(file_dir, song_id, i)) and i in ['0.aff', '1.aff', '2.aff', '3.aff', 'base.ogg']:
|
if os.path.isfile(os.path.join(file_dir, song_id, i)) and i in ['0.aff', '1.aff', '2.aff', '3.aff', 'base.ogg']:
|
||||||
token = hashlib.md5(
|
token = hashlib.md5(
|
||||||
(str(user_id) + song_id + i + str(now)).encode(encoding='UTF-8')).hexdigest()
|
(str(user_id) + song_id + i + str(now)).encode(encoding='UTF-8')).hexdigest()
|
||||||
token = token[:8]
|
|
||||||
|
|
||||||
if i == 'base.ogg':
|
if i == 'base.ogg':
|
||||||
c.execute(
|
c.execute(
|
||||||
@@ -48,8 +64,12 @@ def get_one_song(c, user_id, song_id, file_dir='./database/songs'):
|
|||||||
else:
|
else:
|
||||||
checksum = get_file_md5(os.path.join(
|
checksum = get_file_md5(os.path.join(
|
||||||
file_dir, song_id, 'base.ogg'))
|
file_dir, song_id, 'base.ogg'))
|
||||||
re['audio'] = {"checksum": checksum,
|
|
||||||
"url": url_for('download', file_path=song_id+'/base.ogg', t=token, _external=True)}
|
if url_flag:
|
||||||
|
re['audio'] = {"checksum": checksum, "url": get_url(
|
||||||
|
file_path=song_id+'/base.ogg', t=token)}
|
||||||
|
else:
|
||||||
|
re['audio'] = {"checksum": checksum}
|
||||||
else:
|
else:
|
||||||
if 'chart' not in re:
|
if 'chart' not in re:
|
||||||
re['chart'] = {}
|
re['chart'] = {}
|
||||||
@@ -60,23 +80,28 @@ def get_one_song(c, user_id, song_id, file_dir='./database/songs'):
|
|||||||
checksum = x[0]
|
checksum = x[0]
|
||||||
else:
|
else:
|
||||||
checksum = get_file_md5(os.path.join(file_dir, song_id, i))
|
checksum = get_file_md5(os.path.join(file_dir, song_id, i))
|
||||||
re['chart'][i[0]] = {"checksum": checksum,
|
|
||||||
"url": url_for('download', file_path=song_id+'/'+i, t=token, _external=True)}
|
|
||||||
|
|
||||||
|
if url_flag:
|
||||||
|
re['chart'][i[0]] = {"checksum": checksum, "url": get_url(
|
||||||
|
file_path=song_id+'/'+i, t=token)}
|
||||||
|
else:
|
||||||
|
re['chart'][i[0]] = {"checksum": checksum}
|
||||||
|
|
||||||
|
if url_flag:
|
||||||
c.execute('''insert into download_token values(:a,:b,:c,:d,:e)''', {
|
c.execute('''insert into download_token values(:a,:b,:c,:d,:e)''', {
|
||||||
'a': user_id, 'b': song_id, 'c': i, 'd': token, 'e': now})
|
'a': user_id, 'b': song_id, 'c': i, 'd': token, 'e': now})
|
||||||
|
|
||||||
return {song_id: re}
|
return {song_id: re}
|
||||||
|
|
||||||
|
|
||||||
def get_all_songs(user_id, file_dir='./database/songs'):
|
def get_all_songs(user_id, file_dir='./database/songs', url_flag=True):
|
||||||
# 获取所有歌的下载链接,返回字典
|
# 获取所有歌的下载链接,返回字典
|
||||||
dir_list = os.listdir(file_dir)
|
dir_list = os.listdir(file_dir)
|
||||||
re = {}
|
re = {}
|
||||||
with Connect() as c:
|
with Connect() as c:
|
||||||
for i in dir_list:
|
for i in dir_list:
|
||||||
if os.path.isdir(os.path.join(file_dir, i)):
|
if os.path.isdir(os.path.join(file_dir, i)):
|
||||||
re.update(get_one_song(c, user_id, i, file_dir))
|
re.update(get_one_song(c, user_id, i, file_dir, url_flag))
|
||||||
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
from server.sql import Connect
|
from server.sql import Connect
|
||||||
|
import server.item
|
||||||
|
import server.character
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@@ -11,28 +13,37 @@ def int2b(x):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def get_item(c, type='pack'):
|
def get_purchase(c, type='pack'):
|
||||||
# 读取packs内容,返回字典列表
|
# 读取packs内容,返回字典列表
|
||||||
c.execute('''select * from item where type = :a''', {'a': type})
|
c.execute(
|
||||||
|
'''select * from purchase where purchase_name in (select purchase_name from purchase_item where type = :a)''', {'a': type})
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
if not x:
|
if not x:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
re = []
|
re = []
|
||||||
for i in x:
|
for i in x:
|
||||||
r = {"name": i[0],
|
items = []
|
||||||
"items": [{
|
c.execute(
|
||||||
"type": i[1],
|
'''select a.* from item a, purchase_item b where a.item_id=b.item_id and a.type=b.type and b.purchase_name=:name''', {'name': i[0]})
|
||||||
"id": i[0],
|
y = c.fetchall()
|
||||||
"is_available": int2b(i[2])
|
if y:
|
||||||
}],
|
for j in y:
|
||||||
"price": i[3],
|
items.append({
|
||||||
"orig_price": i[4]}
|
"type": j[1],
|
||||||
|
"id": j[0],
|
||||||
|
"is_available": int2b(j[2])
|
||||||
|
})
|
||||||
|
|
||||||
if i[5] > 0:
|
r = {"name": i[0],
|
||||||
r['discount_from'] = i[5]
|
"items": items,
|
||||||
if i[6] > 0:
|
"price": i[1],
|
||||||
r['discount_to'] = i[6]
|
"orig_price": i[2]}
|
||||||
|
|
||||||
|
if i[3] > 0:
|
||||||
|
r['discount_from'] = i[3]
|
||||||
|
if i[4] > 0:
|
||||||
|
r['discount_to'] = i[4]
|
||||||
|
|
||||||
re.append(r)
|
re.append(r)
|
||||||
|
|
||||||
@@ -43,7 +54,7 @@ def get_single_purchase():
|
|||||||
# main里面没开数据库,这里写一下代替
|
# main里面没开数据库,这里写一下代替
|
||||||
re = []
|
re = []
|
||||||
with Connect() as c:
|
with Connect() as c:
|
||||||
re = get_item(c, type='single')
|
re = get_purchase(c, type='single')
|
||||||
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
@@ -67,49 +78,65 @@ def buy_item(c, user_id, price):
|
|||||||
return True, ticket - price
|
return True, ticket - price
|
||||||
|
|
||||||
|
|
||||||
def buy_pack(user_id, pack_id):
|
def buy_thing(user_id, purchase_id):
|
||||||
# 曲包购买,返回字典
|
# 购买物品接口,返回字典
|
||||||
re = {"success": False}
|
success_flag = False
|
||||||
|
ticket = 0
|
||||||
|
packs = []
|
||||||
|
singles = []
|
||||||
|
characters = []
|
||||||
|
|
||||||
with Connect() as c:
|
with Connect() as c:
|
||||||
c.execute('''select price from item where item_id = :a''',
|
c.execute('''select price, orig_price, discount_from, discount_to from purchase where purchase_name=:a''',
|
||||||
{'a': pack_id})
|
{'a': purchase_id})
|
||||||
price = c.fetchone()
|
x = c.fetchone()
|
||||||
if price:
|
|
||||||
price = price[0]
|
|
||||||
else:
|
|
||||||
price = 0
|
price = 0
|
||||||
|
flag = False
|
||||||
|
if x:
|
||||||
|
price = x[0]
|
||||||
|
orig_price = x[1]
|
||||||
|
discount_from = x[2]
|
||||||
|
discount_to = x[3]
|
||||||
|
else:
|
||||||
|
return {
|
||||||
|
"success": False,
|
||||||
|
"error_code": 501
|
||||||
|
}
|
||||||
|
|
||||||
|
c.execute(
|
||||||
|
'''select item_id, type from purchase_item where purchase_name=:a''', {'a': purchase_id})
|
||||||
|
x = c.fetchall()
|
||||||
|
if x:
|
||||||
|
now = int(time.time() * 1000)
|
||||||
|
if not(discount_from <= now <= discount_to):
|
||||||
|
price = orig_price
|
||||||
|
|
||||||
flag, ticket = buy_item(c, user_id, price)
|
flag, ticket = buy_item(c, user_id, price)
|
||||||
|
|
||||||
if flag:
|
if flag:
|
||||||
c.execute('''insert into user_item values(:a,:b,'pack')''',
|
for i in x:
|
||||||
{'a': user_id, 'b': pack_id})
|
server.item.claim_user_item(c, user_id, i[0], i[1])
|
||||||
|
|
||||||
re = {"success": True}
|
success_flag = True
|
||||||
|
|
||||||
return re
|
|
||||||
|
|
||||||
|
|
||||||
def buy_single(user_id, single_id):
|
|
||||||
# 单曲购买,返回字典
|
|
||||||
re = {"success": False}
|
|
||||||
with Connect() as c:
|
|
||||||
c.execute('''select price from item where item_id = :a''',
|
|
||||||
{'a': single_id})
|
|
||||||
price = c.fetchone()
|
|
||||||
if price:
|
|
||||||
price = price[0]
|
|
||||||
else:
|
else:
|
||||||
price = 0
|
return {
|
||||||
|
"success": False,
|
||||||
|
"error_code": 501
|
||||||
|
}
|
||||||
|
|
||||||
flag, ticket = buy_item(c, user_id, price)
|
packs = server.item.get_user_items(c, user_id, 'pack')
|
||||||
|
singles = server.item.get_user_items(c, user_id, 'single')
|
||||||
|
characters = server.character.get_user_characters(c, user_id)
|
||||||
|
|
||||||
if flag:
|
return {
|
||||||
c.execute('''insert into user_item values(:a,:b,'single')''',
|
"success": success_flag,
|
||||||
{'a': user_id, 'b': single_id})
|
"value": {'user_id': user_id,
|
||||||
re = {"success": True}
|
'ticket': ticket,
|
||||||
|
'packs': packs,
|
||||||
return re
|
'singles': singles,
|
||||||
|
'characters': characters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_prog_boost(user_id):
|
def get_prog_boost(user_id):
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,8 @@
|
|||||||
import json
|
import json
|
||||||
from server.sql import Connect
|
from server.sql import Connect
|
||||||
|
from setting import Config
|
||||||
|
import server.item
|
||||||
|
import server.character
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
@@ -152,6 +155,7 @@ def play_world_song(user_id, args):
|
|||||||
|
|
||||||
def climb_step(user_id, map_id, step, prev_capture, prev_position):
|
def climb_step(user_id, map_id, step, prev_capture, prev_position):
|
||||||
# 爬梯子,返回奖励列表,台阶列表,当前的位置和坐标,图信息
|
# 爬梯子,返回奖励列表,台阶列表,当前的位置和坐标,图信息
|
||||||
|
|
||||||
info = get_world_info(map_id)
|
info = get_world_info(map_id)
|
||||||
step_count = int(info['step_count'])
|
step_count = int(info['step_count'])
|
||||||
|
|
||||||
@@ -245,3 +249,155 @@ def climb_step(user_id, map_id, step, prev_capture, prev_position):
|
|||||||
steps.append(x)
|
steps.append(x)
|
||||||
|
|
||||||
return rewards, steps, curr_position, curr_capture, info
|
return rewards, steps, curr_position, curr_capture, info
|
||||||
|
|
||||||
|
|
||||||
|
def world_update(c, user_id, song_id, difficulty, rating, clear_type, beyond_gauge, stamina_multiply=1, fragment_multiply=100, prog_boost_multiply=0):
|
||||||
|
# 成绩上传后世界模式更新,返回字典
|
||||||
|
|
||||||
|
step_times = stamina_multiply * fragment_multiply / \
|
||||||
|
100 * (prog_boost_multiply+100)/100
|
||||||
|
exp_times = stamina_multiply * (prog_boost_multiply+100)/100
|
||||||
|
if prog_boost_multiply != 0:
|
||||||
|
c.execute('''update user set prog_boost = 0 where user_id = :a''', {
|
||||||
|
'a': user_id})
|
||||||
|
c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', {
|
||||||
|
'a': user_id, 'b': song_id, 'c': difficulty})
|
||||||
|
|
||||||
|
c.execute('''select character_id from user where user_id=?''', (user_id,))
|
||||||
|
x = c.fetchone()
|
||||||
|
character_id = x[0] if x else 0
|
||||||
|
c.execute('''select frag1,prog1,overdrive1,frag20,prog20,overdrive20,frag30,prog30,overdrive30 from character where character_id=?''', (character_id,))
|
||||||
|
x = c.fetchone()
|
||||||
|
|
||||||
|
if Config.CHARACTER_FULL_UNLOCK:
|
||||||
|
c.execute('''select level, exp from user_char_full where user_id = :a and character_id = :b''', {
|
||||||
|
'a': user_id, 'b': character_id})
|
||||||
|
else:
|
||||||
|
c.execute('''select level, exp from user_char where user_id = :a and character_id = :b''', {
|
||||||
|
'a': user_id, 'b': character_id})
|
||||||
|
y = c.fetchone()
|
||||||
|
if y:
|
||||||
|
level = y[0]
|
||||||
|
exp = y[1]
|
||||||
|
else:
|
||||||
|
level = 1
|
||||||
|
exp = 0
|
||||||
|
|
||||||
|
if x:
|
||||||
|
flag = server.character.calc_char_value(level, x[0], x[3], x[6])
|
||||||
|
prog = server.character.calc_char_value(level, x[1], x[4], x[7])
|
||||||
|
overdrive = server.character.calc_char_value(level, x[2], x[5], x[8])
|
||||||
|
else:
|
||||||
|
flag = 0
|
||||||
|
prog = 0
|
||||||
|
overdrive = 0
|
||||||
|
|
||||||
|
c.execute('''select current_map from user where user_id = :a''', {
|
||||||
|
'a': user_id})
|
||||||
|
map_id = c.fetchone()[0]
|
||||||
|
|
||||||
|
if beyond_gauge == 0: # 是否是beyond挑战
|
||||||
|
base_step = 2.5 + 2.45*rating**0.5
|
||||||
|
step = base_step * (prog/50) * step_times
|
||||||
|
else:
|
||||||
|
info = get_world_info(map_id)
|
||||||
|
if clear_type == 0:
|
||||||
|
base_step = 8/9 + (rating/1.3)**0.5
|
||||||
|
else:
|
||||||
|
base_step = 8/3 + (rating/1.3)**0.5
|
||||||
|
|
||||||
|
if character_id in info['character_affinity']:
|
||||||
|
affinity_multiplier = info['affinity_multiplier'][info['character_affinity'].index(
|
||||||
|
character_id)]
|
||||||
|
else:
|
||||||
|
affinity_multiplier = 1
|
||||||
|
|
||||||
|
step = base_step * (prog/50) * step_times * affinity_multiplier
|
||||||
|
|
||||||
|
c.execute('''select * from user_world where user_id = :a and map_id =:b''',
|
||||||
|
{'a': user_id, 'b': map_id})
|
||||||
|
y = c.fetchone()
|
||||||
|
rewards, steps, curr_position, curr_capture, info = climb_step(
|
||||||
|
user_id, map_id, step, y[3], y[2])
|
||||||
|
for i in rewards: # 物品分发
|
||||||
|
for j in i['items']:
|
||||||
|
amount = j['amount'] if 'amount' in j else 1
|
||||||
|
item_id = j['id'] if 'id' in j else ''
|
||||||
|
server.item.claim_user_item(c, user_id, item_id, j['type'], amount)
|
||||||
|
# 角色升级
|
||||||
|
if not Config.CHARACTER_FULL_UNLOCK:
|
||||||
|
exp, level = server.character.calc_level_up(
|
||||||
|
c, user_id, character_id, exp, exp_times*rating*6)
|
||||||
|
c.execute('''update user_char set level=?, exp=? where user_id=? and character_id=?''',
|
||||||
|
(level, exp, user_id, character_id))
|
||||||
|
else:
|
||||||
|
exp = server.character.LEVEL_STEPS[level]
|
||||||
|
|
||||||
|
if beyond_gauge == 0:
|
||||||
|
re = {
|
||||||
|
"rewards": rewards,
|
||||||
|
"exp": exp,
|
||||||
|
"level": level,
|
||||||
|
"base_progress": base_step,
|
||||||
|
"progress": step,
|
||||||
|
"user_map": {
|
||||||
|
"user_id": user_id,
|
||||||
|
"curr_position": curr_position,
|
||||||
|
"curr_capture": curr_capture,
|
||||||
|
"is_locked": int2b(y[4]),
|
||||||
|
"map_id": map_id,
|
||||||
|
"prev_capture": y[3],
|
||||||
|
"prev_position": y[2],
|
||||||
|
"beyond_health": info['beyond_health'],
|
||||||
|
"steps": steps
|
||||||
|
},
|
||||||
|
"char_stats": {
|
||||||
|
"character_id": character_id,
|
||||||
|
"frag": flag,
|
||||||
|
"prog": prog,
|
||||||
|
"overdrive": overdrive
|
||||||
|
},
|
||||||
|
"current_stamina": 12,
|
||||||
|
"max_stamina_ts": 1586274871917
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
re = {
|
||||||
|
"rewards": rewards,
|
||||||
|
"exp": exp,
|
||||||
|
"level": level,
|
||||||
|
"base_progress": base_step,
|
||||||
|
"progress": step,
|
||||||
|
"user_map": {
|
||||||
|
"user_id": user_id,
|
||||||
|
"curr_position": curr_position,
|
||||||
|
"curr_capture": curr_capture,
|
||||||
|
"is_locked": int2b(y[4]),
|
||||||
|
"map_id": map_id,
|
||||||
|
"prev_capture": y[3],
|
||||||
|
"prev_position": y[2],
|
||||||
|
"beyond_health": info['beyond_health'],
|
||||||
|
"step_count": len(steps)
|
||||||
|
},
|
||||||
|
"char_stats": {
|
||||||
|
"character_id": character_id,
|
||||||
|
"frag": flag,
|
||||||
|
"prog": prog,
|
||||||
|
"overdrive": overdrive
|
||||||
|
},
|
||||||
|
"current_stamina": 12,
|
||||||
|
"max_stamina_ts": 1586274871917
|
||||||
|
}
|
||||||
|
|
||||||
|
if stamina_multiply != 1:
|
||||||
|
re['stamina_multiply'] = stamina_multiply
|
||||||
|
if fragment_multiply != 100:
|
||||||
|
re['fragment_multiply'] = fragment_multiply
|
||||||
|
if prog_boost_multiply != 0:
|
||||||
|
re['prog_boost_multiply'] = prog_boost_multiply
|
||||||
|
|
||||||
|
if curr_position == info['step_count']-1 and info['is_repeatable']: # 循环图判断
|
||||||
|
curr_position = 0
|
||||||
|
c.execute('''update user_world set curr_position=:a, curr_capture=:b where user_id=:c and map_id=:d''', {
|
||||||
|
'a': curr_position, 'b': curr_capture, 'c': user_id, 'd': map_id})
|
||||||
|
|
||||||
|
return re
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
import time
|
import time
|
||||||
import server.arcworld
|
|
||||||
from server.sql import Connect
|
from server.sql import Connect
|
||||||
import functools
|
import functools
|
||||||
from setting import Config
|
from setting import Config
|
||||||
|
from flask import jsonify
|
||||||
|
|
||||||
|
|
||||||
def arc_login(name: str, password: str, device_id: str): # 登录判断
|
def arc_login(name: str, password: str, device_id: str, ip: str): # 登录判断
|
||||||
# 查询数据库中的user表,验证账号密码,返回并记录token,多返回个error code
|
# 查询数据库中的user表,验证账号密码,返回并记录token,多返回个error code
|
||||||
# token采用user_id和时间戳连接后hash生成(真的是瞎想的,没用bear)
|
# token采用user_id和时间戳连接后hash生成(真的是瞎想的,没用bear)
|
||||||
# 密码和token的加密方式为 SHA-256
|
# 密码和token的加密方式为 SHA-256
|
||||||
@@ -43,8 +43,8 @@ def arc_login(name: str, password: str, device_id: str): # 登录判断
|
|||||||
|
|
||||||
if not Config.ALLOW_LOGIN_SAME_DEVICE:
|
if not Config.ALLOW_LOGIN_SAME_DEVICE:
|
||||||
if device_id in device_list: # 对相同设备进行删除
|
if device_id in device_list: # 对相同设备进行删除
|
||||||
c.execute('''delete from login where login_device=:a''', {
|
c.execute('''delete from login where login_device=:a and user_id=:b''', {
|
||||||
'a': device_id})
|
'a': device_id, 'b': user_id})
|
||||||
should_delete_num = len(
|
should_delete_num = len(
|
||||||
device_list) + 1 - device_list.count(device_id) - Config.LOGIN_DEVICE_NUMBER_LIMIT
|
device_list) + 1 - device_list.count(device_id) - Config.LOGIN_DEVICE_NUMBER_LIMIT
|
||||||
|
|
||||||
@@ -52,8 +52,8 @@ def arc_login(name: str, password: str, device_id: str): # 登录判断
|
|||||||
c.execute('''delete from login where rowid in (select rowid from login where user_id=:user_id limit :a);''',
|
c.execute('''delete from login where rowid in (select rowid from login where user_id=:user_id limit :a);''',
|
||||||
{'user_id': user_id, 'a': int(should_delete_num)})
|
{'user_id': user_id, 'a': int(should_delete_num)})
|
||||||
|
|
||||||
c.execute('''insert into login(access_token, user_id, login_device) values(:access_token, :user_id, :device_id)''', {
|
c.execute('''insert into login values(:access_token, :user_id, :time, :ip, :device_id)''', {
|
||||||
'user_id': user_id, 'access_token': token, 'device_id': device_id})
|
'user_id': user_id, 'access_token': token, 'device_id': device_id, 'time': now, 'ip': ip})
|
||||||
error_code = None
|
error_code = None
|
||||||
else:
|
else:
|
||||||
# 密码错误
|
# 密码错误
|
||||||
@@ -65,8 +65,8 @@ def arc_login(name: str, password: str, device_id: str): # 登录判断
|
|||||||
return token, error_code
|
return token, error_code
|
||||||
|
|
||||||
|
|
||||||
def arc_register(name: str, password: str, device_id: str): # 注册
|
def arc_register(name: str, password: str, device_id: str, email: str, ip: str): # 注册
|
||||||
# 账号注册,只记录hash密码和用户名,生成user_id和user_code,自动登录返回token
|
# 账号注册,记录hash密码、用户名和邮箱,生成user_id和user_code,自动登录返回token
|
||||||
# token和密码的处理同登录部分
|
# token和密码的处理同登录部分
|
||||||
|
|
||||||
def build_user_code(c):
|
def build_user_code(c):
|
||||||
@@ -91,13 +91,18 @@ def arc_register(name: str, password: str, device_id: str): # 注册
|
|||||||
return 2000001
|
return 2000001
|
||||||
|
|
||||||
def insert_user_char(c, user_id):
|
def insert_user_char(c, user_id):
|
||||||
# 为用户添加所有可用角色
|
# 为用户添加初始角色
|
||||||
c.execute('''select * from character''')
|
c.execute('''insert into user_char values(?,?,?,?,?,?)''',
|
||||||
|
(user_id, 0, 1, 0, 0, 0))
|
||||||
|
c.execute('''insert into user_char values(?,?,?,?,?,?)''',
|
||||||
|
(user_id, 1, 1, 0, 0, 0))
|
||||||
|
c.execute('''select character_id, max_level, is_uncapped from character''')
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
if x != []:
|
if x:
|
||||||
for i in x:
|
for i in x:
|
||||||
c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', {
|
exp = 25000 if i[1] == 30 else 10000
|
||||||
'a': user_id, 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]})
|
c.execute('''insert into user_char_full values(?,?,?,?,?,?)''',
|
||||||
|
(user_id, i[0], i[1], exp, i[2], 0))
|
||||||
|
|
||||||
user_id = None
|
user_id = None
|
||||||
token = None
|
token = None
|
||||||
@@ -106,24 +111,29 @@ def arc_register(name: str, password: str, device_id: str): # 注册
|
|||||||
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
|
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from user where name = :name)''', {'name': name})
|
'''select exists(select * from user where name = :name)''', {'name': name})
|
||||||
|
if c.fetchone() == (0,):
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from user where email = :email)''', {'email': email})
|
||||||
if c.fetchone() == (0,):
|
if c.fetchone() == (0,):
|
||||||
user_code = build_user_code(c)
|
user_code = build_user_code(c)
|
||||||
user_id = build_user_id(c)
|
user_id = build_user_id(c)
|
||||||
now = int(time.time() * 1000)
|
now = int(time.time() * 1000)
|
||||||
c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt,
|
c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt,
|
||||||
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket)
|
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket, prog_boost, email)
|
||||||
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '', 0)
|
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '', :memories, 0, :email)
|
||||||
''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd})
|
''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd, 'memories': Config.DEFAULT_MEMORIES, 'email': email})
|
||||||
c.execute('''insert into recent30(user_id) values(:user_id)''', {
|
c.execute('''insert into recent30(user_id) values(:user_id)''', {
|
||||||
'user_id': user_id})
|
'user_id': user_id})
|
||||||
|
|
||||||
token = hashlib.sha256(
|
token = hashlib.sha256(
|
||||||
(str(user_id) + str(now)).encode("utf8")).hexdigest()
|
(str(user_id) + str(now)).encode("utf8")).hexdigest()
|
||||||
c.execute('''insert into login(access_token, user_id, login_device) values(:access_token, :user_id, :device_id)''', {
|
c.execute('''insert into login values(:access_token, :user_id, :time, :ip, :device_id)''', {
|
||||||
'user_id': user_id, 'access_token': token, 'device_id': device_id})
|
'user_id': user_id, 'access_token': token, 'device_id': device_id, 'time': now, 'ip': ip})
|
||||||
|
|
||||||
insert_user_char(c, user_id)
|
insert_user_char(c, user_id)
|
||||||
error_code = 0
|
error_code = 0
|
||||||
|
else:
|
||||||
|
error_code = 102
|
||||||
else:
|
else:
|
||||||
error_code = 101
|
error_code = 101
|
||||||
|
|
||||||
@@ -166,8 +176,14 @@ def auth_required(request):
|
|||||||
def wrapped_view(*args, **kwargs):
|
def wrapped_view(*args, **kwargs):
|
||||||
|
|
||||||
user_id = None
|
user_id = None
|
||||||
with Connect() as c:
|
|
||||||
headers = request.headers
|
headers = request.headers
|
||||||
|
|
||||||
|
if 'AppVersion' in headers: # 版本检查
|
||||||
|
if Config.ALLOW_APPVERSION:
|
||||||
|
if headers['AppVersion'] not in Config.ALLOW_APPVERSION:
|
||||||
|
return jsonify({"success": False, "error_code": 5})
|
||||||
|
|
||||||
|
if 'Authorization' in headers:
|
||||||
token = headers['Authorization']
|
token = headers['Authorization']
|
||||||
token = token[7:]
|
token = token[7:]
|
||||||
user_id = token_get_id(token)
|
user_id = token_get_id(token)
|
||||||
@@ -175,7 +191,7 @@ def auth_required(request):
|
|||||||
if user_id is not None:
|
if user_id is not None:
|
||||||
return view(user_id, *args, **kwargs)
|
return view(user_id, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
return '''{"success":false,"error_code":108}'''
|
return jsonify({"success": False, "error_code": 108})
|
||||||
|
|
||||||
return wrapped_view
|
return wrapped_view
|
||||||
return decorator
|
return decorator
|
||||||
|
|||||||
255
latest version/server/character.py
Normal file
255
latest version/server/character.py
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
from setting import Config
|
||||||
|
from server.sql import Connect
|
||||||
|
import server.item
|
||||||
|
import server.setme
|
||||||
|
|
||||||
|
LEVEL_STEPS = {1: 0, 2: 50, 3: 100, 4: 150, 5: 200, 6: 300, 7: 450, 8: 650, 9: 900, 10: 1200, 11: 1600, 12: 2100, 13: 2700, 14: 3400, 15: 4200, 16: 5100,
|
||||||
|
17: 6100, 18: 7200, 19: 8500, 20: 10000, 21: 11500, 22: 13000, 23: 14500, 24: 16000, 25: 17500, 26: 19000, 27: 20500, 28: 22000, 29: 23500, 30: 25000}
|
||||||
|
|
||||||
|
|
||||||
|
def int2b(x):
|
||||||
|
# int与布尔值转换
|
||||||
|
if x is None or x == 0:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_level_steps():
|
||||||
|
# 返回level_steps字典数组
|
||||||
|
return [{'level': i, 'level_exp': LEVEL_STEPS[i]} for i in LEVEL_STEPS]
|
||||||
|
|
||||||
|
|
||||||
|
def calc_char_value(level, value1, value20, value30):
|
||||||
|
# 计算搭档数值的核心函数,返回浮点数
|
||||||
|
|
||||||
|
def calc_char_value_20(level, stata, statb, lva=1, lvb=20):
|
||||||
|
# 计算1~20级搭档数值的核心函数,返回浮点数,来自https://redive.estertion.win/arcaea/calc/
|
||||||
|
|
||||||
|
n = [0, 0, 0.0005831753900000081, 0.004665403120000065, 0.015745735529959858, 0.03732322495992008, 0.07289692374980007, 0.12596588423968, 0.2000291587694801, 0.29858579967923987, 0.42513485930893946,
|
||||||
|
0.5748651406910605, 0.7014142003207574, 0.7999708412305152, 0.8740341157603029, 0.9271030762501818, 0.962676775040091, 0.9842542644700301, 0.9953345968799998, 0.9994168246100001, 1]
|
||||||
|
e = n[lva] - n[lvb]
|
||||||
|
a = stata - statb
|
||||||
|
r = a / e
|
||||||
|
d = stata - n[lva] * r
|
||||||
|
|
||||||
|
return d + r * n[level]
|
||||||
|
|
||||||
|
def calc_char_value_30(level, stata, statb, lva=20, lvb=30):
|
||||||
|
# 计算21~30级搭档数值,返回浮点数
|
||||||
|
|
||||||
|
return (level - lva) * (statb - stata) / (lvb - lva) + stata
|
||||||
|
|
||||||
|
if level < 1 or level > 30:
|
||||||
|
return 0
|
||||||
|
elif 1 <= level <= 20:
|
||||||
|
return calc_char_value_20(level, value1, value20)
|
||||||
|
else:
|
||||||
|
return calc_char_value_30(level, value20, value30)
|
||||||
|
|
||||||
|
|
||||||
|
def get_char_core(c, character_id):
|
||||||
|
# 得到对应角色觉醒所需的核心,返回字典列表
|
||||||
|
r = []
|
||||||
|
c.execute(
|
||||||
|
'''select item_id, amount from char_item where character_id = ? and type="core"''', (character_id,))
|
||||||
|
x = c.fetchall()
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
r.append({'core_type': i[0], 'amount': i[1]})
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_characters(c, user_id):
|
||||||
|
# 获取用户所拥有角色,返回列表
|
||||||
|
|
||||||
|
c.execute('''select character_id from user_char where user_id = :user_id''',
|
||||||
|
{'user_id': user_id})
|
||||||
|
|
||||||
|
x = c.fetchall()
|
||||||
|
characters = []
|
||||||
|
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
characters.append(i[0])
|
||||||
|
|
||||||
|
return characters
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_character(c, user_id):
|
||||||
|
# 得到用户拥有的角色列表,返回列表
|
||||||
|
|
||||||
|
if Config.CHARACTER_FULL_UNLOCK:
|
||||||
|
c.execute('''select * from user_char_full a,character b where a.user_id = :user_id and a.character_id=b.character_id''',
|
||||||
|
{'user_id': user_id})
|
||||||
|
else:
|
||||||
|
c.execute('''select * from user_char a,character b where a.user_id = :user_id and a.character_id=b.character_id''',
|
||||||
|
{'user_id': user_id})
|
||||||
|
x = c.fetchall()
|
||||||
|
if not x and not Config.CHARACTER_FULL_UNLOCK:
|
||||||
|
# 添加初始角色
|
||||||
|
c.execute('''insert into user_char values(?,?,?,?,?,?)''',
|
||||||
|
(user_id, 0, 1, 0, 0, 0))
|
||||||
|
c.execute('''insert into user_char values(?,?,?,?,?,?)''',
|
||||||
|
(user_id, 1, 1, 0, 0, 0))
|
||||||
|
c.execute('''select * from user_char a,character b where a.user_id = :user_id and a.character_id=b.character_id''',
|
||||||
|
{'user_id': user_id})
|
||||||
|
x = c.fetchall()
|
||||||
|
|
||||||
|
if not x:
|
||||||
|
return []
|
||||||
|
r = []
|
||||||
|
for i in x:
|
||||||
|
|
||||||
|
char = {
|
||||||
|
"is_uncapped_override": int2b(i[5]),
|
||||||
|
"is_uncapped": int2b(i[4]),
|
||||||
|
"uncap_cores": get_char_core(c, i[1]),
|
||||||
|
"char_type": i[22],
|
||||||
|
"skill_id_uncap": i[21],
|
||||||
|
"skill_requires_uncap": int2b(i[20]),
|
||||||
|
"skill_unlock_level": i[19],
|
||||||
|
"skill_id": i[18],
|
||||||
|
"overdrive": calc_char_value(i[2], i[11], i[14], i[17]),
|
||||||
|
"prog": calc_char_value(i[2], i[10], i[13], i[16]),
|
||||||
|
"frag": calc_char_value(i[2], i[9], i[12], i[15]),
|
||||||
|
"level_exp": LEVEL_STEPS[i[2]],
|
||||||
|
"exp": i[3],
|
||||||
|
"level": i[2],
|
||||||
|
"name": i[7],
|
||||||
|
"character_id": i[1]
|
||||||
|
}
|
||||||
|
if i[1] == 21:
|
||||||
|
char["voice"] = [0, 1, 2, 3, 100, 1000, 1001]
|
||||||
|
r.append(char)
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def get_one_character(c, user_id, character_id):
|
||||||
|
# 得到用户某个拥有的角色列表,返回字典
|
||||||
|
|
||||||
|
if Config.CHARACTER_FULL_UNLOCK:
|
||||||
|
c.execute('''select * from user_char_full a,character b where a.user_id = :user_id and a.character_id=b.character_id and a.character_id=:a''',
|
||||||
|
{'user_id': user_id, 'a': character_id})
|
||||||
|
else:
|
||||||
|
c.execute('''select * from user_char a,character b where a.user_id = :user_id and a.character_id=b.character_id and a.character_id=:a''',
|
||||||
|
{'user_id': user_id, 'a': character_id})
|
||||||
|
x = c.fetchone()
|
||||||
|
if not x:
|
||||||
|
return {}
|
||||||
|
r = {
|
||||||
|
"is_uncapped_override": int2b(x[5]),
|
||||||
|
"is_uncapped": int2b(x[4]),
|
||||||
|
"uncap_cores": get_char_core(c, x[1]),
|
||||||
|
"char_type": x[22],
|
||||||
|
"skill_id_uncap": x[21],
|
||||||
|
"skill_requires_uncap": int2b(x[20]),
|
||||||
|
"skill_unlock_level": x[19],
|
||||||
|
"skill_id": x[18],
|
||||||
|
"overdrive": calc_char_value(x[2], x[11], x[14], x[17]),
|
||||||
|
"prog": calc_char_value(x[2], x[10], x[13], x[16]),
|
||||||
|
"frag": calc_char_value(x[2], x[9], x[12], x[15]),
|
||||||
|
"level_exp": LEVEL_STEPS[x[2]],
|
||||||
|
"exp": x[3],
|
||||||
|
"level": x[2],
|
||||||
|
"name": x[7],
|
||||||
|
"character_id": x[1]
|
||||||
|
}
|
||||||
|
if x[1] == 21:
|
||||||
|
r["voice"] = [0, 1, 2, 3, 100, 1000, 1001]
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def calc_level_up(c, user_id, character_id, exp, exp_addition):
|
||||||
|
# 计算角色升级,返回当前经验和等级
|
||||||
|
|
||||||
|
exp += exp_addition
|
||||||
|
|
||||||
|
if exp >= LEVEL_STEPS[20]: # 未觉醒溢出
|
||||||
|
c.execute('''select is_uncapped from user_char where user_id=? and character_id=?''',
|
||||||
|
(user_id, character_id))
|
||||||
|
x = c.fetchone()
|
||||||
|
if x and x[0] == 0:
|
||||||
|
return LEVEL_STEPS[20], 20
|
||||||
|
|
||||||
|
a = []
|
||||||
|
b = []
|
||||||
|
for i in LEVEL_STEPS:
|
||||||
|
a.append(i)
|
||||||
|
b.append(LEVEL_STEPS[i])
|
||||||
|
|
||||||
|
if exp >= b[-1]: # 溢出
|
||||||
|
return b[-1], a[-1]
|
||||||
|
|
||||||
|
if exp < b[0]: # 向下溢出,是异常状态
|
||||||
|
return 0, 1
|
||||||
|
|
||||||
|
i = len(a) - 1
|
||||||
|
while exp < b[i]:
|
||||||
|
i -= 1
|
||||||
|
|
||||||
|
return exp, a[i]
|
||||||
|
|
||||||
|
|
||||||
|
def char_use_core(user_id, character_id, amount):
|
||||||
|
# 以太之滴升级,返回user_id,core状态,角色状态的字典
|
||||||
|
r = None
|
||||||
|
with Connect() as c:
|
||||||
|
|
||||||
|
c.execute(
|
||||||
|
'''select amount from user_item where user_id=? and item_id="core_generic" and type="core"''', (user_id,))
|
||||||
|
x = c.fetchone()
|
||||||
|
if x:
|
||||||
|
pre_amount = x[0]
|
||||||
|
else:
|
||||||
|
pre_amount = 0
|
||||||
|
|
||||||
|
if amount <= pre_amount:
|
||||||
|
c.execute(
|
||||||
|
'''select exp from user_char where user_id=? and character_id=?''', (user_id, character_id))
|
||||||
|
x = c.fetchone()
|
||||||
|
if x:
|
||||||
|
exp, level = calc_level_up(
|
||||||
|
c, user_id, character_id, x[0], amount*250)
|
||||||
|
c.execute('''update user_char set level=?, exp=? where user_id=? and character_id=?''',
|
||||||
|
(level, exp, user_id, character_id))
|
||||||
|
server.item.claim_user_item(
|
||||||
|
c, user_id, 'core_generic', 'core', -amount)
|
||||||
|
|
||||||
|
r = {'character': [get_one_character(c, user_id, character_id)]}
|
||||||
|
r['cores'] = server.item.get_user_cores(c, user_id)
|
||||||
|
r['user_id'] = user_id
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def char_uncap(user_id, character_id):
|
||||||
|
# 角色觉醒,返回user_id,core状态,角色状态的字典
|
||||||
|
r = None
|
||||||
|
with Connect() as c:
|
||||||
|
c.execute('''select * from char_item where character_id=?''',
|
||||||
|
(character_id,))
|
||||||
|
x = c.fetchall()
|
||||||
|
if not x:
|
||||||
|
return None
|
||||||
|
|
||||||
|
success = True
|
||||||
|
for i in x:
|
||||||
|
c.execute(
|
||||||
|
'''select amount from user_item where user_id=? and item_id=? and type=?''', (user_id, i[1], i[2]))
|
||||||
|
y = c.fetchone()
|
||||||
|
if not y or i[3] > y[0]:
|
||||||
|
success = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if success:
|
||||||
|
for i in x:
|
||||||
|
server.item.claim_user_item(c, user_id, i[1], i[2], -i[3])
|
||||||
|
c.execute('''update user_char set is_uncapped=1, is_uncapped_override=0 where user_id=? and character_id=?''',
|
||||||
|
(user_id, character_id))
|
||||||
|
|
||||||
|
r = {'character': [get_one_character(c, user_id, character_id)]}
|
||||||
|
r['cores'] = server.item.get_user_cores(c, user_id)
|
||||||
|
r['user_id'] = user_id
|
||||||
|
return r
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
from server.sql import Connect
|
from server.sql import Connect
|
||||||
import server.arcworld
|
import server.arcworld
|
||||||
import server.arcpurchase
|
import server.arcpurchase
|
||||||
|
import server.arcdownload
|
||||||
|
import server.character
|
||||||
|
import server.item
|
||||||
import time
|
import time
|
||||||
|
from setting import Config
|
||||||
|
|
||||||
|
|
||||||
def int2b(x):
|
def int2b(x):
|
||||||
@@ -44,47 +48,6 @@ def get_recent_score(c, user_id):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def get_user_character(c, user_id):
|
|
||||||
# 得到用户拥有的角色列表,返回列表
|
|
||||||
c.execute('''select * from user_char where user_id = :user_id''',
|
|
||||||
{'user_id': user_id})
|
|
||||||
x = c.fetchall()
|
|
||||||
if x != []:
|
|
||||||
s = []
|
|
||||||
for i in x:
|
|
||||||
char_name = ''
|
|
||||||
c.execute(
|
|
||||||
'''select name from character where character_id = :x''', {'x': i[1]})
|
|
||||||
y = c.fetchone()
|
|
||||||
if y is not None:
|
|
||||||
char_name = y[0]
|
|
||||||
char = {
|
|
||||||
"is_uncapped_override": int2b(i[14]),
|
|
||||||
"is_uncapped": int2b(i[13]),
|
|
||||||
"uncap_cores": [],
|
|
||||||
"char_type": i[12],
|
|
||||||
"skill_id_uncap": i[11],
|
|
||||||
"skill_requires_uncap": int2b(i[10]),
|
|
||||||
"skill_unlock_level": i[9],
|
|
||||||
"skill_id": i[8],
|
|
||||||
"overdrive": i[7],
|
|
||||||
"prog": i[6],
|
|
||||||
"frag": i[5],
|
|
||||||
"level_exp": i[4],
|
|
||||||
"exp": i[3],
|
|
||||||
"level": i[2],
|
|
||||||
"name": char_name,
|
|
||||||
"character_id": i[1]
|
|
||||||
}
|
|
||||||
if i[1] == 21:
|
|
||||||
char["voice"] = [0, 1, 2, 3, 100, 1000, 1001]
|
|
||||||
s.append(char)
|
|
||||||
|
|
||||||
return s
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_friend(c, user_id):
|
def get_user_friend(c, user_id):
|
||||||
# 得到用户的朋友列表,返回列表
|
# 得到用户的朋友列表,返回列表
|
||||||
c.execute('''select user_id_other from friend where user_id_me = :user_id''', {
|
c.execute('''select user_id_other from friend where user_id_me = :user_id''', {
|
||||||
@@ -109,19 +72,27 @@ def get_user_friend(c, user_id):
|
|||||||
is_char_uncapped_override = int2b(y[9])
|
is_char_uncapped_override = int2b(y[9])
|
||||||
if y[23] != -1:
|
if y[23] != -1:
|
||||||
character = y[23]
|
character = y[23]
|
||||||
|
if not Config.CHARACTER_FULL_UNLOCK:
|
||||||
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id=:a and character_id=:b''', {
|
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id=:a and character_id=:b''', {
|
||||||
'a': i[0], 'b': character})
|
'a': i[0], 'b': character})
|
||||||
|
else:
|
||||||
|
c.execute('''select is_uncapped, is_uncapped_override from user_char_full where user_id=:a and character_id=:b''', {
|
||||||
|
'a': i[0], 'b': character})
|
||||||
z = c.fetchone()
|
z = c.fetchone()
|
||||||
if z:
|
if z:
|
||||||
is_char_uncapped = int2b(z[0])
|
is_char_uncapped = int2b(z[0])
|
||||||
is_char_uncapped_override = int2b(z[1])
|
is_char_uncapped_override = int2b(z[1])
|
||||||
|
|
||||||
|
rating = y[5]
|
||||||
|
if int2b(y[10]):
|
||||||
|
rating = -1
|
||||||
|
|
||||||
s.append({
|
s.append({
|
||||||
"is_mutual": is_mutual,
|
"is_mutual": is_mutual,
|
||||||
"is_char_uncapped_override": is_char_uncapped_override,
|
"is_char_uncapped_override": is_char_uncapped_override,
|
||||||
"is_char_uncapped": is_char_uncapped,
|
"is_char_uncapped": is_char_uncapped,
|
||||||
"is_skill_sealed": int2b(y[7]),
|
"is_skill_sealed": int2b(y[7]),
|
||||||
"rating": y[5],
|
"rating": rating,
|
||||||
"join_date": int(y[3]),
|
"join_date": int(y[3]),
|
||||||
"character": character,
|
"character": character,
|
||||||
"recent_score": get_recent_score(c, i[0]),
|
"recent_score": get_recent_score(c, i[0]),
|
||||||
@@ -132,54 +103,54 @@ def get_user_friend(c, user_id):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
def get_user_singles(c, user_id):
|
def get_user_me(c, user_id):
|
||||||
# 得到用户的单曲,返回列表
|
# 构造user/me的数据,返回字典
|
||||||
c.execute('''select * from user_item where user_id = :user_id and type = "single"''',
|
|
||||||
{'user_id': user_id})
|
|
||||||
x = c.fetchall()
|
|
||||||
if not x:
|
|
||||||
return []
|
|
||||||
|
|
||||||
re = []
|
|
||||||
for i in x:
|
|
||||||
re.append(i[1])
|
|
||||||
return re
|
|
||||||
|
|
||||||
|
|
||||||
def get_user_packs(c, user_id):
|
|
||||||
# 得到用户的曲包,返回列表
|
|
||||||
c.execute('''select * from user_item where user_id = :user_id and type = "pack"''',
|
|
||||||
{'user_id': user_id})
|
|
||||||
x = c.fetchall()
|
|
||||||
if not x:
|
|
||||||
return []
|
|
||||||
|
|
||||||
re = []
|
|
||||||
for i in x:
|
|
||||||
re.append(i[1])
|
|
||||||
return re
|
|
||||||
|
|
||||||
|
|
||||||
def get_value_0(c, user_id):
|
|
||||||
# 构造value id=0的数据,返回字典
|
|
||||||
c.execute('''select * from user where user_id = :x''', {'x': user_id})
|
c.execute('''select * from user where user_id = :x''', {'x': user_id})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
r = {}
|
r = {}
|
||||||
if x is not None:
|
if x is not None:
|
||||||
user_character = get_user_character(c, user_id)
|
user_character = server.character.get_user_character(c, user_id)
|
||||||
|
# 下面没有使用get_user_characters函数是为了节省一次查询
|
||||||
characters = []
|
characters = []
|
||||||
for i in user_character:
|
for i in user_character:
|
||||||
characters.append(i['character_id'])
|
characters.append(i['character_id'])
|
||||||
|
|
||||||
|
character_id = x[6]
|
||||||
|
if character_id not in characters:
|
||||||
|
character_id = 0
|
||||||
|
c.execute(
|
||||||
|
'''update user set character_id=0 where user_id=?''', (user_id,))
|
||||||
|
|
||||||
|
favorite_character_id = x[23]
|
||||||
|
if favorite_character_id not in characters:
|
||||||
|
favorite_character_id = -1
|
||||||
|
c.execute(
|
||||||
|
'''update user set favorite_character=-1 where user_id=?''', (user_id,))
|
||||||
|
|
||||||
|
c.execute(
|
||||||
|
'''select world_rank_score from user where user_id=?''', (user_id,))
|
||||||
|
y = c.fetchone()
|
||||||
|
if y and y[0]:
|
||||||
|
c.execute(
|
||||||
|
'''select count(*) from user where world_rank_score > ?''', (y[0],))
|
||||||
|
y = c.fetchone()
|
||||||
|
if y and y[0] + 1 <= Config.WORLD_RANK_MAX:
|
||||||
|
world_rank = y[0] + 1
|
||||||
|
else:
|
||||||
|
world_rank = 0
|
||||||
|
else:
|
||||||
|
world_rank = 0
|
||||||
|
|
||||||
prog_boost = 0
|
prog_boost = 0
|
||||||
if x[27] and x[27] != 0:
|
if x[27] and x[27] != 0:
|
||||||
prog_boost = 300
|
prog_boost = 300
|
||||||
|
|
||||||
r = {"is_aprilfools": False,
|
r = {"is_aprilfools": Config.IS_APRILFOOLS,
|
||||||
"curr_available_maps": [],
|
"curr_available_maps": [],
|
||||||
"character_stats": user_character,
|
"character_stats": user_character,
|
||||||
"friends": get_user_friend(c, user_id),
|
"friends": get_user_friend(c, user_id),
|
||||||
"settings": {
|
"settings": {
|
||||||
"favorite_character": x[23],
|
"favorite_character": favorite_character_id,
|
||||||
"is_hide_rating": int2b(x[10]),
|
"is_hide_rating": int2b(x[10]),
|
||||||
"max_stamina_notification_enabled": int2b(x[24])
|
"max_stamina_notification_enabled": int2b(x[24])
|
||||||
},
|
},
|
||||||
@@ -188,7 +159,7 @@ def get_value_0(c, user_id):
|
|||||||
"user_code": x[4],
|
"user_code": x[4],
|
||||||
"display_name": x[1],
|
"display_name": x[1],
|
||||||
"ticket": x[26],
|
"ticket": x[26],
|
||||||
"character": x[6],
|
"character": character_id,
|
||||||
"is_locked_name_duplicate": False,
|
"is_locked_name_duplicate": False,
|
||||||
"is_skill_sealed": int2b(x[7]),
|
"is_skill_sealed": int2b(x[7]),
|
||||||
"current_map": x[25],
|
"current_map": x[25],
|
||||||
@@ -196,17 +167,17 @@ def get_value_0(c, user_id):
|
|||||||
"next_fragstam_ts": -1,
|
"next_fragstam_ts": -1,
|
||||||
"max_stamina_ts": 1586274871917,
|
"max_stamina_ts": 1586274871917,
|
||||||
"stamina": 12,
|
"stamina": 12,
|
||||||
"world_unlocks": ["scenery_chap1", "scenery_chap2", "scenery_chap3", "scenery_chap4", "scenery_chap5"],
|
"world_unlocks": server.item.get_user_items(c, user_id, 'world_unlock'),
|
||||||
"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"],
|
"world_songs": server.item.get_user_items(c, user_id, 'world_song'),
|
||||||
"singles": get_user_singles(c, user_id), # ["dataerror", "yourvoiceso", "crosssoul", "impurebird", "auxesia", "modelista", "yozakurafubuki", "surrender", "metallicpunisher", "carminescythe", "bethere", "callmyname", "fallensquare", "dropdead", "alexandrite", "astraltale", "phantasia", "empireofwinter", "libertas", "dottodot", "dreadnought", "mirzam", "heavenlycaress", "filament", "avantraze", "battlenoone", "saikyostronger", "izana", "einherjar", "laqryma", "amygdata", "altale", "feelssoright", "scarletcage", "teriqma", "mahoroba", "badtek", "maliciousmischance", "buchigireberserker", "galaxyfriends", "xeraphinite", "xanatos"]
|
"singles": server.item.get_user_items(c, user_id, 'single'),
|
||||||
"packs": get_user_packs(c, user_id),
|
"packs": server.item.get_user_items(c, user_id, 'pack'),
|
||||||
# ["vs", "extend", "dynamix", "prelude", "core", "yugamu", "omatsuri", "zettai", "mirai", "shiawase", "chunithm", "nijuusei", "groovecoaster", "rei", "tonesphere", "lanota"]
|
|
||||||
"characters": characters,
|
"characters": characters,
|
||||||
"cores": [],
|
"cores": server.item.get_user_cores(c, user_id),
|
||||||
"recent_score": get_recent_score(c, user_id),
|
"recent_score": get_recent_score(c, user_id),
|
||||||
"max_friend": 50,
|
"max_friend": 50,
|
||||||
"rating": x[5],
|
"rating": x[5],
|
||||||
"join_date": int(x[3])
|
"join_date": int(x[3]),
|
||||||
|
"global_rank": world_rank
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
@@ -219,26 +190,33 @@ def arc_aggregate_small(user_id):
|
|||||||
r = {"success": True,
|
r = {"success": True,
|
||||||
"value": [{
|
"value": [{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
"value": get_value_0(c, user_id)
|
"value": get_user_me(c, user_id)
|
||||||
}]}
|
}]}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def arc_aggregate_big(user_id):
|
def arc_aggregate_big(user_id):
|
||||||
# 返回用户数据和地图歌曲信息
|
# 返回比较全的用户数据
|
||||||
r = {"success": False}
|
r = {"success": False}
|
||||||
with Connect() as c:
|
with Connect() as c:
|
||||||
|
# 防止数据库锁
|
||||||
|
id_2 = server.arcdownload.get_all_songs(user_id, url_flag=False)
|
||||||
|
id_5 = {
|
||||||
|
"current_map": server.arcworld.get_current_map(user_id),
|
||||||
|
"user_id": user_id,
|
||||||
|
"maps": server.arcworld.get_world_all(user_id)
|
||||||
|
}
|
||||||
r = {"success": True,
|
r = {"success": True,
|
||||||
"value": [{
|
"value": [{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
"value": get_value_0(c, user_id)
|
"value": get_user_me(c, user_id)
|
||||||
}, {
|
}, {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"value": server.arcpurchase.get_item(c, 'pack')
|
"value": server.arcpurchase.get_purchase(c, 'pack')
|
||||||
}, {
|
}, {
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"value": {}
|
"value": id_2
|
||||||
}, {
|
}, {
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"value": {
|
"value": {
|
||||||
@@ -246,97 +224,7 @@ def arc_aggregate_big(user_id):
|
|||||||
"stamina_recover_tick": 1800000,
|
"stamina_recover_tick": 1800000,
|
||||||
"core_exp": 250,
|
"core_exp": 250,
|
||||||
"curr_ts": int(time.time())*1000,
|
"curr_ts": int(time.time())*1000,
|
||||||
"level_steps": [{
|
"level_steps": server.character.get_level_steps(),
|
||||||
"level": 1,
|
|
||||||
"level_exp": 0
|
|
||||||
}, {
|
|
||||||
"level": 2,
|
|
||||||
"level_exp": 50
|
|
||||||
}, {
|
|
||||||
"level": 3,
|
|
||||||
"level_exp": 100
|
|
||||||
}, {
|
|
||||||
"level": 4,
|
|
||||||
"level_exp": 150
|
|
||||||
}, {
|
|
||||||
"level": 5,
|
|
||||||
"level_exp": 200
|
|
||||||
}, {
|
|
||||||
"level": 6,
|
|
||||||
"level_exp": 300
|
|
||||||
}, {
|
|
||||||
"level": 7,
|
|
||||||
"level_exp": 450
|
|
||||||
}, {
|
|
||||||
"level": 8,
|
|
||||||
"level_exp": 650
|
|
||||||
}, {
|
|
||||||
"level": 9,
|
|
||||||
"level_exp": 900
|
|
||||||
}, {
|
|
||||||
"level": 10,
|
|
||||||
"level_exp": 1200
|
|
||||||
}, {
|
|
||||||
"level": 11,
|
|
||||||
"level_exp": 1600
|
|
||||||
}, {
|
|
||||||
"level": 12,
|
|
||||||
"level_exp": 2100
|
|
||||||
}, {
|
|
||||||
"level": 13,
|
|
||||||
"level_exp": 2700
|
|
||||||
}, {
|
|
||||||
"level": 14,
|
|
||||||
"level_exp": 3400
|
|
||||||
}, {
|
|
||||||
"level": 15,
|
|
||||||
"level_exp": 4200
|
|
||||||
}, {
|
|
||||||
"level": 16,
|
|
||||||
"level_exp": 5100
|
|
||||||
}, {
|
|
||||||
"level": 17,
|
|
||||||
"level_exp": 6100
|
|
||||||
}, {
|
|
||||||
"level": 18,
|
|
||||||
"level_exp": 7200
|
|
||||||
}, {
|
|
||||||
"level": 19,
|
|
||||||
"level_exp": 8500
|
|
||||||
}, {
|
|
||||||
"level": 20,
|
|
||||||
"level_exp": 10000
|
|
||||||
}, {
|
|
||||||
"level": 21,
|
|
||||||
"level_exp": 11500
|
|
||||||
}, {
|
|
||||||
"level": 22,
|
|
||||||
"level_exp": 13000
|
|
||||||
}, {
|
|
||||||
"level": 23,
|
|
||||||
"level_exp": 14500
|
|
||||||
}, {
|
|
||||||
"level": 24,
|
|
||||||
"level_exp": 16000
|
|
||||||
}, {
|
|
||||||
"level": 25,
|
|
||||||
"level_exp": 17500
|
|
||||||
}, {
|
|
||||||
"level": 26,
|
|
||||||
"level_exp": 19000
|
|
||||||
}, {
|
|
||||||
"level": 27,
|
|
||||||
"level_exp": 20500
|
|
||||||
}, {
|
|
||||||
"level": 28,
|
|
||||||
"level_exp": 22000
|
|
||||||
}, {
|
|
||||||
"level": 29,
|
|
||||||
"level_exp": 23500
|
|
||||||
}, {
|
|
||||||
"level": 30,
|
|
||||||
"level_exp": 25000
|
|
||||||
}],
|
|
||||||
"world_ranking_enabled": False,
|
"world_ranking_enabled": False,
|
||||||
"is_byd_chapter_unlocked": True
|
"is_byd_chapter_unlocked": True
|
||||||
}
|
}
|
||||||
@@ -345,11 +233,7 @@ def arc_aggregate_big(user_id):
|
|||||||
"value": server.arcpurchase.get_user_present(c, user_id)
|
"value": server.arcpurchase.get_user_present(c, user_id)
|
||||||
}, {
|
}, {
|
||||||
"id": 5,
|
"id": 5,
|
||||||
"value": {
|
"value": id_5
|
||||||
"current_map": server.arcworld.get_current_map(user_id),
|
|
||||||
"user_id": user_id,
|
|
||||||
"maps": server.arcworld.get_world_all(user_id)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
|
|
||||||
|
|||||||
98
latest version/server/init.py
Normal file
98
latest version/server/init.py
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import os
|
||||||
|
from shutil import copy, copy2
|
||||||
|
from server.sql import Connect
|
||||||
|
from database.database_initialize import main, ARCAEA_SERVER_VERSION
|
||||||
|
from web.system import update_database
|
||||||
|
|
||||||
|
|
||||||
|
def try_rename(path, new_path):
|
||||||
|
# 尝试重命名文件,并尝试避免命名冲突,返回最终路径
|
||||||
|
final_path = new_path
|
||||||
|
if os.path.exists(new_path):
|
||||||
|
i = 1
|
||||||
|
while os.path.exists(new_path + str(i)):
|
||||||
|
i += 1
|
||||||
|
os.rename(path, new_path + str(i))
|
||||||
|
final_path = new_path + str(i)
|
||||||
|
else:
|
||||||
|
os.rename(path, new_path)
|
||||||
|
|
||||||
|
return final_path
|
||||||
|
|
||||||
|
|
||||||
|
def check_before_run(app):
|
||||||
|
# 运行前检查关键文件,返回布尔值,其实是因为有人经常忘了
|
||||||
|
|
||||||
|
f = True
|
||||||
|
|
||||||
|
if not os.path.exists('setting.py'):
|
||||||
|
app.logger.warning('File `setting.py` is missing.')
|
||||||
|
f = False
|
||||||
|
|
||||||
|
if not os.path.exists('database'):
|
||||||
|
app.logger.warning('Folder `database` is missing.')
|
||||||
|
f = False
|
||||||
|
|
||||||
|
if not os.path.exists('database/songs'):
|
||||||
|
app.logger.warning('Folder `database/songs` is missing.')
|
||||||
|
f = False
|
||||||
|
|
||||||
|
if not os.path.exists('database/arcaea_database.db'):
|
||||||
|
app.logger.warning('File `database/arcaea_database.db` is missing.')
|
||||||
|
f = False
|
||||||
|
try:
|
||||||
|
app.logger.info(
|
||||||
|
'Try to new the file `database/arcaea_database.db`.')
|
||||||
|
main('./database/')
|
||||||
|
app.logger.info(
|
||||||
|
'Success to new the file `database/arcaea_database.db`.')
|
||||||
|
f = True
|
||||||
|
except:
|
||||||
|
app.logger.warning(
|
||||||
|
'Fail to new the file `database/arcaea_database.db`.')
|
||||||
|
|
||||||
|
else:
|
||||||
|
with Connect() as c:
|
||||||
|
try:
|
||||||
|
c.execute('''select value from config where id="version"''')
|
||||||
|
x = c.fetchone()
|
||||||
|
except:
|
||||||
|
x = None
|
||||||
|
|
||||||
|
# 数据库自动更新,不强求
|
||||||
|
if not x or x[0] != ARCAEA_SERVER_VERSION:
|
||||||
|
app.logger.warning(
|
||||||
|
'Maybe the file `database/arcaea_database.db` is an old version.')
|
||||||
|
try:
|
||||||
|
app.logger.info(
|
||||||
|
'Try to update the file `database/arcaea_database.db`.')
|
||||||
|
|
||||||
|
path = try_rename('database/arcaea_database.db',
|
||||||
|
'database/arcaea_database.db.bak')
|
||||||
|
|
||||||
|
try:
|
||||||
|
copy2(path, 'database/arcaea_database.db')
|
||||||
|
except:
|
||||||
|
copy(path, 'database/arcaea_database.db')
|
||||||
|
|
||||||
|
if os.path.isfile("database/old_arcaea_database.db"):
|
||||||
|
os.remove('database/old_arcaea_database.db')
|
||||||
|
|
||||||
|
try_rename('database/arcaea_database.db',
|
||||||
|
'database/old_arcaea_database.db')
|
||||||
|
|
||||||
|
main('./database/')
|
||||||
|
update_database()
|
||||||
|
|
||||||
|
app.logger.info(
|
||||||
|
'Success to update the file `database/arcaea_database.db`.')
|
||||||
|
|
||||||
|
except:
|
||||||
|
app.logger.warning(
|
||||||
|
'Fail to update the file `database/arcaea_database.db`.')
|
||||||
|
|
||||||
|
if not os.path.exists('database/arcsong.db'):
|
||||||
|
app.logger.warning('File `database/arcsong.db` is missing.')
|
||||||
|
f = False
|
||||||
|
|
||||||
|
return f
|
||||||
106
latest version/server/item.py
Normal file
106
latest version/server/item.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
from setting import Config
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_items(c, user_id, item_type):
|
||||||
|
# 得到用户的物品,返回列表,不包含数量信息
|
||||||
|
|
||||||
|
if item_type == 'world_song' and Config.WORLD_SONG_FULL_UNLOCK or item_type == 'world_unlock' and Config.WORLD_SCENERY_FULL_UNLOCK:
|
||||||
|
c.execute('''select item_id from item where type=?''', (item_type,))
|
||||||
|
else:
|
||||||
|
c.execute('''select item_id from user_item where user_id = :user_id and type = :item_type''',
|
||||||
|
{'user_id': user_id, 'item_type': item_type})
|
||||||
|
x = c.fetchall()
|
||||||
|
if not x:
|
||||||
|
return []
|
||||||
|
|
||||||
|
re = []
|
||||||
|
for i in x:
|
||||||
|
re.append(i[0])
|
||||||
|
return re
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_cores(c, user_id):
|
||||||
|
# 得到用户的core,返回字典列表
|
||||||
|
r = []
|
||||||
|
c.execute(
|
||||||
|
'''select item_id, amount from user_item where user_id = ? and type="core"''', (user_id,))
|
||||||
|
x = c.fetchall()
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
if i[1]:
|
||||||
|
amount = i[1]
|
||||||
|
else:
|
||||||
|
amount = 0
|
||||||
|
r.append({'core_type': i[0], 'amount': amount})
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def claim_user_item(c, user_id, item_id, item_type, amount=1):
|
||||||
|
# 处理用户物品,包括添加和删除操作,返回成功与否布尔值
|
||||||
|
# 这个接口允许memory变成负数,所以不能用来购买
|
||||||
|
|
||||||
|
try:
|
||||||
|
amount = int(amount)
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if item_type not in ['memory', 'character']:
|
||||||
|
c.execute('''select is_available from item where item_id=? and type=?''',
|
||||||
|
(item_id, item_type))
|
||||||
|
x = c.fetchone()
|
||||||
|
if x:
|
||||||
|
if x[0] == 0:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if item_type == 'core':
|
||||||
|
c.execute(
|
||||||
|
'''select amount from user_item where user_id=? and item_id=? and type="core"''', (user_id, item_id))
|
||||||
|
x = c.fetchone()
|
||||||
|
if x:
|
||||||
|
if x[0] + amount < 0: # 数量不足
|
||||||
|
return False
|
||||||
|
c.execute('''update user_item set amount=? where user_id=? and item_id=? and type="core"''',
|
||||||
|
(x[0]+amount, user_id, item_id))
|
||||||
|
else:
|
||||||
|
if amount < 0: # 添加数量错误
|
||||||
|
return False
|
||||||
|
c.execute('''insert into user_item values(?,?,"core",?)''',
|
||||||
|
(user_id, item_id, amount))
|
||||||
|
|
||||||
|
elif item_type == 'memory':
|
||||||
|
c.execute('''select ticket from user where user_id=?''', (user_id,))
|
||||||
|
x = c.fetchone()
|
||||||
|
if x is not None:
|
||||||
|
c.execute('''update user set ticket=? where user_id=?''',
|
||||||
|
(x[0]+amount, user_id))
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
elif item_type == 'character':
|
||||||
|
if not item_id.isdigit():
|
||||||
|
c.execute(
|
||||||
|
'''select character_id from character where name=?''', (item_id,))
|
||||||
|
x = c.fetchone()
|
||||||
|
if x:
|
||||||
|
character_id = x[0]
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
character_id = int(item_id)
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from user_char where user_id=? and character_id=?)''', (user_id, character_id))
|
||||||
|
if c.fetchone() == (0,):
|
||||||
|
c.execute('''insert into user_char values(?,?,1,0,0,0)''',
|
||||||
|
(user_id, character_id))
|
||||||
|
|
||||||
|
elif item_type in ['world_song', 'world_unlock', 'single', 'pack']:
|
||||||
|
c.execute('''select exists(select * from user_item where user_id=? and item_id=? and type=?)''',
|
||||||
|
(user_id, item_id, item_type))
|
||||||
|
if c.fetchone() == (0,):
|
||||||
|
c.execute('''insert into user_item values(:a,:b,:c,1)''',
|
||||||
|
{'a': user_id, 'b': item_id, 'c': item_type})
|
||||||
|
|
||||||
|
return True
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
from server.sql import Connect
|
from server.sql import Connect
|
||||||
|
from setting import Config
|
||||||
import server.info
|
import server.info
|
||||||
|
import server.character
|
||||||
|
|
||||||
|
|
||||||
def b2int(x):
|
def b2int(x):
|
||||||
@@ -23,16 +25,25 @@ def change_char(user_id, character_id, skill_sealed):
|
|||||||
re = False
|
re = False
|
||||||
|
|
||||||
with Connect() as c:
|
with Connect() as c:
|
||||||
|
if Config.CHARACTER_FULL_UNLOCK:
|
||||||
|
c.execute('''select is_uncapped, is_uncapped_override from user_char_full where user_id = :a and character_id = :b''',
|
||||||
|
{'a': user_id, 'b': character_id})
|
||||||
|
else:
|
||||||
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
|
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
|
||||||
{'a': user_id, 'b': character_id})
|
{'a': user_id, 'b': character_id})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
if x is not None:
|
if x:
|
||||||
|
is_uncapped = x[0]
|
||||||
|
is_uncapped_override = x[1]
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
if skill_sealed == 'false':
|
if skill_sealed == 'false':
|
||||||
skill_sealed = False
|
skill_sealed = False
|
||||||
else:
|
else:
|
||||||
skill_sealed = True
|
skill_sealed = True
|
||||||
c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', {
|
c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', {
|
||||||
'a': b2int(skill_sealed), 'b': character_id, 'c': x[0], 'd': x[1], 'e': user_id})
|
'a': b2int(skill_sealed), 'b': character_id, 'c': is_uncapped, 'd': is_uncapped_override, 'e': user_id})
|
||||||
|
|
||||||
re = True
|
re = True
|
||||||
|
|
||||||
@@ -43,40 +54,46 @@ def change_char_uncap(user_id, character_id):
|
|||||||
# 角色觉醒改变,返回字典
|
# 角色觉醒改变,返回字典
|
||||||
r = None
|
r = None
|
||||||
with Connect() as c:
|
with Connect() as c:
|
||||||
|
if not Config.CHARACTER_FULL_UNLOCK:
|
||||||
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
|
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
|
||||||
{'a': user_id, 'b': character_id})
|
{'a': user_id, 'b': character_id})
|
||||||
|
else:
|
||||||
|
c.execute('''select is_uncapped, is_uncapped_override from user_char_full where user_id = :a and character_id = :b''',
|
||||||
|
{'a': user_id, 'b': character_id})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
|
|
||||||
if x is not None and x[0] == 1:
|
if x is not None and x[0] == 1:
|
||||||
c.execute('''update user set is_char_uncapped_override = :a where user_id = :b''', {
|
c.execute('''update user set is_char_uncapped_override = :a where user_id = :b''', {
|
||||||
'a': b2int(x[1] == 0), 'b': user_id})
|
'a': b2int(x[1] == 0), 'b': user_id})
|
||||||
|
|
||||||
|
if not Config.CHARACTER_FULL_UNLOCK:
|
||||||
c.execute('''update user_char set is_uncapped_override = :a where user_id = :b and character_id = :c''', {
|
c.execute('''update user_char set is_uncapped_override = :a where user_id = :b and character_id = :c''', {
|
||||||
'a': b2int(x[1] == 0), 'b': user_id, 'c': character_id})
|
'a': b2int(x[1] == 0), 'b': user_id, 'c': character_id})
|
||||||
c.execute('''select * from user_char where user_id = :a and character_id = :b''',
|
|
||||||
{'a': user_id, 'b': character_id})
|
|
||||||
y = c.fetchone()
|
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select name from character where character_id = :x''', {'x': y[1]})
|
'''select * from user_char a,character b where a.user_id=? and a.character_id=b.character_id and a.character_id=?''', (user_id, character_id))
|
||||||
z = c.fetchone()
|
else:
|
||||||
if z is not None:
|
c.execute('''update user_char_full set is_uncapped_override = :a where user_id = :b and character_id = :c''', {
|
||||||
char_name = z[0]
|
'a': b2int(x[1] == 0), 'b': user_id, 'c': character_id})
|
||||||
|
c.execute(
|
||||||
|
'''select * from user_char_full a,character b where a.user_id=? and a.character_id=b.character_id and a.character_id=?''', (user_id, character_id))
|
||||||
|
y = c.fetchone()
|
||||||
if y is not None:
|
if y is not None:
|
||||||
r = {
|
r = {
|
||||||
"is_uncapped_override": int2b(y[14]),
|
"is_uncapped_override": int2b(y[5]),
|
||||||
"is_uncapped": int2b(y[13]),
|
"is_uncapped": int2b(y[4]),
|
||||||
"uncap_cores": [],
|
"uncap_cores": server.character.get_char_core(c, y[1]),
|
||||||
"char_type": y[12],
|
"char_type": y[22],
|
||||||
"skill_id_uncap": y[11],
|
"skill_id_uncap": y[21],
|
||||||
"skill_requires_uncap": int2b(y[10]),
|
"skill_requires_uncap": int2b(y[20]),
|
||||||
"skill_unlock_level": y[9],
|
"skill_unlock_level": y[19],
|
||||||
"skill_id": y[8],
|
"skill_id": y[18],
|
||||||
"overdrive": y[7],
|
"overdrive": server.character.calc_char_value(y[2], y[11], y[14], y[17]),
|
||||||
"prog": y[6],
|
"prog": server.character.calc_char_value(y[2], y[10], y[13], y[16]),
|
||||||
"frag": y[5],
|
"frag": server.character.calc_char_value(y[2], y[9], y[12], y[15]),
|
||||||
"level_exp": y[4],
|
"level_exp": server.character.LEVEL_STEPS[y[2]],
|
||||||
"exp": y[3],
|
"exp": y[3],
|
||||||
"level": y[2],
|
"level": y[2],
|
||||||
"name": char_name,
|
"name": y[7],
|
||||||
"character_id": y[1]
|
"character_id": y[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
|
from flask import current_app
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
class Connect():
|
class Connect():
|
||||||
@@ -22,4 +24,57 @@ class Connect():
|
|||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
self.conn.close()
|
self.conn.close()
|
||||||
|
|
||||||
|
if exc_type is not None:
|
||||||
|
current_app.logger.error(
|
||||||
|
traceback.format_exception(exc_type, exc_val, exc_tb))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
class Sql():
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def select(c, table_name, target_column=[], limit=-1, offset=0, query={}, sort=[]):
|
||||||
|
# 执行查询单句sql语句,返回fetchall数据
|
||||||
|
# 使用准确查询,且在单表内
|
||||||
|
|
||||||
|
sql = 'select '
|
||||||
|
sql_dict = {}
|
||||||
|
if len(target_column) >= 2:
|
||||||
|
sql += target_column[0]
|
||||||
|
for i in range(1, len(target_column)):
|
||||||
|
sql += ',' + target_column[i]
|
||||||
|
sql += ' from ' + table_name
|
||||||
|
elif len(target_column) == 1:
|
||||||
|
sql += target_column[0] + ' from ' + table_name
|
||||||
|
else:
|
||||||
|
sql += '* from ' + table_name
|
||||||
|
|
||||||
|
where_field = []
|
||||||
|
where_value = []
|
||||||
|
for i in query:
|
||||||
|
where_field.append(i)
|
||||||
|
where_value.append(query[i])
|
||||||
|
|
||||||
|
if where_field and where_value:
|
||||||
|
sql += ' where '
|
||||||
|
sql += where_field[0] + '=:' + where_field[0]
|
||||||
|
sql_dict[where_field[0]] = where_value[0]
|
||||||
|
if len(where_field) >= 2:
|
||||||
|
for i in range(1, len(where_field)):
|
||||||
|
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 limit >= 0:
|
||||||
|
sql += ' limit :limit offset :offset'
|
||||||
|
sql_dict['limit'] = limit
|
||||||
|
sql_dict['offset'] = offset
|
||||||
|
|
||||||
|
c.execute(sql, sql_dict)
|
||||||
|
|
||||||
|
return c.fetchall()
|
||||||
|
|||||||
@@ -14,6 +14,60 @@ class Config():
|
|||||||
--------------------
|
--------------------
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
游戏API地址前缀
|
||||||
|
Game API's URL prefix
|
||||||
|
'''
|
||||||
|
GAME_API_PREFIX = '/blockchain/14'
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
允许使用的游戏版本,若为空,则默认全部允许
|
||||||
|
Allowed game versions
|
||||||
|
If it is blank, all are allowed.
|
||||||
|
'''
|
||||||
|
ALLOW_APPVERSION = ['3.5.3', '3.5.3c', '3.6.2', '3.6.2c']
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
SSL证书路径
|
||||||
|
留空则使用HTTP
|
||||||
|
SSL certificate path
|
||||||
|
If left blank, use HTTP.
|
||||||
|
'''
|
||||||
|
SSL_CERT = '' # *.pem
|
||||||
|
SSL_KEY = '' # *.key
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
愚人节模式开关
|
||||||
|
Switch of April Fool's Day
|
||||||
|
'''
|
||||||
|
IS_APRILFOOLS = True
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
世界排名的最大显示数量
|
||||||
|
The largest number of global rank
|
||||||
|
'''
|
||||||
|
WORLD_RANK_MAX = 200
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
'''
|
'''
|
||||||
--------------------
|
--------------------
|
||||||
Web后台管理页面的用户名和密码
|
Web后台管理页面的用户名和密码
|
||||||
@@ -38,8 +92,30 @@ class Config():
|
|||||||
|
|
||||||
'''
|
'''
|
||||||
--------------------
|
--------------------
|
||||||
玩家歌曲下载的24小时次数限制
|
API接口完全控制权限Token,留空则不使用
|
||||||
Player's song download limit times in 24 hours
|
API interface full control permission Token
|
||||||
|
If you don't want to use it, leave it blank.
|
||||||
|
'''
|
||||||
|
API_TOKEN = ''
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
歌曲下载地址前缀,留空则自动获取
|
||||||
|
Song download address prefix
|
||||||
|
If left blank, it will be obtained automatically.
|
||||||
|
'''
|
||||||
|
DOWNLOAD_LINK_PREFIX = '' # http://***.com/download/
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
玩家歌曲下载的24小时次数限制,每个文件算一次
|
||||||
|
Player's song download limit times in 24 hours, once per file
|
||||||
'''
|
'''
|
||||||
DOWNLOAD_TIMES_LIMIT = 3000
|
DOWNLOAD_TIMES_LIMIT = 3000
|
||||||
'''
|
'''
|
||||||
@@ -59,9 +135,69 @@ class Config():
|
|||||||
LOGIN_DEVICE_NUMBER_LIMIT = 1
|
LOGIN_DEVICE_NUMBER_LIMIT = 1
|
||||||
'''
|
'''
|
||||||
是否允许同设备多应用共存登录
|
是否允许同设备多应用共存登录
|
||||||
If multiple applications on the same device to log in is allowed
|
If logging in from multiple applications on the same device is allowed
|
||||||
'''
|
'''
|
||||||
ALLOW_LOGIN_SAME_DEVICE = False
|
ALLOW_LOGIN_SAME_DEVICE = False
|
||||||
'''
|
'''
|
||||||
--------------------
|
--------------------
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
是否记录详细的服务器日志
|
||||||
|
If recording detailed server logs is enabled
|
||||||
|
'''
|
||||||
|
ALLOW_LOG_INFO = False
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
用户注册时的默认记忆源点数量
|
||||||
|
The default amount of memories at the time of user registration
|
||||||
|
'''
|
||||||
|
DEFAULT_MEMORIES = 0
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
是否全解锁搭档
|
||||||
|
If unlocking all partners is enabled
|
||||||
|
'''
|
||||||
|
CHARACTER_FULL_UNLOCK = True
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
是否全解锁世界歌曲
|
||||||
|
If unlocking all world songs is enabled
|
||||||
|
'''
|
||||||
|
WORLD_SONG_FULL_UNLOCK = True
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
是否全解锁世界场景
|
||||||
|
If unlocking all world scenerys is enabled
|
||||||
|
'''
|
||||||
|
WORLD_SCENERY_FULL_UNLOCK = True
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
是否强制使用全解锁云端存档
|
||||||
|
If forcing full unlocked cloud save is enabled
|
||||||
|
'''
|
||||||
|
SAVE_FULL_UNLOCK = False
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|||||||
@@ -20,4 +20,4 @@
|
|||||||
{% endfor %} {% block content %}{% endblock %}
|
{% endfor %} {% block content %}{% endblock %}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<footer id="footer" class="footer">Made by Lost@2020</footer>
|
<footer id="footer" class="footer">Made by Lost@2020-2021</footer>
|
||||||
@@ -16,26 +16,54 @@
|
|||||||
<span class="char-name">{{char['name']}}</span>
|
<span class="char-name">{{char['name']}}</span>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span>Level: </span>
|
<span>Max level: </span>
|
||||||
<span class="char-num">{{char['level']}}</span>
|
<span class="char-num">{{char['max_level']}}</span>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span>Frag: </span>
|
<span>Frag-level 1: </span>
|
||||||
<span class="char-num">{{char['frag']}}</span>
|
<span class="char-num">{{char['frag1']}}</span>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span>Prog: </span>
|
<span>Prog-level 1: </span>
|
||||||
<span class="char-num">{{char['prog']}}</span>
|
<span class="char-num">{{char['prog1']}}</span>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span>Overdrive: </span>
|
<span>Overdrive-level 1: </span>
|
||||||
<span class="char-num">{{char['overdrive']}}</span>
|
<span class="char-num">{{char['overdrive1']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Frag-level 20: </span>
|
||||||
|
<span class="char-num">{{char['frag20']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Prog-level 20: </span>
|
||||||
|
<span class="char-num">{{char['prog20']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Overdrive-level 20: </span>
|
||||||
|
<span class="char-num">{{char['overdrive20']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Frag-level 30: </span>
|
||||||
|
<span class="char-num">{{char['frag30']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Prog-level 30: </span>
|
||||||
|
<span class="char-num">{{char['prog30']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Overdrive-level 30: </span>
|
||||||
|
<span class="char-num">{{char['overdrive30']}}</span>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span>Skill id: </span>
|
<span>Skill id: </span>
|
||||||
<span class="char-num">{{char['skill_id']}}</span>
|
<span class="char-num">{{char['skill_id']}}</span>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
<span>Skill unlock level: </span>
|
||||||
|
<span class="char-num">{{char['skill_unlock_level']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
<span>Uncapped skill id: </span>
|
<span>Uncapped skill id: </span>
|
||||||
<span class="char-num">{{char['skill_id_uncap']}}</span>
|
<span class="char-num">{{char['skill_id_uncap']}}</span>
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -20,24 +20,6 @@
|
|||||||
<span class="char-num">{{item['is_available']}}</span>
|
<span class="char-num">{{item['is_available']}}</span>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<span>Price: </span>
|
|
||||||
<span class="char-num">{{item['price']}}</span>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<span>Original price: </span>
|
|
||||||
<span class="char-num">{{item['orig_price']}}</span>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<span>Discount from: </span>
|
|
||||||
<span class="char-num">{{item['discount_from']}}</span>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
<span>Discount to: </span>
|
|
||||||
<span class="char-num">{{item['discount_to']}}</span>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% if not loop.last %}
|
{% if not loop.last %}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@
|
|||||||
<div class="name">{{user['name']}}
|
<div class="name">{{user['name']}}
|
||||||
<span class="rank">UID: {{user['user_id']}}</span>
|
<span class="rank">UID: {{user['user_id']}}</span>
|
||||||
<span class="rank">User code: {{user['user_code']}}</span>
|
<span class="rank">User code: {{user['user_code']}}</span>
|
||||||
|
{% if user['ban_flag'] %}
|
||||||
|
<span class="rank">Banned</span>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
|
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
|
||||||
<div class="ptt">PTT: {{'%0.2f'|format(user['rating_ptt']/100|float)}}</div>
|
<div class="ptt">PTT: {{'%0.2f'|format(user['rating_ptt']/100|float)}}</div>
|
||||||
|
|||||||
57
latest version/templates/web/allpurchase.html
Normal file
57
latest version/templates/web/allpurchase.html
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}All items{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if posts %}<br />
|
||||||
|
{% for item in posts %}
|
||||||
|
|
||||||
|
<div class="char-item">
|
||||||
|
<span>Name: </span>
|
||||||
|
<span class="name">{{item['purchase_name']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Price: </span>
|
||||||
|
<span class="char-num">{{item['price']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Original price: </span>
|
||||||
|
<span class="char-num">{{item['orig_price']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Discount from: </span>
|
||||||
|
<span class="char-num">{{item['discount_from']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Discount to: </span>
|
||||||
|
<span class="char-num">{{item['discount_to']}}</span>
|
||||||
|
<br />
|
||||||
|
{% if item['items'] %}<br />
|
||||||
|
{% for x in item['items'] %}
|
||||||
|
<span>Item id: </span>
|
||||||
|
<span class="char-num">{{x['item_id']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Item type: </span>
|
||||||
|
<span class="char-num">{{x['type']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% if not loop.last %}
|
||||||
|
<br />
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% if not loop.last %}
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
<br />
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
@@ -12,15 +12,6 @@
|
|||||||
<label for="level">Level</label>
|
<label for="level">Level</label>
|
||||||
<input name="level" id="level">
|
<input name="level" id="level">
|
||||||
|
|
||||||
<label for="frag">Frag</label>
|
|
||||||
<input name="frag" id="frag">
|
|
||||||
|
|
||||||
<label for="prog">Prog</label>
|
|
||||||
<input name="prog" id="prog">
|
|
||||||
|
|
||||||
<label for="overdrive">Overdrive</label>
|
|
||||||
<input name="overdrive" id="overdrive">
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<select name="skill_id">
|
<select name="skill_id">
|
||||||
<option value="">Skill id</option>
|
<option value="">Skill id</option>
|
||||||
|
|||||||
@@ -5,37 +5,43 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<form action="/web/changeitem" method="post">
|
<form action="/web/changeitem" method="post">
|
||||||
<div class="title">Change the item</div>
|
<div class="title">Add the item</div>
|
||||||
<label for="item_id">ID of the item</label>
|
<label for="item_id">ID of the item</label>
|
||||||
<input name="item_id" id="item_id" required>
|
<input name="item_id" id="item_id" required>
|
||||||
<label for="type">Type</label>
|
<label for="type">Type</label>
|
||||||
<div>
|
<div>
|
||||||
<select name="type">
|
<select name="type">
|
||||||
<option value='single'>Single</option>
|
<option value='single' selected>Single</option>
|
||||||
<option value='pack'>Pack</option>
|
<option value='pack'>Pack</option>
|
||||||
|
<option value='world_song'>World song</option>
|
||||||
|
<option value='character'>Character</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<div class="content">可修改项 Modifiable items:</div>
|
|
||||||
<div><label for="is_available">是否可用 Is available:</label>
|
<div><label for="is_available">是否可用 Is available:</label>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<label><input type="radio" name="is_available" value=1>True</label>
|
<label><input type="radio" name="is_available" checked value=1>True</label>
|
||||||
<br />
|
<br />
|
||||||
<label><input type="radio" name="is_available" value=0>False</label>
|
<label><input type="radio" name="is_available" value=0>False</label>
|
||||||
</div>
|
</div>
|
||||||
<label for="price">Price</label>
|
<br />
|
||||||
<input name="price" id="price">
|
<input type="submit" value="Add">
|
||||||
<label for="orig_price">Original price</label>
|
</form>
|
||||||
<input name="orig_price" id="orig_price">
|
<form action="/web/changeitem/delete" method="post">
|
||||||
<label for="discount_from">Discount from</label>
|
<div class="title">Delete the item</div>
|
||||||
<input type="datetime-local" name="discount_from" id="discount_from">
|
<label for="item_id">ID of the item</label>
|
||||||
<label for="discount_to">Discount to</label>
|
<input name="item_id" id="item_id" required>
|
||||||
<input type="datetime-local" name="discount_to" id="discount_to">
|
<label for="type">Type</label>
|
||||||
<div class="content">如果某些不需要修改,留空即可</div>
|
<div>
|
||||||
<div class="content">If some things do not need to be modified, leave it blank.</div>
|
<select name="type">
|
||||||
<div class="content">时间填写是一个HTML5控件</div>
|
<option value='single' selected>Single</option>
|
||||||
<div class="content">Time filling is an HTML5 control.</div>
|
<option value='pack'>Pack</option>
|
||||||
<input type="submit" value="Edit">
|
<option value='world_song'>World song</option>
|
||||||
|
<option value='character'>Character</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<input type="submit" value="Delete">
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
32
latest version/templates/web/changepurchase.html
Normal file
32
latest version/templates/web/changepurchase.html
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}Change the purchases{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form action="/web/changepurchase" method="post">
|
||||||
|
<div class="title">Add the purchase</div>
|
||||||
|
<label for="purchase_name">Purchase name</label>
|
||||||
|
<input name="purchase_name" id="purchase_name" required>
|
||||||
|
<label for="price">Price</label>
|
||||||
|
<input name="price" id="price">
|
||||||
|
<label for="orig_price">Original price</label>
|
||||||
|
<input name="orig_price" id="orig_price">
|
||||||
|
<label for="discount_from">Discount from</label>
|
||||||
|
<input type="datetime-local" name="discount_from" id="discount_from">
|
||||||
|
<label for="discount_to">Discount to</label>
|
||||||
|
<input type="datetime-local" name="discount_to" id="discount_to">
|
||||||
|
<div class="content">时间填写是一个HTML5控件</div>
|
||||||
|
<div class="content">Time filling is an HTML5 control.</div>
|
||||||
|
<br />
|
||||||
|
<input type="submit" value="Add">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form action="/web/changepurchase/delete" method="post">
|
||||||
|
<div class="title">Delete the purchase</div>
|
||||||
|
<label for="purchase_name">Purchase name</label>
|
||||||
|
<input name="purchase_name" id="purchase_name" required>
|
||||||
|
<br />
|
||||||
|
<input type="submit" value="Delete">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
44
latest version/templates/web/changepurchaseitem.html
Normal file
44
latest version/templates/web/changepurchaseitem.html
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}Change the purchase's items{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form action="/web/changepurchaseitem" method="post">
|
||||||
|
<div class="title">Add the purchase's item</div>
|
||||||
|
<label for="purchase_name">Purchase name</label>
|
||||||
|
<input name="purchase_name" id="purchase_name" required>
|
||||||
|
<label for="item_id">ID of the item</label>
|
||||||
|
<input name="item_id" id="item_id" required>
|
||||||
|
<label for="type">Type</label>
|
||||||
|
<div>
|
||||||
|
<select name="type">
|
||||||
|
<option value='single' selected>Single</option>
|
||||||
|
<option value='pack'>Pack</option>
|
||||||
|
<option value='world_song'>World song</option>
|
||||||
|
<option value='character'>Character</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<input type="submit" value="Add">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form action="/web/changepurchaseitem/delete" method="post">
|
||||||
|
<div class="title">Delete the purchase's item</div>
|
||||||
|
<label for="purchase_name">Purchase name</label>
|
||||||
|
<input name="purchase_name" id="purchase_name" required>
|
||||||
|
<label for="item_id">ID of the item</label>
|
||||||
|
<input name="item_id" id="item_id" required>
|
||||||
|
<label for="type">Type</label>
|
||||||
|
<div>
|
||||||
|
<select name="type">
|
||||||
|
<option value='single' selected>Single</option>
|
||||||
|
<option value='pack'>Pack</option>
|
||||||
|
<option value='world_song'>World song</option>
|
||||||
|
<option value='character'>Character</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<input type="submit" value="Delete">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
38
latest version/templates/web/changescore.html
Normal file
38
latest version/templates/web/changescore.html
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}Change the scores{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form action="/web/changescore/delete" method="post">
|
||||||
|
<div class="title">Delete the scores</div>
|
||||||
|
<label for="sid">SID of the song</label>
|
||||||
|
<input name="sid" id="sid">
|
||||||
|
|
||||||
|
<label for="difficulty">Difficulty</label>
|
||||||
|
<select name='difficulty' id='difficulty'>
|
||||||
|
<option value="-1" selected>All</option>
|
||||||
|
<option value="0">Past</option>
|
||||||
|
<option value="1">Present</option>
|
||||||
|
<option value="2">Future</option>
|
||||||
|
<option value="3">Beyond</option>
|
||||||
|
</select>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="name">Arcaea Username</label>
|
||||||
|
<input name="name" id="name">
|
||||||
|
or<br />
|
||||||
|
<label for="user_code">Arcaea User Code</label>
|
||||||
|
<input name="user_code" id="user_code">
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<div class="content">上述三项是查询参数,如果留空,则被认为是全部,都不填则认为是错误的。</div>
|
||||||
|
<div class="content">The above three are query parameters. If they are left blank, they are considered all. However,
|
||||||
|
if you don't fill in all of them, it's wrong.</div>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<input type="submit" value="Delete">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<input name="rating_ftr" id="rating_ftr" required>
|
<input name="rating_ftr" id="rating_ftr" required>
|
||||||
<label for="rating_byd">Beyond chart const</label>
|
<label for="rating_byd">Beyond chart const</label>
|
||||||
<input name="rating_byd" id="rating_byd" required>
|
<input name="rating_byd" id="rating_byd" required>
|
||||||
<div class="content">如果没有某个铺面,应该填入-1。</div>
|
<div class="content">如果没有某个谱面,应该填入-1。</div>
|
||||||
<div class="content">If there is no some chart, fill in -1 please.</div>
|
<div class="content">If there is no some chart, fill in -1 please.</div>
|
||||||
<input type="submit" value="Add">
|
<input type="submit" value="Add">
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -13,9 +13,10 @@
|
|||||||
<a href="{{ url_for('index.single_player_score') }}">单个玩家成绩查询 Single player score</a></br></br>
|
<a href="{{ url_for('index.single_player_score') }}">单个玩家成绩查询 Single player score</a></br></br>
|
||||||
<a href="{{ url_for('index.single_player_ptt') }}">单个玩家PTT详情查询 Single player ptt</a></br></br>
|
<a href="{{ url_for('index.single_player_ptt') }}">单个玩家PTT详情查询 Single player ptt</a></br></br>
|
||||||
<a href="{{ url_for('index.all_player') }}">所有玩家信息查询 All players</a></br></br>
|
<a href="{{ url_for('index.all_player') }}">所有玩家信息查询 All players</a></br></br>
|
||||||
<a href="{{ url_for('index.all_song') }}">铺面信息查询 All songs</a></br></br>
|
<a href="{{ url_for('index.all_song') }}">谱面信息查询 All songs</a></br></br>
|
||||||
<a href="{{ url_for('index.all_character') }}">角色信息查询 All characters</a></br></br>
|
<a href="{{ url_for('index.all_character') }}">角色信息查询 All characters</a></br></br>
|
||||||
<a href="{{ url_for('index.all_item') }}">购买信息查询 All items</a></br></br>
|
<a href="{{ url_for('index.all_item') }}">物品信息查询 All items</a></br></br>
|
||||||
|
<a href="{{ url_for('index.all_purchase') }}">购买信息查询 All purchases</a></br></br>
|
||||||
<a href="{{ url_for('index.all_present') }}">奖励信息查询 All presents</a></br></br>
|
<a href="{{ url_for('index.all_present') }}">奖励信息查询 All presents</a></br></br>
|
||||||
<a href="{{ url_for('index.all_redeem') }}">兑换码信息查询 All redeem codes</a></br></br>
|
<a href="{{ url_for('index.all_redeem') }}">兑换码信息查询 All redeem codes</a></br></br>
|
||||||
<a href="{{ url_for('index.single_chart_top') }}">单个铺面排行榜查询 Single song chart tops</a>
|
<a href="{{ url_for('index.single_chart_top') }}">单个铺面排行榜查询 Single song chart tops</a>
|
||||||
@@ -24,10 +25,13 @@
|
|||||||
<a href="{{ url_for('index.update_database') }}">数据库更新 Update databases</a></br></br>
|
<a href="{{ url_for('index.update_database') }}">数据库更新 Update databases</a></br></br>
|
||||||
<a href="{{ url_for('index.edit_userpwd') }}">用户密码修改 Change user password</a></br></br>
|
<a href="{{ url_for('index.edit_userpwd') }}">用户密码修改 Change user password</a></br></br>
|
||||||
<a href="{{ url_for('index.ban_user') }}">封禁用户 Ban the user</a></br></br>
|
<a href="{{ url_for('index.ban_user') }}">封禁用户 Ban the user</a></br></br>
|
||||||
|
<a href="{{ url_for('index.change_score') }}">成绩删除 Delete the scores</a></br></br>
|
||||||
<a href="{{ url_for('index.update_user_save') }}">用户存档更新 Update user saves</a></br></br>
|
<a href="{{ url_for('index.update_user_save') }}">用户存档更新 Update user saves</a></br></br>
|
||||||
<a href="{{ url_for('index.change_song') }}">歌曲修改 Change the songs</a></br></br>
|
<a href="{{ url_for('index.change_song') }}">歌曲修改 Change the songs</a></br></br>
|
||||||
<a href="{{ url_for('index.change_character') }}">角色修改 Change the characters</a></br></br>
|
<a href="{{ url_for('index.change_character') }}">角色修改 Change the characters</a></br></br>
|
||||||
<a href="{{ url_for('index.change_item') }}">购买信息修改 Change the items</a></br></br>
|
<a href="{{ url_for('index.change_item') }}">物品信息修改 Change the items</a></br></br>
|
||||||
|
<a href="{{ url_for('index.change_purchase') }}">购买信息修改 Change the purchases</a></br></br>
|
||||||
|
<a href="{{ url_for('index.change_purchase_item') }}">购买信息的物品修改 Change the purchase items</a></br></br>
|
||||||
<a href="{{ url_for('index.change_user') }}">用户信息修改 Change user information</a></br></br>
|
<a href="{{ url_for('index.change_user') }}">用户信息修改 Change user information</a></br></br>
|
||||||
<a href="{{ url_for('index.change_user_purchase') }}">用户购买信息修改 Change user purchase information</a></br></br>
|
<a href="{{ url_for('index.change_user_purchase') }}">用户购买信息修改 Change user purchase information</a></br></br>
|
||||||
<a href="{{ url_for('index.change_present') }}">奖励修改 Change the presents</a></br></br>
|
<a href="{{ url_for('index.change_present') }}">奖励修改 Change the presents</a></br></br>
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
<div class="name">{{user['name']}}
|
<div class="name">{{user['name']}}
|
||||||
<span class="rank">UID: {{user['user_id']}}</span>
|
<span class="rank">UID: {{user['user_id']}}</span>
|
||||||
<span class="rank">User code: {{user['user_code']}}</span>
|
<span class="rank">User code: {{user['user_code']}}</span>
|
||||||
|
{% if user['ban_flag'] %}
|
||||||
|
<span class="rank">Banned</span>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
|
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
|
||||||
<div class="ptt">Memories: {{user['ticket']}}</div>
|
<div class="ptt">Memories: {{user['ticket']}}</div>
|
||||||
|
|||||||
@@ -18,4 +18,26 @@
|
|||||||
Uploadable files: arcaea_database.db & arcsong.db<br />
|
Uploadable files: arcaea_database.db & arcsong.db<br />
|
||||||
Data that does not exist in the new database will be added and the existing duplicate data will also be changed.
|
Data that does not exist in the new database will be added and the existing duplicate data will also be changed.
|
||||||
</div>
|
</div>
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
<form action="/web/updatedatabase/refreshsonghash" method="post">
|
||||||
|
<div class="title">Refresh songs' hash</div>
|
||||||
|
<br />
|
||||||
|
<input type="submit" value="Refresh">
|
||||||
|
|
||||||
|
<div class="content">这里可以刷新储存在数据库中的songs文件夹下所有文件的Hash值。目的是应对歌曲谱面文件的更新。</div>
|
||||||
|
<div class="content">Here you can refresh the hash values of all the files stored in the songs folder in the
|
||||||
|
database. The purpose is to deal with the updating of songs' files.</div>
|
||||||
|
</form>
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
<form action="/web/updatedatabase/refreshsongrating" method="post">
|
||||||
|
<div class="title">Refresh songs' rating</div>
|
||||||
|
<br />
|
||||||
|
<input type="submit" value="Refresh">
|
||||||
|
|
||||||
|
<div class="content">这里可以刷新数据库中所有成绩的评分。目的是应对歌曲谱面定数的更新。</div>
|
||||||
|
<div class="content">Here you can refresh the ratings of all scores in the database. The purpose is to deal
|
||||||
|
with the updating of songs' chart consts.</div>
|
||||||
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -10,6 +10,7 @@ import time
|
|||||||
import server.arcscore
|
import server.arcscore
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
from server.arcdownload import initialize_songfile
|
||||||
|
|
||||||
UPLOAD_FOLDER = 'database'
|
UPLOAD_FOLDER = 'database'
|
||||||
ALLOWED_EXTENSIONS = {'db'}
|
ALLOWED_EXTENSIONS = {'db'}
|
||||||
@@ -138,6 +139,11 @@ def all_player():
|
|||||||
if i[20]:
|
if i[20]:
|
||||||
time_played = time.strftime('%Y-%m-%d %H:%M:%S',
|
time_played = time.strftime('%Y-%m-%d %H:%M:%S',
|
||||||
time.localtime(int(i[20])//1000))
|
time.localtime(int(i[20])//1000))
|
||||||
|
if i[2] == '':
|
||||||
|
ban_flag = True
|
||||||
|
else:
|
||||||
|
ban_flag = False
|
||||||
|
|
||||||
posts.append({'name': i[1],
|
posts.append({'name': i[1],
|
||||||
'user_id': i[0],
|
'user_id': i[0],
|
||||||
'join_date': join_date,
|
'join_date': join_date,
|
||||||
@@ -153,7 +159,8 @@ def all_player():
|
|||||||
'time_played': time_played,
|
'time_played': time_played,
|
||||||
'clear_type': i[21],
|
'clear_type': i[21],
|
||||||
'rating': i[22],
|
'rating': i[22],
|
||||||
'ticket': i[26]
|
'ticket': i[26],
|
||||||
|
'ban_flag': ban_flag
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
error = '没有玩家数据 No player data.'
|
error = '没有玩家数据 No player data.'
|
||||||
@@ -185,10 +192,10 @@ def all_song():
|
|||||||
for i in x:
|
for i in x:
|
||||||
posts.append({'song_id': i[0],
|
posts.append({'song_id': i[0],
|
||||||
'name_en': i[1],
|
'name_en': i[1],
|
||||||
'rating_pst': defnum(i[12]),
|
'rating_pst': defnum(i[13]),
|
||||||
'rating_prs': defnum(i[13]),
|
'rating_prs': defnum(i[14]),
|
||||||
'rating_ftr': defnum(i[14]),
|
'rating_ftr': defnum(i[15]),
|
||||||
'rating_byn': defnum(i[15])
|
'rating_byn': defnum(i[16])
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
error = '没有铺面数据 No song data.'
|
error = '没有铺面数据 No song data.'
|
||||||
@@ -271,6 +278,30 @@ def update_database():
|
|||||||
return render_template('web/updatedatabase.html')
|
return render_template('web/updatedatabase.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/updatedatabase/refreshsonghash', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def update_song_hash():
|
||||||
|
# 更新数据库内谱面文件hash值
|
||||||
|
error = initialize_songfile()
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
else:
|
||||||
|
flash('数据刷新成功 Success refresh data.')
|
||||||
|
return render_template('web/updatedatabase.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/updatedatabase/refreshsongrating', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def update_song_rating():
|
||||||
|
# 更新所有分数的rating
|
||||||
|
error = server.arcscore.refresh_all_score_rating()
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
else:
|
||||||
|
flash('数据刷新成功 Success refresh data.')
|
||||||
|
return render_template('web/updatedatabase.html')
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/changesong', methods=['GET'])
|
@bp.route('/changesong', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def change_song():
|
def change_song():
|
||||||
@@ -356,14 +387,21 @@ def all_character():
|
|||||||
for i in x:
|
for i in x:
|
||||||
posts.append({'character_id': i[0],
|
posts.append({'character_id': i[0],
|
||||||
'name': i[1],
|
'name': i[1],
|
||||||
'level': i[2],
|
'max_level': i[2],
|
||||||
'frag': i[5],
|
'frag1': i[3],
|
||||||
'prog': i[6],
|
'prog1': i[4],
|
||||||
'overdrive': i[7],
|
'overdrive1': i[5],
|
||||||
'skill_id': i[8],
|
'frag20': i[6],
|
||||||
'skill_id_uncap': i[11],
|
'prog20': i[7],
|
||||||
'char_type': i[12],
|
'overdrive20': i[8],
|
||||||
'is_uncapped': i[14] == 1
|
'frag30': i[9],
|
||||||
|
'prog30': i[10],
|
||||||
|
'overdrive30': i[11],
|
||||||
|
'skill_id': i[12],
|
||||||
|
'skill_unlock_level': i[13],
|
||||||
|
'skill_id_uncap': i[15],
|
||||||
|
'char_type': i[16],
|
||||||
|
'is_uncapped': i[17] == 1
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
error = '没有角色数据 No character data.'
|
error = '没有角色数据 No character data.'
|
||||||
@@ -380,7 +418,7 @@ def all_character():
|
|||||||
def change_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',
|
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']
|
'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']
|
||||||
return render_template('web/changechar.html', skill_ids=skill_ids)
|
return render_template('web/changechar.html', skill_ids=skill_ids)
|
||||||
|
|
||||||
|
|
||||||
@@ -394,27 +432,12 @@ def edit_char():
|
|||||||
try:
|
try:
|
||||||
character_id = int(request.form['id'])
|
character_id = int(request.form['id'])
|
||||||
level = request.form['level']
|
level = request.form['level']
|
||||||
frag = request.form['frag']
|
|
||||||
prog = request.form['prog']
|
|
||||||
overdrive = request.form['overdrive']
|
|
||||||
skill_id = request.form['skill_id']
|
skill_id = request.form['skill_id']
|
||||||
skill_id_uncap = request.form['skill_id_uncap']
|
skill_id_uncap = request.form['skill_id_uncap']
|
||||||
if level:
|
if level:
|
||||||
level = int(level)
|
level = int(level)
|
||||||
else:
|
else:
|
||||||
level = None
|
level = None
|
||||||
if frag:
|
|
||||||
frag = float(frag)
|
|
||||||
else:
|
|
||||||
frag = None
|
|
||||||
if prog:
|
|
||||||
prog = float(prog)
|
|
||||||
else:
|
|
||||||
prog = None
|
|
||||||
if overdrive:
|
|
||||||
overdrive = float(overdrive)
|
|
||||||
else:
|
|
||||||
overdrive = None
|
|
||||||
except:
|
except:
|
||||||
error = '数据错误 Wrong data.'
|
error = '数据错误 Wrong data.'
|
||||||
flash(error)
|
flash(error)
|
||||||
@@ -424,36 +447,28 @@ def edit_char():
|
|||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from character where character_id=:a)''', {'a': character_id})
|
'''select exists(select * from character where character_id=:a)''', {'a': character_id})
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (1,):
|
||||||
if level is None and frag is None and prog is None and overdrive is None and skill_id is None and skill_id_uncap is None:
|
if level is None and skill_id is None and skill_id_uncap is None:
|
||||||
error = '无修改 No change.'
|
error = '无修改 No change.'
|
||||||
else:
|
else:
|
||||||
|
sql = '''update character set '''
|
||||||
sql = '''update character set level_exp=25000'''
|
|
||||||
sql_dict = {'character_id': character_id}
|
sql_dict = {'character_id': character_id}
|
||||||
if level is not None:
|
if level is not None:
|
||||||
sql += ', level = :level'
|
sql += 'max_level = :level, '
|
||||||
sql_dict['level'] = level
|
sql_dict['level'] = level
|
||||||
if frag is not None:
|
|
||||||
sql += ', frag = :frag'
|
|
||||||
sql_dict['frag'] = frag
|
|
||||||
if prog is not None:
|
|
||||||
sql += ', prog = :prog'
|
|
||||||
sql_dict['prog'] = prog
|
|
||||||
if overdrive is not None:
|
|
||||||
sql += ', overdrive = :overdrive'
|
|
||||||
sql_dict['overdrive'] = overdrive
|
|
||||||
if skill_id is not None:
|
if skill_id is not None:
|
||||||
sql += ', skill_id = :skill_id'
|
sql += 'skill_id = :skill_id, '
|
||||||
if skill_id == 'No_skill':
|
if skill_id == 'No_skill':
|
||||||
sql_dict['skill_id'] = ''
|
sql_dict['skill_id'] = ''
|
||||||
else:
|
else:
|
||||||
sql_dict['skill_id'] = skill_id
|
sql_dict['skill_id'] = skill_id
|
||||||
if skill_id_uncap is not None:
|
if skill_id_uncap is not None:
|
||||||
sql += ', skill_id_uncap = :skill_id_uncap'
|
sql += 'skill_id_uncap = :skill_id_uncap, '
|
||||||
if skill_id_uncap == 'No_skill':
|
if skill_id_uncap == 'No_skill':
|
||||||
sql_dict['skill_id_uncap'] = ''
|
sql_dict['skill_id_uncap'] = ''
|
||||||
else:
|
else:
|
||||||
sql_dict['skill_id_uncap'] = skill_id_uncap
|
sql_dict['skill_id_uncap'] = skill_id_uncap
|
||||||
|
|
||||||
|
sql = sql[:-2]
|
||||||
sql += ' where character_id = :character_id'
|
sql += ' where character_id = :character_id'
|
||||||
c.execute(sql, sql_dict)
|
c.execute(sql, sql_dict)
|
||||||
flash('角色修改成功 Successfully edit the character.')
|
flash('角色修改成功 Successfully edit the character.')
|
||||||
@@ -634,16 +649,16 @@ def edit_user_purchase():
|
|||||||
@bp.route('/allitem', methods=['GET'])
|
@bp.route('/allitem', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
def all_item():
|
def all_item():
|
||||||
# 所有购买数据
|
# 所有物品数据
|
||||||
|
|
||||||
error = None
|
error = None
|
||||||
posts = web.system.get_all_item()
|
posts = web.system.get_all_item()
|
||||||
if not posts:
|
if not posts:
|
||||||
error = '没有购买数据 No item data.'
|
error = '没有物品数据 No item data.'
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
return redirect(url_for('index.all_item'))
|
return render_template('web/allitem.html')
|
||||||
else:
|
else:
|
||||||
return render_template('web/allitem.html', posts=posts)
|
return render_template('web/allitem.html', posts=posts)
|
||||||
|
|
||||||
@@ -651,25 +666,103 @@ def all_item():
|
|||||||
@bp.route('/changeitem', methods=['GET', 'POST'])
|
@bp.route('/changeitem', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def change_item():
|
def change_item():
|
||||||
# 修改购买信息
|
# 添加物品信息
|
||||||
|
|
||||||
error = None
|
error = None
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
try:
|
try:
|
||||||
item_id = request.form['item_id']
|
item_id = request.form['item_id']
|
||||||
item_type = request.form['type']
|
item_type = request.form['type']
|
||||||
price = request.form['price']
|
|
||||||
orig_price = request.form['orig_price']
|
|
||||||
discount_from = request.form['discount_from']
|
|
||||||
discount_to = request.form['discount_to']
|
|
||||||
try:
|
try:
|
||||||
is_available = request.form['is_available']
|
is_available = request.form['is_available']
|
||||||
if is_available:
|
if is_available:
|
||||||
is_available = int(is_available)
|
is_available = int(is_available)
|
||||||
else:
|
else:
|
||||||
is_available = None
|
is_available = 0
|
||||||
except:
|
except:
|
||||||
is_available = None
|
is_available = 0
|
||||||
|
|
||||||
|
except:
|
||||||
|
error = '数据错误 Wrong data.'
|
||||||
|
flash(error)
|
||||||
|
return redirect(url_for('index.change_item'))
|
||||||
|
|
||||||
|
with Connect() as c:
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from item where item_id=:a and type=:b)''', {'a': item_id, 'b': item_type})
|
||||||
|
if c.fetchone() == (0,):
|
||||||
|
c.execute('''insert into item values(?,?,?,'')''',
|
||||||
|
(item_id, item_type, is_available))
|
||||||
|
flash('物品添加成功 Successfully add the item.')
|
||||||
|
else:
|
||||||
|
error = '物品已存在 The item exists.'
|
||||||
|
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return render_template('web/changeitem.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changeitem/delete', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def change_item_delete():
|
||||||
|
# 删除物品信息
|
||||||
|
|
||||||
|
error = None
|
||||||
|
try:
|
||||||
|
item_id = request.form['item_id']
|
||||||
|
item_type = request.form['type']
|
||||||
|
except:
|
||||||
|
error = '数据错误 Wrong data.'
|
||||||
|
flash(error)
|
||||||
|
return redirect(url_for('index.change_item'))
|
||||||
|
|
||||||
|
with Connect() as c:
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from item where item_id=:a and type=:b)''', {'a': item_id, 'b': item_type})
|
||||||
|
if c.fetchone() == (1,):
|
||||||
|
c.execute('''delete from item where item_id=? and type=?''',
|
||||||
|
(item_id, item_type))
|
||||||
|
flash('物品删除成功 Successfully delete the item.')
|
||||||
|
else:
|
||||||
|
error = '物品不存在 The item does not exist.'
|
||||||
|
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return render_template('web/changeitem.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/allpurchase', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
def all_purchase():
|
||||||
|
# 所有购买数据
|
||||||
|
|
||||||
|
error = None
|
||||||
|
posts = web.system.get_all_purchase()
|
||||||
|
if not posts:
|
||||||
|
error = '没有购买数据 No purchase data.'
|
||||||
|
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
return render_template('web/allpurchase.html')
|
||||||
|
else:
|
||||||
|
return render_template('web/allpurchase.html', posts=posts)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changepurchase', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def change_purchase():
|
||||||
|
# 添加购买信息
|
||||||
|
|
||||||
|
error = None
|
||||||
|
if request.method == 'POST':
|
||||||
|
try:
|
||||||
|
purchase_name = request.form['purchase_name']
|
||||||
|
price = request.form['price']
|
||||||
|
orig_price = request.form['orig_price']
|
||||||
|
discount_from = request.form['discount_from']
|
||||||
|
discount_to = request.form['discount_to']
|
||||||
|
|
||||||
if price:
|
if price:
|
||||||
price = int(price)
|
price = int(price)
|
||||||
@@ -692,43 +785,128 @@ def change_item():
|
|||||||
except:
|
except:
|
||||||
error = '数据错误 Wrong data.'
|
error = '数据错误 Wrong data.'
|
||||||
flash(error)
|
flash(error)
|
||||||
return redirect(url_for('index.change_item'))
|
return redirect(url_for('index.change_purchase'))
|
||||||
|
|
||||||
with Connect() as c:
|
with Connect() as c:
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from item where item_id=:a and type=:b)''', {'a': item_id, 'b': item_type})
|
'''select exists(select * from purchase where purchase_name=:a)''', {'a': purchase_name})
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (0,):
|
||||||
if is_available is None and price is None and orig_price is None and not discount_from and not discount_to:
|
c.execute('''insert into purchase values(?,?,?,?,?)''',
|
||||||
error = '无修改 No change.'
|
(purchase_name, price, orig_price, discount_from, discount_to))
|
||||||
else:
|
|
||||||
sql = '''update item set type=:type'''
|
|
||||||
sql_dict = {'item_id': item_id, 'type': item_type}
|
|
||||||
if price is not None:
|
|
||||||
sql += ', price = :price'
|
|
||||||
sql_dict['price'] = price
|
|
||||||
if orig_price is not None:
|
|
||||||
sql += ', orig_price = :orig_price'
|
|
||||||
sql_dict['orig_price'] = orig_price
|
|
||||||
if discount_from is not None:
|
|
||||||
sql += ', discount_from = :discount_from'
|
|
||||||
sql_dict['discount_from'] = discount_from
|
|
||||||
if discount_to is not None:
|
|
||||||
sql += ', discount_to = :discount_to'
|
|
||||||
sql_dict['discount_to'] = discount_to
|
|
||||||
if is_available is not None:
|
|
||||||
sql += ', is_available = :is_available'
|
|
||||||
sql_dict['is_available'] = is_available
|
|
||||||
|
|
||||||
sql += ' where item_id = :item_id and type = :type'
|
flash('购买项目添加成功 Successfully add the purchase.')
|
||||||
c.execute(sql, sql_dict)
|
|
||||||
flash('购买项目修改成功 Successfully edit the item.')
|
|
||||||
else:
|
else:
|
||||||
error = '购买项目不存在 The item does not exist.'
|
error = '购买项目已存在 The purchase exists.'
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
return render_template('web/changeitem.html')
|
return render_template('web/changepurchase.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changepurchase/delete', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def change_purchase_delete():
|
||||||
|
# 删除购买信息
|
||||||
|
|
||||||
|
error = None
|
||||||
|
try:
|
||||||
|
purchase_name = request.form['purchase_name']
|
||||||
|
except:
|
||||||
|
error = '数据错误 Wrong data.'
|
||||||
|
flash(error)
|
||||||
|
return redirect(url_for('index.change_purchase'))
|
||||||
|
|
||||||
|
with Connect() as c:
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from purchase where purchase_name=:a)''', {'a': purchase_name})
|
||||||
|
if c.fetchone() == (1,):
|
||||||
|
c.execute('''delete from purchase where purchase_name=?''',
|
||||||
|
(purchase_name,))
|
||||||
|
c.execute('''delete from purchase_item where purchase_name=?''',
|
||||||
|
(purchase_name,))
|
||||||
|
flash('购买信息删除成功 Successfully delete the purchase.')
|
||||||
|
else:
|
||||||
|
error = '购买信息不存在 The purchase does not exist.'
|
||||||
|
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return render_template('web/changepurchase.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changepurchaseitem', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def change_purchase_item():
|
||||||
|
# 添加购买的物品信息
|
||||||
|
|
||||||
|
error = None
|
||||||
|
if request.method == 'POST':
|
||||||
|
try:
|
||||||
|
purchase_name = request.form['purchase_name']
|
||||||
|
item_id = request.form['item_id']
|
||||||
|
item_type = request.form['type']
|
||||||
|
except:
|
||||||
|
error = '数据错误 Wrong data.'
|
||||||
|
flash(error)
|
||||||
|
return redirect(url_for('index.change_purchase_item'))
|
||||||
|
|
||||||
|
with Connect() as c:
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from purchase_item where purchase_name=? and item_id=? and type=?)''', (purchase_name, item_id, item_type))
|
||||||
|
if c.fetchone() == (0,):
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from purchase where purchase_name=?)''', (purchase_name,))
|
||||||
|
if c.fetchone() == (1,):
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from item where item_id=? and type=?)''', (item_id, item_type))
|
||||||
|
if c.fetchone() == (1,):
|
||||||
|
c.execute('''insert into purchase_item values(?,?,?)''',
|
||||||
|
(purchase_name, item_id, item_type))
|
||||||
|
flash('''购买项目的物品添加成功 Successfully add the purchase's item.''')
|
||||||
|
else:
|
||||||
|
error = '''物品不存在 The item does not exist.'''
|
||||||
|
else:
|
||||||
|
error = '''购买项目不存在 The purchase does not exist.'''
|
||||||
|
else:
|
||||||
|
error = '''购买项目的物品已存在 The purchase's item exists.'''
|
||||||
|
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return render_template('web/changepurchaseitem.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changepurchaseitem/delete', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def change_purchase_item_delete():
|
||||||
|
# 删除购买的物品信息
|
||||||
|
|
||||||
|
error = None
|
||||||
|
try:
|
||||||
|
purchase_name = request.form['purchase_name']
|
||||||
|
item_id = request.form['item_id']
|
||||||
|
item_type = request.form['type']
|
||||||
|
except:
|
||||||
|
error = '数据错误 Wrong data.'
|
||||||
|
flash(error)
|
||||||
|
return redirect(url_for('index.change_purchase_item'))
|
||||||
|
|
||||||
|
with Connect() as c:
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from purchase_item where purchase_name=? and item_id=? and type=?)''', (purchase_name, item_id, item_type))
|
||||||
|
if c.fetchone() == (1,):
|
||||||
|
c.execute('''delete from purchase_item where purchase_name=? and item_id=? and type=?''',
|
||||||
|
(purchase_name, item_id, item_type))
|
||||||
|
|
||||||
|
flash('''购买项目的物品删除成功 Successfully delete the purchase's item.''')
|
||||||
|
else:
|
||||||
|
error = '''购买项目的物品不存在 The purchase's item does not exist.'''
|
||||||
|
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return render_template('web/changepurchaseitem.html')
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/updateusersave', methods=['POST', 'GET'])
|
@bp.route('/updateusersave', methods=['POST', 'GET'])
|
||||||
@@ -1197,3 +1375,73 @@ def delete_user_score():
|
|||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
return redirect(url_for('index.ban_user'))
|
return redirect(url_for('index.ban_user'))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changescore', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
def change_score():
|
||||||
|
# 修改成绩页面
|
||||||
|
return render_template('web/changescore.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changescore/delete', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def delete_score():
|
||||||
|
# 删除成绩
|
||||||
|
|
||||||
|
song_id = request.form['sid']
|
||||||
|
difficulty = request.form['difficulty']
|
||||||
|
if difficulty.isdigit() or difficulty == '-1':
|
||||||
|
difficulty = int(difficulty)
|
||||||
|
|
||||||
|
name = request.form['name']
|
||||||
|
user_code = request.form['user_code']
|
||||||
|
|
||||||
|
error = 'Unknown error.'
|
||||||
|
flag = [False, False, False]
|
||||||
|
if song_id:
|
||||||
|
flag[0] = True
|
||||||
|
if difficulty != -1:
|
||||||
|
flag[1] = True
|
||||||
|
|
||||||
|
with Connect() as c:
|
||||||
|
if name or user_code:
|
||||||
|
if user_code:
|
||||||
|
c.execute('''select user_id from user where user_code=:a''', {
|
||||||
|
'a': user_code})
|
||||||
|
else:
|
||||||
|
c.execute(
|
||||||
|
'''select user_id from user where name=:a''', {'a': name})
|
||||||
|
|
||||||
|
user_id = c.fetchone()
|
||||||
|
if user_id:
|
||||||
|
user_id = user_id[0]
|
||||||
|
flag[2] = True
|
||||||
|
else:
|
||||||
|
error = '玩家不存在 The player does not exist.'
|
||||||
|
|
||||||
|
if flag[0] or flag[1] or flag[2]:
|
||||||
|
sql = '''delete from best_score where '''
|
||||||
|
sql_dict = {}
|
||||||
|
if flag[0]:
|
||||||
|
sql += 'song_id=:song_id and '
|
||||||
|
sql_dict['song_id'] = song_id
|
||||||
|
if flag[1]:
|
||||||
|
sql += 'difficulty=:difficulty and '
|
||||||
|
sql_dict['difficulty'] = difficulty
|
||||||
|
if flag[2]:
|
||||||
|
sql += 'user_id=:user_id '
|
||||||
|
sql_dict['user_id'] = user_id
|
||||||
|
if sql[-4:-1] == 'and':
|
||||||
|
sql = sql[:-4]
|
||||||
|
|
||||||
|
c.execute(sql, sql_dict)
|
||||||
|
flash('成功删除成绩 Successfully delete the scores.')
|
||||||
|
error = None
|
||||||
|
else:
|
||||||
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return redirect(url_for('index.change_score'))
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from flask import (Blueprint, flash, g, redirect,
|
|||||||
render_template, request, session, url_for)
|
render_template, request, session, url_for)
|
||||||
import functools
|
import functools
|
||||||
from setting import Config
|
from setting import Config
|
||||||
|
import hashlib
|
||||||
|
|
||||||
bp = Blueprint('login', __name__, url_prefix='/web')
|
bp = Blueprint('login', __name__, url_prefix='/web')
|
||||||
|
|
||||||
@@ -20,7 +21,11 @@ def login():
|
|||||||
|
|
||||||
if error is None:
|
if error is None:
|
||||||
session.clear()
|
session.clear()
|
||||||
session['user_id'] = Config.USERNAME + Config.PASSWORD
|
hash_session = username + \
|
||||||
|
hashlib.sha256(password.encode("utf8")).hexdigest()
|
||||||
|
hash_session = hashlib.sha256(
|
||||||
|
hash_session.encode("utf8")).hexdigest()
|
||||||
|
session['user_id'] = hash_session
|
||||||
return redirect(url_for('index.index'))
|
return redirect(url_for('index.index'))
|
||||||
|
|
||||||
flash(error)
|
flash(error)
|
||||||
@@ -42,7 +47,11 @@ def login_required(view):
|
|||||||
def wrapped_view(**kwargs):
|
def wrapped_view(**kwargs):
|
||||||
x = session.get('user_id')
|
x = session.get('user_id')
|
||||||
|
|
||||||
if x != Config.USERNAME + Config.PASSWORD:
|
hash_session = Config.USERNAME + \
|
||||||
|
hashlib.sha256(Config.PASSWORD.encode("utf8")).hexdigest()
|
||||||
|
hash_session = hashlib.sha256(hash_session.encode("utf8")).hexdigest()
|
||||||
|
|
||||||
|
if x != hash_session:
|
||||||
return redirect(url_for('login.login'))
|
return redirect(url_for('login.login'))
|
||||||
|
|
||||||
g.user = {'user_id': x, 'username': Config.USERNAME}
|
g.user = {'user_id': x, 'username': Config.USERNAME}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
import sqlite3
|
from server.sql import Connect
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
import server.arcscore
|
import server.arcscore
|
||||||
@@ -161,17 +161,18 @@ def update_one_table(c1, c2, table_name):
|
|||||||
|
|
||||||
def update_user_char(c):
|
def update_user_char(c):
|
||||||
# 用character数据更新user_char
|
# 用character数据更新user_char
|
||||||
c.execute('''select * from character''')
|
c.execute('''select character_id, max_level, is_uncapped from character''')
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
c.execute('''select user_id from user''')
|
c.execute('''select user_id from user''')
|
||||||
y = c.fetchall()
|
y = c.fetchall()
|
||||||
if x and y:
|
if x and y:
|
||||||
for j in y:
|
for j in y:
|
||||||
for i in x:
|
for i in x:
|
||||||
c.execute('''delete from user_char where user_id=:a and character_id=:b''', {
|
c.execute('''delete from user_char_full where user_id=:a and character_id=:b''', {
|
||||||
'a': j[0], 'b': i[0]})
|
'a': j[0], 'b': i[0]})
|
||||||
c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', {
|
exp = 25000 if i[1] == 30 else 10000
|
||||||
'a': j[0], 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]})
|
c.execute('''insert into user_char_full values(?,?,?,?,?,?)''',
|
||||||
|
(j[0], i[0], i[1], exp, i[2], 0))
|
||||||
|
|
||||||
|
|
||||||
def update_database():
|
def update_database():
|
||||||
@@ -179,10 +180,8 @@ def update_database():
|
|||||||
# 对于arcaea_datebase.db,更新一些表,并用character数据更新user_char
|
# 对于arcaea_datebase.db,更新一些表,并用character数据更新user_char
|
||||||
# 对于arcsong.db,更新songs
|
# 对于arcsong.db,更新songs
|
||||||
if os.path.isfile("database/old_arcaea_database.db") and os.path.isfile("database/arcaea_database.db"):
|
if os.path.isfile("database/old_arcaea_database.db") and os.path.isfile("database/arcaea_database.db"):
|
||||||
conn1 = sqlite3.connect('./database/old_arcaea_database.db')
|
with Connect('./database/old_arcaea_database.db') as c1:
|
||||||
c1 = conn1.cursor()
|
with Connect() as c2:
|
||||||
conn2 = sqlite3.connect('./database/arcaea_database.db')
|
|
||||||
c2 = conn2.cursor()
|
|
||||||
|
|
||||||
update_one_table(c1, c2, 'user')
|
update_one_table(c1, c2, 'user')
|
||||||
update_one_table(c1, c2, 'friend')
|
update_one_table(c1, c2, 'friend')
|
||||||
@@ -191,34 +190,32 @@ def update_database():
|
|||||||
update_one_table(c1, c2, 'user_world')
|
update_one_table(c1, c2, 'user_world')
|
||||||
update_one_table(c1, c2, 'item')
|
update_one_table(c1, c2, 'item')
|
||||||
update_one_table(c1, c2, 'user_item')
|
update_one_table(c1, c2, 'user_item')
|
||||||
|
update_one_table(c1, c2, 'purchase')
|
||||||
|
update_one_table(c1, c2, 'purchase_item')
|
||||||
update_one_table(c1, c2, 'user_save')
|
update_one_table(c1, c2, 'user_save')
|
||||||
update_one_table(c1, c2, 'login')
|
update_one_table(c1, c2, 'login')
|
||||||
update_one_table(c1, c2, 'present')
|
update_one_table(c1, c2, 'present')
|
||||||
update_one_table(c1, c2, 'user_present')
|
update_one_table(c1, c2, 'user_present')
|
||||||
update_one_table(c1, c2, 'redeem')
|
update_one_table(c1, c2, 'redeem')
|
||||||
update_one_table(c1, c2, 'user_redeem')
|
update_one_table(c1, c2, 'user_redeem')
|
||||||
|
update_one_table(c1, c2, 'role')
|
||||||
|
update_one_table(c1, c2, 'user_role')
|
||||||
|
update_one_table(c1, c2, 'power')
|
||||||
|
update_one_table(c1, c2, 'role_power')
|
||||||
|
update_one_table(c1, c2, 'api_auth')
|
||||||
|
|
||||||
update_user_char(c2)
|
update_one_table(c1, c2, 'user_char')
|
||||||
|
update_user_char(c2) # 更新user_char_full
|
||||||
|
|
||||||
conn1.commit()
|
|
||||||
conn1.close()
|
|
||||||
conn2.commit()
|
|
||||||
conn2.close()
|
|
||||||
os.remove('database/old_arcaea_database.db')
|
os.remove('database/old_arcaea_database.db')
|
||||||
|
|
||||||
# songs
|
# songs
|
||||||
if os.path.isfile("database/old_arcsong.db") and os.path.isfile("database/arcsong.db"):
|
if os.path.isfile("database/old_arcsong.db") and os.path.isfile("database/arcsong.db"):
|
||||||
conn1 = sqlite3.connect('./database/old_arcsong.db')
|
with Connect('./database/old_arcsong.db') as c1:
|
||||||
c1 = conn1.cursor()
|
with Connect('./database/arcsong.db') as c2:
|
||||||
conn2 = sqlite3.connect('./database/arcsong.db')
|
|
||||||
c2 = conn2.cursor()
|
|
||||||
|
|
||||||
update_one_table(c1, c2, 'songs')
|
update_one_table(c1, c2, 'songs')
|
||||||
|
|
||||||
conn1.commit()
|
|
||||||
conn1.close()
|
|
||||||
conn2.commit()
|
|
||||||
conn2.close()
|
|
||||||
os.remove('database/old_arcsong.db')
|
os.remove('database/old_arcsong.db')
|
||||||
|
|
||||||
|
|
||||||
@@ -256,35 +253,56 @@ def unlock_user_item(c, user_id):
|
|||||||
|
|
||||||
|
|
||||||
def get_all_item():
|
def get_all_item():
|
||||||
# 所有购买数据查询
|
# 所有物品数据查询
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute('''select * from item''')
|
c.execute('''select * from item''')
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
re = []
|
re = []
|
||||||
if x:
|
if x:
|
||||||
for i in x:
|
for i in x:
|
||||||
|
re.append({'item_id': i[0],
|
||||||
|
'type': i[1],
|
||||||
|
'is_available': int2b(i[2])
|
||||||
|
})
|
||||||
|
|
||||||
|
return re
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_purchase():
|
||||||
|
# 所有购买数据查询
|
||||||
|
with Connect() as c:
|
||||||
|
c.execute('''select * from purchase''')
|
||||||
|
x = c.fetchall()
|
||||||
|
re = []
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
|
||||||
discount_from = None
|
discount_from = None
|
||||||
discount_to = None
|
discount_to = None
|
||||||
|
|
||||||
if i[5] and i[5] >= 0:
|
if i[3] and i[3] >= 0:
|
||||||
discount_from = time.strftime(
|
discount_from = time.strftime(
|
||||||
"%Y-%m-%d %H:%M:%S", time.localtime(int(i[5])/1000))
|
"%Y-%m-%d %H:%M:%S", time.localtime(int(i[3])/1000))
|
||||||
if i[6] and i[6] >= 0:
|
if i[4] and i[4] >= 0:
|
||||||
discount_to = time.strftime(
|
discount_to = time.strftime(
|
||||||
"%Y-%m-%d %H:%M:%S", time.localtime(int(i[6])//1000))
|
"%Y-%m-%d %H:%M:%S", time.localtime(int(i[4])//1000))
|
||||||
|
|
||||||
re.append({'item_id': i[0],
|
c.execute(
|
||||||
'type': i[1],
|
'''select * from purchase_item where purchase_name=?''', (i[0],))
|
||||||
'is_available': int2b(i[2]),
|
y = c.fetchall()
|
||||||
'price': i[3],
|
items = []
|
||||||
'orig_price': i[4],
|
if y:
|
||||||
|
for j in y:
|
||||||
|
items.append({'item_id': j[1], 'type': j[2]})
|
||||||
|
|
||||||
|
re.append({'purchase_name': i[0],
|
||||||
|
'price': i[1],
|
||||||
|
'orig_price': i[2],
|
||||||
'discount_from': discount_from,
|
'discount_from': discount_from,
|
||||||
'discount_to': discount_to
|
'discount_to': discount_to,
|
||||||
|
'items': items
|
||||||
})
|
})
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
@@ -346,8 +364,7 @@ def add_one_present(present_id, expire_ts, description, items):
|
|||||||
# 添加一个奖励
|
# 添加一个奖励
|
||||||
|
|
||||||
message = None
|
message = None
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from present where present_id=:a)''', {'a': present_id})
|
'''select exists(select * from present where present_id=:a)''', {'a': present_id})
|
||||||
if c.fetchone() == (0,):
|
if c.fetchone() == (0,):
|
||||||
@@ -357,8 +374,6 @@ def add_one_present(present_id, expire_ts, description, items):
|
|||||||
else:
|
else:
|
||||||
message = '奖励已存在 The present exists.'
|
message = '奖励已存在 The present exists.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
@@ -366,8 +381,7 @@ def delete_one_present(present_id):
|
|||||||
# 删除一个奖励
|
# 删除一个奖励
|
||||||
|
|
||||||
message = None
|
message = None
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from present where present_id=:a)''', {'a': present_id})
|
'''select exists(select * from present where present_id=:a)''', {'a': present_id})
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (1,):
|
||||||
@@ -379,8 +393,6 @@ def delete_one_present(present_id):
|
|||||||
else:
|
else:
|
||||||
message = '奖励不存在 The present does not exist.'
|
message = '奖励不存在 The present does not exist.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
@@ -423,8 +435,7 @@ def add_one_redeem(code, redeem_type, items):
|
|||||||
# 添加一个兑换码
|
# 添加一个兑换码
|
||||||
|
|
||||||
message = None
|
message = None
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from redeem where code=:a)''', {'a': code})
|
'''select exists(select * from redeem where code=:a)''', {'a': code})
|
||||||
if c.fetchone() == (0,):
|
if c.fetchone() == (0,):
|
||||||
@@ -434,8 +445,6 @@ def add_one_redeem(code, redeem_type, items):
|
|||||||
else:
|
else:
|
||||||
message = '兑换码已存在 The redeem code exists.'
|
message = '兑换码已存在 The redeem code exists.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
@@ -443,8 +452,7 @@ def add_some_random_redeem(amount, redeem_type, items):
|
|||||||
# 随机生成一堆10位的兑换码
|
# 随机生成一堆10位的兑换码
|
||||||
|
|
||||||
message = None
|
message = None
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
i = 1
|
i = 1
|
||||||
while i <= amount:
|
while i <= amount:
|
||||||
code = random_str()
|
code = random_str()
|
||||||
@@ -456,8 +464,7 @@ def add_some_random_redeem(amount, redeem_type, items):
|
|||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
message = '添加成功 Successfully add it.'
|
message = '添加成功 Successfully add it.'
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
@@ -465,19 +472,17 @@ def delete_one_redeem(code):
|
|||||||
# 删除一个兑换码
|
# 删除一个兑换码
|
||||||
|
|
||||||
message = None
|
message = None
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from redeem where code=:a)''', {'a': code})
|
'''select exists(select * from redeem where code=:a)''', {'a': code})
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (1,):
|
||||||
c.execute('''delete from redeem where code = :a''', {'a': code})
|
c.execute('''delete from redeem where code = :a''', {'a': code})
|
||||||
c.execute('''delete from user_redeem where code =:a''', {'a': code})
|
c.execute(
|
||||||
|
'''delete from user_redeem where code =:a''', {'a': code})
|
||||||
message = '删除成功 Successfully delete it.'
|
message = '删除成功 Successfully delete it.'
|
||||||
else:
|
else:
|
||||||
message = '兑换码不存在 The redeem code does not exist.'
|
message = '兑换码不存在 The redeem code does not exist.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
@@ -499,7 +504,7 @@ def ban_one_user(c, user_id):
|
|||||||
|
|
||||||
def clear_user_score(c, user_id):
|
def clear_user_score(c, user_id):
|
||||||
# 清除用户所有成绩,包括best_score和recent30,以及recent数据,但不包括云端存档
|
# 清除用户所有成绩,包括best_score和recent30,以及recent数据,但不包括云端存档
|
||||||
c.execute('''update user set rating_ptt=0, song_id='', difficulty=0, score=0, shiny_perfect_count=0, perfect_count=0, near_count=0, miss_count=0, health=0, time_played=0, rating=0 where user_id=:a''',
|
c.execute('''update user set rating_ptt=0, song_id='', difficulty=0, score=0, shiny_perfect_count=0, perfect_count=0, near_count=0, miss_count=0, health=0, time_played=0, rating=0, world_rank_score=0 where user_id=:a''',
|
||||||
{'a': user_id})
|
{'a': user_id})
|
||||||
c.execute('''delete from best_score where user_id=:a''', {'a': user_id})
|
c.execute('''delete from best_score where user_id=:a''', {'a': user_id})
|
||||||
c.execute('''delete from recent30 where user_id=:a''', {'a': user_id})
|
c.execute('''delete from recent30 where user_id=:a''', {'a': user_id})
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
def get_user_score(c, user_id, limit=-1):
|
def get_user_score(c, user_id, limit=-1, offset=0):
|
||||||
# 返回用户的所有歌曲数据,带排名,返回字典列表
|
# 返回用户的所有歌曲数据,带排名,返回字典列表
|
||||||
if limit >= 0:
|
if limit >= 0:
|
||||||
c.execute('''select * from best_score where user_id =:a order by rating DESC limit :b''',
|
c.execute('''select * from best_score where user_id =:a order by rating DESC limit :b offset :c''',
|
||||||
{'a': user_id, 'b': limit})
|
{'a': user_id, 'b': limit, 'c': offset})
|
||||||
else:
|
else:
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select * from best_score where user_id =:a order by rating DESC''', {'a': user_id})
|
'''select * from best_score where user_id =:a order by rating DESC''', {'a': user_id})
|
||||||
@@ -49,6 +49,10 @@ def get_user(c, user_id):
|
|||||||
if x[20]:
|
if x[20]:
|
||||||
time_played = time.strftime('%Y-%m-%d %H:%M:%S',
|
time_played = time.strftime('%Y-%m-%d %H:%M:%S',
|
||||||
time.localtime(int(x[20])//1000))
|
time.localtime(int(x[20])//1000))
|
||||||
|
if x[2] == '':
|
||||||
|
ban_flag = True
|
||||||
|
else:
|
||||||
|
ban_flag = False
|
||||||
|
|
||||||
r = {'name': x[1],
|
r = {'name': x[1],
|
||||||
'user_id': user_id,
|
'user_id': user_id,
|
||||||
@@ -65,14 +69,15 @@ def get_user(c, user_id):
|
|||||||
'time_played': time_played,
|
'time_played': time_played,
|
||||||
'clear_type': x[21],
|
'clear_type': x[21],
|
||||||
'rating': x[22],
|
'rating': x[22],
|
||||||
'ticket': x[26]
|
'ticket': x[26],
|
||||||
|
'ban_flag': ban_flag
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def get_user_recent30(c, user_id):
|
def get_user_recent30(c, user_id):
|
||||||
# 获取玩家recent30信息并计算这一部分的ptt,返回字典列表和一个值
|
# 获取玩家recent30信息并计算recent10的ptt,返回字典列表和一个值
|
||||||
c.execute('''select * from recent30 where user_id=:a''', {'a': user_id})
|
c.execute('''select * from recent30 where user_id=:a''', {'a': user_id})
|
||||||
sumr = 0
|
sumr = 0
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
|
|||||||
Reference in New Issue
Block a user