mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-09 01:07:27 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dfcbb6f9c0 | ||
|
|
30690b2fbf | ||
|
|
56ae7047fc | ||
|
|
f5d2589971 | ||
|
|
8bb5c28663 |
51
README.md
51
README.md
@@ -8,7 +8,7 @@ This is a small local Arcaea server based on Python and Flask, which can simulat
|
|||||||
> It looks stupid, but it works!
|
> It looks stupid, but it works!
|
||||||
|
|
||||||
## 特性 Features
|
## 特性 Features
|
||||||
有 We have:
|
有以下 We have:
|
||||||
- 登录、注册 Login and registration
|
- 登录、注册 Login and registration
|
||||||
- 成绩上传 Score upload
|
- 成绩上传 Score upload
|
||||||
- PTT
|
- PTT
|
||||||
@@ -17,42 +17,53 @@ This is a small local Arcaea server based on Python and Flask, which can simulat
|
|||||||
- 数据同步 Data synchronization
|
- 数据同步 Data synchronization
|
||||||
- 爬梯 Climbing steps
|
- 爬梯 Climbing steps
|
||||||
- 自定义世界模式 Customizable World Mode
|
- 自定义世界模式 Customizable World Mode
|
||||||
|
- 自定义歌曲下载 Customizable songs download
|
||||||
|
- 单曲和曲包购买(没啥用) Single songs and song packs purchase(useless)
|
||||||
- 全角色立绘 All character drawings
|
- 全角色立绘 All character drawings
|
||||||
- 全剧情解锁 Unlock all the storys
|
- 角色技能 Character skills
|
||||||
- 后台查分 Background search scores
|
- 自定义角色属性 Customizable characters attributes
|
||||||
- 后台自定义歌曲定数 Customize chart consts in the background
|
- 全剧情解锁 Unlock all the stories
|
||||||
|
- 后台查询 Background search
|
||||||
|
- 后台自定义信息 Customize some things in the background
|
||||||
|
- 成绩校验 Score check
|
||||||
|
- 下载校验 Download check
|
||||||
|
|
||||||
没有以下 We don't have:
|
没有以下 We don't have:
|
||||||
- 角色特性 Character characteristics
|
- 角色数值 Character characteristic value
|
||||||
- 购买 Purchase
|
- 数据同步的时间和设备记录 The record of time and device for data synchronization
|
||||||
- 歌曲解锁、曲包解锁 Songs unlocking and music packs unlocking
|
|
||||||
- 反作弊系统 Anti cheating system
|
|
||||||
- 服务器安全性保证 Server security assurance
|
- 服务器安全性保证 Server security assurance
|
||||||
|
|
||||||
可能有问题 There may be problems:
|
可能有问题 There may be problems:
|
||||||
- Recent 30
|
- Recent 30
|
||||||
|
- 一些歌曲的解锁 Some Songs' unlocking
|
||||||
|
|
||||||
## 说明 Statement
|
## 说明 Statement
|
||||||
只是很有趣,用处探索中。
|
只是很有趣,用处探索中。
|
||||||
It is just so interesting. What it can do is under exploration.
|
It is just so interesting. What it can do is under exploration.
|
||||||
|
|
||||||
进行了一下项目改进,可能目录有所变化
|
|
||||||
Some project improvements have been made and the catalog may have changed.
|
|
||||||
|
|
||||||
## 下载 Download
|
## 下载 Download
|
||||||
[这里 Here](https://github.com/Lost-MSth/Arcaea-server/releases)
|
[这里 Here](https://github.com/Lost-MSth/Arcaea-server/releases)
|
||||||
|
|
||||||
|
[Arcaea](https://konmai.cn/#arcaea)
|
||||||
|
|
||||||
## 更新日志 Update log
|
## 更新日志 Update log
|
||||||
只保留最新版本 Only keep the latest version.
|
只保留最新版本 Only keep the latest version.
|
||||||
### Version 1.3
|
|
||||||
- 适用于Arcaea 3.2.1版本 For Arcaea 3.2.1
|
> 提醒:更新时请注意保留原先的数据库,以防数据丢失
|
||||||
|
>
|
||||||
|
> Tips: When updating, please keep the original database in case of data loss.
|
||||||
|
|
||||||
|
### Version 1.7
|
||||||
|
- 仍然适用于Arcaea 3.2.3版本 Still for Arcaea 3.2.3
|
||||||
- 更新了歌曲数据库 Update the song database.
|
- 更新了歌曲数据库 Update the song database.
|
||||||
- 新增了可自定义的世界模式 Add customizable World Mode.
|
- 新增了购买系统,包括单曲购买和曲包购买 Add purchase system, including single purchase and pack purchase.
|
||||||
- 对于官方版本,解锁几乎所有歌曲 For the official version, unlock almost all songs.
|
- 后台查询与修改项目增多 Increase background query and modification items.
|
||||||
|
- 新增用户下载量限制和下载校验 Add user download limit and download verification.
|
||||||
> 更新说明:本次更新无法从旧版本同步数据,请使用游戏内数据同步功能上传best_score数据
|
- 新增了**梦**的语音 Add the voice of **Yume**.
|
||||||
|
- 新增了网站图标 Add a favicon.
|
||||||
> Update note: In this update you cannot synchronize data from an older version. Please use the data synchronization function in game to upload best_score data.
|
- 尝试解锁了所有的场景 Try to unlock all the scenes.
|
||||||
|
- 修复了一些Bug Fix some bugs.
|
||||||
|
|
||||||
## 运行环境与依赖 Running environment and requirements
|
## 运行环境与依赖 Running environment and requirements
|
||||||
- Windows操作系统 Windows operating system
|
- Windows操作系统 Windows operating system
|
||||||
@@ -74,7 +85,9 @@ Some project improvements have been made and the catalog may have changed.
|
|||||||
|
|
||||||
## 鸣谢 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)
|
||||||
|
|
||||||
|
网站图标来自 Using favicon from [black fate - てんてん - pixiv](https://www.pixiv.net/artworks/82374369)
|
||||||
|
|
||||||
## 联系方式 Contact
|
## 联系方式 Contact
|
||||||
如有必要,可以联系本人 Contact me if necessary
|
如有必要,可以联系本人 Contact me if necessary
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,7 @@
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
import hashlib
|
import hashlib
|
||||||
import time
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
# 数据库初始化文件,删掉arcaea_database.db文件后运行即可,谨慎使用
|
# 数据库初始化文件,删掉arcaea_database.db文件后运行即可,谨慎使用
|
||||||
|
|
||||||
@@ -31,7 +32,8 @@ clear_type int,
|
|||||||
rating real,
|
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
|
||||||
);''')
|
);''')
|
||||||
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,
|
user_id int,
|
||||||
@@ -170,48 +172,116 @@ fragment_multiply int,
|
|||||||
prog_boost_multiply int,
|
prog_boost_multiply int,
|
||||||
primary key(user_id, song_id, difficulty)
|
primary key(user_id, song_id, difficulty)
|
||||||
);''')
|
);''')
|
||||||
|
c.execute('''create table if not exists download_token(user_id int,
|
||||||
|
song_id text,
|
||||||
|
file_name text,
|
||||||
|
token text,
|
||||||
|
time int,
|
||||||
|
primary key(user_id, song_id, file_name)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_download(user_id int,
|
||||||
|
token text,
|
||||||
|
time int,
|
||||||
|
primary key(user_id, token, time)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists item(item_id text,
|
||||||
|
type text,
|
||||||
|
is_available int,
|
||||||
|
price int,
|
||||||
|
orig_price int,
|
||||||
|
discount_from int,
|
||||||
|
discount_to int,
|
||||||
|
_id text,
|
||||||
|
primary key(item_id, type)
|
||||||
|
);''')
|
||||||
|
c.execute('''create table if not exists user_item(user_id int,
|
||||||
|
item_id text,
|
||||||
|
type text,
|
||||||
|
primary key(user_id, item_id, type)
|
||||||
|
);''')
|
||||||
|
|
||||||
char = ['Hikari','Tairitsu','Kou','Sapphire','Lethe','','Tairitsu(Axium)'
|
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',
|
||||||
,'Tairitsu(Grievous Lady)','Stella','Hikari & Fisica','Ilith','Eto','Luna'
|
'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']
|
||||||
,'Shirabe','Hikari(Zero)','Hikari(Fracture)','Hikari(Summer)','Tairitsu(Summer)'
|
|
||||||
,'Tairitsu&Trin','Ayu','Eto&Luna','Yume','Seine & Hikari','Saya','Tairitsu & Chuni Penguin'
|
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',
|
||||||
,'Chuni Penguin','Haruna','Nono','MTA-XXX','MDA-21','Kanae','Hikari(Fantasia)','Tairitsu(Sonata)','Sia','DORO*C'
|
'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', '']
|
||||||
,'Tairitsu(Tempest)','Brillante','Ilith(Summer)','Etude']
|
|
||||||
|
skill_id_uncap = ['', '', 'frags_kou', '', 'visual_ink', '', '', '', '', '', '', '', '', 'shirabe_entry_fee',
|
||||||
|
'', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
|
||||||
|
|
||||||
for i in range(0, 39):
|
for i in range(0, 39):
|
||||||
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
|
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
|
||||||
sql = 'insert into character values('+str(i)+',"'+char[i]+'''",30,25000,25000,90,90,90,'',0,0,'',0,'',1,1)'''
|
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)'''
|
||||||
c.execute(sql)
|
c.execute(sql)
|
||||||
else:
|
else:
|
||||||
if i != 5:
|
if i != 5:
|
||||||
sql = 'insert into character values('+str(i)+',"'+char[i]+'''",30,25000,25000,90,90,90,'',0,0,'',0,'',0,0)'''
|
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,'',0,0)'''
|
||||||
c.execute(sql)
|
c.execute(sql)
|
||||||
|
|
||||||
|
|
||||||
|
def b2int(x):
|
||||||
|
# int与布尔值转换
|
||||||
|
if x:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def insert_items(c, items):
|
||||||
|
# 物品数据导入
|
||||||
|
for i in items:
|
||||||
|
if 'discount_from' not in i:
|
||||||
|
discount_from = -1
|
||||||
|
else:
|
||||||
|
discount_from = i['discount_from']
|
||||||
|
if 'discount_to' not in i:
|
||||||
|
discount_to = -1
|
||||||
|
else:
|
||||||
|
discount_to = i['discount_to']
|
||||||
|
for j in i['items']:
|
||||||
|
if "_id" not in j:
|
||||||
|
_id = ''
|
||||||
|
else:
|
||||||
|
_id = j['_id']
|
||||||
|
if j['type'] != 'character':
|
||||||
|
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})
|
||||||
|
|
||||||
|
|
||||||
|
f = open('singles.json', 'r')
|
||||||
|
singles = json.load(f)
|
||||||
|
f.close()
|
||||||
|
insert_items(c, singles)
|
||||||
|
|
||||||
|
f = open('packs.json', 'r')
|
||||||
|
packs = json.load(f)
|
||||||
|
f.close()
|
||||||
|
insert_items(c, packs)
|
||||||
|
|
||||||
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'
|
||||||
|
|
||||||
def build_user_id(c):
|
def build_user_id(c):
|
||||||
return 2000000
|
return 2000000
|
||||||
|
|
||||||
## def insert_user_char(c, user_id):
|
# def insert_user_char(c, user_id):
|
||||||
## for i in range(0, 38):
|
# for i in range(0, 38):
|
||||||
## if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
|
# if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
|
||||||
## sql = 'insert into user_char values('+str(user_id)+','+str(
|
# sql = 'insert into user_char values('+str(user_id)+','+str(
|
||||||
## i)+''',30,25000,25000,90,90,90,'',0,0,'',0,1,1)'''
|
# i)+''',30,25000,25000,90,90,90,'',0,0,'',0,1,1)'''
|
||||||
## c.execute(sql)
|
# c.execute(sql)
|
||||||
## else:
|
# else:
|
||||||
## if i != 5:
|
# if i != 5:
|
||||||
## sql = 'insert into user_char values('+str(user_id)+','+str(
|
# sql = 'insert into user_char values('+str(user_id)+','+str(
|
||||||
## i)+''',30,25000,25000,90,90,90,'',0,0,'',0,0,0)'''
|
# i)+''',30,25000,25000,90,90,90,'',0,0,'',0,0,0)'''
|
||||||
## c.execute(sql)
|
# c.execute(sql)
|
||||||
def insert_user_char(c, user_id):
|
def insert_user_char(c, user_id):
|
||||||
# 为用户添加所有可用角色
|
# 为用户添加所有可用角色
|
||||||
c.execute('''select * from character''')
|
c.execute('''select * from character''')
|
||||||
@@ -221,7 +291,6 @@ 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('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()
|
||||||
@@ -231,13 +300,14 @@ def arc_register(name: str, password: str):
|
|||||||
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)
|
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket)
|
||||||
values(:user_id, :name, :password, :join_date, :user_code, 1250, 1, 0, 1, 0, 0, -1, 0, '')
|
values(:user_id, :name, :password, :join_date, :user_code, 1250, 1, 0, 1, 0, 0, -1, 0, '', 114514)
|
||||||
''', {'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})
|
||||||
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})
|
||||||
c.execute('''insert into best_score values(2000000,'vexaria',3,10000000,100,0,0,0,100,0,1599667200,3,3,10.8)''')
|
c.execute(
|
||||||
|
'''insert into best_score values(2000000,'vexaria',3,10000000,100,0,0,0,100,0,1599667200,3,3,10.8)''')
|
||||||
insert_user_char(c, user_id)
|
insert_user_char(c, user_id)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|||||||
70
latest version/database/map/byd_lumia.json
Normal file
70
latest version/database/map/byd_lumia.json
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"map_id": "byd_lumia",
|
||||||
|
"is_legacy": false,
|
||||||
|
"chapter": 1001,
|
||||||
|
"available_from": -1,
|
||||||
|
"available_to": 9999999999999,
|
||||||
|
"is_repeatable": false,
|
||||||
|
"require_id": "lumia2",
|
||||||
|
"require_type": "chart_unlock",
|
||||||
|
"coordinate": "650,-650",
|
||||||
|
"is_beyond": true,
|
||||||
|
"stamina_cost": 3,
|
||||||
|
"beyond_health": 150,
|
||||||
|
"character_affinity": [0, 15, 14, 16],
|
||||||
|
"affinity_multiplier": [2.4, 1.9, 2.4, 2.9],
|
||||||
|
"step_count": 6,
|
||||||
|
"custom_bg": "",
|
||||||
|
"curr_position": 0,
|
||||||
|
"curr_capture": 0,
|
||||||
|
"is_locked": false,
|
||||||
|
"steps": [{
|
||||||
|
"map_id": "byd_lumia",
|
||||||
|
"position": 0,
|
||||||
|
"capture": 10,
|
||||||
|
"restrict_id": "core",
|
||||||
|
"restrict_type": "pack_id"
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lumia",
|
||||||
|
"position": 1,
|
||||||
|
"capture": 20,
|
||||||
|
"items": [{
|
||||||
|
"type": "fragment",
|
||||||
|
"amount": 200
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lumia",
|
||||||
|
"position": 2,
|
||||||
|
"capture": 30,
|
||||||
|
"items": [{
|
||||||
|
"type": "core",
|
||||||
|
"id": "core_generic",
|
||||||
|
"amount": 1
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lumia",
|
||||||
|
"position": 3,
|
||||||
|
"capture": 40,
|
||||||
|
"items": [{
|
||||||
|
"type": "fragment",
|
||||||
|
"amount": 250
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lumia",
|
||||||
|
"position": 4,
|
||||||
|
"capture": 50,
|
||||||
|
"items": [{
|
||||||
|
"type": "core",
|
||||||
|
"id": "core_generic",
|
||||||
|
"amount": 1
|
||||||
|
}]
|
||||||
|
}, {
|
||||||
|
"map_id": "byd_lumia",
|
||||||
|
"position": 5,
|
||||||
|
"capture": 0,
|
||||||
|
"items": [{
|
||||||
|
"id": "lumia3",
|
||||||
|
"type": "world_song"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
198
latest version/database/packs.json
Normal file
198
latest version/database/packs.json
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
[{
|
||||||
|
"name": "core",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "core",
|
||||||
|
"_id": "5fb5b68a68273a03de60f205",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "shiawase",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "shiawase",
|
||||||
|
"_id": "5fb5b68a68273a03de60f234",
|
||||||
|
"is_available": true
|
||||||
|
}, {
|
||||||
|
"type": "character",
|
||||||
|
"id": "kou",
|
||||||
|
"_id": "5fb5b68a68273a03de60f233",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1552089600000,
|
||||||
|
"discount_to": 1552694399000
|
||||||
|
}, {
|
||||||
|
"name": "dynamix",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "dynamix",
|
||||||
|
"_id": "5fb5b68a68273a03de60f238",
|
||||||
|
"is_available": true
|
||||||
|
}, {
|
||||||
|
"type": "character",
|
||||||
|
"id": "sapphire",
|
||||||
|
"_id": "5fb5b68a68273a03de60f237",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "mirai",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "mirai",
|
||||||
|
"_id": "5fb5b68a68273a03de60f23e",
|
||||||
|
"is_available": true
|
||||||
|
}, {
|
||||||
|
"type": "character",
|
||||||
|
"id": "lethe",
|
||||||
|
"_id": "5fb5b68a68273a03de60f23d",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1552089600000,
|
||||||
|
"discount_to": 1552694399000
|
||||||
|
}, {
|
||||||
|
"name": "yugamu",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "yugamu",
|
||||||
|
"_id": "5fb5b68a68273a03de60f206",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "lanota",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "lanota",
|
||||||
|
"_id": "5fb5b68a68273a03de60f211",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "nijuusei",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "nijuusei",
|
||||||
|
"_id": "5fb5b68a68273a03de60f207",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "rei",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "rei",
|
||||||
|
"_id": "5fb5b68a68273a03de60f1fd",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "tonesphere",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "tonesphere",
|
||||||
|
"_id": "5fb5b68a68273a03de60f213",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "groovecoaster",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "groovecoaster",
|
||||||
|
"_id": "5fb5b68a68273a03de60f22c",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "zettai",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "zettai",
|
||||||
|
"_id": "5fb5b68a68273a03de60f1ff",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "chunithm",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "chunithm",
|
||||||
|
"_id": "5fb5b68a68273a03de60f221",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 300,
|
||||||
|
"orig_price": 300
|
||||||
|
}, {
|
||||||
|
"name": "prelude",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "prelude",
|
||||||
|
"_id": "5fb5b68a68273a03de60f22d",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 400,
|
||||||
|
"orig_price": 400
|
||||||
|
}, {
|
||||||
|
"name": "omatsuri",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "omatsuri",
|
||||||
|
"_id": "5fb5b68a68273a03de60f200",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500
|
||||||
|
}, {
|
||||||
|
"name": "vs",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "vs",
|
||||||
|
"_id": "5fb5b68a68273a03de60f224",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 500,
|
||||||
|
"orig_price": 500
|
||||||
|
}, {
|
||||||
|
"name": "extend",
|
||||||
|
"items": [{
|
||||||
|
"type": "pack",
|
||||||
|
"id": "extend",
|
||||||
|
"_id": "5fb5b68a68273a03de60f230",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 700,
|
||||||
|
"orig_price": 700
|
||||||
|
}]
|
||||||
466
latest version/database/singles.json
Normal file
466
latest version/database/singles.json
Normal file
@@ -0,0 +1,466 @@
|
|||||||
|
[{
|
||||||
|
"name": "testsingle",
|
||||||
|
"items": [{
|
||||||
|
"id": "testsingle",
|
||||||
|
"type": "single",
|
||||||
|
"is_available": false
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "dataerror",
|
||||||
|
"items": [{
|
||||||
|
"id": "dataerror",
|
||||||
|
"type": "single",
|
||||||
|
"_id": "5fb5b68a68273a03de60f210",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "yourvoiceso",
|
||||||
|
"items": [{
|
||||||
|
"id": "yourvoiceso",
|
||||||
|
"type": "single",
|
||||||
|
"_id": "5fb5b68a68273a03de60f227",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "crosssoul",
|
||||||
|
"items": [{
|
||||||
|
"id": "crosssoul",
|
||||||
|
"type": "single",
|
||||||
|
"_id": "5fb5b68a68273a03de60f21b",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "impurebird",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "impurebird",
|
||||||
|
"_id": "5fb5b68a68273a03de60f21c",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "auxesia",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "auxesia",
|
||||||
|
"_id": "5fb5b68a68273a03de60f228",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1520413239000,
|
||||||
|
"discount_to": 1521072000000
|
||||||
|
}, {
|
||||||
|
"name": "modelista",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "modelista",
|
||||||
|
"_id": "5fb5b68a68273a03de60f1fb",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "yozakurafubuki",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "yozakurafubuki",
|
||||||
|
"_id": "5fb5b68a68273a03de60f21d",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "surrender",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "surrender",
|
||||||
|
"_id": "5fb5b68a68273a03de60f229",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "metallicpunisher",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "metallicpunisher",
|
||||||
|
"_id": "5fb5b68a68273a03de60f1fc",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "carminescythe",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "carminescythe",
|
||||||
|
"_id": "5fb5b68a68273a03de60f21e",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "bethere",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "bethere",
|
||||||
|
"_id": "5fb5b68a68273a03de60f22a",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "callmyname",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "callmyname",
|
||||||
|
"_id": "5fb5b68a68273a03de60f212",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "fallensquare",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "fallensquare",
|
||||||
|
"_id": "5fb5b68a68273a03de60f208",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "dropdead",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "dropdead",
|
||||||
|
"_id": "5fb5b68a68273a03de60f21f",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "alexandrite",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "alexandrite",
|
||||||
|
"_id": "5fb5b68a68273a03de60f22b",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "astraltale",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "astraltale",
|
||||||
|
"_id": "5fb5b68a68273a03de60f1fe",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "phantasia",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "phantasia",
|
||||||
|
"_id": "5fb5b68a68273a03de60f209",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "empireofwinter",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "empireofwinter",
|
||||||
|
"_id": "5fb5b68a68273a03de60f220",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "libertas",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "libertas",
|
||||||
|
"_id": "5fb5b68a68273a03de60f214",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "dottodot",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "dottodot",
|
||||||
|
"_id": "5fb5b68a68273a03de60f20a",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "dreadnought",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "dreadnought",
|
||||||
|
"_id": "5fb5b68a68273a03de60f215",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "mirzam",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "mirzam",
|
||||||
|
"_id": "5fb5b68a68273a03de60f20b",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100,
|
||||||
|
"discount_from": 1583712000000,
|
||||||
|
"discount_to": 1584316799000
|
||||||
|
}, {
|
||||||
|
"name": "heavenlycaress",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "heavenlycaress",
|
||||||
|
"_id": "5fb5b68a68273a03de60f222",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "filament",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "filament",
|
||||||
|
"_id": "5fb5b68a68273a03de60f22e",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "avantraze",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "avantraze",
|
||||||
|
"_id": "5fb5b68a68273a03de60f216",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "battlenoone",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "battlenoone",
|
||||||
|
"_id": "5fb5b68a68273a03de60f201",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "saikyostronger",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "saikyostronger",
|
||||||
|
"_id": "5fb5b68a68273a03de60f20c",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "izana",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "izana",
|
||||||
|
"_id": "5fb5b68a68273a03de60f223",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "einherjar",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "einherjar",
|
||||||
|
"_id": "5fb5b68a68273a03de60f22f",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "laqryma",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "laqryma",
|
||||||
|
"_id": "5fb5b68a68273a03de60f217",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "amygdata",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "amygdata",
|
||||||
|
"_id": "5fb5b68a68273a03de60f202",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "altale",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "altale",
|
||||||
|
"_id": "5fb5b68a68273a03de60f20d",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "feelssoright",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "feelssoright",
|
||||||
|
"_id": "5fb5b68a68273a03de60f218",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "scarletcage",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "scarletcage",
|
||||||
|
"_id": "5fb5b68a68273a03de60f203",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "teriqma",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "teriqma",
|
||||||
|
"_id": "5fb5b68a68273a03de60f20e",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "mahoroba",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "mahoroba",
|
||||||
|
"_id": "5fb5b68a68273a03de60f225",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "badtek",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "badtek",
|
||||||
|
"_id": "5fb5b68a68273a03de60f219",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "maliciousmischance",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "maliciousmischance",
|
||||||
|
"_id": "5fb5b68a68273a03de60f231",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "buchigireberserker",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "buchigireberserker",
|
||||||
|
"_id": "5fb5b68a68273a03de60f20f",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "galaxyfriends",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "galaxyfriends",
|
||||||
|
"_id": "5fb5b68a68273a03de60f226",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}, {
|
||||||
|
"name": "xeraphinite",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "xeraphinite",
|
||||||
|
"_id": "5fb5b68a68273a03de60f232",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"orig_price": 100,
|
||||||
|
"price": 100
|
||||||
|
}, {
|
||||||
|
"name": "xanatos",
|
||||||
|
"items": [{
|
||||||
|
"type": "single",
|
||||||
|
"id": "xanatos",
|
||||||
|
"_id": "5fb5b68a68273a03de60f21a",
|
||||||
|
"is_available": true
|
||||||
|
}],
|
||||||
|
"price": 100,
|
||||||
|
"orig_price": 100
|
||||||
|
}]
|
||||||
@@ -2,6 +2,7 @@ AudioOffset:408
|
|||||||
-
|
-
|
||||||
timing(0,210.00,4.00);
|
timing(0,210.00,4.00);
|
||||||
(1142,4);
|
(1142,4);
|
||||||
|
flick(1142,0.50,0.50,0.00,1.00);
|
||||||
(1571,2);
|
(1571,2);
|
||||||
(2857,1);
|
(2857,1);
|
||||||
(3142,2);
|
(3142,2);
|
||||||
|
|||||||
@@ -9,13 +9,21 @@ import web.login
|
|||||||
import web.index
|
import web.index
|
||||||
import server.arcworld
|
import server.arcworld
|
||||||
import server.arcdownload
|
import server.arcdownload
|
||||||
|
import server.arcpurchase
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
wsgi_app = app.wsgi_app
|
wsgi_app = app.wsgi_app
|
||||||
|
|
||||||
|
|
||||||
def error_return(error_code): # 错误返回
|
def error_return(error_code): # 错误返回
|
||||||
|
# -7 处理交易时发生了错误
|
||||||
|
# -5 所有的曲目都已经下载完毕
|
||||||
|
# -4 您的账号已在别处登录
|
||||||
|
# -3 无法连接至服务器
|
||||||
|
# 2 Arcaea服务器正在维护
|
||||||
|
# 5 请更新Arcaea到最新版本
|
||||||
# 100 无法在此ip地址下登录游戏
|
# 100 无法在此ip地址下登录游戏
|
||||||
# 101 用户名占用
|
# 101 用户名占用
|
||||||
# 102 电子邮箱已注册
|
# 102 电子邮箱已注册
|
||||||
@@ -30,19 +38,27 @@ def error_return(error_code): # 错误返回
|
|||||||
# 121 账户冻结
|
# 121 账户冻结
|
||||||
# 122 账户暂时冻结
|
# 122 账户暂时冻结
|
||||||
# 123 账户被限制
|
# 123 账户被限制
|
||||||
|
# 124 你今天不能再使用这个IP地址创建新的账号
|
||||||
# 150 非常抱歉您已被限制使用此功能
|
# 150 非常抱歉您已被限制使用此功能
|
||||||
# 151 目前无法使用此功能
|
# 151 目前无法使用此功能
|
||||||
# 401 用户不存在
|
# 401 用户不存在
|
||||||
# 403 无法连接至服务器
|
# 403 无法连接至服务器
|
||||||
# 501 502 此物品目前无法获取
|
# 501 502 -6 此物品目前无法获取
|
||||||
# 504 无效的序列码
|
# 504 无效的序列码
|
||||||
# 505 此序列码已被使用
|
# 505 此序列码已被使用
|
||||||
# 506 你已拥有了此物品
|
# 506 你已拥有了此物品
|
||||||
# 601 好友列表已满
|
# 601 好友列表已满
|
||||||
# 602 此用户已是好友
|
# 602 此用户已是好友
|
||||||
# 604 你不能加自己为好友
|
# 604 你不能加自己为好友
|
||||||
|
# 903 下载量超过了限制,请24小时后重试
|
||||||
|
# 905 请在再次使用此功能前等待24小时
|
||||||
# 1001 设备数量达到上限
|
# 1001 设备数量达到上限
|
||||||
# 1002 该设备已使用过本功能
|
# 1002 此设备已使用过此功能
|
||||||
|
# 9801 下载歌曲时发生问题,请再试一次
|
||||||
|
# 9802 保存歌曲时发生问题,请检查设备空间容量
|
||||||
|
# 9905 没有在云端发现任何数据
|
||||||
|
# 9907 更新数据时发生了问题
|
||||||
|
# 9908 服务器只支持最新的版本,请更新Arcaea
|
||||||
# 其它 发生未知错误
|
# 其它 发生未知错误
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": False,
|
"success": False,
|
||||||
@@ -55,6 +71,15 @@ def hello():
|
|||||||
return "Hello World!"
|
return "Hello World!"
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/favicon.ico', methods=['GET']) # 图标
|
||||||
|
def favicon():
|
||||||
|
# Pixiv ID: 82374369
|
||||||
|
# 我觉得这张图虽然并不是那么精细,但很有感觉,色彩的强烈对比下给人带来一种惊艳
|
||||||
|
# 然后在压缩之下什么也看不清了:(
|
||||||
|
|
||||||
|
return app.send_static_file('favicon.ico')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/coffee/12/auth/login', methods=['POST']) # 登录接口
|
@app.route('/coffee/12/auth/login', methods=['POST']) # 登录接口
|
||||||
def login():
|
def login():
|
||||||
headers = request.headers
|
headers = request.headers
|
||||||
@@ -90,7 +115,8 @@ def register():
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/coffee/12/compose/aggregate', methods=['GET']) # 用户信息获取
|
# 集成式请求,没想到什么好办法处理,就先这样写着
|
||||||
|
@app.route('/coffee/12/compose/aggregate', methods=['GET'])
|
||||||
def aggregate():
|
def aggregate():
|
||||||
calls = request.args.get('calls')
|
calls = request.args.get('calls')
|
||||||
headers = request.headers
|
headers = request.headers
|
||||||
@@ -307,6 +333,8 @@ def song_score_post():
|
|||||||
headers = request.headers
|
headers = request.headers
|
||||||
token = headers['Authorization']
|
token = headers['Authorization']
|
||||||
token = token[7:]
|
token = token[7:]
|
||||||
|
song_token = request.form['song_token']
|
||||||
|
song_hash = request.form['song_hash']
|
||||||
song_id = request.form['song_id']
|
song_id = request.form['song_id']
|
||||||
difficulty = int(request.form['difficulty'])
|
difficulty = int(request.form['difficulty'])
|
||||||
score = int(request.form['score'])
|
score = int(request.form['score'])
|
||||||
@@ -318,10 +346,15 @@ def song_score_post():
|
|||||||
modifier = int(request.form['modifier'])
|
modifier = int(request.form['modifier'])
|
||||||
beyond_gauge = int(request.form['beyond_gauge'])
|
beyond_gauge = int(request.form['beyond_gauge'])
|
||||||
clear_type = int(request.form['clear_type'])
|
clear_type = int(request.form['clear_type'])
|
||||||
|
submission_hash = request.form['submission_hash']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user_id = server.auth.token_get_id(token)
|
user_id = server.auth.token_get_id(token)
|
||||||
if user_id is not None:
|
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):
|
||||||
|
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:
|
||||||
@@ -423,12 +456,20 @@ def cloud_post():
|
|||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/coffee/12/purchase/me/redeem', methods=['POST']) # 兑换码,自然没有用
|
@app.route('/coffee/12/purchase/me/redeem', methods=['POST']) # 兑换码,依然没有用
|
||||||
def redeem():
|
def redeem():
|
||||||
return error_return(504)
|
return error_return(504)
|
||||||
|
|
||||||
|
|
||||||
# 购买,自然没有用,只是为了world模式boost一下
|
# 礼物确认
|
||||||
|
@app.route('/coffee/12/present/me/claim/<present_id>', methods=['POST'])
|
||||||
|
def claim_present(present_id):
|
||||||
|
return jsonify({
|
||||||
|
"success": True
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# 购买,为了world模式boost一下
|
||||||
@app.route('/coffee/12/purchase/me/item', methods=['POST'])
|
@app.route('/coffee/12/purchase/me/item', methods=['POST'])
|
||||||
def item():
|
def item():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -436,27 +477,32 @@ def item():
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/coffee/12/purchase/me/pack', methods=['POST']) # 购买,自然没有用
|
@app.route('/coffee/12/purchase/me/pack', methods=['POST']) # 曲包和单曲购买
|
||||||
def pack():
|
def pack():
|
||||||
|
headers = request.headers
|
||||||
|
token = headers['Authorization']
|
||||||
|
token = token[7:]
|
||||||
|
try:
|
||||||
|
user_id = server.auth.token_get_id(token)
|
||||||
|
if user_id:
|
||||||
|
if 'pack_id' in request.form:
|
||||||
|
return jsonify(server.arcpurchase.buy_pack(user_id, request.form['pack_id']))
|
||||||
|
if 'single_id' in request.form:
|
||||||
|
return jsonify(server.arcpurchase.buy_single(user_id, request.form['single_id']))
|
||||||
|
else:
|
||||||
|
return error_return(108)
|
||||||
|
except:
|
||||||
|
return error_return(108)
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True
|
"success": True
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/coffee/12/purchase/bundle/single', methods=['GET']) # 单曲购买,自然没有用
|
@app.route('/coffee/12/purchase/bundle/single', methods=['GET']) # 单曲购买信息获取
|
||||||
def single():
|
def single():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
"value": [{
|
"value": server.arcpurchase.get_single_purchase()
|
||||||
"name": "testsingle",
|
|
||||||
"items": [{
|
|
||||||
"id": "testsingle",
|
|
||||||
"type": "single",
|
|
||||||
"is_available": False
|
|
||||||
}],
|
|
||||||
"price": 100,
|
|
||||||
"orig_price": 100
|
|
||||||
}]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@@ -466,6 +512,7 @@ def world_all():
|
|||||||
token = headers['Authorization']
|
token = headers['Authorization']
|
||||||
token = token[7:]
|
token = token[7:]
|
||||||
try:
|
try:
|
||||||
|
|
||||||
user_id = server.auth.token_get_id(token)
|
user_id = server.auth.token_get_id(token)
|
||||||
if user_id:
|
if user_id:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -530,21 +577,22 @@ def download_song():
|
|||||||
token = headers['Authorization']
|
token = headers['Authorization']
|
||||||
token = token[7:]
|
token = token[7:]
|
||||||
song_ids = request.args.getlist('sid')
|
song_ids = request.args.getlist('sid')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user_id = server.auth.token_get_id(token)
|
user_id = server.auth.token_get_id(token)
|
||||||
if user_id:
|
if user_id:
|
||||||
re = {}
|
if server.arcdownload.is_able_download(user_id):
|
||||||
if not song_ids:
|
re = {}
|
||||||
re = server.arcdownload.get_all_songs()
|
if not song_ids:
|
||||||
else:
|
re = server.arcdownload.get_all_songs(user_id)
|
||||||
for song_id in song_ids:
|
else:
|
||||||
re.update(server.arcdownload.get_one_song(song_id))
|
re = server.arcdownload.get_some_songs(user_id, song_ids)
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"success": True,
|
"success": True,
|
||||||
"value": re
|
"value": re
|
||||||
})
|
})
|
||||||
|
else:
|
||||||
|
return error_return(903)
|
||||||
else:
|
else:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
except:
|
except:
|
||||||
@@ -553,12 +601,17 @@ def download_song():
|
|||||||
|
|
||||||
@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:
|
||||||
path = os.path.join('./database/songs', file_path)
|
message = server.arcdownload.is_token_able_download(t)
|
||||||
if os.path.isfile(path) and not('../' in path or '..\\' in path):
|
if message == 0:
|
||||||
return send_from_directory('./database/songs', file_path, as_attachment=True)
|
path = os.path.join('./database/songs', file_path)
|
||||||
|
if os.path.isfile(path) and not('../' in path or '..\\' in path):
|
||||||
|
return send_from_directory('./database/songs', file_path, as_attachment=True)
|
||||||
|
else:
|
||||||
|
return error_return(109)
|
||||||
else:
|
else:
|
||||||
return error_return(109)
|
return error_return(message)
|
||||||
except:
|
except:
|
||||||
return error_return(108)
|
return error_return(108)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import os
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
from flask import url_for
|
from flask import url_for
|
||||||
|
import sqlite3
|
||||||
|
import time
|
||||||
|
|
||||||
|
time_limit = 3000 # 每个玩家24小时下载次数限制
|
||||||
|
time_gap_limit = 1000 # 下载链接有效秒数
|
||||||
|
|
||||||
|
|
||||||
def get_file_md5(file_path):
|
def get_file_md5(file_path):
|
||||||
@@ -18,31 +23,105 @@ def get_file_md5(file_path):
|
|||||||
return myhash.hexdigest()
|
return myhash.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def get_one_song(song_id, file_dir='./database/songs'):
|
def get_one_song(c, user_id, song_id, file_dir='./database/songs'):
|
||||||
# 获取一首歌的下载链接,返回字典
|
# 获取一首歌的下载链接,返回字典
|
||||||
dir_list = os.listdir(os.path.join(file_dir, song_id))
|
dir_list = os.listdir(os.path.join(file_dir, song_id))
|
||||||
re = {}
|
re = {}
|
||||||
|
now = int(time.time())
|
||||||
|
c.execute('''delete from download_token where user_id=:a and song_id=:b''', {
|
||||||
|
'a': user_id, 'b': song_id})
|
||||||
|
|
||||||
for i in dir_list:
|
for i in dir_list:
|
||||||
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(
|
||||||
|
(str(user_id) + song_id + i + str(now)).encode(encoding='UTF-8')).hexdigest()
|
||||||
|
token = token[:8]
|
||||||
|
|
||||||
if i == 'base.ogg':
|
if i == 'base.ogg':
|
||||||
re['audio'] = {"checksum": get_file_md5(os.path.join(file_dir, song_id, 'base.ogg')),
|
re['audio'] = {"checksum": get_file_md5(os.path.join(file_dir, song_id, 'base.ogg')),
|
||||||
"url": url_for('download', file_path=song_id+'/base.ogg', _external=True)}
|
"url": url_for('download', file_path=song_id+'/base.ogg', t=token, _external=True)}
|
||||||
else:
|
else:
|
||||||
if 'chart' not in re:
|
if 'chart' not in re:
|
||||||
re['chart'] = {}
|
re['chart'] = {}
|
||||||
|
|
||||||
re['chart'][i[0]] = {"checksum": get_file_md5(os.path.join(file_dir, song_id, i)),
|
re['chart'][i[0]] = {"checksum": get_file_md5(os.path.join(file_dir, song_id, i)),
|
||||||
"url": url_for('download', file_path=song_id+'/'+i, _external=True)}
|
"url": url_for('download', file_path=song_id+'/'+i, t=token, _external=True)}
|
||||||
|
|
||||||
|
c.execute('''insert into download_token values(:a,:b,:c,:d,:e)''', {
|
||||||
|
'a': user_id, 'b': song_id, 'c': i, 'd': token, 'e': now})
|
||||||
|
|
||||||
return {song_id: re}
|
return {song_id: re}
|
||||||
|
|
||||||
|
|
||||||
def get_all_songs(file_dir='./database/songs'):
|
def get_all_songs(user_id, file_dir='./database/songs'):
|
||||||
# 获取所有歌的下载链接,返回字典
|
# 获取所有歌的下载链接,返回字典
|
||||||
dir_list = os.listdir(file_dir)
|
dir_list = os.listdir(file_dir)
|
||||||
re = {}
|
re = {}
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
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(i))
|
re.update(get_one_song(c, user_id, i))
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
return re
|
return re
|
||||||
|
|
||||||
|
|
||||||
|
def get_some_songs(user_id, song_ids):
|
||||||
|
# 获取一些歌的下载链接,返回字典
|
||||||
|
re = {}
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
for song_id in song_ids:
|
||||||
|
re.update(get_one_song(c, user_id, song_id))
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return re
|
||||||
|
|
||||||
|
|
||||||
|
def is_token_able_download(t):
|
||||||
|
# token是否可以下载,返回错误码,0即可以
|
||||||
|
errorcode = 0
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''select * from download_token where token = :t limit 1''',
|
||||||
|
{'t': t})
|
||||||
|
x = c.fetchone()
|
||||||
|
now = int(time.time())
|
||||||
|
if x and now - x[4] <= time_gap_limit:
|
||||||
|
c.execute(
|
||||||
|
'''select count(*) from user_download where user_id = :a''', {'a': x[0]})
|
||||||
|
y = c.fetchone()
|
||||||
|
if y and y[0] <= time_limit:
|
||||||
|
c.execute('''insert into user_download values(:a,:b,:c)''', {
|
||||||
|
'a': x[0], 'b': x[3], 'c': now})
|
||||||
|
else:
|
||||||
|
errorcode = 903
|
||||||
|
else:
|
||||||
|
errorcode = 108
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return errorcode
|
||||||
|
|
||||||
|
|
||||||
|
def is_able_download(user_id):
|
||||||
|
# 是否可以下载,返回布尔值
|
||||||
|
f = True
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
now = int(time.time())
|
||||||
|
c.execute(
|
||||||
|
'''delete from user_download where user_id = :a and time <= :b''', {'a': user_id, 'b': now - 24*3600})
|
||||||
|
c.execute(
|
||||||
|
'''select count(*) from user_download where user_id = :a''', {'a': user_id})
|
||||||
|
y = c.fetchone()
|
||||||
|
if y and y[0] <= time_limit:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
f = False
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return f
|
||||||
|
|||||||
122
latest version/server/arcpurchase.py
Normal file
122
latest version/server/arcpurchase.py
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
|
||||||
|
def int2b(x):
|
||||||
|
# int与布尔值转换
|
||||||
|
if x is None or x == 0:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_item(c, type='pack'):
|
||||||
|
# 读取packs内容,返回字典列表
|
||||||
|
c.execute('''select * from item where type = :a''', {'a': type})
|
||||||
|
x = c.fetchall()
|
||||||
|
if not x:
|
||||||
|
return []
|
||||||
|
|
||||||
|
re = []
|
||||||
|
for i in x:
|
||||||
|
r = {"name": i[0],
|
||||||
|
"items": [{
|
||||||
|
"type": i[1],
|
||||||
|
"id": i[0],
|
||||||
|
"is_available": int2b(i[2])
|
||||||
|
}],
|
||||||
|
"price": i[3],
|
||||||
|
"orig_price": i[4]}
|
||||||
|
|
||||||
|
if i[5] > 0:
|
||||||
|
r['discount_from'] = i[5]
|
||||||
|
if i[6] > 0:
|
||||||
|
r['discount_to'] = i[6]
|
||||||
|
|
||||||
|
re.append(r)
|
||||||
|
|
||||||
|
return re
|
||||||
|
|
||||||
|
|
||||||
|
def get_single_purchase():
|
||||||
|
# main里面没开数据库,这里写一下代替
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
re = get_item(c, type='single')
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return re
|
||||||
|
|
||||||
|
|
||||||
|
def buy_pack(user_id, pack_id):
|
||||||
|
# 曲包购买,返回字典
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
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()
|
||||||
|
if ticket:
|
||||||
|
ticket = ticket[0]
|
||||||
|
else:
|
||||||
|
ticket = 0
|
||||||
|
|
||||||
|
if ticket < price:
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return {
|
||||||
|
"success": False
|
||||||
|
}
|
||||||
|
|
||||||
|
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,'pack')''',
|
||||||
|
{'a': user_id, 'b': pack_id})
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return {
|
||||||
|
"success": True
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def buy_single(user_id, single_id):
|
||||||
|
# 单曲购买,返回字典
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
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
|
||||||
|
|
||||||
|
if ticket < price:
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return {
|
||||||
|
"success": False
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
conn.close()
|
||||||
|
return {
|
||||||
|
"success": True
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ import sqlite3
|
|||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
import server.arcworld
|
import server.arcworld
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
|
||||||
def b2int(x):
|
def b2int(x):
|
||||||
@@ -20,6 +21,16 @@ def int2b(x):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def md5(code):
|
||||||
|
# md5加密算法
|
||||||
|
code = code.encode()
|
||||||
|
md5s = hashlib.md5()
|
||||||
|
md5s.update(code)
|
||||||
|
codes = md5s.hexdigest()
|
||||||
|
|
||||||
|
return codes
|
||||||
|
|
||||||
|
|
||||||
def get_score(c, user_id, song_id, difficulty):
|
def get_score(c, user_id, song_id, difficulty):
|
||||||
# 根据user_id、song_id、难度得到该曲目最好成绩,返回字典
|
# 根据user_id、song_id、难度得到该曲目最好成绩,返回字典
|
||||||
c.execute('''select * from best_score where user_id = :a and song_id = :b and difficulty = :c''',
|
c.execute('''select * from best_score where user_id = :a and song_id = :b and difficulty = :c''',
|
||||||
@@ -480,6 +491,29 @@ def arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count, per
|
|||||||
return ptt, re
|
return ptt, re
|
||||||
|
|
||||||
|
|
||||||
|
def 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 shiny_perfect_count < 0 or perfect_count < 0 or near_count < 0 or miss_count < 0 or score < 0:
|
||||||
|
return False
|
||||||
|
if difficulty not in [0, 1, 2, 3]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
all_note = perfect_count + near_count + miss_count
|
||||||
|
ascore = 10000000 / all_note * \
|
||||||
|
(perfect_count + near_count/2) + shiny_perfect_count
|
||||||
|
if abs(ascore - score) >= 5:
|
||||||
|
return False
|
||||||
|
|
||||||
|
x = song_token + song_hash + song_id + str(difficulty) + str(score) + str(shiny_perfect_count) + str(
|
||||||
|
perfect_count) + str(near_count) + str(miss_count) + str(health) + str(modifier) + str(clear_type)
|
||||||
|
y = str(user_id) + song_hash
|
||||||
|
checksum = md5(x+md5(y))
|
||||||
|
if checksum != submission_hash:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def arc_all_post(user_id, scores_data, clearlamps_data):
|
def arc_all_post(user_id, scores_data, clearlamps_data):
|
||||||
# 向云端同步,无返回
|
# 向云端同步,无返回
|
||||||
# 注意,best_score表不比较,直接覆盖
|
# 注意,best_score表不比较,直接覆盖
|
||||||
@@ -1356,7 +1390,18 @@ def arc_all_get(user_id):
|
|||||||
}, {
|
}, {
|
||||||
"complete": 1,
|
"complete": 1,
|
||||||
"unlock_key": "dreaminattraction|1|0"
|
"unlock_key": "dreaminattraction|1|0"
|
||||||
}]
|
}, {
|
||||||
|
"complete": 1,
|
||||||
|
"unlock_key": "buchigireberserker|2|0"
|
||||||
|
}, {
|
||||||
|
"complete": 1,
|
||||||
|
"unlock_key": "gothiveofra|2|0"
|
||||||
|
}, {
|
||||||
|
"complete": 1,
|
||||||
|
"unlock_key": "gothiveofra|1|0"
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
}, "clearedsongs": {
|
}, "clearedsongs": {
|
||||||
"": song_1
|
"": song_1
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -62,18 +62,6 @@ def arc_register(name: str, password: str): # 注册
|
|||||||
else:
|
else:
|
||||||
return 2000001
|
return 2000001
|
||||||
|
|
||||||
# def insert_user_char(c, user_id):
|
|
||||||
# # 为用户添加所有可用角色
|
|
||||||
# for i in range(0, 38):
|
|
||||||
# if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]:
|
|
||||||
# sql = 'insert into user_char values('+str(user_id)+','+str(
|
|
||||||
# i)+''',30,25000,25000,90,90,90,'',0,0,'',0,1,1)'''
|
|
||||||
# c.execute(sql)
|
|
||||||
# else:
|
|
||||||
# if i != 5:
|
|
||||||
# sql = 'insert into user_char values('+str(user_id)+','+str(
|
|
||||||
# i)+''',30,25000,25000,90,90,90,'',0,0,'',0,0,0)'''
|
|
||||||
# c.execute(sql)
|
|
||||||
def insert_user_char(c, user_id):
|
def insert_user_char(c, user_id):
|
||||||
# 为用户添加所有可用角色
|
# 为用户添加所有可用角色
|
||||||
c.execute('''select * from character''')
|
c.execute('''select * from character''')
|
||||||
@@ -93,8 +81,8 @@ def arc_register(name: str, password: str): # 注册
|
|||||||
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)
|
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket)
|
||||||
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '')
|
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '', 114514)
|
||||||
''', {'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})
|
||||||
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})
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
import server.arcworld
|
import server.arcworld
|
||||||
|
import server.arcpurchase
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
def int2b(x):
|
def int2b(x):
|
||||||
@@ -56,7 +58,7 @@ def get_user_character(c, user_id):
|
|||||||
y = c.fetchone()
|
y = c.fetchone()
|
||||||
if y is not None:
|
if y is not None:
|
||||||
char_name = y[0]
|
char_name = y[0]
|
||||||
s.append({
|
char = {
|
||||||
"is_uncapped_override": int2b(i[14]),
|
"is_uncapped_override": int2b(i[14]),
|
||||||
"is_uncapped": int2b(i[13]),
|
"is_uncapped": int2b(i[13]),
|
||||||
"uncap_cores": [],
|
"uncap_cores": [],
|
||||||
@@ -73,7 +75,10 @@ def get_user_character(c, user_id):
|
|||||||
"level": i[2],
|
"level": i[2],
|
||||||
"name": char_name,
|
"name": char_name,
|
||||||
"character_id": i[1]
|
"character_id": i[1]
|
||||||
})
|
}
|
||||||
|
if i[1] == 21:
|
||||||
|
char["voice"] = [0, 1, 2, 3, 100, 1000, 1001]
|
||||||
|
s.append(char)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
else:
|
else:
|
||||||
@@ -115,6 +120,34 @@ def get_user_friend(c, user_id):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_singles(c, user_id):
|
||||||
|
# 得到用户的单曲,返回列表
|
||||||
|
c.execute('''select * from user_item where user_id = :user_id and type = "single"''',
|
||||||
|
{'user_id': user_id})
|
||||||
|
x = c.fetchall()
|
||||||
|
if not x:
|
||||||
|
return []
|
||||||
|
|
||||||
|
re = []
|
||||||
|
for i in x:
|
||||||
|
re.append(i[1])
|
||||||
|
return re
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_packs(c, user_id):
|
||||||
|
# 得到用户的曲包,返回列表
|
||||||
|
c.execute('''select * from user_item where user_id = :user_id and type = "pack"''',
|
||||||
|
{'user_id': user_id})
|
||||||
|
x = c.fetchall()
|
||||||
|
if not x:
|
||||||
|
return []
|
||||||
|
|
||||||
|
re = []
|
||||||
|
for i in x:
|
||||||
|
re.append(i[1])
|
||||||
|
return re
|
||||||
|
|
||||||
|
|
||||||
def get_value_0(c, user_id):
|
def get_value_0(c, user_id):
|
||||||
# 构造value id=0的数据,返回字典
|
# 构造value id=0的数据,返回字典
|
||||||
c.execute('''select * from user where user_id = :x''', {'x': user_id})
|
c.execute('''select * from user where user_id = :x''', {'x': user_id})
|
||||||
@@ -139,7 +172,7 @@ def get_value_0(c, user_id):
|
|||||||
"name": x[1],
|
"name": x[1],
|
||||||
"user_code": x[4],
|
"user_code": x[4],
|
||||||
"display_name": x[1],
|
"display_name": x[1],
|
||||||
"ticket": 114514,
|
"ticket": x[26],
|
||||||
"character": x[6],
|
"character": x[6],
|
||||||
"is_locked_name_duplicate": False,
|
"is_locked_name_duplicate": False,
|
||||||
"is_skill_sealed": int2b(x[7]),
|
"is_skill_sealed": int2b(x[7]),
|
||||||
@@ -148,10 +181,11 @@ def get_value_0(c, user_id):
|
|||||||
"next_fragstam_ts": -1,
|
"next_fragstam_ts": -1,
|
||||||
"max_stamina_ts": 1586274871917,
|
"max_stamina_ts": 1586274871917,
|
||||||
"stamina": 12,
|
"stamina": 12,
|
||||||
"world_unlocks": [],
|
"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"],
|
"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"],
|
||||||
"singles": ["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", "buchigireberserker2", "xeraphinite"],
|
"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"]
|
||||||
"packs": ["vs", "extend", "dynamix", "prelude", "core", "yugamu", "omatsuri", "zettai", "mirai", "shiawase", "chunithm", "nijuusei", "groovecoaster", "rei", "tonesphere", "lanota"],
|
"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),
|
||||||
@@ -180,7 +214,6 @@ def arc_aggregate_small(user_id):
|
|||||||
|
|
||||||
def arc_aggregate_big(user_id):
|
def arc_aggregate_big(user_id):
|
||||||
# 返回用户数据和地图歌曲信息
|
# 返回用户数据和地图歌曲信息
|
||||||
# 因为没有整理地图和曲包数据(不需要世界模式),所以直接复制了
|
|
||||||
|
|
||||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
@@ -190,185 +223,7 @@ def arc_aggregate_big(user_id):
|
|||||||
"value": get_value_0(c, user_id)
|
"value": get_value_0(c, user_id)
|
||||||
}, {
|
}, {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"value": [{
|
"value": server.arcpurchase.get_item(c, 'pack')
|
||||||
"name": "core",
|
|
||||||
"items": [{
|
|
||||||
"id": "core",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1583712000000,
|
|
||||||
"discount_to": 1584316799000
|
|
||||||
}, {
|
|
||||||
"name": "shiawase",
|
|
||||||
"items": [{
|
|
||||||
"id": "shiawase",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}, {
|
|
||||||
"id": "kou",
|
|
||||||
"type": "character",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1552089600000,
|
|
||||||
"discount_to": 1552694399000
|
|
||||||
}, {
|
|
||||||
"name": "dynamix",
|
|
||||||
"items": [{
|
|
||||||
"id": "dynamix",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}, {
|
|
||||||
"id": "sapphire",
|
|
||||||
"type": "character",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1583712000000,
|
|
||||||
"discount_to": 1584316799000
|
|
||||||
}, {
|
|
||||||
"name": "mirai",
|
|
||||||
"items": [{
|
|
||||||
"id": "mirai",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}, {
|
|
||||||
"id": "lethe",
|
|
||||||
"type": "character",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1552089600000,
|
|
||||||
"discount_to": 1552694399000
|
|
||||||
}, {
|
|
||||||
"name": "yugamu",
|
|
||||||
"items": [{
|
|
||||||
"id": "yugamu",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1583712000000,
|
|
||||||
"discount_to": 1584316799000
|
|
||||||
}, {
|
|
||||||
"name": "lanota",
|
|
||||||
"items": [{
|
|
||||||
"id": "lanota",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1583712000000,
|
|
||||||
"discount_to": 1584316799000
|
|
||||||
}, {
|
|
||||||
"name": "nijuusei",
|
|
||||||
"items": [{
|
|
||||||
"id": "nijuusei",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1583712000000,
|
|
||||||
"discount_to": 1584316799000
|
|
||||||
}, {
|
|
||||||
"name": "rei",
|
|
||||||
"items": [{
|
|
||||||
"id": "rei",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1583712000000,
|
|
||||||
"discount_to": 1584316799000
|
|
||||||
}, {
|
|
||||||
"name": "tonesphere",
|
|
||||||
"items": [{
|
|
||||||
"id": "tonesphere",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1583712000000,
|
|
||||||
"discount_to": 1584316799000
|
|
||||||
}, {
|
|
||||||
"name": "groovecoaster",
|
|
||||||
"items": [{
|
|
||||||
"id": "groovecoaster",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1583712000000,
|
|
||||||
"discount_to": 1584316799000
|
|
||||||
}, {
|
|
||||||
"name": "zettai",
|
|
||||||
"items": [{
|
|
||||||
"id": "zettai",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500,
|
|
||||||
"discount_from": 1583712000000,
|
|
||||||
"discount_to": 1584316799000
|
|
||||||
}, {
|
|
||||||
"name": "chunithm",
|
|
||||||
"items": [{
|
|
||||||
"id": "chunithm",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 300,
|
|
||||||
"orig_price": 300
|
|
||||||
}, {
|
|
||||||
"name": "prelude",
|
|
||||||
"items": [{
|
|
||||||
"id": "prelude",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 400,
|
|
||||||
"orig_price": 400
|
|
||||||
}, {
|
|
||||||
"name": "omatsuri",
|
|
||||||
"items": [{
|
|
||||||
"id": "omatsuri",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500
|
|
||||||
}, {
|
|
||||||
"name": "vs",
|
|
||||||
"items": [{
|
|
||||||
"id": "vs",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 500,
|
|
||||||
"orig_price": 500
|
|
||||||
}, {
|
|
||||||
"name": "extend",
|
|
||||||
"items": [{
|
|
||||||
"id": "extend",
|
|
||||||
"type": "pack",
|
|
||||||
"is_available": True
|
|
||||||
}],
|
|
||||||
"price": 700,
|
|
||||||
"orig_price": 700
|
|
||||||
}]
|
|
||||||
}, {
|
}, {
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"value": {}
|
"value": {}
|
||||||
@@ -378,7 +233,7 @@ def arc_aggregate_big(user_id):
|
|||||||
"max_stamina": 12,
|
"max_stamina": 12,
|
||||||
"stamina_recover_tick": 1800000,
|
"stamina_recover_tick": 1800000,
|
||||||
"core_exp": 250,
|
"core_exp": 250,
|
||||||
"curr_ts": 1599547606825,
|
"curr_ts": int(time.time())*1000,
|
||||||
"level_steps": [{
|
"level_steps": [{
|
||||||
"level": 1,
|
"level": 1,
|
||||||
"level_exp": 0
|
"level_exp": 0
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
[CONFIG]
|
[CONFIG]
|
||||||
HOST = 192.168.1.113
|
HOST = 192.168.1.113
|
||||||
PORT = 80
|
PORT = 80
|
||||||
|
|
||||||
|
[WEB]
|
||||||
|
USERNAME = admin
|
||||||
|
PASSWORD = admin
|
||||||
BIN
latest version/static/favicon.ico
Normal file
BIN
latest version/static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -210,8 +210,28 @@ input[type=submit] {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer{
|
.footer {
|
||||||
font-size: 0.5em;
|
font-size: 0.5em;
|
||||||
color: grey;
|
color: grey;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.char-item {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.char-name {
|
||||||
|
font-size: 1.3em;
|
||||||
|
font-weight: bold;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.char-id {
|
||||||
|
font-size: 1em;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.char-num {
|
||||||
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
59
latest version/templates/web/allchar.html
Normal file
59
latest version/templates/web/allchar.html
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}All characters{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if posts %}<br />
|
||||||
|
{% for char in posts %}
|
||||||
|
|
||||||
|
<div class="char-item">
|
||||||
|
<span>Id: </span>
|
||||||
|
<span class="char-id">{{char['character_id']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Name: </span>
|
||||||
|
<span class="char-name">{{char['name']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Level: </span>
|
||||||
|
<span class="char-num">{{char['level']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Frag: </span>
|
||||||
|
<span class="char-num">{{char['frag']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Prog: </span>
|
||||||
|
<span class="char-num">{{char['prog']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Overdrive: </span>
|
||||||
|
<span class="char-num">{{char['overdrive']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Skill id: </span>
|
||||||
|
<span class="char-num">{{char['skill_id']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Uncapped skill id: </span>
|
||||||
|
<span class="char-num">{{char['skill_id_uncap']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Is uncapped: </span>
|
||||||
|
<span class="char-num">{{char['is_uncapped']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% if not loop.last %}
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
<br />
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
51
latest version/templates/web/allitem.html
Normal file
51
latest version/templates/web/allitem.html
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}All items{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if posts %}<br />
|
||||||
|
{% for item in posts %}
|
||||||
|
|
||||||
|
<div class="char-item">
|
||||||
|
<span>Id: </span>
|
||||||
|
<span class="name">{{item['item_id']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Type: </span>
|
||||||
|
<span class="char-num">{{item['type']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Is available: </span>
|
||||||
|
<span class="char-num">{{item['is_available']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Price: </span>
|
||||||
|
<span class="char-num">{{item['price']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Original price: </span>
|
||||||
|
<span class="char-num">{{item['orig_price']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Discount from: </span>
|
||||||
|
<span class="char-num">{{item['discount_from']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<span>Discount to: </span>
|
||||||
|
<span class="char-num">{{item['discount_to']}}</span>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% if not loop.last %}
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
<br />
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
<span class="rank">User code: {{user['user_code']}}</span>
|
<span class="rank">User code: {{user['user_code']}}</span>
|
||||||
</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: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}</div>
|
<div class="ptt">PTT: {{'%0.2f'|format(user['rating_ptt']/100|float)}}</div>
|
||||||
|
<div class="ptt">Memories: {{user['ticket']}}</div>
|
||||||
<div>
|
<div>
|
||||||
<div>Recent plays: </div>
|
<div>Recent plays: </div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
55
latest version/templates/web/changechar.html
Normal file
55
latest version/templates/web/changechar.html
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}Change the characters{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form action="/web/changesong/editchar" method="post">
|
||||||
|
<div class="title">Edit the character</div>
|
||||||
|
<label for="id">ID of the character</label>
|
||||||
|
<input name="id" id="sid" required>
|
||||||
|
|
||||||
|
<label for="level">Level</label>
|
||||||
|
<input name="level" id="level">
|
||||||
|
|
||||||
|
<label for="frag">Frag</label>
|
||||||
|
<input name="frag" id="frag">
|
||||||
|
|
||||||
|
<label for="prog">Prog</label>
|
||||||
|
<input name="prog" id="prog">
|
||||||
|
|
||||||
|
<label for="overdrive">Overdrive</label>
|
||||||
|
<input name="overdrive" id="overdrive">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<select name="skill_id">
|
||||||
|
<option value="">Skill id</option>
|
||||||
|
{% for skill_id in skill_ids %}
|
||||||
|
<option value={{ skill_id }}>{{ skill_id }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<select name="skill_id_uncap">
|
||||||
|
<option value="">Uncapped skill id</option>
|
||||||
|
{% for skill_id in skill_ids %}
|
||||||
|
<option value={{ skill_id }}>{{ skill_id }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="content">如果某些不需要修改,留空即可</div>
|
||||||
|
<div class="content">If some things do not need to be modified, leave it blank.</div>
|
||||||
|
<div class="content">更新时角色数据表不会同步</div>
|
||||||
|
<div class="content">The character table will not be synchronized when updated.</div>
|
||||||
|
<input type="submit" value="Edit">
|
||||||
|
</form>
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
<form action="/web/changesong/updatechar" method="post">
|
||||||
|
<div class="title">Update the character</div>
|
||||||
|
<div class="content">更新所有用户拥有的角色</div>
|
||||||
|
<div class="content">Update all users' characters.</div>
|
||||||
|
<input type="submit" value="Update">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
41
latest version/templates/web/changeitem.html
Normal file
41
latest version/templates/web/changeitem.html
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}Change the items{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form action="/web/changeitem" method="post">
|
||||||
|
<div class="title">Change the item</div>
|
||||||
|
<label for="item_id">ID of the item</label>
|
||||||
|
<input name="item_id" id="item_id" required>
|
||||||
|
<label for="type">Type</label>
|
||||||
|
<div>
|
||||||
|
<select name="type">
|
||||||
|
<option value='single'>Single</option>
|
||||||
|
<option value='pack'>Pack</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="content">可修改项 Modifiable items:</div>
|
||||||
|
<div><label for="is_available">是否可用 Is available:</label>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<label><input type="radio" name="is_available" value=1>True</label>
|
||||||
|
<br />
|
||||||
|
<label><input type="radio" name="is_available" value=0>False</label>
|
||||||
|
</div>
|
||||||
|
<label for="price">Price</label>
|
||||||
|
<input name="price" id="price">
|
||||||
|
<label for="orig_price">Original price</label>
|
||||||
|
<input name="orig_price" id="orig_price">
|
||||||
|
<label for="discount_from">Discount from</label>
|
||||||
|
<input type="datetime-local" name="discount_from" id="discount_from">
|
||||||
|
<label for="discount_to">Discount to</label>
|
||||||
|
<input type="datetime-local" name="discount_to" id="discount_to">
|
||||||
|
<div class="content">如果某些不需要修改,留空即可</div>
|
||||||
|
<div class="content">If some things do not need to be modified, leave it blank.</div>
|
||||||
|
<div class="content">时间填写是一个HTML5控件</div>
|
||||||
|
<div class="content">Time filling is an HTML5 control.</div>
|
||||||
|
<input type="submit" value="Edit">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
37
latest version/templates/web/changeuser.html
Normal file
37
latest version/templates/web/changeuser.html
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}Change user information{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form action="/web/changeuser/edituser" method="post">
|
||||||
|
<div class="title">Edit the user</div>
|
||||||
|
<label for="name">Arcaea Username</label>
|
||||||
|
<input name="name" id="name">
|
||||||
|
or<br />
|
||||||
|
<label for="user_code">Arcaea User Code</label>
|
||||||
|
<input name="user_code" id="user_code">
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="ticket">Memories</label>
|
||||||
|
<input name="ticket" id="ticket">
|
||||||
|
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<div class="content">如果某些不需要修改,留空即可</div>
|
||||||
|
<div class="content">If some things do not need to be modified, leave it blank.</div>
|
||||||
|
<div class="content">目前只支持修改记忆源点</div>
|
||||||
|
<div class="content">At present, only memories can be modified.</div>
|
||||||
|
<input type="submit" value="Edit">
|
||||||
|
</form>
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
<form action="/web/changeuser/edituser" method="post">
|
||||||
|
<div class="title">Edit all the users</div>
|
||||||
|
<label for="ticket">Memories</label>
|
||||||
|
<input name="ticket" id="ticket">
|
||||||
|
|
||||||
|
<input type="submit" value="Edit all">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
44
latest version/templates/web/changeuserpurchase.html
Normal file
44
latest version/templates/web/changeuserpurchase.html
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block header %}
|
||||||
|
<h1>{% block title %}Change user purchase information{% endblock %}</h1>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form action="/web/changeuserpurchase/edituser" method="post">
|
||||||
|
<div class="title">Edit the user</div>
|
||||||
|
<label for="name">Arcaea Username</label>
|
||||||
|
<input name="name" id="name">
|
||||||
|
or<br />
|
||||||
|
<label for="user_code">Arcaea User Code</label>
|
||||||
|
<input name="user_code" id="user_code">
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<div>对所有单曲和曲包的操作 Operation to all singles and packs:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<label><input type="radio" name="method" value="0">解锁 Unlock</label>
|
||||||
|
<br />
|
||||||
|
<label><input type="radio" name="method" value="1">封绝 Lock</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<input type="submit" value="Execute">
|
||||||
|
</form>
|
||||||
|
<br />
|
||||||
|
<hr />
|
||||||
|
<form action="/web/changeuserpurchase/" method="post">
|
||||||
|
<div class="title">Edit all the users</div>
|
||||||
|
<br />
|
||||||
|
<div>对所有单曲和曲包的操作 Operation to all singles and packs:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<label><input type="radio" name="method" value="0">解锁 Unlock</label>
|
||||||
|
<br />
|
||||||
|
<label><input type="radio" name="method" value="1">封绝 Lock</label>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<input type="submit" value="Execute">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -14,11 +14,17 @@
|
|||||||
<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_item') }}">购买信息查询 All items</a></br></br>
|
||||||
<a href="{{ url_for('index.single_chart_top') }}">单个铺面排行榜查询 Single song chart tops</a>
|
<a href="{{ url_for('index.single_chart_top') }}">单个铺面排行榜查询 Single song chart tops</a>
|
||||||
<hr>
|
<hr>
|
||||||
<h1>系统方面 System</h1>
|
<h1>系统方面 System</h1>
|
||||||
<a href="{{ url_for('index.update_database') }}">数据库更新 Update databases</a></br></br>
|
<a href="{{ url_for('index.update_database') }}">数据库更新 Update databases</a></br></br>
|
||||||
<a href="{{ url_for('index.change_song') }}">歌曲修改 Change the songs</a>
|
<a href="{{ url_for('index.change_song') }}">歌曲修改 Change the songs</a></br></br>
|
||||||
|
<a href="{{ url_for('index.change_character') }}">角色修改 Change the characters</a></br></br>
|
||||||
|
<a href="{{ url_for('index.change_item') }}">购买信息修改 Change the items</a></br></br>
|
||||||
|
<a href="{{ url_for('index.change_user') }}">用户信息修改 Change user information</a></br></br>
|
||||||
|
<a href="{{ url_for('index.change_user_purchase') }}">用户购买信息修改 Change user purchase information</a>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -24,7 +24,8 @@
|
|||||||
<span class="rank">User code: {{user['user_code']}}</span>
|
<span class="rank">User code: {{user['user_code']}}</span>
|
||||||
</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: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}</div>
|
<div class="ptt">Memories: {{user['ticket']}}</div>
|
||||||
|
<div class="ptt">PTT: {{'%0.2f'|format(user['rating_ptt']/100|float)}}</div>
|
||||||
<div class="ptt">Best 30 PTT: {{bestptt}}</div>
|
<div class="ptt">Best 30 PTT: {{bestptt}}</div>
|
||||||
<div class="ptt">Recent 10 PTT: {{recentptt}}</div>
|
<div class="ptt">Recent 10 PTT: {{recentptt}}</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -157,7 +157,8 @@ def all_player():
|
|||||||
'miss_count': i[17],
|
'miss_count': i[17],
|
||||||
'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]
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
error = '没有玩家数据 No player data.'
|
error = '没有玩家数据 No player data.'
|
||||||
@@ -358,3 +359,411 @@ def delete_song():
|
|||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
return redirect(url_for('index.change_song'))
|
return redirect(url_for('index.change_song'))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/allchar', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
def all_character():
|
||||||
|
# 所有角色数据
|
||||||
|
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''select * from character''')
|
||||||
|
x = c.fetchall()
|
||||||
|
error = None
|
||||||
|
if x:
|
||||||
|
posts = []
|
||||||
|
for i in x:
|
||||||
|
posts.append({'character_id': i[0],
|
||||||
|
'name': i[1],
|
||||||
|
'level': i[2],
|
||||||
|
'frag': i[5],
|
||||||
|
'prog': i[6],
|
||||||
|
'overdrive': i[7],
|
||||||
|
'skill_id': i[8],
|
||||||
|
'skill_id_uncap': i[11],
|
||||||
|
'char_type': i[12],
|
||||||
|
'is_uncapped': i[14] == 1
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
error = '没有角色数据 No character data.'
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
return render_template('web/allchar.html')
|
||||||
|
else:
|
||||||
|
return render_template('web/allchar.html', posts=posts)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changechar', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
def change_character():
|
||||||
|
# 修改角色数据
|
||||||
|
skill_ids = ['No_skill', 'gauge_easy', 'note_mirror', 'gauge_hard', 'frag_plus_10_pack_stellights', 'gauge_easy|frag_plus_15_pst&prs', 'gauge_hard|fail_frag_minus_100', 'frag_plus_5_side_light', 'visual_hide_hp', 'frag_plus_5_side_conflict', 'challenge_fullcombo_0gauge', 'gauge_overflow', 'gauge_easy|note_mirror', 'note_mirror', 'visual_tomato_pack_tonesphere',
|
||||||
|
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', 'frags_kou', 'visual_ink', 'shirabe_entry_fee', 'frags_yume']
|
||||||
|
return render_template('web/changechar.html', skill_ids=skill_ids)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changesong/editchar', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def edit_char():
|
||||||
|
# 修改角色数据
|
||||||
|
|
||||||
|
error = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
character_id = int(request.form['id'])
|
||||||
|
level = request.form['level']
|
||||||
|
frag = request.form['frag']
|
||||||
|
prog = request.form['prog']
|
||||||
|
overdrive = request.form['overdrive']
|
||||||
|
skill_id = request.form['skill_id']
|
||||||
|
skill_id_uncap = request.form['skill_id_uncap']
|
||||||
|
if level:
|
||||||
|
level = int(level)
|
||||||
|
else:
|
||||||
|
level = None
|
||||||
|
if frag:
|
||||||
|
frag = float(frag)
|
||||||
|
else:
|
||||||
|
frag = None
|
||||||
|
if prog:
|
||||||
|
prog = float(prog)
|
||||||
|
else:
|
||||||
|
prog = None
|
||||||
|
if overdrive:
|
||||||
|
overdrive = float(overdrive)
|
||||||
|
else:
|
||||||
|
overdrive = None
|
||||||
|
except:
|
||||||
|
error = '数据错误 Wrong data.'
|
||||||
|
flash(error)
|
||||||
|
return redirect(url_for('index.change_character'))
|
||||||
|
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from character where character_id=:a)''', {'a': character_id})
|
||||||
|
if c.fetchone() == (1,):
|
||||||
|
if level is None and frag is None and prog is None and overdrive is None and skill_id is None and skill_id_uncap is None:
|
||||||
|
error = '无修改 No change.'
|
||||||
|
else:
|
||||||
|
|
||||||
|
sql = '''update character set level_exp=25000'''
|
||||||
|
sql_dict = {'character_id': character_id}
|
||||||
|
if level is not None:
|
||||||
|
sql += ', level = :level'
|
||||||
|
sql_dict['level'] = level
|
||||||
|
if frag is not None:
|
||||||
|
sql += ', frag = :frag'
|
||||||
|
sql_dict['frag'] = frag
|
||||||
|
if prog is not None:
|
||||||
|
sql += ', prog = :prog'
|
||||||
|
sql_dict['prog'] = prog
|
||||||
|
if overdrive is not None:
|
||||||
|
sql += ', overdrive = :overdrive'
|
||||||
|
sql_dict['overdrive'] = overdrive
|
||||||
|
if skill_id is not None:
|
||||||
|
sql += ', skill_id = :skill_id'
|
||||||
|
if skill_id == 'No_skill':
|
||||||
|
sql_dict['skill_id'] = ''
|
||||||
|
else:
|
||||||
|
sql_dict['skill_id'] = skill_id
|
||||||
|
if skill_id_uncap is not None:
|
||||||
|
sql += ', skill_id_uncap = :skill_id_uncap'
|
||||||
|
if skill_id_uncap == 'No_skill':
|
||||||
|
sql_dict['skill_id_uncap'] = ''
|
||||||
|
else:
|
||||||
|
sql_dict['skill_id_uncap'] = skill_id_uncap
|
||||||
|
sql += ' where character_id = :character_id'
|
||||||
|
c.execute(sql, sql_dict)
|
||||||
|
flash('角色修改成功 Successfully edit the character.')
|
||||||
|
else:
|
||||||
|
error = '角色不存在 The character does not exist.'
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return redirect(url_for('index.change_character'))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changesong/updatechar', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def update_character():
|
||||||
|
# 更新角色数据
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
web.system.update_user_char(c)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
flash('数据更新成功 Success update data.')
|
||||||
|
return redirect(url_for('index.change_character'))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changeuser', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
def change_user():
|
||||||
|
# 修改用户信息
|
||||||
|
|
||||||
|
return render_template('web/changeuser.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changeuser/edituser', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def edit_user():
|
||||||
|
# 修改用户数据
|
||||||
|
|
||||||
|
error = None
|
||||||
|
flag = True
|
||||||
|
name = None
|
||||||
|
user_code = None
|
||||||
|
try:
|
||||||
|
ticket = request.form['ticket']
|
||||||
|
if ticket:
|
||||||
|
ticket = int(ticket)
|
||||||
|
else:
|
||||||
|
ticket = None
|
||||||
|
except:
|
||||||
|
error = '数据错误 Wrong data.'
|
||||||
|
flash(error)
|
||||||
|
return redirect(url_for('index.change_user'))
|
||||||
|
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
|
||||||
|
# 全修改
|
||||||
|
if 'name' not in request.form and 'user_code' not in request.form:
|
||||||
|
flag = False
|
||||||
|
if not ticket:
|
||||||
|
error = '无修改 No change.'
|
||||||
|
else:
|
||||||
|
sql = '''update user set ticket = :ticket'''
|
||||||
|
sql_dict = {'ticket': ticket}
|
||||||
|
c.execute(sql, sql_dict)
|
||||||
|
flash("全部用户信息修改成功 Successfully edit all the users' information.")
|
||||||
|
|
||||||
|
else:
|
||||||
|
name = request.form['name']
|
||||||
|
user_code = request.form['user_code']
|
||||||
|
|
||||||
|
# 指定修改
|
||||||
|
|
||||||
|
if name or user_code:
|
||||||
|
|
||||||
|
if user_code:
|
||||||
|
c.execute('''select user_id from user where user_code=:a''', {
|
||||||
|
'a': user_code})
|
||||||
|
else:
|
||||||
|
c.execute(
|
||||||
|
'''select user_id from user where name=:a''', {'a': name})
|
||||||
|
|
||||||
|
user_id = c.fetchone()
|
||||||
|
posts = []
|
||||||
|
if user_id:
|
||||||
|
user_id = user_id[0]
|
||||||
|
|
||||||
|
if not ticket:
|
||||||
|
error = '无修改 No change.'
|
||||||
|
else:
|
||||||
|
sql = '''update user set ticket = :ticket where user_id = :user_id'''
|
||||||
|
sql_dict = {'ticket': ticket, 'user_id': user_id}
|
||||||
|
c.execute(sql, sql_dict)
|
||||||
|
flash('用户信息修改成功 Successfully edit the user information.')
|
||||||
|
|
||||||
|
else:
|
||||||
|
error = '玩家不存在 The player does not exist.'
|
||||||
|
|
||||||
|
else:
|
||||||
|
if flag:
|
||||||
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return redirect(url_for('index.change_user'))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changeuserpurchase', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
def change_user_purchase():
|
||||||
|
# 修改用户购买
|
||||||
|
|
||||||
|
return render_template('web/changeuserpurchase.html')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changeuserpurchase/edituser', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def edit_user_purchase():
|
||||||
|
# 修改用户购买
|
||||||
|
|
||||||
|
error = None
|
||||||
|
flag = True
|
||||||
|
name = None
|
||||||
|
user_code = None
|
||||||
|
try:
|
||||||
|
method = request.form['method']
|
||||||
|
except:
|
||||||
|
flash('输入为空 Null Input.')
|
||||||
|
return redirect(url_for('index.change_user_purchase'))
|
||||||
|
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
|
||||||
|
# 全修改
|
||||||
|
if 'name' not in request.form and 'user_code' not in request.form:
|
||||||
|
flag = False
|
||||||
|
if method == '0':
|
||||||
|
web.system.unlock_all_user_item(c)
|
||||||
|
else:
|
||||||
|
c.execute('''delete from user_item''')
|
||||||
|
|
||||||
|
flash("全部用户购买信息修改成功 Successfully edit all the users' purchase information.")
|
||||||
|
|
||||||
|
else:
|
||||||
|
name = request.form['name']
|
||||||
|
user_code = request.form['user_code']
|
||||||
|
|
||||||
|
# 指定修改
|
||||||
|
if name or user_code:
|
||||||
|
|
||||||
|
if user_code:
|
||||||
|
c.execute('''select user_id from user where user_code=:a''', {
|
||||||
|
'a': user_code})
|
||||||
|
else:
|
||||||
|
c.execute(
|
||||||
|
'''select user_id from user where name=:a''', {'a': name})
|
||||||
|
|
||||||
|
user_id = c.fetchone()
|
||||||
|
posts = []
|
||||||
|
if user_id:
|
||||||
|
user_id = user_id[0]
|
||||||
|
|
||||||
|
if method == '0':
|
||||||
|
web.system.unlock_user_item(c, user_id)
|
||||||
|
else:
|
||||||
|
c.execute('''delete from user_item where user_id=:a''', {
|
||||||
|
'a': user_id})
|
||||||
|
flash('用户购买信息修改成功 Successfully edit the user purchase information.')
|
||||||
|
|
||||||
|
else:
|
||||||
|
error = '玩家不存在 The player does not exist.'
|
||||||
|
|
||||||
|
else:
|
||||||
|
if flag:
|
||||||
|
error = '输入为空 Null Input.'
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return redirect(url_for('index.change_user_purchase'))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/allitem', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
def all_item():
|
||||||
|
# 所有购买数据
|
||||||
|
|
||||||
|
error = None
|
||||||
|
posts = web.system.get_all_item()
|
||||||
|
if not posts:
|
||||||
|
error = '没有购买数据 No item data.'
|
||||||
|
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
return redirect(url_for('index.all_item'))
|
||||||
|
else:
|
||||||
|
return render_template('web/allitem.html', posts=posts)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/changeitem', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def change_item():
|
||||||
|
# 修改购买信息
|
||||||
|
|
||||||
|
error = None
|
||||||
|
if request.method == 'POST':
|
||||||
|
try:
|
||||||
|
item_id = request.form['item_id']
|
||||||
|
item_type = request.form['type']
|
||||||
|
price = request.form['price']
|
||||||
|
orig_price = request.form['orig_price']
|
||||||
|
discount_from = request.form['discount_from']
|
||||||
|
discount_to = request.form['discount_to']
|
||||||
|
try:
|
||||||
|
is_available = request.form['is_available']
|
||||||
|
if is_available:
|
||||||
|
is_available = int(is_available)
|
||||||
|
else:
|
||||||
|
is_available = None
|
||||||
|
except:
|
||||||
|
is_available = None
|
||||||
|
|
||||||
|
if price:
|
||||||
|
price = int(price)
|
||||||
|
else:
|
||||||
|
price = None
|
||||||
|
if orig_price:
|
||||||
|
orig_price = int(orig_price)
|
||||||
|
else:
|
||||||
|
orig_price = None
|
||||||
|
if discount_from:
|
||||||
|
discount_from = int(time.mktime(time.strptime(discount_from, "%Y-%m-%dT%H:%M"))) * 1000
|
||||||
|
else:
|
||||||
|
discount_from = None
|
||||||
|
if discount_to:
|
||||||
|
discount_to = int(time.mktime(time.strptime(discount_to, "%Y-%m-%dT%H:%M"))) * 1000
|
||||||
|
else:
|
||||||
|
discount_to = None
|
||||||
|
except:
|
||||||
|
error = '数据错误 Wrong data.'
|
||||||
|
flash(error)
|
||||||
|
return redirect(url_for('index.change_item'))
|
||||||
|
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute(
|
||||||
|
'''select exists(select * from item where item_id=:a and type=:b)''', {'a': item_id, 'b': item_type})
|
||||||
|
if c.fetchone() == (1,):
|
||||||
|
if is_available is None and price is None and orig_price is None and not discount_from and not discount_to:
|
||||||
|
error = '无修改 No change.'
|
||||||
|
else:
|
||||||
|
sql = '''update item set type=:type'''
|
||||||
|
sql_dict = {'item_id': item_id, 'type': item_type}
|
||||||
|
if price is not None:
|
||||||
|
sql += ', price = :price'
|
||||||
|
sql_dict['price'] = price
|
||||||
|
if orig_price is not None:
|
||||||
|
sql += ', orig_price = :orig_price'
|
||||||
|
sql_dict['orig_price'] = orig_price
|
||||||
|
if discount_from is not None:
|
||||||
|
sql += ', discount_from = :discount_from'
|
||||||
|
sql_dict['discount_from'] = discount_from
|
||||||
|
if discount_to is not None:
|
||||||
|
sql += ', discount_to = :discount_to'
|
||||||
|
sql_dict['discount_to'] = discount_to
|
||||||
|
if is_available is not None:
|
||||||
|
sql += ', is_available = :is_available'
|
||||||
|
sql_dict['is_available'] = is_available
|
||||||
|
|
||||||
|
sql += ' where item_id = :item_id and type = :type'
|
||||||
|
c.execute(sql, sql_dict)
|
||||||
|
flash('购买项目修改成功 Successfully edit the item.')
|
||||||
|
else:
|
||||||
|
error = '购买项目不存在 The item does not exist.'
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
if error:
|
||||||
|
flash(error)
|
||||||
|
|
||||||
|
return render_template('web/changeitem.html')
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
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
|
||||||
|
|
||||||
bp = Blueprint('login', __name__, url_prefix='/web')
|
bp = Blueprint('login', __name__, url_prefix='/web')
|
||||||
|
|
||||||
@@ -14,12 +15,18 @@ def login():
|
|||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
error = None
|
error = None
|
||||||
|
|
||||||
if username != 'admin' and password != 'admin':
|
config = configparser.ConfigParser()
|
||||||
|
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'] = 'admin'
|
session['user_id'] = USERNAME + PASSWORD
|
||||||
return redirect(url_for('index.index'))
|
return redirect(url_for('index.index'))
|
||||||
|
|
||||||
flash(error)
|
flash(error)
|
||||||
@@ -40,11 +47,17 @@ def login_required(view):
|
|||||||
@functools.wraps(view)
|
@functools.wraps(view)
|
||||||
def wrapped_view(**kwargs):
|
def wrapped_view(**kwargs):
|
||||||
x = session.get('user_id')
|
x = session.get('user_id')
|
||||||
# 少用户存在验证
|
|
||||||
if x is None:
|
config = configparser.ConfigParser()
|
||||||
|
path = r'setting.ini'
|
||||||
|
config.read(path, encoding="utf-8")
|
||||||
|
USERNAME = config.get('WEB', 'USERNAME')
|
||||||
|
PASSWORD = config.get('WEB', 'PASSWORD')
|
||||||
|
|
||||||
|
if x != USERNAME + PASSWORD:
|
||||||
return redirect(url_for('login.login'))
|
return redirect(url_for('login.login'))
|
||||||
|
|
||||||
g.user = {'user_id': x, 'username': 'admin'}
|
g.user = {'user_id': x, 'username': USERNAME}
|
||||||
return view(**kwargs)
|
return view(**kwargs)
|
||||||
|
|
||||||
return wrapped_view
|
return wrapped_view
|
||||||
|
|||||||
@@ -1,5 +1,126 @@
|
|||||||
import os
|
import os
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def int2b(x):
|
||||||
|
# int与布尔值转换
|
||||||
|
if x is None or x == 0:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def get_table_info(c, table_name):
|
||||||
|
# 得到表结构,返回主键列表和字段名列表
|
||||||
|
pk = []
|
||||||
|
name = []
|
||||||
|
|
||||||
|
c.execute('''pragma table_info ("'''+table_name+'''")''')
|
||||||
|
x = c.fetchall()
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
name.append(i[1])
|
||||||
|
if i[5] != 0:
|
||||||
|
pk.append(i[1])
|
||||||
|
|
||||||
|
return pk, name
|
||||||
|
|
||||||
|
|
||||||
|
def get_sql_select_table(table_name, get_field, where_field=[], where_value=[]):
|
||||||
|
# sql语句拼接,select ... from ... where ...
|
||||||
|
sql = 'select '
|
||||||
|
sql_dict = {}
|
||||||
|
if len(get_field) >= 2:
|
||||||
|
sql += get_field[0]
|
||||||
|
for i in range(1, len(get_field)):
|
||||||
|
sql += ',' + get_field[i]
|
||||||
|
sql += ' from ' + table_name
|
||||||
|
elif len(get_field) == 1:
|
||||||
|
sql += get_field[0] + ' from ' + table_name
|
||||||
|
else:
|
||||||
|
sql += '* from ' + table_name
|
||||||
|
|
||||||
|
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) >= 1:
|
||||||
|
for i in range(1, len(where_field)):
|
||||||
|
sql_dict[where_field[i]] = where_value[i]
|
||||||
|
sql += ' and ' + where_field[i] + '=:' + where_field[i]
|
||||||
|
|
||||||
|
sql += ' order by rowid'
|
||||||
|
return sql, sql_dict
|
||||||
|
|
||||||
|
|
||||||
|
def get_sql_insert_table(table_name, field, value):
|
||||||
|
# sql语句拼接,insert into ...(...) values(...)
|
||||||
|
sql = 'insert into ' + table_name + '('
|
||||||
|
sql_dict = {}
|
||||||
|
sql2 = ''
|
||||||
|
if len(field) >= 2:
|
||||||
|
sql += field[0]
|
||||||
|
sql2 += ':' + field[0]
|
||||||
|
sql_dict[field[0]] = value[0]
|
||||||
|
for i in range(1, len(field)):
|
||||||
|
sql += ',' + field[i]
|
||||||
|
sql2 += ', :' + field[i]
|
||||||
|
sql_dict[field[i]] = value[i]
|
||||||
|
|
||||||
|
sql += ') values('
|
||||||
|
|
||||||
|
elif len(field) == 1:
|
||||||
|
sql += field[0] + ') values('
|
||||||
|
sql2 += ':' + field[0]
|
||||||
|
sql_dict[field[0]] = value[0]
|
||||||
|
|
||||||
|
else:
|
||||||
|
return 'error', {}
|
||||||
|
|
||||||
|
sql += sql2 + ')'
|
||||||
|
|
||||||
|
return sql, sql_dict
|
||||||
|
|
||||||
|
|
||||||
|
def update_one_table(c1, c2, table_name):
|
||||||
|
# 从c1向c2更新数据表,c2中存在的信息不变
|
||||||
|
c1.execute(
|
||||||
|
'''select * from sqlite_master where type = 'table' and name = :a''', {'a': table_name})
|
||||||
|
c2.execute(
|
||||||
|
'''select * from sqlite_master where type = 'table' and name = :a''', {'a': table_name})
|
||||||
|
if not c1.fetchone() or not c2.fetchone():
|
||||||
|
return 'error'
|
||||||
|
|
||||||
|
db1_pk, db1_name = get_table_info(c1, table_name)
|
||||||
|
db2_pk, db2_name = get_table_info(c2, table_name)
|
||||||
|
if db1_pk != db2_pk:
|
||||||
|
return 'error'
|
||||||
|
|
||||||
|
field = []
|
||||||
|
for i in db1_name:
|
||||||
|
if i in db2_name:
|
||||||
|
field.append(i)
|
||||||
|
|
||||||
|
sql, sql_dict = get_sql_select_table(table_name, db1_pk)
|
||||||
|
c1.execute(sql)
|
||||||
|
x = c1.fetchall()
|
||||||
|
sql, sql_dict = get_sql_select_table(table_name, field)
|
||||||
|
c1.execute(sql)
|
||||||
|
y = c1.fetchall()
|
||||||
|
if x:
|
||||||
|
for i in range(0, len(x)):
|
||||||
|
sql, sql_dict = get_sql_select_table(
|
||||||
|
table_name, [], db1_pk, list(x[i]))
|
||||||
|
sql = 'select exists(' + sql + ')'
|
||||||
|
c2.execute(sql, sql_dict)
|
||||||
|
|
||||||
|
if c2.fetchone() == (0,):
|
||||||
|
sql, sql_dict = get_sql_insert_table(
|
||||||
|
table_name, field, list(y[i]))
|
||||||
|
c2.execute(sql, sql_dict)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def update_user_char(c):
|
def update_user_char(c):
|
||||||
@@ -19,7 +140,7 @@ def update_user_char(c):
|
|||||||
|
|
||||||
def update_database():
|
def update_database():
|
||||||
# 将old数据库不存在数据加入到新数据库上,并删除old数据库
|
# 将old数据库不存在数据加入到新数据库上,并删除old数据库
|
||||||
# 对于arcaea_datebase.db,更新best_score,friend,recent30,user,user_world并用character数据更新user_char
|
# 对于arcaea_datebase.db,更新best_score,friend,recent30,user,user_world, user_item并用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')
|
conn1 = sqlite3.connect('./database/old_arcaea_database.db')
|
||||||
@@ -27,62 +148,15 @@ def update_database():
|
|||||||
conn2 = sqlite3.connect('./database/arcaea_database.db')
|
conn2 = sqlite3.connect('./database/arcaea_database.db')
|
||||||
c2 = conn2.cursor()
|
c2 = conn2.cursor()
|
||||||
|
|
||||||
# user
|
update_one_table(c1, c2, 'user')
|
||||||
c1.execute('''select * from user''')
|
update_one_table(c1, c2, 'friend')
|
||||||
x = c1.fetchall()
|
update_one_table(c1, c2, 'best_score')
|
||||||
if x:
|
update_one_table(c1, c2, 'recent30')
|
||||||
for i in x:
|
update_one_table(c1, c2, 'user_world')
|
||||||
c2.execute(
|
update_one_table(c1, c2, 'user_item')
|
||||||
'''select exists(select * from user where user_id=:a)''', {'a': i[0]})
|
|
||||||
if c2.fetchone() == (0,):
|
|
||||||
c2.execute('''insert into user values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25)''', {
|
|
||||||
'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25]})
|
|
||||||
|
|
||||||
# friend
|
|
||||||
c1.execute('''select * from friend''')
|
|
||||||
x = c1.fetchall()
|
|
||||||
if x:
|
|
||||||
for i in x:
|
|
||||||
c2.execute(
|
|
||||||
'''select exists(select * from friend where user_id_me=:a and user_id_other=:b)''', {'a': i[0], 'b': i[1]})
|
|
||||||
if c2.fetchone() == (0,):
|
|
||||||
c2.execute('''insert into friend values(:a,:b)''', {
|
|
||||||
'a': i[0], 'b': i[1]})
|
|
||||||
|
|
||||||
# best_score
|
|
||||||
c1.execute('''select * from best_score''')
|
|
||||||
x = c1.fetchall()
|
|
||||||
if x:
|
|
||||||
for i in x:
|
|
||||||
c2.execute('''select exists(select * from best_score where user_id=:a and song_id=:b and difficulty=:c)''', {
|
|
||||||
'a': i[0], 'b': i[1], 'c': i[2]})
|
|
||||||
if c2.fetchone() == (0,):
|
|
||||||
c2.execute('''insert into best_score values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13)''', {
|
|
||||||
'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13]})
|
|
||||||
|
|
||||||
# recent30
|
|
||||||
c1.execute('''select * from recent30''')
|
|
||||||
x = c1.fetchall()
|
|
||||||
if x:
|
|
||||||
for i in x:
|
|
||||||
c2.execute(
|
|
||||||
'''select exists(select * from recent30 where user_id=:a)''', {'a': i[0]})
|
|
||||||
if c2.fetchone() == (0,):
|
|
||||||
c2.execute('''insert into recent30 values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27,:a28,:a29,:a30,:a31,:a32,:a33,:a34,:a35,:a36,:a37,:a38,:a39,:a40,:a41,:a42,:a43,:a44,:a45,:a46,:a47,:a48,:a49,:a50,:a51,:a52,:a53,:a54,:a55,:a56,:a57,:a58,:a59,:a60)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[
|
|
||||||
18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27], 'a28': i[28], 'a29': i[29], 'a30': i[30], 'a31': i[31], 'a32': i[32], 'a33': i[33], 'a34': i[34], 'a35': i[35], 'a36': i[36], 'a37': i[37], 'a38': i[38], 'a39': i[39], 'a40': i[40], 'a41': i[41], 'a42': i[42], 'a43': i[43], 'a44': i[44], 'a45': i[45], 'a46': i[46], 'a47': i[47], 'a48': i[48], 'a49': i[49], 'a50': i[50], 'a51': i[51], 'a52': i[52], 'a53': i[53], 'a54': i[54], 'a55': i[55], 'a56': i[56], 'a57': i[57], 'a58': i[58], 'a59': i[59], 'a60': i[60]})
|
|
||||||
|
|
||||||
# user_world
|
|
||||||
c1.execute('''select * from user_world''')
|
|
||||||
x = c1.fetchall()
|
|
||||||
if x:
|
|
||||||
for i in x:
|
|
||||||
c2.execute(
|
|
||||||
'''select exists(select * from user_world where user_id=:a and map_id=:b)''', {'a': i[0], 'b': i[1]})
|
|
||||||
if c2.fetchone() == (0,):
|
|
||||||
c2.execute('''insert into user_world values(:a0,:a1,:a2,:a3,:a4)''', {
|
|
||||||
'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4]})
|
|
||||||
|
|
||||||
update_user_char(c2)
|
update_user_char(c2)
|
||||||
|
|
||||||
conn1.commit()
|
conn1.commit()
|
||||||
conn1.close()
|
conn1.close()
|
||||||
conn2.commit()
|
conn2.commit()
|
||||||
@@ -96,18 +170,76 @@ def update_database():
|
|||||||
conn2 = sqlite3.connect('./database/arcsong.db')
|
conn2 = sqlite3.connect('./database/arcsong.db')
|
||||||
c2 = conn2.cursor()
|
c2 = conn2.cursor()
|
||||||
|
|
||||||
c1.execute('''select * from songs''')
|
update_one_table(c1, c2, 'songs')
|
||||||
x = c1.fetchall()
|
|
||||||
if x:
|
|
||||||
for i in x:
|
|
||||||
c2.execute(
|
|
||||||
'''select exists(select * from songs where sid=:a)''', {'a': i[0]})
|
|
||||||
if c2.fetchone() == (0,):
|
|
||||||
c2.execute('''insert into songs values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[
|
|
||||||
8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27]})
|
|
||||||
|
|
||||||
conn1.commit()
|
conn1.commit()
|
||||||
conn1.close()
|
conn1.close()
|
||||||
conn2.commit()
|
conn2.commit()
|
||||||
conn2.close()
|
conn2.close()
|
||||||
os.remove('database/old_arcsong.db')
|
os.remove('database/old_arcsong.db')
|
||||||
|
|
||||||
|
|
||||||
|
def unlock_all_user_item(c):
|
||||||
|
# 解锁所有用户购买
|
||||||
|
|
||||||
|
c.execute('''select user_id from user''')
|
||||||
|
x = c.fetchall()
|
||||||
|
c.execute('''select item_id, type from item''')
|
||||||
|
y = c.fetchall()
|
||||||
|
c.execute('''delete from user_item''')
|
||||||
|
if x and y:
|
||||||
|
for i in x:
|
||||||
|
for j in y:
|
||||||
|
c.execute('''insert into user_item values(:a,:b,:c)''', {
|
||||||
|
'a': i[0], 'b': j[0], 'c': j[1]})
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def unlock_user_item(c, user_id):
|
||||||
|
# 解锁用户购买
|
||||||
|
|
||||||
|
c.execute('''select item_id, type from item''')
|
||||||
|
y = c.fetchall()
|
||||||
|
|
||||||
|
for j in y:
|
||||||
|
c.execute('''select exists(select * from user_item where user_id=:a and item_id=:b and type=:c)''', {
|
||||||
|
'a': user_id, 'b': j[0], 'c': j[1]})
|
||||||
|
if c.fetchone() == (0,):
|
||||||
|
c.execute('''insert into user_item values(:a,:b,:c)''', {
|
||||||
|
'a': user_id, 'b': j[0], 'c': j[1]})
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_item():
|
||||||
|
# 所有购买数据查询
|
||||||
|
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''select * from item''')
|
||||||
|
x = c.fetchall()
|
||||||
|
re = []
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
discount_from = None
|
||||||
|
discount_to = None
|
||||||
|
|
||||||
|
if i[5] and i[5] >= 0:
|
||||||
|
discount_from = time.strftime(
|
||||||
|
"%Y-%m-%d %H:%M:%S", time.localtime(int(i[5])/1000))
|
||||||
|
if i[6] and i[6] >= 0:
|
||||||
|
discount_to = time.strftime(
|
||||||
|
"%Y-%m-%d %H:%M:%S", time.localtime(int(i[6])//1000))
|
||||||
|
|
||||||
|
re.append({'item_id': i[0],
|
||||||
|
'type': i[1],
|
||||||
|
'is_available': int2b(i[2]),
|
||||||
|
'price': i[3],
|
||||||
|
'orig_price': i[4],
|
||||||
|
'discount_from': discount_from,
|
||||||
|
'discount_to': discount_to
|
||||||
|
})
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return re
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ def get_user(c, user_id):
|
|||||||
'miss_count': x[17],
|
'miss_count': x[17],
|
||||||
'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]
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|||||||
Reference in New Issue
Block a user