mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-16 13:37:26 +08:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a3cec05b7 | ||
|
|
e3d81436d0 | ||
|
|
941a79ccc7 | ||
|
|
62902a561c | ||
|
|
1660bc5899 | ||
|
|
d577246d28 | ||
|
|
9fd626468e | ||
|
|
c51a1b4e85 | ||
|
|
0e42123417 | ||
|
|
e216e6144b | ||
|
|
b70c435a4a | ||
|
|
eb03d2be93 | ||
|
|
fcb5d264ef | ||
|
|
d617951e1f | ||
|
|
febf931f1a | ||
|
|
981961d6a1 | ||
|
|
a90380df4c | ||
|
|
4f66f492fc | ||
|
|
df181f104e | ||
|
|
a890a9af4a | ||
|
|
c6bb4c9afb | ||
|
|
98358ad216 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.log
|
||||||
51
README.md
51
README.md
@@ -2,14 +2,21 @@
|
|||||||
一个微型的Arcaea本地服务器 A small local server for Arcaea
|
一个微型的Arcaea本地服务器 A small local server for Arcaea
|
||||||
|
|
||||||
## 简介 Introduction
|
## 简介 Introduction
|
||||||
这是基于Python以及Flask的微型本地Arcaea服务器,可以模拟游戏的主要功能,一时兴起在五天之内糊了出来。这可能是我第一次写这种大程序,若有不妥之处,敬请谅解。
|
这是基于Python以及Flask的微型本地Arcaea服务器,可以模拟游戏的主要功能。这可能是我第一次写这种大程序,若有不妥之处,敬请谅解。
|
||||||
This is a small local Arcaea server based on Python and Flask, which can simulate the main functions of the game. I completed it on the spur of the moment in five days. This may be the first time I have written such a large program. Please understand if there is something wrong with it.
|
|
||||||
|
本程序主要用于学习研究,不得用于任何商业行为,否则后果自负,这不是强制要求,只是一个提醒与警告。
|
||||||
|
|
||||||
|
This is a small local Arcaea server based on Python and Flask, which can simulate the main functions of the game. This may be the first time I have written such a large program. Please understand if there is something wrong with it.
|
||||||
|
|
||||||
|
This procedure is mainly used for study and research, and shall not be used for any commercial activities, otherwise the consequences will be borne by oneself. This is not a mandatory requirement, just a reminder and warning.
|
||||||
|
|
||||||
> 虽然看起来很蠢,但是可以用!
|
> 虽然看起来很蠢,但是可以用!
|
||||||
> It looks stupid, but it works!
|
> It looks stupid, but it works!
|
||||||
|
|
||||||
## 特性 Features
|
## 特性 Features
|
||||||
有以下 We have:
|
有以下 We have:
|
||||||
- 登录、注册 Login and registration
|
- 登录、注册 Login and registration
|
||||||
|
- 多设备登录 Multi device login
|
||||||
- 成绩上传 Score upload
|
- 成绩上传 Score upload
|
||||||
- PTT
|
- PTT
|
||||||
- 排名 Rank
|
- 排名 Rank
|
||||||
@@ -29,14 +36,17 @@ This is a small local Arcaea server based on Python and Flask, which can simulat
|
|||||||
- 后台自定义信息 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
|
||||||
|
- 世界模式下的搭档升级、觉醒,以及某些奖励的获取 Partner upgrading, uncapping, and receiving some rewards in the world mode
|
||||||
|
- 世界排名 Global rank
|
||||||
|
|
||||||
可能有问题 There may be problems:
|
可能有问题 There may be problems:
|
||||||
- Recent 30
|
- Recent 30
|
||||||
- 一些歌曲的解锁 Some songs' unlocking
|
- 一些歌曲的解锁 Some songs' unlocking
|
||||||
|
- 同设备多共存登录 Multiple app logins on the same device
|
||||||
|
|
||||||
## 说明 Statement
|
## 说明 Statement
|
||||||
只是很有趣,用处探索中。
|
只是很有趣,用处探索中。
|
||||||
@@ -51,34 +61,29 @@ 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.0
|
### Version 2.4
|
||||||
- 适用于Arcaea 3.4.1版本 For Arcaea 3.4.1
|
- 适用于Arcaea 3.6.0版本 For Arcaea 3.6.0
|
||||||
- 更新API接口至13 Update API interface to 13.
|
|
||||||
- 更新了歌曲数据库 Update the song database.
|
- 更新了歌曲数据库 Update the song database.
|
||||||
- 新增了兑换码系统 Add the redeem code system.
|
- 新搭档 **拉格兰(拉格朗日!)** 已解锁 Unlock the new character **Lagrange**.
|
||||||
- 优化了下载时文件MD5的读取速度 Optimize the reading speed of MD5 when downloading.
|
- 新增游戏版本校验 Add game version verification.
|
||||||
- 新增初见保护 Add initial protection.
|
- 新增注册时邮箱记录 Add email recording while registering.
|
||||||
- EX保护机制修改,现在重复歌曲若分数较高,会刷新r30中最早的记录,并保证ptt不下降,仍不清楚能否正常起效 EX protection mechanism has been modified. If the score of one repetitive song is higher, it will refresh the earliest record in r30 and ensure that PTT won't not drop. It is still unclear whether it can work normally.
|
- 新增登录时IP地址记录 Add IP address recording at login time.
|
||||||
- 数据迁移机制修改,现在重复数据以旧数据库数据为准 The database migration mechanism has been modified. Now the duplicate data is subject to the old database data.
|
- 新增了一些设置选项和后台功能 Add some setting options and background functions.
|
||||||
- 机制修改,数据库缺少歌曲定数会当做Unrank处理 The mechanism has been modified. The lack of chart constant of songs in the database will be treated as unrank.
|
- 新增数据库自动更新功能 Add database automatic update function.
|
||||||
- 后台新增用户密码修改、用户封禁和成绩清除 Add user password modification, user ban and score clearance in the background.
|
- 正在构建API接口 Building API interface.
|
||||||
- 游戏内数据同步将记录同步时间 Data synchronization in game will record synchronization time.
|
|
||||||
- 修复了一些Bug Fix some bugs.
|
- 修复了一些Bug Fix some bugs.
|
||||||
|
|
||||||
> 提醒:本次更新针对了API接口更新,将无法兼容Arcaea 3.4.1以下版本
|
|
||||||
>
|
|
||||||
> Tips: This update includes API interface update, and will not be compatible with the version below Arcaea 3.4.1.
|
|
||||||
|
|
||||||
## 运行环境与依赖 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)
|
||||||
@@ -86,11 +91,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)
|
||||||
|
|||||||
119
latest version/api/api_auth.py
Normal file
119
latest version/api/api_auth.py
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import hashlib
|
||||||
|
import time
|
||||||
|
from server.sql import Connect
|
||||||
|
import functools
|
||||||
|
from setting import Config
|
||||||
|
from flask import jsonify
|
||||||
|
|
||||||
|
|
||||||
|
class User():
|
||||||
|
# 用户类,当数据类型用
|
||||||
|
def __init__(self, user_id=None, role='', power=[]):
|
||||||
|
self.user_id = user_id
|
||||||
|
self.role = role
|
||||||
|
self.power = power
|
||||||
|
|
||||||
|
|
||||||
|
def login():
|
||||||
|
# 登录接口
|
||||||
|
return {'token': 1}, 0
|
||||||
|
|
||||||
|
|
||||||
|
def logout():
|
||||||
|
# 登出接口
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def id_get_role_id(c, user_id):
|
||||||
|
# user_id获取role_id
|
||||||
|
role_id = 1
|
||||||
|
c.execute('''select role_id from user_role where user_id = :a''',
|
||||||
|
{'a': user_id})
|
||||||
|
x = c.fetchone()
|
||||||
|
if x is not None:
|
||||||
|
role_id = int(x[0])
|
||||||
|
|
||||||
|
return role_id
|
||||||
|
|
||||||
|
|
||||||
|
def role_id_get_role(c, role_id):
|
||||||
|
# role_id获取role
|
||||||
|
role = ''
|
||||||
|
c.execute('''select role_name from role where role_id = :a''',
|
||||||
|
{'a': role_id})
|
||||||
|
x = c.fetchone()
|
||||||
|
if x is not None:
|
||||||
|
role = x[0]
|
||||||
|
|
||||||
|
return role
|
||||||
|
|
||||||
|
|
||||||
|
def api_token_get_id(c, token):
|
||||||
|
# api的token获取user_id
|
||||||
|
user_id = None
|
||||||
|
c.execute('''select user_id from api_login where token = :token''', {
|
||||||
|
'token': token})
|
||||||
|
x = c.fetchone()
|
||||||
|
if x is not None:
|
||||||
|
user_id = x[0]
|
||||||
|
|
||||||
|
return user_id
|
||||||
|
|
||||||
|
|
||||||
|
def get_role_power(c, role_id):
|
||||||
|
# 获取role_id对应power,返回列表
|
||||||
|
|
||||||
|
role_power = []
|
||||||
|
|
||||||
|
c.execute('''select power_name from power where power_id in (select power_id from role_power where role_id=:a)''', {
|
||||||
|
'a': role_id})
|
||||||
|
x = c.fetchall()
|
||||||
|
for i in x:
|
||||||
|
role_power.append(i[0])
|
||||||
|
|
||||||
|
return role_power
|
||||||
|
|
||||||
|
|
||||||
|
def role_required(request, power=[]):
|
||||||
|
# api token验证,写成了修饰器
|
||||||
|
def decorator(view):
|
||||||
|
@functools.wraps(view)
|
||||||
|
def wrapped_view(*args, **kwargs):
|
||||||
|
|
||||||
|
try:
|
||||||
|
request.json # 检查请求json格式
|
||||||
|
except:
|
||||||
|
return jsonify({'status': 400, 'code': -1, 'data': {}, 'msg': 'Payload must be a valid json'})
|
||||||
|
|
||||||
|
if not 'Token' in request.headers:
|
||||||
|
return jsonify({'status': 401, 'code': -1, 'data': {}, 'msg': 'No Token'})
|
||||||
|
|
||||||
|
user = User()
|
||||||
|
if power == []:
|
||||||
|
if Config.API_TOKEN == request.headers['Token'] and Config.API_TOKEN != '':
|
||||||
|
user.user_id = 0
|
||||||
|
else:
|
||||||
|
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
|
||||||
|
else:
|
||||||
|
with Connect() as c:
|
||||||
|
user.user_id = api_token_get_id(
|
||||||
|
c, request.headers['Token'])
|
||||||
|
if user.user_id is None:
|
||||||
|
return jsonify({'status': 404, 'code': -1, 'data': {}, 'msg': ''})
|
||||||
|
|
||||||
|
role_id = id_get_role_id(c, user.user_id)
|
||||||
|
user.role = role_id_get_role(c, role_id)
|
||||||
|
user.role_power = get_role_power(c, role_id)
|
||||||
|
|
||||||
|
f = False
|
||||||
|
for i in power:
|
||||||
|
if i in user.role_power:
|
||||||
|
f = True
|
||||||
|
break
|
||||||
|
if not f:
|
||||||
|
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
|
||||||
|
|
||||||
|
return view(user, *args, **kwargs)
|
||||||
|
|
||||||
|
return wrapped_view
|
||||||
|
return decorator
|
||||||
15
latest version/api/api_code.py
Normal file
15
latest version/api/api_code.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
def code_get_msg(code):
|
||||||
|
# api接口code获取msg,返回字符串
|
||||||
|
msg = {
|
||||||
|
'0': '',
|
||||||
|
'-1': 'See status code',
|
||||||
|
'-2': 'No data',
|
||||||
|
'-3': 'No data or user',
|
||||||
|
'-4': 'No user_id',
|
||||||
|
'-101': 'Wrong data type',
|
||||||
|
'-102': 'Wrong query parameter',
|
||||||
|
'-103': 'Wrong sort parameter',
|
||||||
|
'-104': 'Wrong sort order parameter'
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg[str(code)]
|
||||||
223
latest version/api/api_main.py
Normal file
223
latest version/api/api_main.py
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
from flask import (
|
||||||
|
Blueprint, request, jsonify
|
||||||
|
)
|
||||||
|
import api.api_auth
|
||||||
|
import api.users
|
||||||
|
import api.songs
|
||||||
|
from api.api_code import code_get_msg
|
||||||
|
|
||||||
|
|
||||||
|
bp = Blueprint('api', __name__, url_prefix='/api/v1')
|
||||||
|
|
||||||
|
|
||||||
|
def get_query_parameter(request, query_able=[], sort_able=[]):
|
||||||
|
# 提取查询请求参数,返回四个参数和code
|
||||||
|
|
||||||
|
limit = -1
|
||||||
|
offset = 0
|
||||||
|
query = {} # {'name': 'admin'}
|
||||||
|
sort = [] # [{'column': 'user_id', 'order': 'ASC'}, ...]
|
||||||
|
|
||||||
|
if 'limit' in request.json:
|
||||||
|
try:
|
||||||
|
limit = int(request.json['limit'])
|
||||||
|
except:
|
||||||
|
return -1, 0, {}, {}, -101
|
||||||
|
if 'offset' in request.json:
|
||||||
|
try:
|
||||||
|
offset = int(request.json['offset'])
|
||||||
|
except:
|
||||||
|
return -1, 0, {}, {}, -101
|
||||||
|
if 'query' in request.json:
|
||||||
|
query = request.json['query']
|
||||||
|
for i in query:
|
||||||
|
if i not in query_able:
|
||||||
|
return -1, 0, {}, {}, -102
|
||||||
|
if 'sort' in request.json:
|
||||||
|
sort = request.json['sort']
|
||||||
|
for i in sort:
|
||||||
|
if 'column' not in i or i['column'] not in sort_able:
|
||||||
|
return -1, 0, {}, {}, -103
|
||||||
|
if not 'order' in i:
|
||||||
|
i['order'] = 'ASC'
|
||||||
|
else:
|
||||||
|
if i['order'] not in ['ASC', 'DESC']:
|
||||||
|
return -1, 0, {}, {}, -104
|
||||||
|
|
||||||
|
return limit, offset, query, sort, 0
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/')
|
||||||
|
def ping():
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/token', methods=['POST'])
|
||||||
|
def token_post():
|
||||||
|
# 登录,获取token
|
||||||
|
|
||||||
|
if 'auth' in request.json:
|
||||||
|
data, code = api.api_auth.login(
|
||||||
|
request.json['auth'], request.remote_addr)
|
||||||
|
if code < 0:
|
||||||
|
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
|
||||||
|
else:
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
|
||||||
|
else:
|
||||||
|
return jsonify({'status': 401, 'code': -1, 'data': {}, 'msg': 'No authentication'})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/token', methods=['GET'])
|
||||||
|
@api.api_auth.role_required(request, ['select_me', 'select'])
|
||||||
|
def token_get(user):
|
||||||
|
# 判断登录有效性
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/token', methods=['DELETE'])
|
||||||
|
@api.api_auth.role_required(request, ['change_me', 'select_me', 'select'])
|
||||||
|
def token_delete(user):
|
||||||
|
# 登出
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': {}, 'msg': ''})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/users', methods=['GET'])
|
||||||
|
@api.api_auth.role_required(request, ['select'])
|
||||||
|
def users_get(user):
|
||||||
|
# 查询全用户信息
|
||||||
|
|
||||||
|
limit, offset, query, sort, code = get_query_parameter(request, ['user_id', 'name', 'user_code'], [
|
||||||
|
'user_id', 'name', 'user_code', 'join_date', 'rating_ptt', 'time_played', 'ticket'])
|
||||||
|
if code < 0:
|
||||||
|
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
|
||||||
|
|
||||||
|
data = api.users.get_users(limit, offset, query, sort)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
|
||||||
|
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/users/<int:user_id>', methods=['GET'])
|
||||||
|
@api.api_auth.role_required(request, ['select', 'select_me'])
|
||||||
|
def users_user_get(user, user_id):
|
||||||
|
# 查询用户信息
|
||||||
|
|
||||||
|
if user_id == 'me':
|
||||||
|
user_id = user.user_id
|
||||||
|
|
||||||
|
if user_id <= 0:
|
||||||
|
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
|
||||||
|
|
||||||
|
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
||||||
|
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
|
||||||
|
|
||||||
|
data = api.users.get_user_info(user_id)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
|
||||||
|
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/users/<int:user_id>/b30', methods=['GET'])
|
||||||
|
@api.api_auth.role_required(request, ['select', 'select_me'])
|
||||||
|
def users_user_b30_get(user, user_id):
|
||||||
|
# 查询用户b30
|
||||||
|
|
||||||
|
if user_id == 'me':
|
||||||
|
user_id = user.user_id
|
||||||
|
|
||||||
|
if user_id <= 0:
|
||||||
|
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
|
||||||
|
|
||||||
|
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
||||||
|
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
|
||||||
|
|
||||||
|
data = api.users.get_user_b30(user_id)
|
||||||
|
|
||||||
|
if data['data'] == []:
|
||||||
|
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
|
||||||
|
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/users/<int:user_id>/best', methods=['GET'])
|
||||||
|
@api.api_auth.role_required(request, ['select', 'select_me'])
|
||||||
|
def users_user_best_get(user, user_id):
|
||||||
|
# 查询用户所有best成绩
|
||||||
|
|
||||||
|
if user_id == 'me':
|
||||||
|
user_id = user.user_id
|
||||||
|
|
||||||
|
if user_id <= 0:
|
||||||
|
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
|
||||||
|
|
||||||
|
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
||||||
|
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
|
||||||
|
|
||||||
|
limit, offset, query, sort, code = get_query_parameter(request, ['song_id', 'difficulty'], [
|
||||||
|
'song_id', 'difficulty', 'score', 'time_played', 'rating'])
|
||||||
|
if code < 0:
|
||||||
|
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
|
||||||
|
|
||||||
|
data = api.users.get_user_best(user_id, limit, offset, query, sort)
|
||||||
|
|
||||||
|
if data['data'] == []:
|
||||||
|
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
|
||||||
|
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/users/<int:user_id>/r30', methods=['GET'])
|
||||||
|
@api.api_auth.role_required(request, ['select', 'select_me'])
|
||||||
|
def users_user_r30_get(user, user_id):
|
||||||
|
# 查询用户r30
|
||||||
|
|
||||||
|
if user_id == 'me':
|
||||||
|
user_id = user.user_id
|
||||||
|
|
||||||
|
if user_id <= 0:
|
||||||
|
return jsonify({'status': 200, 'code': -4, 'data': {}, 'msg': code_get_msg(-4)})
|
||||||
|
|
||||||
|
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
||||||
|
return jsonify({'status': 403, 'code': -1, 'data': {}, 'msg': 'No permission'})
|
||||||
|
|
||||||
|
data = api.users.get_user_r30(user_id)
|
||||||
|
|
||||||
|
if data['data'] == []:
|
||||||
|
return jsonify({'status': 200, 'code': -3, 'data': {}, 'msg': code_get_msg(-3)})
|
||||||
|
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/songs/<string:song_id>', methods=['GET'])
|
||||||
|
@api.api_auth.role_required(request, ['select', 'select_song_info'])
|
||||||
|
def songs_song_get(user, song_id):
|
||||||
|
# 查询歌曲信息
|
||||||
|
|
||||||
|
data = api.songs.get_song_info(song_id)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
|
||||||
|
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/songs', methods=['GET'])
|
||||||
|
@api.api_auth.role_required(request, ['select', 'select_song_info'])
|
||||||
|
def songs_get(user):
|
||||||
|
# 查询全歌曲信息
|
||||||
|
|
||||||
|
limit, offset, query, sort, code = get_query_parameter(request, ['sid', 'name_en', 'name_jp', 'pakset', 'artist'], [
|
||||||
|
'sid', 'name_en', 'name_jp', 'pakset', 'artist', 'date', 'rating_pst', 'rating_prs', 'rating_ftr', 'rating_byn'])
|
||||||
|
if code < 0:
|
||||||
|
return jsonify({'status': 200, 'code': code, 'data': {}, 'msg': code_get_msg(code)})
|
||||||
|
|
||||||
|
data = api.songs.get_songs(limit, offset, query, sort)
|
||||||
|
|
||||||
|
if not data:
|
||||||
|
return jsonify({'status': 200, 'code': -2, 'data': {}, 'msg': code_get_msg(-2)})
|
||||||
|
|
||||||
|
return jsonify({'status': 200, 'code': 0, 'data': data, 'msg': ''})
|
||||||
58
latest version/api/songs.py
Normal file
58
latest version/api/songs.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
from server.sql import Connect
|
||||||
|
from server.sql import Sql
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def get_song_info(song_id):
|
||||||
|
# 查询指定歌曲信息,返回字典
|
||||||
|
r = {}
|
||||||
|
|
||||||
|
with Connect('./database/arcsong.db') as c:
|
||||||
|
c.execute('''select * from songs where sid=:a''', {'a': song_id})
|
||||||
|
x = c.fetchone()
|
||||||
|
if x:
|
||||||
|
r = {'song_id': x[0],
|
||||||
|
'name': {'name_en': x[1],
|
||||||
|
'name_jp': x[2]},
|
||||||
|
'pakset': x[5],
|
||||||
|
'artist': x[6],
|
||||||
|
'date': x[9],
|
||||||
|
'rating_pst': x[12]/10,
|
||||||
|
'rating_prs': x[13]/10,
|
||||||
|
'rating_ftr': x[14]/10,
|
||||||
|
'rating_byn': x[15]/10,
|
||||||
|
'difficultly_pst': x[16]/2,
|
||||||
|
'difficultly_prs': x[17]/2,
|
||||||
|
'difficultly_ftr': x[18]/2,
|
||||||
|
'difficultly_byn': x[19]/2
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def get_songs(limit=-1, offset=0, query={}, sort=[]):
|
||||||
|
# 查询全部歌曲信息,返回字典列表
|
||||||
|
r = []
|
||||||
|
|
||||||
|
with Connect('./database/arcsong.db') as c:
|
||||||
|
x = Sql.select(c, 'songs', [], limit, offset, query, sort)
|
||||||
|
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
r.append({'sid': i[0],
|
||||||
|
'name': {'name_en': i[1],
|
||||||
|
'name_jp': i[2]},
|
||||||
|
'pakset': i[5],
|
||||||
|
'artist': i[6],
|
||||||
|
'date': i[9],
|
||||||
|
'rating_pst': i[12]/10,
|
||||||
|
'rating_prs': i[13]/10,
|
||||||
|
'rating_ftr': i[14]/10,
|
||||||
|
'rating_byn': i[15]/10,
|
||||||
|
'difficultly_pst': i[16]/2,
|
||||||
|
'difficultly_prs': i[17]/2,
|
||||||
|
'difficultly_ftr': i[18]/2,
|
||||||
|
'difficultly_byn': i[19]/2
|
||||||
|
})
|
||||||
|
|
||||||
|
return r
|
||||||
99
latest version/api/users.py
Normal file
99
latest version/api/users.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
from server.sql import Connect
|
||||||
|
from server.sql import Sql
|
||||||
|
import time
|
||||||
|
import web.webscore
|
||||||
|
import server.info
|
||||||
|
|
||||||
|
|
||||||
|
def get_users(limit=-1, offset=0, query={}, sort=[]):
|
||||||
|
# 获取全用户信息,返回字典列表
|
||||||
|
|
||||||
|
r = []
|
||||||
|
with Connect() as c:
|
||||||
|
x = Sql.select(c, 'user', [], limit, offset, query, sort)
|
||||||
|
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
if i[23] != -1:
|
||||||
|
character_id = i[23]
|
||||||
|
else:
|
||||||
|
character_id = i[6]
|
||||||
|
r.append({
|
||||||
|
'user_id': i[0],
|
||||||
|
'name': i[1],
|
||||||
|
'join_date': i[3],
|
||||||
|
'user_code': i[4],
|
||||||
|
'rating_ptt': i[5]/100,
|
||||||
|
'character_id': character_id,
|
||||||
|
'is_char_uncapped': i[8] == 1,
|
||||||
|
'is_char_uncapped_override': i[9] == 1,
|
||||||
|
'is_hide_rating': i[10],
|
||||||
|
'ticket': i[26]
|
||||||
|
})
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_info(user_id):
|
||||||
|
# 获取用户信息,返回字典,其实就是调用user/me信息
|
||||||
|
|
||||||
|
r = {}
|
||||||
|
with Connect() as c:
|
||||||
|
r = server.info.get_user_me(c, user_id)
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_b30(user_id):
|
||||||
|
# 获取用户b30信息,返回字典
|
||||||
|
|
||||||
|
r = []
|
||||||
|
with Connect() as c:
|
||||||
|
r = web.webscore.get_user_score(c, user_id, 30)
|
||||||
|
|
||||||
|
bestptt = 0
|
||||||
|
for i in r:
|
||||||
|
if i['rating']:
|
||||||
|
bestptt += i['rating']
|
||||||
|
if 'time_played' in i:
|
||||||
|
i['time_played'] = int(time.mktime(time.strptime(
|
||||||
|
i['time_played'], '%Y-%m-%d %H:%M:%S')))
|
||||||
|
|
||||||
|
return {'user_id': user_id, 'b30_ptt': bestptt / 30, 'data': r}
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_best(user_id, limit=-1, offset=0, query={}, sort=[]):
|
||||||
|
# 获取用户b30信息,返回字典
|
||||||
|
|
||||||
|
r = []
|
||||||
|
with Connect() as c:
|
||||||
|
x = Sql.select(c, 'best_score', [], limit, offset, query, sort)
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
r.append({
|
||||||
|
"song_id": i[1],
|
||||||
|
"difficulty": i[2],
|
||||||
|
"score": i[3],
|
||||||
|
"shiny_perfect_count": i[4],
|
||||||
|
"perfect_count": i[5],
|
||||||
|
"near_count": i[6],
|
||||||
|
"miss_count": i[7],
|
||||||
|
"health": i[8],
|
||||||
|
"modifier": i[9],
|
||||||
|
"time_played": i[10],
|
||||||
|
"best_clear_type": i[11],
|
||||||
|
"clear_type": i[12],
|
||||||
|
"rating": i[13]
|
||||||
|
})
|
||||||
|
|
||||||
|
return {'user_id': user_id, 'data': r}
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_r30(user_id):
|
||||||
|
# 获取用户r30信息,返回字典
|
||||||
|
|
||||||
|
r = []
|
||||||
|
with Connect() as c:
|
||||||
|
r, r10_ptt = web.webscore.get_user_recent30(c, user_id)
|
||||||
|
|
||||||
|
return {'user_id': user_id, 'r10_ptt': r10_ptt, 'data': r}
|
||||||
Binary file not shown.
Binary file not shown.
@@ -5,8 +5,17 @@ import json
|
|||||||
|
|
||||||
# 数据库初始化文件,删掉arcaea_database.db文件后运行即可,谨慎使用
|
# 数据库初始化文件,删掉arcaea_database.db文件后运行即可,谨慎使用
|
||||||
|
|
||||||
conn = sqlite3.connect('arcaea_database.db')
|
ARCAEA_SERVER_VERSION = 'v2.4.0'
|
||||||
|
|
||||||
|
|
||||||
|
def main(path='./'):
|
||||||
|
conn = sqlite3.connect(path+'arcaea_database.db')
|
||||||
c = conn.cursor()
|
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,
|
c.execute('''create table if not exists user(user_id int primary key,
|
||||||
name text unique,
|
name text unique,
|
||||||
password text not null,
|
password text not null,
|
||||||
@@ -33,13 +42,16 @@ rating real,
|
|||||||
favorite_character int,
|
favorite_character int,
|
||||||
max_stamina_notification_enabled int,
|
max_stamina_notification_enabled int,
|
||||||
current_map text,
|
current_map text,
|
||||||
ticket int
|
ticket int,
|
||||||
|
prog_boost int,
|
||||||
|
email text
|
||||||
);''')
|
);''')
|
||||||
c.execute('''create table if not exists login(access_token text,
|
c.execute('''create table if not exists login(access_token text,
|
||||||
user_id int primary key,
|
user_id int,
|
||||||
last_login_time int,
|
login_time int,
|
||||||
last_login_ip text,
|
login_ip text,
|
||||||
last_login_device text
|
login_device text,
|
||||||
|
primary key(access_token, user_id)
|
||||||
);''')
|
);''')
|
||||||
c.execute('''create table if not exists friend(user_id_me int,
|
c.execute('''create table if not exists friend(user_id_me int,
|
||||||
user_id_other int,
|
user_id_other int,
|
||||||
@@ -232,27 +244,69 @@ code text,
|
|||||||
primary key(user_id, code)
|
primary key(user_id, code)
|
||||||
);''')
|
);''')
|
||||||
|
|
||||||
|
c.execute('''create table if not exists role(role_id int primary key,
|
||||||
|
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)
|
||||||
|
);''')
|
||||||
|
|
||||||
|
# 搭档初始化
|
||||||
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',
|
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']
|
'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',
|
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']
|
'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',
|
skill_id_uncap = ['', '', 'frags_kou', '', 'visual_ink', '', '', '', '', '', '', '', '', 'shirabe_entry_fee',
|
||||||
'', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
|
'', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
|
||||||
|
|
||||||
for i in range(0, 41):
|
frag = [88, 90, 100, 75, 80, 0, 70, 79, 65, 40, 50, 80, 90, 92, 0, 61, 67, 92, 85, 50, 86, 62,
|
||||||
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
|
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]
|
||||||
sql = 'insert into character values('+str(
|
|
||||||
i)+',"'+char[i]+'''",30,25000,25000,90,90,90,"'''+skill_id[i]+'''",0,0,"'''+skill_id_uncap[i]+'''",0,'',1,1)'''
|
prog = [71, 90, 80, 75, 100, 0, 90, 102, 84, 78, 105, 67, 63, 78, 0, 99, 80, 66, 46, 83, 40, 83,
|
||||||
c.execute(sql)
|
80, 90, 93, 50, 96, 88, 99, 108, 75, 80, 50, 64, 55, 100, 100, 110, 80, 50, 74, 90, 80, 80, 56, 80]
|
||||||
|
|
||||||
|
overdrive = [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, 90, 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]
|
||||||
|
|
||||||
|
# print(len(char))
|
||||||
|
# print(len(skill_id))
|
||||||
|
# print(len(skill_id_uncap))
|
||||||
|
# print(len(frag))
|
||||||
|
# print(len(prog))
|
||||||
|
# print(len(overdrive))
|
||||||
|
# print(len(char_type))
|
||||||
|
|
||||||
|
for i in range(0, 46):
|
||||||
|
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21, 42, 43]:
|
||||||
|
sql = '''insert into character values(:a,:b,30,25000,25000,:c,:d,:e,:f,0,0,:g,:h,'',1,1)'''
|
||||||
|
c.execute(sql, {'a': i, 'b': char[i], 'c': frag[i], 'd': prog[i],
|
||||||
|
'e': overdrive[i], 'f': skill_id[i], 'g': skill_id_uncap[i], 'h': char_type[i]})
|
||||||
else:
|
else:
|
||||||
if i != 5:
|
if i != 5:
|
||||||
sql = 'insert into character values('+str(
|
sql = '''insert into character values(:a,:b,20,10000,10000,:c,:d,:e,:f,0,0,:g,:h,'',0,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, {'a': i, 'b': char[i], 'c': frag[i], 'd': prog[i],
|
||||||
c.execute(sql)
|
'e': overdrive[i], 'f': skill_id[i], 'g': skill_id_uncap[i], 'h': char_type[i]})
|
||||||
|
|
||||||
|
|
||||||
def b2int(x):
|
def b2int(x):
|
||||||
# int与布尔值转换
|
# int与布尔值转换
|
||||||
@@ -261,7 +315,6 @@ def b2int(x):
|
|||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def insert_items(c, items):
|
def insert_items(c, items):
|
||||||
# 物品数据导入
|
# 物品数据导入
|
||||||
for i in items:
|
for i in items:
|
||||||
@@ -282,21 +335,45 @@ def insert_items(c, items):
|
|||||||
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)''', {
|
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)''', {
|
||||||
'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})
|
'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})
|
||||||
|
|
||||||
|
# item初始化
|
||||||
f = open('singles.json', 'r')
|
f = open(path+'singles.json', 'r')
|
||||||
singles = json.load(f)
|
singles = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
insert_items(c, singles)
|
insert_items(c, singles)
|
||||||
|
|
||||||
f = open('packs.json', 'r')
|
f = open(path+'packs.json', 'r')
|
||||||
packs = json.load(f)
|
packs = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
insert_items(c, packs)
|
insert_items(c, packs)
|
||||||
|
|
||||||
|
# api权限与权限组初始化
|
||||||
|
role = ['admin', 'user', 'selecter']
|
||||||
|
role_caption = ['管理员', '用户', '查询接口']
|
||||||
|
|
||||||
|
power = ['select', 'select_me', 'change', 'change_me', 'grant',
|
||||||
|
'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]
|
||||||
|
}
|
||||||
|
|
||||||
|
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.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
def arc_register(name: str, password: str):
|
def arc_register(name: str, password: str):
|
||||||
def build_user_code(c):
|
def build_user_code(c):
|
||||||
return '123456789'
|
return '123456789'
|
||||||
@@ -324,7 +401,7 @@ def arc_register(name: str, password: str):
|
|||||||
c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', {
|
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]})
|
'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')
|
conn = sqlite3.connect(path+'arcaea_database.db')
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
|
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
|
||||||
c.execute(
|
c.execute(
|
||||||
@@ -350,5 +427,8 @@ def arc_register(name: str, password: str):
|
|||||||
conn.close()
|
conn.close()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
arc_register('admin', 'admin123')
|
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"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
@@ -3,154 +3,139 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "core",
|
"id": "core",
|
||||||
"_id": "5ff79fc6a6e343038b058bd3",
|
|
||||||
"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": "5ff79fc6a6e343038b058c18",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}, {
|
}, {
|
||||||
"type": "character",
|
"type": "character",
|
||||||
"id": "kou",
|
"id": "kou",
|
||||||
"_id": "5ff79fc6a6e343038b058c17",
|
|
||||||
"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": "5ff79fc6a6e343038b058c1c",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}, {
|
}, {
|
||||||
"type": "character",
|
"type": "character",
|
||||||
"id": "sapphire",
|
"id": "sapphire",
|
||||||
"_id": "5ff79fc6a6e343038b058c1b",
|
|
||||||
"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": "5ff79fc6a6e343038b058c10",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}, {
|
}, {
|
||||||
"type": "character",
|
"type": "character",
|
||||||
"id": "lethe",
|
"id": "lethe",
|
||||||
"_id": "5ff79fc6a6e343038b058c0f",
|
|
||||||
"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": "5ff79fc6a6e343038b058bd4",
|
|
||||||
"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": "5ff79fc6a6e343038b058bf9",
|
|
||||||
"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": "5ff79fc6a6e343038b058bd5",
|
|
||||||
"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": "5ff79fc6a6e343038b058c06",
|
|
||||||
"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": "5ff79fc6a6e343038b058bfb",
|
|
||||||
"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": "5ff79fc6a6e343038b058bf0",
|
|
||||||
"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": "5ff79fc6a6e343038b058c08",
|
|
||||||
"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": "5ff79fc6a6e343038b058be4",
|
|
||||||
"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": "5ff79fc6a6e343038b058bf1",
|
|
||||||
"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": "5ff79fc6a6e343038b058c09",
|
|
||||||
"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": "5ff79fc6a6e343038b058be7",
|
|
||||||
"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": "5ff79fc6a6e343038b058bf4",
|
|
||||||
"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": "5ff79fc6a6e343038b058c0e",
|
|
||||||
"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": "5ff79fc6a6e343038b058bde",
|
|
||||||
"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": "5ff79fc6a6e343038b058bea",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 400,
|
"orig_price": 400,
|
||||||
@@ -230,9 +216,35 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "pack",
|
"type": "pack",
|
||||||
"id": "maimai",
|
"id": "maimai",
|
||||||
"_id": "5ff79fc6a6e343038b058bf7",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 400,
|
"orig_price": 400,
|
||||||
"price": 400
|
"price": 400
|
||||||
|
}, {
|
||||||
|
"name": "chunithm_append_1",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "chunithm_append_1",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"orig_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": "5ff79fc6a6e343038b058beb",
|
|
||||||
"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": "5ff79fc6a6e343038b058bf8",
|
|
||||||
"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": "5ff79fc6a6e343038b058c03",
|
|
||||||
"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": "5ff79fc6a6e343038b058bdf",
|
|
||||||
"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": "5ff79fc6a6e343038b058bec",
|
|
||||||
"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": "5ff79fc6a6e343038b058c04",
|
|
||||||
"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": "5ff79fc6a6e343038b058be0",
|
|
||||||
"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": "5ff79fc6a6e343038b058bed",
|
|
||||||
"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": "5ff79fc6a6e343038b058c05",
|
|
||||||
"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": "5ff79fc6a6e343038b058be1",
|
|
||||||
"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": "5ff79fc6a6e343038b058bee",
|
|
||||||
"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": "5ff79fc6a6e343038b058bfa",
|
|
||||||
"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": "5ff79fc6a6e343038b058bd6",
|
|
||||||
"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": "5ff79fc6a6e343038b058be2",
|
|
||||||
"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": "5ff79fc6a6e343038b058bef",
|
|
||||||
"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": "5ff79fc6a6e343038b058c07",
|
|
||||||
"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": "5ff79fc6a6e343038b058bd7",
|
|
||||||
"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": "5ff79fc6a6e343038b058be3",
|
|
||||||
"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": "5ff79fc6a6e343038b058bfc",
|
|
||||||
"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": "5ff79fc6a6e343038b058bd8",
|
|
||||||
"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": "5ff79fc6a6e343038b058bfd",
|
|
||||||
"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": "5ff79fc6a6e343038b058bd9",
|
|
||||||
"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": "5ff79fc6a6e343038b058be5",
|
|
||||||
"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": "5ff79fc6a6e343038b058bf2",
|
|
||||||
"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": "5ff79fc6a6e343038b058bfe",
|
|
||||||
"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": "5ff79fc6a6e343038b058c0a",
|
|
||||||
"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": "5ff79fc6a6e343038b058bda",
|
|
||||||
"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": "5ff79fc6a6e343038b058be6",
|
|
||||||
"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": "5ff79fc6a6e343038b058bf3",
|
|
||||||
"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": "5ff79fc6a6e343038b058bff",
|
|
||||||
"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": "5ff79fc6a6e343038b058c0b",
|
|
||||||
"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": "5ff79fc6a6e343038b058bdb",
|
|
||||||
"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": "5ff79fc6a6e343038b058c00",
|
|
||||||
"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": "5ff79fc6a6e343038b058c0c",
|
|
||||||
"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": "5ff79fc6a6e343038b058bdc",
|
|
||||||
"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": "5ff79fc6a6e343038b058be8",
|
|
||||||
"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": "5ff79fc6a6e343038b058c01",
|
|
||||||
"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": "5ff79fc6a6e343038b058c0d",
|
|
||||||
"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": "5ff79fc6a6e343038b058bdd",
|
|
||||||
"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": "5ff79fc6a6e343038b058be9",
|
|
||||||
"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": "5ff79fc6a6e343038b058bf6",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"orig_price": 100,
|
"orig_price": 100,
|
||||||
@@ -458,9 +441,35 @@
|
|||||||
"items": [{
|
"items": [{
|
||||||
"type": "single",
|
"type": "single",
|
||||||
"id": "xanatos",
|
"id": "xanatos",
|
||||||
"_id": "5ff79fc6a6e343038b058c02",
|
|
||||||
"is_available": true
|
"is_available": true
|
||||||
}],
|
}],
|
||||||
"price": 100,
|
"price": 100,
|
||||||
"orig_price": 100
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "attraqtia",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "attraqtia",
|
||||||
|
"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
|
||||||
|
}],
|
||||||
|
"orig_price": 100,
|
||||||
|
"price": 100
|
||||||
}]
|
}]
|
||||||
0
latest version/log/error.log
Normal file
0
latest version/log/error.log
Normal file
@@ -1,6 +1,8 @@
|
|||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
from flask import Flask, request, jsonify, make_response, send_from_directory
|
from flask import Flask, request, jsonify, make_response, send_from_directory
|
||||||
from logging.config import dictConfig
|
from logging.config import dictConfig
|
||||||
import configparser
|
from setting import Config
|
||||||
import base64
|
import base64
|
||||||
import server.auth
|
import server.auth
|
||||||
import server.info
|
import server.info
|
||||||
@@ -8,15 +10,107 @@ 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 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 处理交易时发生了错误
|
||||||
@@ -70,6 +164,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']) # 图标
|
||||||
@@ -81,74 +176,76 @@ 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']
|
||||||
|
else:
|
||||||
|
device_id = 'low_version'
|
||||||
|
|
||||||
try:
|
token, error_code = server.auth.arc_login(
|
||||||
token, error_code = server.auth.arc_login(name, password)
|
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
|
||||||
return jsonify(r)
|
return jsonify(r)
|
||||||
else:
|
else:
|
||||||
return error_return(error_code)
|
return error_return(error_code)
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@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']
|
||||||
try:
|
email = request.form['email']
|
||||||
user_id, token, error_code = server.auth.arc_register(name, password)
|
if 'device_id' in request.form:
|
||||||
|
device_id = request.form['device_id']
|
||||||
|
else:
|
||||||
|
device_id = 'low_version'
|
||||||
|
|
||||||
|
user_id, token, error_code = server.auth.arc_register(
|
||||||
|
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)
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
# 集成式请求,没想到什么好办法处理,就先这样写着
|
# 集成式请求,没想到什么好办法处理,就先这样写着
|
||||||
@app.route('/latte/13/compose/aggregate', methods=['GET'])
|
@app.route(add_url_prefix('/compose/aggregate'), methods=['GET'])
|
||||||
def aggregate():
|
@server.auth.auth_required(request)
|
||||||
|
def aggregate(user_id):
|
||||||
calls = request.args.get('calls')
|
calls = request.args.get('calls')
|
||||||
headers = request.headers
|
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
if calls == '[{ "endpoint": "/user/me", "id": 0 }]': # 极其沙雕的判断,我猜get的参数就两种
|
if calls == '[{ "endpoint": "/user/me", "id": 0 }]': # 极其沙雕的判断,我猜get的参数就两种
|
||||||
r = server.info.arc_aggregate_small(user_id)
|
r = server.info.arc_aggregate_small(user_id)
|
||||||
else:
|
else:
|
||||||
r = server.info.arc_aggregate_big(user_id)
|
r = server.info.arc_aggregate_big(user_id)
|
||||||
return jsonify(r)
|
return jsonify(r)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/user/me/character', methods=['POST']) # 角色切换
|
@app.route(add_url_prefix('/user/me/character'), methods=['POST']) # 角色切换
|
||||||
def character_change():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def character_change(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
character_id = request.form['character']
|
character_id = request.form['character']
|
||||||
skill_sealed = request.form['skill_sealed']
|
skill_sealed = request.form['skill_sealed']
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
flag = server.setme.change_char(user_id, character_id, skill_sealed)
|
||||||
if user_id is not None:
|
|
||||||
flag = server.setme.change_char(
|
|
||||||
user_id, character_id, skill_sealed)
|
|
||||||
if flag:
|
if flag:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
@@ -159,21 +256,15 @@ def character_change():
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/<path:path>/toggle_uncap', methods=['POST']) # 角色觉醒切换
|
# 角色觉醒切换
|
||||||
def character_uncap(path):
|
@app.route(add_url_prefix('/<path:path>/toggle_uncap', True), methods=['POST'])
|
||||||
character_id = int(path[22:])
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def character_uncap(user_id, path):
|
||||||
token = headers['Authorization']
|
while '//' in path:
|
||||||
token = token[7:]
|
path = path.replace('//', '/')
|
||||||
try:
|
character_id = int(path[21:])
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
r = server.setme.change_char_uncap(user_id, character_id)
|
r = server.setme.change_char_uncap(user_id, character_id)
|
||||||
if r is not None:
|
if r is not None:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -185,22 +276,14 @@ def character_uncap(path):
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/friend/me/add', methods=['POST']) # 加好友
|
@app.route(add_url_prefix('/friend/me/add'), methods=['POST']) # 加好友
|
||||||
def add_friend():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def add_friend(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
friend_code = request.form['friend_code']
|
friend_code = request.form['friend_code']
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
friend_id = server.auth.code_get_id(friend_code)
|
friend_id = server.auth.code_get_id(friend_code)
|
||||||
if user_id is not None and friend_id is not None:
|
if friend_id is not None:
|
||||||
r = server.setme.arc_add_friend(user_id, friend_id)
|
r = server.setme.arc_add_friend(user_id, friend_id)
|
||||||
if r is not None and r != 602 and r != 604:
|
if r is not None and r != 602 and r != 604:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -218,23 +301,14 @@ def add_friend():
|
|||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
else:
|
||||||
if friend_id is None:
|
|
||||||
return error_return(401)
|
return error_return(401)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/friend/me/delete', methods=['POST']) # 删好友
|
@app.route(add_url_prefix('/friend/me/delete'), methods=['POST']) # 删好友
|
||||||
def delete_friend():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def delete_friend(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
friend_id = int(request.form['friend_id'])
|
friend_id = int(request.form['friend_id'])
|
||||||
try:
|
if friend_id is not None:
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None and friend_id is not None:
|
|
||||||
r = server.setme.arc_delete_friend(user_id, friend_id)
|
r = server.setme.arc_delete_friend(user_id, friend_id)
|
||||||
if r is not None:
|
if r is not None:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -249,24 +323,15 @@ def delete_friend():
|
|||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
else:
|
||||||
if friend_id is None:
|
|
||||||
return error_return(401)
|
return error_return(401)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/score/song/friend', methods=['GET']) # 好友排名,默认最多50
|
# 好友排名,默认最多50
|
||||||
def song_score_friend():
|
@app.route(add_url_prefix('/score/song/friend'), methods=['GET'])
|
||||||
|
@server.auth.auth_required(request)
|
||||||
|
def song_score_friend(user_id):
|
||||||
song_id = request.args.get('song_id')
|
song_id = request.args.get('song_id')
|
||||||
difficulty = request.args.get('difficulty')
|
difficulty = request.args.get('difficulty')
|
||||||
headers = request.headers
|
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
r = server.arcscore.arc_score_friend(user_id, song_id, difficulty)
|
r = server.arcscore.arc_score_friend(user_id, song_id, difficulty)
|
||||||
if r is not None:
|
if r is not None:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -275,22 +340,13 @@ def song_score_friend():
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
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
|
||||||
def song_score_me():
|
@server.auth.auth_required(request)
|
||||||
|
def song_score_me(user_id):
|
||||||
song_id = request.args.get('song_id')
|
song_id = request.args.get('song_id')
|
||||||
difficulty = request.args.get('difficulty')
|
difficulty = request.args.get('difficulty')
|
||||||
headers = request.headers
|
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
r = server.arcscore.arc_score_me(user_id, song_id, difficulty)
|
r = server.arcscore.arc_score_me(user_id, song_id, difficulty)
|
||||||
if r is not None:
|
if r is not None:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -299,22 +355,13 @@ def song_score_me():
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/score/song', methods=['GET']) # TOP20
|
@app.route(add_url_prefix('/score/song'), methods=['GET']) # TOP20
|
||||||
def song_score_top():
|
@server.auth.auth_required(request)
|
||||||
|
def song_score_top(user_id):
|
||||||
song_id = request.args.get('song_id')
|
song_id = request.args.get('song_id')
|
||||||
difficulty = request.args.get('difficulty')
|
difficulty = request.args.get('difficulty')
|
||||||
headers = request.headers
|
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
r = server.arcscore.arc_score_top(song_id, difficulty)
|
r = server.arcscore.arc_score_top(song_id, difficulty)
|
||||||
if r is not None:
|
if r is not None:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -323,17 +370,11 @@ def song_score_top():
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/score/song', methods=['POST']) # 成绩上传
|
@app.route(add_url_prefix('/score/song'), methods=['POST']) # 成绩上传
|
||||||
def song_score_post():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def song_score_post(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
song_token = request.form['song_token']
|
song_token = request.form['song_token']
|
||||||
song_hash = request.form['song_hash']
|
song_hash = request.form['song_hash']
|
||||||
song_id = request.form['song_id']
|
song_id = request.form['song_id']
|
||||||
@@ -349,16 +390,13 @@ def song_score_post():
|
|||||||
clear_type = int(request.form['clear_type'])
|
clear_type = int(request.form['clear_type'])
|
||||||
submission_hash = request.form['submission_hash']
|
submission_hash = request.form['submission_hash']
|
||||||
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
# 增加成绩校验
|
# 增加成绩校验
|
||||||
if not server.arcscore.arc_score_check(user_id, song_id, difficulty, score, shiny_perfect_count, perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type, song_token, song_hash, submission_hash):
|
if not server.arcscore.arc_score_check(user_id, song_id, difficulty, score, shiny_perfect_count, perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type, song_token, song_hash, submission_hash):
|
||||||
return error_return(107)
|
return error_return(107)
|
||||||
|
|
||||||
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:
|
if r is not None:
|
||||||
if re:
|
if re:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
@@ -371,13 +409,10 @@ def song_score_post():
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
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,
|
||||||
@@ -388,15 +423,10 @@ def score_token():
|
|||||||
|
|
||||||
|
|
||||||
# 世界模式成绩上传所需的token,无验证
|
# 世界模式成绩上传所需的token,无验证
|
||||||
@app.route('/latte/13/score/token/world', methods=['GET'])
|
@app.route(add_url_prefix('/score/token/world'), methods=['GET'])
|
||||||
def score_token_world():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def score_token_world(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
args = request.args
|
args = request.args
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id:
|
|
||||||
server.arcworld.play_world_song(user_id, args)
|
server.arcworld.play_world_song(user_id, args)
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
@@ -406,20 +436,11 @@ def score_token_world():
|
|||||||
"token": "13145201919810"
|
"token": "13145201919810"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/user/me/save', methods=['GET']) # 从云端同步
|
@app.route(add_url_prefix('/user/me/save'), methods=['GET']) # 从云端同步
|
||||||
def cloud_get():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def cloud_get(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
r = server.arcscore.arc_all_get(user_id)
|
r = server.arcscore.arc_all_get(user_id)
|
||||||
if r is not None:
|
if r is not None:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -428,17 +449,11 @@ def cloud_get():
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/user/me/save', methods=['POST']) # 向云端同步
|
@app.route(add_url_prefix('/user/me/save'), methods=['POST']) # 向云端同步
|
||||||
def cloud_post():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def cloud_post(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
scores_data = request.form['scores_data']
|
scores_data = request.form['scores_data']
|
||||||
clearlamps_data = request.form['clearlamps_data']
|
clearlamps_data = request.form['clearlamps_data']
|
||||||
clearedsongs_data = request.form['clearedsongs_data']
|
clearedsongs_data = request.form['clearedsongs_data']
|
||||||
@@ -446,9 +461,7 @@ def cloud_post():
|
|||||||
installid_data = request.form['installid_data']
|
installid_data = request.form['installid_data']
|
||||||
devicemodelname_data = request.form['devicemodelname_data']
|
devicemodelname_data = request.form['devicemodelname_data']
|
||||||
story_data = request.form['story_data']
|
story_data = request.form['story_data']
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
server.arcscore.arc_all_post(user_id, scores_data, clearlamps_data, clearedsongs_data,
|
server.arcscore.arc_all_post(user_id, scores_data, clearlamps_data, clearedsongs_data,
|
||||||
unlocklist_data, installid_data, devicemodelname_data, story_data)
|
unlocklist_data, installid_data, devicemodelname_data, story_data)
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -457,21 +470,12 @@ def cloud_post():
|
|||||||
"user_id": user_id
|
"user_id": user_id
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/purchase/me/redeem', methods=['POST']) # 兑换码
|
@app.route(add_url_prefix('/purchase/me/redeem'), methods=['POST']) # 兑换码
|
||||||
def redeem():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def redeem(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
code = request.form['code']
|
code = request.form['code']
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
fragment, error_code = server.arcpurchase.claim_user_redeem(
|
fragment, error_code = server.arcpurchase.claim_user_redeem(
|
||||||
user_id, code)
|
user_id, code)
|
||||||
if not error_code:
|
if not error_code:
|
||||||
@@ -487,21 +491,12 @@ def redeem():
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(error_code)
|
return error_return(error_code)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
# 礼物确认
|
# 礼物确认
|
||||||
@app.route('/latte/13/present/me/claim/<present_id>', methods=['POST'])
|
@app.route(add_url_prefix('/present/me/claim/<present_id>'), methods=['POST'])
|
||||||
def claim_present(present_id):
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def claim_present(user_id, present_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
flag = server.arcpurchase.claim_user_present(user_id, present_id)
|
flag = server.arcpurchase.claim_user_present(user_id, present_id)
|
||||||
if flag:
|
if flag:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -509,42 +504,39 @@ def claim_present(present_id):
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
# 购买,为了world模式boost一下
|
# 购买,world模式boost
|
||||||
@app.route('/latte/13/purchase/me/item', methods=['POST'])
|
@app.route(add_url_prefix('/purchase/me/item'), methods=['POST'])
|
||||||
def item():
|
@server.auth.auth_required(request)
|
||||||
return jsonify({
|
def prog_boost(user_id):
|
||||||
"success": True
|
re = {"success": False}
|
||||||
})
|
if 'item_id' in request.form:
|
||||||
|
if request.form['item_id'] == 'prog_boost_300':
|
||||||
|
ticket, error_code = server.arcpurchase.get_prog_boost(user_id)
|
||||||
|
if error_code:
|
||||||
|
return error_return(error_code)
|
||||||
|
|
||||||
|
re = {
|
||||||
|
"success": True,
|
||||||
|
"value": {'ticket': ticket}
|
||||||
|
}
|
||||||
|
return jsonify(re)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/purchase/me/pack', methods=['POST']) # 曲包和单曲购买
|
@app.route(add_url_prefix('/purchase/me/pack'), methods=['POST']) # 曲包和单曲购买
|
||||||
def pack():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def pack(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if 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'], 'pack'))
|
||||||
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'], 'single'))
|
||||||
else:
|
|
||||||
return error_return(108)
|
return jsonify({"success": True})
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
return jsonify({
|
|
||||||
"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,
|
||||||
@@ -552,15 +544,9 @@ def single():
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/world/map/me', methods=['GET']) # 获得世界模式信息,所有地图
|
@app.route(add_url_prefix('/world/map/me'), methods=['GET']) # 获得世界模式信息,所有地图
|
||||||
def world_all():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def world_all(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
try:
|
|
||||||
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id:
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
"value": {
|
"value": {
|
||||||
@@ -569,39 +555,22 @@ def world_all():
|
|||||||
"maps": server.arcworld.get_world_all(user_id)
|
"maps": server.arcworld.get_world_all(user_id)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/world/map/me/', methods=['POST']) # 进入地图
|
@app.route(add_url_prefix('/world/map/me/'), methods=['POST']) # 进入地图
|
||||||
def world_in():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def world_in(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
map_id = request.form['map_id']
|
map_id = request.form['map_id']
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id:
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
"value": server.arcworld.get_user_world(user_id, map_id)
|
"value": server.arcworld.get_user_world(user_id, map_id)
|
||||||
})
|
})
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/world/map/me/<map_id>', methods=['GET']) # 获得单个地图完整信息
|
# 获得单个地图完整信息
|
||||||
def world_one(map_id):
|
@app.route(add_url_prefix('/world/map/me/<map_id>'), methods=['GET'])
|
||||||
headers = request.headers
|
@server.auth.auth_required(request)
|
||||||
token = headers['Authorization']
|
def world_one(user_id, map_id):
|
||||||
token = token[7:]
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id:
|
|
||||||
server.arcworld.change_user_current_map(user_id, map_id)
|
server.arcworld.change_user_current_map(user_id, map_id)
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
@@ -611,21 +580,12 @@ def world_one(map_id):
|
|||||||
"maps": [server.arcworld.get_user_world_info(user_id, map_id)]
|
"maps": [server.arcworld.get_user_world_info(user_id, map_id)]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/13/serve/download/me/song', methods=['GET']) # 歌曲下载
|
@app.route(add_url_prefix('/serve/download/me/song'), methods=['GET']) # 歌曲下载
|
||||||
def download_song():
|
@server.auth.auth_required(request)
|
||||||
headers = request.headers
|
def download_song(user_id):
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
song_ids = request.args.getlist('sid')
|
song_ids = request.args.getlist('sid')
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id:
|
|
||||||
if server.arcdownload.is_able_download(user_id):
|
if server.arcdownload.is_able_download(user_id):
|
||||||
re = {}
|
re = {}
|
||||||
if not song_ids:
|
if not song_ids:
|
||||||
@@ -639,16 +599,12 @@ def download_song():
|
|||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
return error_return(903)
|
return error_return(903)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/download/<path:file_path>', methods=['GET']) # 下载
|
@app.route('/download/<path:file_path>', methods=['GET']) # 下载
|
||||||
def download(file_path):
|
def download(file_path):
|
||||||
t = request.args.get('t')
|
|
||||||
try:
|
try:
|
||||||
|
t = request.args.get('t')
|
||||||
message = server.arcdownload.is_token_able_download(t)
|
message = server.arcdownload.is_token_able_download(t)
|
||||||
if message == 0:
|
if message == 0:
|
||||||
path = os.path.join('./database/songs', file_path)
|
path = os.path.join('./database/songs', file_path)
|
||||||
@@ -662,58 +618,24 @@ def download(file_path):
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/latte/<path:path>', methods=['POST']) # 三个设置,写在最后降低优先级
|
# 三个设置,写在最后降低优先级
|
||||||
def sys_set(path):
|
@app.route(add_url_prefix('/<path:path>', True), methods=['POST'])
|
||||||
|
@server.auth.auth_required(request)
|
||||||
|
def sys_set(user_id, path):
|
||||||
set_arg = path[10:]
|
set_arg = path[10:]
|
||||||
headers = request.headers
|
|
||||||
token = headers['Authorization']
|
|
||||||
token = token[7:]
|
|
||||||
value = request.form['value']
|
value = request.form['value']
|
||||||
|
|
||||||
try:
|
|
||||||
user_id = server.auth.token_get_id(token)
|
|
||||||
if user_id is not None:
|
|
||||||
server.setme.arc_sys_set(user_id, value, set_arg)
|
server.setme.arc_sys_set(user_id, value, set_arg)
|
||||||
r = server.info.arc_aggregate_small(user_id)
|
r = server.info.arc_aggregate_small(user_id)
|
||||||
r['value'] = r['value'][0]['value']
|
r['value'] = r['value'][0]['value']
|
||||||
return jsonify(r)
|
return jsonify(r)
|
||||||
else:
|
|
||||||
return error_return(108)
|
|
||||||
except:
|
|
||||||
return error_return(108)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
config = configparser.ConfigParser()
|
if Config.SSL_CERT and Config.SSL_KEY:
|
||||||
path = r'setting.ini'
|
app.run(Config.HOST, Config.PORT, ssl_context=(
|
||||||
config.read(path, encoding="utf-8")
|
Config.SSL_CERT, Config.SSL_KEY))
|
||||||
HOST = config.get('CONFIG', 'HOST')
|
|
||||||
PORT = config.get('CONFIG', 'PORT')
|
|
||||||
app.config.from_mapping(SECRET_KEY='1145141919810')
|
|
||||||
app.register_blueprint(web.login.bp)
|
|
||||||
app.register_blueprint(web.index.bp)
|
|
||||||
|
|
||||||
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(HOST, PORT)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
python main.py
|
python -B main.py
|
||||||
@@ -2,10 +2,12 @@ import os
|
|||||||
import hashlib
|
import hashlib
|
||||||
from flask import url_for
|
from flask import url_for
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
from server.sql import Connect
|
||||||
import time
|
import time
|
||||||
|
from setting import Config
|
||||||
|
|
||||||
time_limit = 3000 # 每个玩家24小时下载次数限制
|
time_limit = Config.DOWNLOAD_TIMES_LIMIT # 每个玩家24小时下载次数限制
|
||||||
time_gap_limit = 1000 # 下载链接有效秒数
|
time_gap_limit = Config.DOWNLOAD_TIME_GAP_LIMIT # 下载链接有效秒数
|
||||||
|
|
||||||
|
|
||||||
def get_file_md5(file_path):
|
def get_file_md5(file_path):
|
||||||
@@ -13,17 +15,34 @@ def get_file_md5(file_path):
|
|||||||
if not os.path.isfile(file_path):
|
if not os.path.isfile(file_path):
|
||||||
return None
|
return None
|
||||||
myhash = hashlib.md5()
|
myhash = hashlib.md5()
|
||||||
f = open(file_path, 'rb')
|
with open(file_path, 'rb') as f:
|
||||||
while True:
|
while True:
|
||||||
b = f.read(8096)
|
b = f.read(8096)
|
||||||
if not b:
|
if not b:
|
||||||
break
|
break
|
||||||
myhash.update(b)
|
myhash.update(b)
|
||||||
f.close()
|
|
||||||
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 = {}
|
||||||
@@ -35,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(
|
||||||
@@ -46,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'] = {}
|
||||||
@@ -58,48 +80,46 @@ 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 = {}
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
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))
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
def get_some_songs(user_id, song_ids):
|
def get_some_songs(user_id, song_ids):
|
||||||
# 获取一些歌的下载链接,返回字典
|
# 获取一些歌的下载链接,返回字典
|
||||||
re = {}
|
re = {}
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
for song_id in song_ids:
|
for song_id in song_ids:
|
||||||
re.update(get_one_song(c, user_id, song_id))
|
re.update(get_one_song(c, user_id, song_id))
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
def is_token_able_download(t):
|
def is_token_able_download(t):
|
||||||
# token是否可以下载,返回错误码,0即可以
|
# token是否可以下载,返回错误码,0即可以
|
||||||
errorcode = 0
|
errorcode = 108
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute('''select * from download_token where token = :t limit 1''',
|
c.execute('''select * from download_token where token = :t limit 1''',
|
||||||
{'t': t})
|
{'t': t})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
@@ -111,21 +131,19 @@ def is_token_able_download(t):
|
|||||||
if y and y[0] <= time_limit:
|
if y and y[0] <= time_limit:
|
||||||
c.execute('''insert into user_download values(:a,:b,:c)''', {
|
c.execute('''insert into user_download values(:a,:b,:c)''', {
|
||||||
'a': x[0], 'b': x[3], 'c': now})
|
'a': x[0], 'b': x[3], 'c': now})
|
||||||
|
errorcode = 0
|
||||||
else:
|
else:
|
||||||
errorcode = 903
|
errorcode = 903
|
||||||
else:
|
else:
|
||||||
errorcode = 108
|
errorcode = 108
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return errorcode
|
return errorcode
|
||||||
|
|
||||||
|
|
||||||
def is_able_download(user_id):
|
def is_able_download(user_id):
|
||||||
# 是否可以下载,返回布尔值
|
# 是否可以下载,返回布尔值
|
||||||
f = True
|
f = False
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
c.execute(
|
c.execute(
|
||||||
'''delete from user_download where user_id = :a and time <= :b''', {'a': user_id, 'b': now - 24*3600})
|
'''delete from user_download where user_id = :a and time <= :b''', {'a': user_id, 'b': now - 24*3600})
|
||||||
@@ -133,12 +151,10 @@ def is_able_download(user_id):
|
|||||||
'''select count(*) from user_download where user_id = :a''', {'a': user_id})
|
'''select count(*) from user_download where user_id = :a''', {'a': user_id})
|
||||||
y = c.fetchone()
|
y = c.fetchone()
|
||||||
if y and y[0] <= time_limit:
|
if y and y[0] <= time_limit:
|
||||||
pass
|
f = True
|
||||||
else:
|
else:
|
||||||
f = False
|
f = False
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import sqlite3
|
from server.sql import Connect
|
||||||
|
import server.info
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@@ -41,26 +42,17 @@ def get_item(c, type='pack'):
|
|||||||
|
|
||||||
def get_single_purchase():
|
def get_single_purchase():
|
||||||
# main里面没开数据库,这里写一下代替
|
# main里面没开数据库,这里写一下代替
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
re = []
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
re = get_item(c, type='single')
|
re = get_item(c, type='single')
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
def buy_pack(user_id, pack_id):
|
def buy_item(c, user_id, price):
|
||||||
# 曲包购买,返回字典
|
# 购买接口,返回成功与否标识符和剩余源点数
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
c.execute('''select ticket from user where user_id = :a''',
|
||||||
c = conn.cursor()
|
{'a': user_id})
|
||||||
c.execute('''select price from item where item_id = :a''', {'a': pack_id})
|
|
||||||
price = c.fetchone()
|
|
||||||
if price:
|
|
||||||
price = price[0]
|
|
||||||
else:
|
|
||||||
price = 0
|
|
||||||
|
|
||||||
c.execute('''select ticket from user where user_id = :a''', {'a': user_id})
|
|
||||||
ticket = c.fetchone()
|
ticket = c.fetchone()
|
||||||
if ticket:
|
if ticket:
|
||||||
ticket = ticket[0]
|
ticket = ticket[0]
|
||||||
@@ -68,60 +60,79 @@ def buy_pack(user_id, pack_id):
|
|||||||
ticket = 0
|
ticket = 0
|
||||||
|
|
||||||
if ticket < price:
|
if ticket < price:
|
||||||
conn.commit()
|
return False, ticket
|
||||||
conn.close()
|
|
||||||
return {
|
|
||||||
"success": False
|
|
||||||
}
|
|
||||||
|
|
||||||
c.execute('''update user set ticket = :b where user_id = :a''',
|
c.execute('''update user set ticket = :b where user_id = :a''',
|
||||||
{'a': user_id, 'b': ticket-price})
|
{'a': user_id, 'b': ticket-price})
|
||||||
c.execute('''insert into user_item values(:a,:b,'pack')''',
|
|
||||||
{'a': user_id, 'b': pack_id})
|
|
||||||
|
|
||||||
conn.commit()
|
return True, ticket - price
|
||||||
conn.close()
|
|
||||||
return {
|
|
||||||
"success": True
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def buy_single(user_id, single_id):
|
def buy_thing(user_id, item_id, item_type):
|
||||||
# 单曲购买,返回字典
|
# 购买物品接口,返回字典
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
success_flag = False
|
||||||
c = conn.cursor()
|
|
||||||
c.execute('''select price from item where item_id = :a''',
|
|
||||||
{'a': single_id})
|
|
||||||
price = c.fetchone()
|
|
||||||
if price:
|
|
||||||
price = price[0]
|
|
||||||
else:
|
|
||||||
price = 0
|
|
||||||
|
|
||||||
c.execute('''select ticket from user where user_id = :a''', {'a': user_id})
|
|
||||||
ticket = c.fetchone()
|
|
||||||
if ticket:
|
|
||||||
ticket = ticket[0]
|
|
||||||
else:
|
|
||||||
ticket = 0
|
ticket = 0
|
||||||
|
packs = []
|
||||||
|
singles = []
|
||||||
|
characters = []
|
||||||
|
|
||||||
|
with Connect() as c:
|
||||||
|
c.execute('''select is_available, price, orig_price, discount_from, discount_to from item where item_id=:a and type=:b''',
|
||||||
|
{'a': item_id, 'b': item_type})
|
||||||
|
x = c.fetchone()
|
||||||
|
price = 0
|
||||||
|
flag = False
|
||||||
|
if x:
|
||||||
|
is_available = x[0]
|
||||||
|
price = x[1]
|
||||||
|
orig_price = x[2]
|
||||||
|
discount_from = x[3]
|
||||||
|
discount_to = x[4]
|
||||||
|
|
||||||
|
if not is_available:
|
||||||
|
return False
|
||||||
|
|
||||||
|
now = int(time.time() * 1000)
|
||||||
|
if not(discount_from <= now <= discount_to):
|
||||||
|
price = orig_price
|
||||||
|
|
||||||
|
flag, ticket = buy_item(c, user_id, price)
|
||||||
|
|
||||||
|
if flag:
|
||||||
|
c.execute('''insert into user_item values(:a,:b,:c)''',
|
||||||
|
{'a': user_id, 'b': item_id, 'c': item_type})
|
||||||
|
|
||||||
|
success_flag = True
|
||||||
|
|
||||||
|
packs = server.info.get_user_packs(c, user_id)
|
||||||
|
singles = server.info.get_user_singles(c, user_id)
|
||||||
|
characters = server.info.get_user_characters(c, user_id)
|
||||||
|
|
||||||
if ticket < price:
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return {
|
return {
|
||||||
"success": False
|
"success": success_flag,
|
||||||
|
"value": {'user_id': user_id,
|
||||||
|
'ticket': ticket,
|
||||||
|
'packs': packs,
|
||||||
|
'singles': singles,
|
||||||
|
'characters': characters
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.execute('''update user set ticket = :b where user_id = :a''',
|
|
||||||
{'a': user_id, 'b': ticket-price})
|
|
||||||
c.execute('''insert into user_item values(:a,:b,'single')''',
|
|
||||||
{'a': user_id, 'b': single_id})
|
|
||||||
|
|
||||||
conn.commit()
|
def get_prog_boost(user_id):
|
||||||
conn.close()
|
# 世界模式源韵强化,扣50源点,返回剩余源点数
|
||||||
return {
|
|
||||||
"success": True
|
ticket = -1
|
||||||
}
|
with Connect() as c:
|
||||||
|
flag, ticket = buy_item(c, user_id, 50)
|
||||||
|
|
||||||
|
if flag:
|
||||||
|
c.execute('''update user set prog_boost = 1 where user_id = :a''', {
|
||||||
|
'a': user_id})
|
||||||
|
if ticket >= 0:
|
||||||
|
return ticket, None
|
||||||
|
else:
|
||||||
|
return 0, 108
|
||||||
|
|
||||||
|
|
||||||
def get_user_present(c, user_id):
|
def get_user_present(c, user_id):
|
||||||
@@ -146,13 +157,10 @@ def get_user_present(c, user_id):
|
|||||||
def claim_user_present(user_id, present_id):
|
def claim_user_present(user_id, present_id):
|
||||||
# 确认并删除用户奖励,返回成功与否的布尔值
|
# 确认并删除用户奖励,返回成功与否的布尔值
|
||||||
flag = False
|
flag = False
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
c.execute('''select exists(select * from user_present where user_id=:a and present_id=:b)''',
|
c.execute('''select exists(select * from user_present where user_id=:a and present_id=:b)''',
|
||||||
{'a': user_id, 'b': present_id})
|
{'a': user_id, 'b': present_id})
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (1,):
|
||||||
flag = True
|
|
||||||
c.execute('''delete from user_present where user_id=:a and present_id=:b''',
|
c.execute('''delete from user_present where user_id=:a and present_id=:b''',
|
||||||
{'a': user_id, 'b': present_id})
|
{'a': user_id, 'b': present_id})
|
||||||
c.execute('''select * from present where present_id=:b''',
|
c.execute('''select * from present where present_id=:b''',
|
||||||
@@ -170,41 +178,33 @@ def claim_user_present(user_id, present_id):
|
|||||||
ticket += int(i['amount'])
|
ticket += int(i['amount'])
|
||||||
c.execute('''update user set ticket=:b where user_id=:a''', {
|
c.execute('''update user set ticket=:b where user_id=:a''', {
|
||||||
'a': user_id, 'b': ticket})
|
'a': user_id, 'b': ticket})
|
||||||
|
flag = True
|
||||||
else:
|
else:
|
||||||
# 过期
|
# 过期
|
||||||
flag = False
|
flag = False
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return flag
|
return flag
|
||||||
|
|
||||||
|
|
||||||
def claim_user_redeem(user_id, code):
|
def claim_user_redeem(user_id, code):
|
||||||
# 处理兑换码,返回碎片数量和错误码
|
# 处理兑换码,返回碎片数量和错误码
|
||||||
fragment = 0
|
fragment = 0
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
error_code = 108
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
c.execute('''select * from redeem where code=:a''', {'a': code})
|
c.execute('''select * from redeem where code=:a''', {'a': code})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
if not x:
|
if not x:
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return 0, 504
|
return 0, 504
|
||||||
|
|
||||||
if x[2] == 0: # 一次性
|
if x[2] == 0: # 一次性
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from user_redeem where code=:a)''', {'a': code})
|
'''select exists(select * from user_redeem where code=:a)''', {'a': code})
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (1,):
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return 0, 505
|
return 0, 505
|
||||||
elif x[2] == 1: # 每个玩家一次
|
elif x[2] == 1: # 每个玩家一次
|
||||||
c.execute('''select exists(select * from user_redeem where code=:a and user_id=:b)''',
|
c.execute('''select exists(select * from user_redeem where code=:a and user_id=:b)''',
|
||||||
{'a': code, 'b': user_id})
|
{'a': code, 'b': user_id})
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (1,):
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return 0, 506
|
return 0, 506
|
||||||
|
|
||||||
c.execute('''insert into user_redeem values(:b,:a)''',
|
c.execute('''insert into user_redeem values(:b,:a)''',
|
||||||
@@ -221,7 +221,6 @@ def claim_user_redeem(user_id, code):
|
|||||||
ticket += int(i['amount'])
|
ticket += int(i['amount'])
|
||||||
c.execute('''update user set ticket=:b where user_id=:a''', {
|
c.execute('''update user set ticket=:b where user_id=:a''', {
|
||||||
'a': user_id, 'b': ticket})
|
'a': user_id, 'b': ticket})
|
||||||
|
error_code = None
|
||||||
|
|
||||||
conn.commit()
|
return fragment, error_code
|
||||||
conn.close()
|
|
||||||
return fragment, None
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
import sqlite3
|
from server.sql import Connect
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
@@ -23,17 +23,17 @@ def get_world_name(file_dir='./database/map'):
|
|||||||
|
|
||||||
def get_world_info(map_id):
|
def get_world_info(map_id):
|
||||||
# 读取json文件内容,返回字典
|
# 读取json文件内容,返回字典
|
||||||
f = open('./database/map/'+map_id+'.json', 'r')
|
world_info = {}
|
||||||
|
with open('./database/map/'+map_id+'.json', 'r') as f:
|
||||||
world_info = json.load(f)
|
world_info = json.load(f)
|
||||||
f.close()
|
|
||||||
return world_info
|
return world_info
|
||||||
|
|
||||||
|
|
||||||
def get_user_world_info(user_id, map_id):
|
def get_user_world_info(user_id, map_id):
|
||||||
# 读取json文件内容,加上用户信息,返回字典
|
# 读取json文件内容,加上用户信息,返回字典
|
||||||
info = get_world_info(map_id)
|
info = get_world_info(map_id)
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute('''select * from user_world where map_id = :a and user_id = :b''',
|
c.execute('''select * from user_world where map_id = :a and user_id = :b''',
|
||||||
{'a': map_id, 'b': user_id})
|
{'a': map_id, 'b': user_id})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
@@ -44,33 +44,28 @@ def get_user_world_info(user_id, map_id):
|
|||||||
else:
|
else:
|
||||||
c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
|
c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
|
||||||
'a': user_id, 'b': map_id})
|
'a': user_id, 'b': map_id})
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
|
||||||
def get_current_map(user_id):
|
def get_current_map(user_id):
|
||||||
# 得到user的当前图,返回字符串
|
# 得到user的当前图,返回字符串
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
re = ''
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
c.execute('''select current_map from user where user_id = :a''',
|
c.execute('''select current_map from user where user_id = :a''',
|
||||||
{'a': user_id})
|
{'a': user_id})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
re = ''
|
|
||||||
if x:
|
if x:
|
||||||
re = x[0]
|
re = x[0]
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
def get_world_all(user_id):
|
def get_world_all(user_id):
|
||||||
# 读取所有地图信息并处理,返回字典列表
|
# 读取所有地图信息并处理,返回字典列表
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
|
||||||
c = conn.cursor()
|
|
||||||
worlds = get_world_name()
|
|
||||||
re = []
|
re = []
|
||||||
|
with Connect() as c:
|
||||||
|
worlds = get_world_name()
|
||||||
for map_id in worlds:
|
for map_id in worlds:
|
||||||
info = get_world_info(map_id)
|
info = get_world_info(map_id)
|
||||||
steps = info['steps']
|
steps = info['steps']
|
||||||
@@ -94,15 +89,13 @@ def get_world_all(user_id):
|
|||||||
|
|
||||||
re.append(info)
|
re.append(info)
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
def get_user_world(user_id, map_id):
|
def get_user_world(user_id, map_id):
|
||||||
# 获取用户图信息,返回字典
|
# 获取用户图信息,返回字典
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
re = {}
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
c.execute('''select * from user_world where map_id = :a and user_id = :b''',
|
c.execute('''select * from user_world where map_id = :a and user_id = :b''',
|
||||||
{'a': map_id, 'b': user_id})
|
{'a': map_id, 'b': user_id})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
@@ -121,27 +114,20 @@ def get_user_world(user_id, map_id):
|
|||||||
c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
|
c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
|
||||||
'a': user_id, 'b': map_id})
|
'a': user_id, 'b': map_id})
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
def change_user_current_map(user_id, map_id):
|
def change_user_current_map(user_id, map_id):
|
||||||
# 改变用户当前图
|
# 改变用户当前图
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute('''update user set current_map = :a where user_id=:b''', {
|
c.execute('''update user set current_map = :a where user_id=:b''', {
|
||||||
'a': map_id, 'b': user_id})
|
'a': map_id, 'b': user_id})
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def play_world_song(user_id, args):
|
def play_world_song(user_id, args):
|
||||||
# 声明是世界模式的打歌,并且记录加成信息
|
# 声明是世界模式的打歌,并且记录加成信息
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
stamina_multiply = 1
|
stamina_multiply = 1
|
||||||
fragment_multiply = 100
|
fragment_multiply = 100
|
||||||
prog_boost_multiply = 0
|
prog_boost_multiply = 0
|
||||||
@@ -150,15 +136,17 @@ def play_world_song(user_id, args):
|
|||||||
if 'fragment_multiply' in args:
|
if 'fragment_multiply' in args:
|
||||||
fragment_multiply = int(args['fragment_multiply'])
|
fragment_multiply = int(args['fragment_multiply'])
|
||||||
if 'prog_boost_multiply' in args:
|
if 'prog_boost_multiply' in args:
|
||||||
prog_boost_multiply = int(args['prog_boost_multiply'])
|
c.execute('''select prog_boost from user where user_id=:a''', {
|
||||||
|
'a': user_id})
|
||||||
|
x = c.fetchone()
|
||||||
|
if x and x[0] == 1:
|
||||||
|
prog_boost_multiply = 300
|
||||||
|
|
||||||
c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', {
|
c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', {
|
||||||
'a': user_id, 'b': args['song_id'], 'c': args['difficulty']})
|
'a': user_id, 'b': args['song_id'], 'c': args['difficulty']})
|
||||||
c.execute('''insert into world_songplay values(:a,:b,:c,:d,:e,:f)''', {
|
c.execute('''insert into world_songplay values(:a,:b,:c,:d,:e,:f)''', {
|
||||||
'a': user_id, 'b': args['song_id'], 'c': args['difficulty'], 'd': stamina_multiply, 'e': fragment_multiply, 'f': prog_boost_multiply})
|
'a': user_id, 'b': args['song_id'], 'c': args['difficulty'], 'd': stamina_multiply, 'e': fragment_multiply, 'f': prog_boost_multiply})
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
import sqlite3
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import time
|
import time
|
||||||
import server.arcworld
|
from server.sql import Connect
|
||||||
|
import functools
|
||||||
|
from setting import Config
|
||||||
|
from flask import jsonify
|
||||||
|
|
||||||
|
|
||||||
def arc_login(name: str, password: str) -> 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
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
error_code = 108
|
||||||
c = conn.cursor()
|
|
||||||
error_code = None
|
|
||||||
token = None
|
token = None
|
||||||
|
with Connect() as c:
|
||||||
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
|
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
|
||||||
c.execute('''select user_id, password from user where name = :name''', {
|
c.execute('''select user_id, password from user where name = :name''', {
|
||||||
'name': name})
|
'name': name})
|
||||||
@@ -27,14 +28,33 @@ def arc_login(name: str, password: str) -> str: # 登录判断
|
|||||||
token = hashlib.sha256(
|
token = hashlib.sha256(
|
||||||
(user_id + str(now)).encode("utf8")).hexdigest()
|
(user_id + str(now)).encode("utf8")).hexdigest()
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from login where user_id = :user_id)''', {"user_id": user_id})
|
'''select login_device from login where user_id = :user_id''', {"user_id": user_id})
|
||||||
|
y = c.fetchall()
|
||||||
|
if y:
|
||||||
|
device_list = []
|
||||||
|
for i in y:
|
||||||
|
if i[0]:
|
||||||
|
device_list.append(i[0])
|
||||||
|
else:
|
||||||
|
device_list.append('')
|
||||||
|
|
||||||
if c.fetchone() == (1,): # 删掉多余token
|
should_delete_num = len(
|
||||||
c.execute('''delete from login where user_id = :user_id''',
|
device_list) + 1 - Config.LOGIN_DEVICE_NUMBER_LIMIT
|
||||||
{'user_id': user_id})
|
|
||||||
|
|
||||||
c.execute('''insert into login(access_token, user_id) values(:access_token, :user_id)''', {
|
if not Config.ALLOW_LOGIN_SAME_DEVICE:
|
||||||
'user_id': user_id, 'access_token': token})
|
if device_id in device_list: # 对相同设备进行删除
|
||||||
|
c.execute('''delete from login where login_device=:a and user_id=:b''', {
|
||||||
|
'a': device_id, 'b': user_id})
|
||||||
|
should_delete_num = len(
|
||||||
|
device_list) + 1 - device_list.count(device_id) - Config.LOGIN_DEVICE_NUMBER_LIMIT
|
||||||
|
|
||||||
|
if should_delete_num >= 1: # 删掉多余token
|
||||||
|
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)})
|
||||||
|
|
||||||
|
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, 'time': now, 'ip': ip})
|
||||||
|
error_code = None
|
||||||
else:
|
else:
|
||||||
# 密码错误
|
# 密码错误
|
||||||
error_code = 104
|
error_code = 104
|
||||||
@@ -42,13 +62,11 @@ def arc_login(name: str, password: str) -> str: # 登录判断
|
|||||||
# 用户名错误
|
# 用户名错误
|
||||||
error_code = 104
|
error_code = 104
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return token, error_code
|
return token, error_code
|
||||||
|
|
||||||
|
|
||||||
def arc_register(name: str, password: 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):
|
||||||
@@ -81,68 +99,94 @@ def arc_register(name: str, password: str): # 注册
|
|||||||
c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', {
|
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]})
|
'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('./database/arcaea_database.db')
|
user_id = None
|
||||||
c = conn.cursor()
|
token = None
|
||||||
|
error_code = 108
|
||||||
|
with Connect() as c:
|
||||||
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) values(:access_token, :user_id)''', {
|
c.execute('''insert into login values(:access_token, :user_id, :time, :ip, :device_id)''', {
|
||||||
'user_id': user_id, 'access_token': token})
|
'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)
|
||||||
conn.commit()
|
error_code = 0
|
||||||
conn.close()
|
|
||||||
return user_id, token, 0
|
|
||||||
else:
|
else:
|
||||||
conn.commit()
|
error_code = 102
|
||||||
conn.close()
|
else:
|
||||||
return None, None, 101
|
error_code = 101
|
||||||
|
|
||||||
|
return user_id, token, error_code
|
||||||
|
|
||||||
|
|
||||||
def token_get_id(token: str):
|
def token_get_id(token: str):
|
||||||
# 用token获取id,没有考虑不同用户token相同情况,说不定会有bug
|
# 用token获取id,没有考虑不同用户token相同情况,说不定会有bug
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
user_id = None
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
c.execute('''select user_id from login where access_token = :token''', {
|
c.execute('''select user_id from login where access_token = :token''', {
|
||||||
'token': token})
|
'token': token})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
if x is not None:
|
if x is not None:
|
||||||
conn.commit()
|
user_id = x[0]
|
||||||
conn.close()
|
|
||||||
return x[0]
|
return user_id
|
||||||
else:
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def code_get_id(user_code):
|
def code_get_id(user_code):
|
||||||
# 用user_code获取id
|
# 用user_code获取id
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
user_id = None
|
||||||
c = conn.cursor()
|
|
||||||
|
with Connect() as c:
|
||||||
c.execute('''select user_id from user where user_code = :a''',
|
c.execute('''select user_id from user where user_code = :a''',
|
||||||
{'a': user_code})
|
{'a': user_code})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
if x is not None:
|
if x is not None:
|
||||||
conn.commit()
|
user_id = x[0]
|
||||||
conn.close()
|
|
||||||
return x[0]
|
return user_id
|
||||||
|
|
||||||
|
|
||||||
|
def auth_required(request):
|
||||||
|
# arcaea登录验证,写成了修饰器
|
||||||
|
def decorator(view):
|
||||||
|
@functools.wraps(view)
|
||||||
|
def wrapped_view(*args, **kwargs):
|
||||||
|
|
||||||
|
user_id = None
|
||||||
|
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 = token[7:]
|
||||||
|
user_id = token_get_id(token)
|
||||||
|
|
||||||
|
if user_id is not None:
|
||||||
|
return view(user_id, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
conn.commit()
|
return jsonify({"success": False, "error_code": 108})
|
||||||
conn.close()
|
|
||||||
return None
|
return wrapped_view
|
||||||
|
return decorator
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import sqlite3
|
from server.sql import Connect
|
||||||
import server.arcworld
|
import server.arcworld
|
||||||
import server.arcpurchase
|
import server.arcpurchase
|
||||||
|
import server.arcdownload
|
||||||
import time
|
import time
|
||||||
|
from setting import Config
|
||||||
|
|
||||||
|
|
||||||
def int2b(x):
|
def int2b(x):
|
||||||
@@ -116,12 +118,16 @@ def get_user_friend(c, user_id):
|
|||||||
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]),
|
||||||
@@ -160,18 +166,39 @@ def get_user_packs(c, user_id):
|
|||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
def get_value_0(c, user_id):
|
def get_user_characters(c, user_id):
|
||||||
# 构造value id=0的数据,返回字典
|
# 获取用户所拥有角色,返回列表
|
||||||
|
|
||||||
|
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_me(c, user_id):
|
||||||
|
# 构造user/me的数据,返回字典
|
||||||
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 = 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'])
|
||||||
|
|
||||||
r = {"is_aprilfools": False,
|
prog_boost = 0
|
||||||
|
if x[27] and x[27] != 0:
|
||||||
|
prog_boost = 300
|
||||||
|
|
||||||
|
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),
|
||||||
@@ -189,21 +216,21 @@ def get_value_0(c, user_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],
|
||||||
"prog_boost": 0,
|
"prog_boost": prog_boost,
|
||||||
"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": ["scenery_chap1", "scenery_chap2", "scenery_chap3", "scenery_chap4", "scenery_chap5"],
|
||||||
"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"],
|
"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"],
|
||||||
"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": get_user_singles(c, user_id),
|
||||||
"packs": get_user_packs(c, user_id),
|
"packs": get_user_packs(c, user_id),
|
||||||
# ["vs", "extend", "dynamix", "prelude", "core", "yugamu", "omatsuri", "zettai", "mirai", "shiawase", "chunithm", "nijuusei", "groovecoaster", "rei", "tonesphere", "lanota"]
|
|
||||||
"characters": characters,
|
"characters": characters,
|
||||||
"cores": [],
|
"cores": [],
|
||||||
"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": 114514
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
@@ -211,34 +238,31 @@ def get_value_0(c, user_id):
|
|||||||
|
|
||||||
def arc_aggregate_small(user_id):
|
def arc_aggregate_small(user_id):
|
||||||
# 返回用户数据
|
# 返回用户数据
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
r = {"success": False}
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
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)
|
||||||
}]}
|
}]}
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def arc_aggregate_big(user_id):
|
def arc_aggregate_big(user_id):
|
||||||
# 返回用户数据和地图歌曲信息
|
# 返回比较全的用户数据
|
||||||
|
r = {"success": False}
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
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_item(c, 'pack')
|
||||||
}, {
|
}, {
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"value": {}
|
"value": server.arcdownload.get_all_songs(user_id, url_flag=False)
|
||||||
}, {
|
}, {
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"value": {
|
"value": {
|
||||||
@@ -353,6 +377,4 @@ def arc_aggregate_big(user_id):
|
|||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return r
|
return r
|
||||||
|
|||||||
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
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import sqlite3
|
from server.sql import Connect
|
||||||
import server.info
|
import server.info
|
||||||
|
|
||||||
|
|
||||||
@@ -20,8 +20,9 @@ def int2b(x):
|
|||||||
|
|
||||||
def change_char(user_id, character_id, skill_sealed):
|
def change_char(user_id, character_id, skill_sealed):
|
||||||
# 角色改变,包括技能封印的改变,返回成功与否的布尔值
|
# 角色改变,包括技能封印的改变,返回成功与否的布尔值
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
re = False
|
||||||
c = conn.cursor()
|
|
||||||
|
with Connect() as c:
|
||||||
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()
|
||||||
@@ -33,23 +34,19 @@ def change_char(user_id, character_id, skill_sealed):
|
|||||||
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': x[0], 'd': x[1], 'e': user_id})
|
||||||
|
|
||||||
conn.commit()
|
re = True
|
||||||
conn.close()
|
|
||||||
return True
|
|
||||||
|
|
||||||
conn.commit()
|
return re
|
||||||
conn.close()
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def change_char_uncap(user_id, character_id):
|
def change_char_uncap(user_id, character_id):
|
||||||
# 角色觉醒改变,返回字典
|
# 角色觉醒改变,返回字典
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
r = None
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
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()
|
||||||
r = None
|
|
||||||
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})
|
||||||
@@ -83,15 +80,12 @@ def change_char_uncap(user_id, character_id):
|
|||||||
"character_id": y[1]
|
"character_id": y[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def arc_sys_set(user_id, value, set_arg):
|
def arc_sys_set(user_id, value, set_arg):
|
||||||
# 三个设置,PTT隐藏、体力满通知、最爱角色,无返回
|
# 三个设置,PTT隐藏、体力满通知、最爱角色,无返回
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
if 'favorite_character' in set_arg:
|
if 'favorite_character' in set_arg:
|
||||||
value = int(value)
|
value = int(value)
|
||||||
c.execute('''update user set favorite_character = :a where user_id = :b''', {
|
c.execute('''update user set favorite_character = :a where user_id = :b''', {
|
||||||
@@ -110,8 +104,6 @@ def arc_sys_set(user_id, value, set_arg):
|
|||||||
c.execute('''update user set max_stamina_notification_enabled = :a where user_id = :b''', {
|
c.execute('''update user set max_stamina_notification_enabled = :a where user_id = :b''', {
|
||||||
'a': b2int(value), 'b': user_id})
|
'a': b2int(value), 'b': user_id})
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -119,37 +111,32 @@ def arc_add_friend(user_id, friend_id):
|
|||||||
# 加好友,返回好友列表,或者是错误码602、604
|
# 加好友,返回好友列表,或者是错误码602、604
|
||||||
if user_id == friend_id:
|
if user_id == friend_id:
|
||||||
return 604
|
return 604
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
|
||||||
c = conn.cursor()
|
r = None
|
||||||
|
with Connect() as c:
|
||||||
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
|
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
|
||||||
{'x': user_id, 'y': friend_id})
|
{'x': user_id, 'y': friend_id})
|
||||||
r = None
|
|
||||||
if c.fetchone() == (0,):
|
if c.fetchone() == (0,):
|
||||||
c.execute('''insert into friend values(:a, :b)''',
|
c.execute('''insert into friend values(:a, :b)''',
|
||||||
{'a': user_id, 'b': friend_id})
|
{'a': user_id, 'b': friend_id})
|
||||||
r = server.info.get_user_friend(c, user_id)
|
r = server.info.get_user_friend(c, user_id)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return 602
|
r = 602
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
def arc_delete_friend(user_id, friend_id):
|
def arc_delete_friend(user_id, friend_id):
|
||||||
# 删好友,返回好友列表
|
# 删好友,返回好友列表
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
r = None
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
|
|
||||||
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
|
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
|
||||||
{'x': user_id, 'y': friend_id})
|
{'x': user_id, 'y': friend_id})
|
||||||
r = None
|
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (1,):
|
||||||
c.execute('''delete from friend where user_id_me = :x and user_id_other = :y''',
|
c.execute('''delete from friend where user_id_me = :x and user_id_other = :y''',
|
||||||
{'x': user_id, 'y': friend_id})
|
{'x': user_id, 'y': friend_id})
|
||||||
|
|
||||||
r = server.info.get_user_friend(c, user_id)
|
r = server.info.get_user_friend(c, user_id)
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return r
|
return r
|
||||||
|
|||||||
80
latest version/server/sql.py
Normal file
80
latest version/server/sql.py
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import sqlite3
|
||||||
|
from flask import current_app
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
class Connect():
|
||||||
|
# 数据库连接类,上下文管理
|
||||||
|
|
||||||
|
def __init__(self, file_path='./database/arcaea_database.db'):
|
||||||
|
"""
|
||||||
|
数据库连接,默认连接arcaea_database.db
|
||||||
|
接受:文件路径
|
||||||
|
返回:sqlite3连接操作对象
|
||||||
|
"""
|
||||||
|
self.file_path = file_path
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.conn = sqlite3.connect(self.file_path)
|
||||||
|
self.c = self.conn.cursor()
|
||||||
|
return self.c
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
if self.conn:
|
||||||
|
self.conn.commit()
|
||||||
|
self.conn.close()
|
||||||
|
|
||||||
|
if exc_type is not None:
|
||||||
|
current_app.logger.error(
|
||||||
|
traceback.format_exception(exc_type, exc_val, exc_tb))
|
||||||
|
|
||||||
|
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()
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[CONFIG]
|
|
||||||
HOST = 192.168.1.113
|
|
||||||
PORT = 80
|
|
||||||
|
|
||||||
[WEB]
|
|
||||||
USERNAME = admin
|
|
||||||
PASSWORD = admin
|
|
||||||
164
latest version/setting.py
Normal file
164
latest version/setting.py
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
class Config():
|
||||||
|
'''
|
||||||
|
This is the setting file. You can change some parameters here.
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
主机的地址和端口号
|
||||||
|
Host and port of your server
|
||||||
|
'''
|
||||||
|
HOST = '192.168.1.101'
|
||||||
|
PORT = '80'
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
游戏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.0', '3.6.0c', '3.6.1', '3.6.1c']
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
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
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
Web后台管理页面的用户名和密码
|
||||||
|
Username and password of web background management page
|
||||||
|
'''
|
||||||
|
USERNAME = 'admin'
|
||||||
|
PASSWORD = 'admin'
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
Web后台管理页面的session秘钥,如果不知道是什么,请不要修改
|
||||||
|
Session key of web background management page
|
||||||
|
If you don't know what it is, please don't modify it.
|
||||||
|
'''
|
||||||
|
SECRET_KEY = '1145141919810'
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
API接口完全控制权限Token,留空则不使用
|
||||||
|
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
|
||||||
|
'''
|
||||||
|
歌曲下载链接的有效时长,单位:秒
|
||||||
|
Effective duration of song download link, unit: seconds
|
||||||
|
'''
|
||||||
|
DOWNLOAD_TIME_GAP_LIMIT = 1000
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
'''
|
||||||
|
|
||||||
|
'''
|
||||||
|
--------------------
|
||||||
|
Arcaea登录的最大允许设备数量,最小值为1
|
||||||
|
The maximum number of devices allowed to log in Arcaea, minimum: 1
|
||||||
|
'''
|
||||||
|
LOGIN_DEVICE_NUMBER_LIMIT = 1
|
||||||
|
'''
|
||||||
|
是否允许同设备多应用共存登录
|
||||||
|
If logging in from multiple applications on the same device is allowed
|
||||||
|
'''
|
||||||
|
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 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>
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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,7 +13,7 @@
|
|||||||
<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_present') }}">奖励信息查询 All presents</a></br></br>
|
<a href="{{ url_for('index.all_present') }}">奖励信息查询 All 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 %}
|
||||||
@@ -3,13 +3,14 @@ from flask import (
|
|||||||
)
|
)
|
||||||
from web.login import login_required
|
from web.login import login_required
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
import sqlite3
|
from server.sql import Connect
|
||||||
import web.webscore
|
import web.webscore
|
||||||
import web.system
|
import web.system
|
||||||
import time
|
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'}
|
||||||
@@ -43,8 +44,7 @@ def single_player_score():
|
|||||||
user_code = request.form['user_code']
|
user_code = request.form['user_code']
|
||||||
error = None
|
error = None
|
||||||
if name or user_code:
|
if name or user_code:
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
if user_code:
|
if user_code:
|
||||||
c.execute('''select user_id from user where user_code=:a''', {
|
c.execute('''select user_id from user where user_code=:a''', {
|
||||||
'a': user_code})
|
'a': user_code})
|
||||||
@@ -61,8 +61,6 @@ def single_player_score():
|
|||||||
error = '无成绩 No score.'
|
error = '无成绩 No score.'
|
||||||
else:
|
else:
|
||||||
error = '玩家不存在 The player does not exist.'
|
error = '玩家不存在 The player does not exist.'
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = '输入为空 Null Input.'
|
error = '输入为空 Null Input.'
|
||||||
@@ -84,8 +82,7 @@ def single_player_ptt():
|
|||||||
user_code = request.form['user_code']
|
user_code = request.form['user_code']
|
||||||
error = None
|
error = None
|
||||||
if name or user_code:
|
if name or user_code:
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
if user_code:
|
if user_code:
|
||||||
c.execute('''select user_id from user where user_code=:a''', {
|
c.execute('''select user_id from user where user_code=:a''', {
|
||||||
'a': user_code})
|
'a': user_code})
|
||||||
@@ -99,7 +96,8 @@ def single_player_ptt():
|
|||||||
user_id = user_id[0]
|
user_id = user_id[0]
|
||||||
user = web.webscore.get_user(c, user_id)
|
user = web.webscore.get_user(c, user_id)
|
||||||
posts = web.webscore.get_user_score(c, user_id, 30)
|
posts = web.webscore.get_user_score(c, user_id, 30)
|
||||||
recent, recentptt = web.webscore.get_user_recent30(c, user_id)
|
recent, recentptt = web.webscore.get_user_recent30(
|
||||||
|
c, user_id)
|
||||||
if not posts:
|
if not posts:
|
||||||
error = '无成绩 No score.'
|
error = '无成绩 No score.'
|
||||||
else:
|
else:
|
||||||
@@ -111,8 +109,6 @@ def single_player_ptt():
|
|||||||
else:
|
else:
|
||||||
error = '玩家不存在 The player does not exist.'
|
error = '玩家不存在 The player does not exist.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
else:
|
else:
|
||||||
error = '输入为空 Null Input.'
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
@@ -128,11 +124,10 @@ def single_player_ptt():
|
|||||||
@login_required
|
@login_required
|
||||||
def all_player():
|
def all_player():
|
||||||
# 所有玩家数据,按照ptt排序
|
# 所有玩家数据,按照ptt排序
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
error = None
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
c.execute('''select * from user order by rating_ptt DESC''')
|
c.execute('''select * from user order by rating_ptt DESC''')
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
error = None
|
|
||||||
if x:
|
if x:
|
||||||
posts = []
|
posts = []
|
||||||
for i in x:
|
for i in x:
|
||||||
@@ -144,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,
|
||||||
@@ -159,13 +159,12 @@ 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.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
return render_template('web/allplayer.html')
|
return render_template('web/allplayer.html')
|
||||||
@@ -184,11 +183,10 @@ def all_song():
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcsong.db')
|
error = None
|
||||||
c = conn.cursor()
|
with Connect('./database/arcsong.db') as c:
|
||||||
c.execute('''select * from songs''')
|
c.execute('''select * from songs''')
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
error = None
|
|
||||||
if x:
|
if x:
|
||||||
posts = []
|
posts = []
|
||||||
for i in x:
|
for i in x:
|
||||||
@@ -202,8 +200,6 @@ def all_song():
|
|||||||
else:
|
else:
|
||||||
error = '没有铺面数据 No song data.'
|
error = '没有铺面数据 No song data.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
return render_template('web/allsong.html')
|
return render_template('web/allsong.html')
|
||||||
@@ -221,15 +217,13 @@ def single_chart_top():
|
|||||||
if difficulty.isdigit():
|
if difficulty.isdigit():
|
||||||
difficulty = int(difficulty)
|
difficulty = int(difficulty)
|
||||||
error = None
|
error = None
|
||||||
conn = sqlite3.connect('./database/arcsong.db')
|
x = None
|
||||||
c = conn.cursor()
|
with Connect('./database/arcsong.db') as c:
|
||||||
song_name = '%'+song_name+'%'
|
song_name = '%'+song_name+'%'
|
||||||
c.execute('''select sid, name_en from songs where sid like :a limit 1''',
|
c.execute('''select sid, name_en from songs where sid like :a limit 1''',
|
||||||
{'a': song_name})
|
{'a': song_name})
|
||||||
x = c.fetchone()
|
x = c.fetchone()
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
print(x)
|
|
||||||
if x:
|
if x:
|
||||||
song_id = x[0]
|
song_id = x[0]
|
||||||
posts = server.arcscore.arc_score_top(song_id, difficulty, -1)
|
posts = server.arcscore.arc_score_top(song_id, difficulty, -1)
|
||||||
@@ -284,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():
|
||||||
@@ -317,8 +335,8 @@ def add_song():
|
|||||||
song_id = song_id[:200]
|
song_id = song_id[:200]
|
||||||
if len(name_en) >= 256:
|
if len(name_en) >= 256:
|
||||||
name_en = name_en[:200]
|
name_en = name_en[:200]
|
||||||
conn = sqlite3.connect('./database/arcsong.db')
|
|
||||||
c = conn.cursor()
|
with Connect('./database/arcsong.db') as c:
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from songs where sid=:a)''', {'a': song_id})
|
'''select exists(select * from songs where sid=:a)''', {'a': song_id})
|
||||||
if c.fetchone() == (0,):
|
if c.fetchone() == (0,):
|
||||||
@@ -328,9 +346,6 @@ def add_song():
|
|||||||
else:
|
else:
|
||||||
error = '歌曲已存在 The song exists.'
|
error = '歌曲已存在 The song exists.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -344,8 +359,7 @@ def delete_song():
|
|||||||
|
|
||||||
error = None
|
error = None
|
||||||
song_id = request.form['sid']
|
song_id = request.form['sid']
|
||||||
conn = sqlite3.connect('./database/arcsong.db')
|
with Connect('./database/arcsong.db') as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select exists(select * from songs where sid=:a)''', {'a': song_id})
|
'''select exists(select * from songs where sid=:a)''', {'a': song_id})
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (1,):
|
||||||
@@ -354,8 +368,6 @@ def delete_song():
|
|||||||
else:
|
else:
|
||||||
error = "歌曲不存在 The song doesn't exist."
|
error = "歌曲不存在 The song doesn't exist."
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -366,12 +378,10 @@ def delete_song():
|
|||||||
@login_required
|
@login_required
|
||||||
def all_character():
|
def all_character():
|
||||||
# 所有角色数据
|
# 所有角色数据
|
||||||
|
error = None
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
c.execute('''select * from character''')
|
c.execute('''select * from character''')
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
error = None
|
|
||||||
if x:
|
if x:
|
||||||
posts = []
|
posts = []
|
||||||
for i in x:
|
for i in x:
|
||||||
@@ -389,8 +399,6 @@ def all_character():
|
|||||||
else:
|
else:
|
||||||
error = '没有角色数据 No character data.'
|
error = '没有角色数据 No character data.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
return render_template('web/allchar.html')
|
return render_template('web/allchar.html')
|
||||||
@@ -403,7 +411,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']
|
'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)
|
||||||
|
|
||||||
|
|
||||||
@@ -443,8 +451,7 @@ def edit_char():
|
|||||||
flash(error)
|
flash(error)
|
||||||
return redirect(url_for('index.change_character'))
|
return redirect(url_for('index.change_character'))
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
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,):
|
||||||
@@ -484,9 +491,6 @@ def edit_char():
|
|||||||
else:
|
else:
|
||||||
error = '角色不存在 The character does not exist.'
|
error = '角色不存在 The character does not exist.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -497,11 +501,8 @@ def edit_char():
|
|||||||
@login_required
|
@login_required
|
||||||
def update_character():
|
def update_character():
|
||||||
# 更新角色数据
|
# 更新角色数据
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
web.system.update_user_char(c)
|
web.system.update_user_char(c)
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
flash('数据更新成功 Success update data.')
|
flash('数据更新成功 Success update data.')
|
||||||
return redirect(url_for('index.change_character'))
|
return redirect(url_for('index.change_character'))
|
||||||
@@ -535,8 +536,7 @@ def edit_user():
|
|||||||
flash(error)
|
flash(error)
|
||||||
return redirect(url_for('index.change_user'))
|
return redirect(url_for('index.change_user'))
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
# 全修改
|
# 全修改
|
||||||
if 'name' not in request.form and 'user_code' not in request.form:
|
if 'name' not in request.form and 'user_code' not in request.form:
|
||||||
@@ -583,8 +583,6 @@ def edit_user():
|
|||||||
if flag:
|
if flag:
|
||||||
error = '输入为空 Null Input.'
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -614,8 +612,7 @@ def edit_user_purchase():
|
|||||||
flash('输入为空 Null Input.')
|
flash('输入为空 Null Input.')
|
||||||
return redirect(url_for('index.change_user_purchase'))
|
return redirect(url_for('index.change_user_purchase'))
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
# 全修改
|
# 全修改
|
||||||
if 'name' not in request.form and 'user_code' not in request.form:
|
if 'name' not in request.form and 'user_code' not in request.form:
|
||||||
@@ -659,8 +656,6 @@ def edit_user_purchase():
|
|||||||
if flag:
|
if flag:
|
||||||
error = '输入为空 Null Input.'
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -730,8 +725,7 @@ def change_item():
|
|||||||
flash(error)
|
flash(error)
|
||||||
return redirect(url_for('index.change_item'))
|
return redirect(url_for('index.change_item'))
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
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 item where item_id=:a and type=:b)''', {'a': item_id, 'b': item_type})
|
||||||
if c.fetchone() == (1,):
|
if c.fetchone() == (1,):
|
||||||
@@ -762,8 +756,6 @@ def change_item():
|
|||||||
else:
|
else:
|
||||||
error = '购买项目不存在 The item does not exist.'
|
error = '购买项目不存在 The item does not exist.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -783,8 +775,7 @@ def update_user_save():
|
|||||||
name = None
|
name = None
|
||||||
user_code = None
|
user_code = None
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
# 全修改
|
# 全修改
|
||||||
if 'name' not in request.form and 'user_code' not in request.form:
|
if 'name' not in request.form and 'user_code' not in request.form:
|
||||||
@@ -819,8 +810,6 @@ def update_user_save():
|
|||||||
if flag:
|
if flag:
|
||||||
error = '输入为空 Null Input.'
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -832,11 +821,10 @@ def update_user_save():
|
|||||||
def all_present():
|
def all_present():
|
||||||
# 所有奖励数据
|
# 所有奖励数据
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
error = None
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
c.execute('''select * from present''')
|
c.execute('''select * from present''')
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
error = None
|
|
||||||
if x:
|
if x:
|
||||||
posts = []
|
posts = []
|
||||||
for i in x:
|
for i in x:
|
||||||
@@ -854,8 +842,6 @@ def all_present():
|
|||||||
else:
|
else:
|
||||||
error = '没有奖励数据 No present data.'
|
error = '没有奖励数据 No present data.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
return render_template('web/allpresent.html')
|
return render_template('web/allpresent.html')
|
||||||
@@ -941,12 +927,9 @@ def deliver_present():
|
|||||||
user_code = None
|
user_code = None
|
||||||
present_id = request.form['present_id']
|
present_id = request.form['present_id']
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
if not web.system.is_present_available(c, present_id):
|
if not web.system.is_present_available(c, present_id):
|
||||||
flash("奖励不存在 The present does not exist.")
|
flash("奖励不存在 The present does not exist.")
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return render_template('web/deliverpresent.html')
|
return render_template('web/deliverpresent.html')
|
||||||
|
|
||||||
# 全修改
|
# 全修改
|
||||||
@@ -980,8 +963,6 @@ def deliver_present():
|
|||||||
if flag:
|
if flag:
|
||||||
error = '输入为空 Null Input.'
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -993,11 +974,10 @@ def deliver_present():
|
|||||||
def all_redeem():
|
def all_redeem():
|
||||||
# 所有兑换码数据
|
# 所有兑换码数据
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
error = None
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
c.execute('''select * from redeem''')
|
c.execute('''select * from redeem''')
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
error = None
|
|
||||||
if x:
|
if x:
|
||||||
posts = []
|
posts = []
|
||||||
for i in x:
|
for i in x:
|
||||||
@@ -1014,8 +994,6 @@ def all_redeem():
|
|||||||
else:
|
else:
|
||||||
error = '没有兑换码数据 No redeem code data.'
|
error = '没有兑换码数据 No redeem code data.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
return render_template('web/allredeem.html')
|
return render_template('web/allredeem.html')
|
||||||
@@ -1106,12 +1084,11 @@ def delete_redeem():
|
|||||||
def one_redeem(code):
|
def one_redeem(code):
|
||||||
# 某个兑换码的用户使用情况数据
|
# 某个兑换码的用户使用情况数据
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
error = None
|
||||||
c = conn.cursor()
|
with Connect() as c:
|
||||||
c.execute(
|
c.execute(
|
||||||
'''select user_id, name, user_code from user where user_id in (select user_id from user_redeem where code=:a)''', {'a': code})
|
'''select user_id, name, user_code from user where user_id in (select user_id from user_redeem where code=:a)''', {'a': code})
|
||||||
x = c.fetchall()
|
x = c.fetchall()
|
||||||
error = None
|
|
||||||
if x:
|
if x:
|
||||||
posts = []
|
posts = []
|
||||||
for i in x:
|
for i in x:
|
||||||
@@ -1122,8 +1099,6 @@ def one_redeem(code):
|
|||||||
else:
|
else:
|
||||||
error = '没有数据 No data.'
|
error = '没有数据 No data.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
return render_template('web/redeem.html', code=code)
|
return render_template('web/redeem.html', code=code)
|
||||||
@@ -1152,9 +1127,7 @@ def edit_userpwd():
|
|||||||
flash('密码太长或太短 Password is too long or too short!')
|
flash('密码太长或太短 Password is too long or too short!')
|
||||||
return render_template('web/changeuserpwd.html')
|
return render_template('web/changeuserpwd.html')
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
if name or user_code:
|
if name or user_code:
|
||||||
|
|
||||||
if user_code:
|
if user_code:
|
||||||
@@ -1176,8 +1149,6 @@ def edit_userpwd():
|
|||||||
else:
|
else:
|
||||||
error = '输入为空 Null Input.'
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -1196,9 +1167,7 @@ def ban_user():
|
|||||||
name = request.form['name']
|
name = request.form['name']
|
||||||
user_code = request.form['user_code']
|
user_code = request.form['user_code']
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
if name or user_code:
|
if name or user_code:
|
||||||
if user_code:
|
if user_code:
|
||||||
c.execute('''select user_id from user where user_code=:a''', {
|
c.execute('''select user_id from user where user_code=:a''', {
|
||||||
@@ -1219,8 +1188,6 @@ def ban_user():
|
|||||||
else:
|
else:
|
||||||
error = '输入为空 Null Input.'
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
@@ -1236,9 +1203,7 @@ def delete_user_score():
|
|||||||
name = request.form['name']
|
name = request.form['name']
|
||||||
user_code = request.form['user_code']
|
user_code = request.form['user_code']
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
with Connect() as c:
|
||||||
c = conn.cursor()
|
|
||||||
|
|
||||||
if name or user_code:
|
if name or user_code:
|
||||||
if user_code:
|
if user_code:
|
||||||
c.execute('''select user_id from user where user_code=:a''', {
|
c.execute('''select user_id from user where user_code=:a''', {
|
||||||
@@ -1259,8 +1224,6 @@ def delete_user_score():
|
|||||||
else:
|
else:
|
||||||
error = '输入为空 Null Input.'
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
if error:
|
if error:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
from flask import (Blueprint, flash, g, redirect,
|
from flask import (Blueprint, flash, g, redirect,
|
||||||
render_template, request, session, url_for)
|
render_template, request, session, url_for)
|
||||||
import functools
|
import functools
|
||||||
import configparser
|
from setting import Config
|
||||||
|
import hashlib
|
||||||
|
|
||||||
bp = Blueprint('login', __name__, url_prefix='/web')
|
bp = Blueprint('login', __name__, url_prefix='/web')
|
||||||
|
|
||||||
@@ -15,18 +16,16 @@ def login():
|
|||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
error = None
|
error = None
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
if username != Config.USERNAME or password != Config.PASSWORD:
|
||||||
path = r'setting.ini'
|
|
||||||
config.read(path, encoding="utf-8")
|
|
||||||
USERNAME = config.get('WEB', 'USERNAME')
|
|
||||||
PASSWORD = config.get('WEB', 'PASSWORD')
|
|
||||||
|
|
||||||
if username != USERNAME and password != PASSWORD:
|
|
||||||
error = '错误的用户名或密码 Incorrect username or password.'
|
error = '错误的用户名或密码 Incorrect username or password.'
|
||||||
|
|
||||||
if error is None:
|
if error is None:
|
||||||
session.clear()
|
session.clear()
|
||||||
session['user_id'] = USERNAME + 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)
|
||||||
@@ -48,16 +47,14 @@ def login_required(view):
|
|||||||
def wrapped_view(**kwargs):
|
def wrapped_view(**kwargs):
|
||||||
x = session.get('user_id')
|
x = session.get('user_id')
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
hash_session = Config.USERNAME + \
|
||||||
path = r'setting.ini'
|
hashlib.sha256(Config.PASSWORD.encode("utf8")).hexdigest()
|
||||||
config.read(path, encoding="utf-8")
|
hash_session = hashlib.sha256(hash_session.encode("utf8")).hexdigest()
|
||||||
USERNAME = config.get('WEB', 'USERNAME')
|
|
||||||
PASSWORD = config.get('WEB', 'PASSWORD')
|
|
||||||
|
|
||||||
if x != USERNAME + PASSWORD:
|
if x != hash_session:
|
||||||
return redirect(url_for('login.login'))
|
return redirect(url_for('login.login'))
|
||||||
|
|
||||||
g.user = {'user_id': x, 'username': USERNAME}
|
g.user = {'user_id': x, 'username': Config.USERNAME}
|
||||||
return view(**kwargs)
|
return view(**kwargs)
|
||||||
|
|
||||||
return wrapped_view
|
return wrapped_view
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -179,10 +179,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')
|
||||||
@@ -197,28 +195,23 @@ def update_database():
|
|||||||
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_user_char(c2)
|
||||||
|
|
||||||
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')
|
||||||
|
|
||||||
|
|
||||||
@@ -257,8 +250,7 @@ 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 = []
|
||||||
@@ -283,8 +275,6 @@ def get_all_item():
|
|||||||
'discount_to': discount_to
|
'discount_to': discount_to
|
||||||
})
|
})
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
@@ -346,8 +336,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 +346,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 +353,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 +365,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 +407,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 +417,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,9 +424,8 @@ 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 = 0
|
|
||||||
while i <= amount:
|
while i <= amount:
|
||||||
code = random_str()
|
code = random_str()
|
||||||
c.execute(
|
c.execute(
|
||||||
@@ -456,8 +436,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 +444,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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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