13 Commits
v2.0 ... v2.3.1

Author SHA1 Message Date
Lost-MSth
e216e6144b Update README.md 2021-04-01 17:05:53 +08:00
Lost-MSth
b70c435a4a Update to v2.3.1 2021-04-01 17:02:56 +08:00
Lost-MSth
eb03d2be93 Update README.md 2021-03-14 22:37:59 +08:00
Lost-MSth
fcb5d264ef Add something and fix something
Add character values.
Do something about #16.
Fix a problem about relative path.
2021-03-14 22:33:13 +08:00
Lost-MSth
d617951e1f Fix a bug(Follow last commit)
Ctrl c and Ctrl v,
A bug appears!
2021-03-09 20:09:58 +08:00
Lost-MSth
febf931f1a Fix something
I don't know if it is a bug and I haven't test it.

Maybe it makes low version arcaea can log in.
2021-03-09 19:47:54 +08:00
Lost-MSth
981961d6a1 Update README.md 2021-03-09 14:20:54 +08:00
Lost-MSth
a90380df4c Create error.log 2021-03-09 13:55:09 +08:00
Lost-MSth
4f66f492fc Update to v2.3 2021-03-09 13:46:49 +08:00
Lost-MSth
df181f104e Update to v2.2
close #13
2021-02-11 15:26:58 +08:00
Lost-MSth
a890a9af4a Waiting for updating and fix some bugs
It will be released soon because lowiro will update in some days.
Fix many bugs and I forgot them. :<

I push this because there's a small but serious safety problem. It should be fixed immediately.

Oh, and this update needs you to login in arcaea again because a new function is added.
2021-02-08 14:45:10 +08:00
Lost-MSth
c6bb4c9afb Update to v2.1 2021-01-21 14:42:57 +08:00
Lost-MSth
98358ad216 Fix two small bugs. 2021-01-10 16:29:18 +08:00
26 changed files with 2232 additions and 2276 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.log

View File

@@ -2,14 +2,21 @@
一个微型的Arcaea本地服务器 A small local server for Arcaea 一个微型的Arcaea本地服务器 A small local server for Arcaea
## 简介 Introduction ## 简介 Introduction
这是基于Python以及Flask的微型本地Arcaea服务器可以模拟游戏的主要功能,一时兴起在五天之内糊了出来。这可能是我第一次写这种大程序,若有不妥之处,敬请谅解。 这是基于Python以及Flask的微型本地Arcaea服务器可以模拟游戏的主要功能。这可能是我第一次写这种大程序若有不妥之处敬请谅解。
This is a small local Arcaea server based on Python and Flask, which can simulate the main functions of the game. I completed it on the spur of the moment in five days. This may be the first time I have written such a large program. Please understand if there is something wrong with it.
本程序主要用于学习研究,不得用于任何商业行为,否则后果自负,这不是强制要求,只是一个提醒与警告。
This is a small local Arcaea server based on Python and Flask, which can simulate the main functions of the game. This may be the first time I have written such a large program. Please understand if there is something wrong with it.
This procedure is mainly used for study and research, and shall not be used for any commercial activities, otherwise the consequences will be borne by oneself. This is not a mandatory requirement, just a reminder and warning.
> 虽然看起来很蠢,但是可以用! > 虽然看起来很蠢,但是可以用!
> It looks stupid, but it works! > It looks stupid, but it works!
## 特性 Features ## 特性 Features
有以下 We have 有以下 We have
- 登录、注册 Login and registration - 登录、注册 Login and registration
- 多设备登录 Multi device login
- 成绩上传 Score upload - 成绩上传 Score upload
- PTT - PTT
- 排名 Rank - 排名 Rank
@@ -29,14 +36,15 @@ This is a small local Arcaea server based on Python and Flask, which can simulat
- 后台自定义信息 Customize some things in the background - 后台自定义信息 Customize some things in the background
- 成绩校验 Score check - 成绩校验 Score check
- 下载校验 Download check - 下载校验 Download check
- 服务器日志 Server log
没有以下 We don't have 没有以下 We don't have
- 角色数值 Character characteristic value
- 服务器安全性保证 Server security assurance - 服务器安全性保证 Server security assurance
可能有问题 There may be problems 可能有问题 There may be problems
- Recent 30 - Recent 30
- 一些歌曲的解锁 Some songs' unlocking - 一些歌曲的解锁 Some songs' unlocking
- 同设备多共存登录 Multiple app logins on the same device
## 说明 Statement ## 说明 Statement
只是很有趣,用处探索中。 只是很有趣,用处探索中。
@@ -55,30 +63,20 @@ It is just so interesting. What it can do is under exploration.
> >
> Tips: When updating, please keep the original database in case of data loss. > Tips: When updating, please keep the original database in case of data loss.
### Version 2.0 ### Version 2.3.1
- 适用于Arcaea 3.4.1版本 For Arcaea 3.4.1 - **不**适用于Arcaea 3.5.3版本 **Not** for Arcaea 3.5.3
- 更新API接口至13 Update API interface to 13. - **新增**了一些Bug **Add** some bugs.
- 更新了歌曲数据库 Update the song database.
- 新增了兑换码系统 Add the redeem code system. > Happy April Fool's Day!
- 优化了下载时文件MD5的读取速度 Optimize the reading speed of MD5 when downloading.
- 新增初见保护 Add initial protection.
- EX保护机制修改现在重复歌曲若分数较高会刷新r30中最早的记录并保证ptt不下降仍不清楚能否正常起效 EX protection mechanism has been modified. If the score of one repetitive song is higher, it will refresh the earliest record in r30 and ensure that PTT won't not drop. It is still unclear whether it can work normally.
- 数据迁移机制修改,现在重复数据以旧数据库数据为准 The database migration mechanism has been modified. Now the duplicate data is subject to the old database data.
- 机制修改数据库缺少歌曲定数会当做Unrank处理 The mechanism has been modified. The lack of chart constant of songs in the database will be treated as unrank.
- 后台新增用户密码修改、用户封禁和成绩清除 Add user password modification, user ban and score clearance in the background.
- 游戏内数据同步将记录同步时间 Data synchronization in game will record synchronization time.
- 修复了一些Bug Fix some bugs.
> 提醒本次更新针对了API接口更新将无法兼容Arcaea 3.4.1以下版本
>
> Tips: This update includes API interface update, and will not be compatible with the version below Arcaea 3.4.1.
## 运行环境与依赖 Running environment and requirements ## 运行环境与依赖 Running environment and requirements
- Windows操作系统 Windows operating system - Windows/Linux/Mac OS/Android
- Python 3 - Python 3
- Flask模块 Flask module - Flask module
- Charles - Charles (optional)
<!--
## 环境搭建 Environment construction ## 环境搭建 Environment construction
[中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA) [中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
[English](https://github.com/Lost-MSth/Arcaea-server/wiki/Environment-construction) [English](https://github.com/Lost-MSth/Arcaea-server/wiki/Environment-construction)
@@ -90,6 +88,7 @@ It is just so interesting. What it can do is under exploration.
## 注意 Attentions ## 注意 Attentions
[中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E6%B3%A8%E6%84%8F) [中文](https://github.com/Lost-MSth/Arcaea-server/wiki/%E6%B3%A8%E6%84%8F)
[English](https://github.com/Lost-MSth/Arcaea-server/wiki/Attentions) [English](https://github.com/Lost-MSth/Arcaea-server/wiki/Attentions)
-->
## 鸣谢 Thanks ## 鸣谢 Thanks
歌曲数据库来自 Using song database from 歌曲数据库来自 Using song database from

Binary file not shown.

View File

@@ -33,13 +33,15 @@ rating real,
favorite_character int, favorite_character int,
max_stamina_notification_enabled int, max_stamina_notification_enabled int,
current_map text, current_map text,
ticket int ticket int,
prog_boost int
);''') );''')
c.execute('''create table if not exists login(access_token text, c.execute('''create table if not exists login(access_token text,
user_id int primary key, user_id int,
last_login_time int, login_time int,
last_login_ip text, login_ip text,
last_login_device text login_device text,
primary key(access_token, user_id)
);''') );''')
c.execute('''create table if not exists friend(user_id_me int, c.execute('''create table if not exists friend(user_id_me int,
user_id_other int, user_id_other int,
@@ -234,24 +236,44 @@ primary key(user_id, code)
char = ['Hikari', 'Tairitsu', 'Kou', 'Sapphire', 'Lethe', '', 'Tairitsu(Axium)', 'Tairitsu(Grievous Lady)', 'Stella', 'Hikari & Fisica', 'Ilith', 'Eto', 'Luna', 'Shirabe', 'Hikari(Zero)', 'Hikari(Fracture)', 'Hikari(Summer)', 'Tairitsu(Summer)', 'Tairitsu & Trin', char = ['Hikari', 'Tairitsu', 'Kou', 'Sapphire', 'Lethe', '', 'Tairitsu(Axium)', 'Tairitsu(Grievous Lady)', 'Stella', 'Hikari & Fisica', 'Ilith', 'Eto', 'Luna', 'Shirabe', 'Hikari(Zero)', 'Hikari(Fracture)', 'Hikari(Summer)', 'Tairitsu(Summer)', 'Tairitsu & Trin',
'Ayu', 'Eto & Luna', 'Yume', 'Seine & Hikari', 'Saya', 'Tairitsu & Chuni Penguin', 'Chuni Penguin', 'Haruna', 'Nono', 'MTA-XXX', 'MDA-21', 'Kanae', 'Hikari(Fantasia)', 'Tairitsu(Sonata)', 'Sia', 'DORO*C', 'Tairitsu(Tempest)', 'Brillante', 'Ilith(Summer)', 'Etude', 'Alice & Tenniel', 'Luna & Mia'] 'Ayu', 'Eto & Luna', 'Yume', 'Seine & Hikari', 'Saya', 'Tairitsu & Chuni Penguin', 'Chuni Penguin', 'Haruna', 'Nono', 'MTA-XXX', 'MDA-21', 'Kanae', 'Hikari(Fantasia)', 'Tairitsu(Sonata)', 'Sia', 'DORO*C', 'Tairitsu(Tempest)', 'Brillante', 'Ilith(Summer)', 'Etude', 'Alice & Tenniel', 'Luna & Mia', 'Areus', 'Seele', 'Isabelle', 'Mir']
skill_id = ['gauge_easy', '', '', '', 'note_mirror', '', '', 'gauge_hard', 'frag_plus_10_pack_stellights', 'gauge_easy|frag_plus_15_pst&prs', 'gauge_hard|fail_frag_minus_100', 'frag_plus_5_side_light', 'visual_hide_hp', 'frag_plus_5_side_conflict', 'challenge_fullcombo_0gauge', 'gauge_overflow', 'gauge_easy|note_mirror', 'note_mirror', 'visual_tomato_pack_tonesphere', skill_id = ['gauge_easy', '', '', '', 'note_mirror', '', '', 'gauge_hard', 'frag_plus_10_pack_stellights', 'gauge_easy|frag_plus_15_pst&prs', 'gauge_hard|fail_frag_minus_100', 'frag_plus_5_side_light', 'visual_hide_hp', 'frag_plus_5_side_conflict', 'challenge_fullcombo_0gauge', 'gauge_overflow', 'gauge_easy|note_mirror', 'note_mirror', 'visual_tomato_pack_tonesphere',
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', '', '', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', '', 'note_mirror|visual_hide_far', 'frags_ongeki'] 'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', '', '', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', '', 'note_mirror|visual_hide_far', 'frags_ongeki', 'gauge_areus', 'gauge_seele', 'gauge_isabelle', 'gauge_exhaustion']
skill_id_uncap = ['', '', 'frags_kou', '', 'visual_ink', '', '', '', '', '', '', '', '', 'shirabe_entry_fee', skill_id_uncap = ['', '', 'frags_kou', '', 'visual_ink', '', '', '', '', '', '', '', '', 'shirabe_entry_fee',
'', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''] '', '', '', '', '', '', '', 'frags_yume', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
for i in range(0, 41): frag = [88, 90, 100, 75, 80, 0, 70, 79, 65, 40, 50, 80, 90, 92, 0, 61, 67, 92, 85, 50, 86, 62,
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21]: 65, 85, 67, 88, 74, 0.5, 105, 80, 95, 50, 80, 87, 71, 50, 95, 0, 80, 75, 50, 70, 80, 100, 65]
sql = 'insert into character values('+str(
i)+',"'+char[i]+'''",30,25000,25000,90,90,90,"'''+skill_id[i]+'''",0,0,"'''+skill_id_uncap[i]+'''",0,'',1,1)''' prog = [71, 90, 80, 75, 100, 0, 90, 102, 84, 78, 105, 67, 63, 78, 0, 99, 80, 66, 46, 83, 40, 83,
c.execute(sql) 80, 90, 93, 50, 96, 88, 99, 108, 75, 80, 50, 64, 55, 100, 100, 110, 80, 50, 74, 90, 80, 80, 56]
overdrive = [71, 90, 57, 75, 80, 0, 95, 79, 65, 31, 50, 59, 90, 68, 0, 78, 50, 70, 62, 49, 64,
56, 73, 95, 67, 84, 80, 88, 79, 80, 50, 80, 80, 63, 25, 50, 82, 55, 50, 95, 55, 70, 100, 80, 90]
char_type = [1, 0, 0, 0, 0, 0, 0, 2, 0, 1, 2, 0, 0, 0, 2, 3, 1, 0, 0, 0, 1,
0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2, 1]
print(len(char))
print(len(skill_id))
print(len(skill_id_uncap))
print(len(frag))
print(len(prog))
print(len(overdrive))
print(len(char_type))
for i in range(0, 45):
if i in [0, 1, 2, 4, 13, 26, 27, 28, 29, 36, 21, 42, 43]:
sql = '''insert into character values(:a,:b,30,25000,25000,:c,:d,:e,:f,0,0,:g,:h,'',1,1)'''
c.execute(sql, {'a': i, 'b': char[i], 'c': frag[i], 'd': prog[i],
'e': overdrive[i], 'f': skill_id[i], 'g': skill_id_uncap[i], 'h': char_type[i]})
else: else:
if i != 5: if i != 5:
sql = 'insert into character values('+str( sql = '''insert into character values(:a,:b,20,10000,10000,:c,:d,:e,:f,0,0,:g,:h,'',0,0)'''
i)+',"'+char[i]+'''",30,25000,25000,90,90,90,"'''+skill_id[i]+'''",0,0,"'''+skill_id_uncap[i]+'''",0,'',0,0)''' c.execute(sql, {'a': i, 'b': char[i], 'c': frag[i], 'd': prog[i],
c.execute(sql) 'e': overdrive[i], 'f': skill_id[i], 'g': skill_id_uncap[i], 'h': char_type[i]})
def b2int(x): def b2int(x):

View File

@@ -3,154 +3,154 @@
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "core", "id": "core",
"_id": "5ff79fc6a6e343038b058bd3", "_id": "6046bab736651a07ebc537db",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 400,
"orig_price": 500, "orig_price": 500,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "shiawase", "name": "shiawase",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "shiawase", "id": "shiawase",
"_id": "5ff79fc6a6e343038b058c18", "_id": "6046bab736651a07ebc53823",
"is_available": true "is_available": true
}, { }, {
"type": "character", "type": "character",
"id": "kou", "id": "kou",
"_id": "5ff79fc6a6e343038b058c17", "_id": "6046bab736651a07ebc53822",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 250,
"orig_price": 500, "orig_price": 500,
"discount_from": 1552089600000, "discount_from": 1615248000000,
"discount_to": 1552694399000 "discount_to": 1615852799000
}, { }, {
"name": "dynamix", "name": "dynamix",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "dynamix", "id": "dynamix",
"_id": "5ff79fc6a6e343038b058c1c", "_id": "6046bab736651a07ebc53827",
"is_available": true "is_available": true
}, { }, {
"type": "character", "type": "character",
"id": "sapphire", "id": "sapphire",
"_id": "5ff79fc6a6e343038b058c1b", "_id": "6046bab736651a07ebc53826",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 250,
"orig_price": 500, "orig_price": 500,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "mirai", "name": "mirai",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "mirai", "id": "mirai",
"_id": "5ff79fc6a6e343038b058c10", "_id": "6046bab736651a07ebc5381d",
"is_available": true "is_available": true
}, { }, {
"type": "character", "type": "character",
"id": "lethe", "id": "lethe",
"_id": "5ff79fc6a6e343038b058c0f", "_id": "6046bab736651a07ebc5381c",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 250,
"orig_price": 500, "orig_price": 500,
"discount_from": 1552089600000, "discount_from": 1615248000000,
"discount_to": 1552694399000 "discount_to": 1615852799000
}, { }, {
"name": "yugamu", "name": "yugamu",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "yugamu", "id": "yugamu",
"_id": "5ff79fc6a6e343038b058bd4", "_id": "6046bab736651a07ebc537dc",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 400,
"orig_price": 500, "orig_price": 500,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "lanota", "name": "lanota",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "lanota", "id": "lanota",
"_id": "5ff79fc6a6e343038b058bf9", "_id": "6046bab736651a07ebc537e8",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 250,
"orig_price": 500, "orig_price": 500,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "nijuusei", "name": "nijuusei",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "nijuusei", "id": "nijuusei",
"_id": "5ff79fc6a6e343038b058bd5", "_id": "6046bab736651a07ebc537dd",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 250,
"orig_price": 500, "orig_price": 500,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "rei", "name": "rei",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "rei", "id": "rei",
"_id": "5ff79fc6a6e343038b058c06", "_id": "6046bab736651a07ebc537f6",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 400,
"orig_price": 500, "orig_price": 500,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "tonesphere", "name": "tonesphere",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "tonesphere", "id": "tonesphere",
"_id": "5ff79fc6a6e343038b058bfb", "_id": "6046bab736651a07ebc537ea",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 250,
"orig_price": 500, "orig_price": 500,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "groovecoaster", "name": "groovecoaster",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "groovecoaster", "id": "groovecoaster",
"_id": "5ff79fc6a6e343038b058bf0", "_id": "6046bab736651a07ebc53812",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 250,
"orig_price": 500, "orig_price": 500,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "zettai", "name": "zettai",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "zettai", "id": "zettai",
"_id": "5ff79fc6a6e343038b058c08", "_id": "6046bab736651a07ebc537f8",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 250,
"orig_price": 500, "orig_price": 500,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "chunithm", "name": "chunithm",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "chunithm", "id": "chunithm",
"_id": "5ff79fc6a6e343038b058be4", "_id": "6046bab736651a07ebc53806",
"is_available": true "is_available": true
}], }],
"price": 300, "price": 300,
@@ -160,47 +160,55 @@
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "prelude", "id": "prelude",
"_id": "5ff79fc6a6e343038b058bf1", "_id": "6046bab736651a07ebc53813",
"is_available": true "is_available": true
}], }],
"price": 400, "price": 250,
"orig_price": 400 "orig_price": 400,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "omatsuri", "name": "omatsuri",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "omatsuri", "id": "omatsuri",
"_id": "5ff79fc6a6e343038b058c09", "_id": "6046bab736651a07ebc537f9",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 250,
"orig_price": 500 "orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "vs", "name": "vs",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "vs", "id": "vs",
"_id": "5ff79fc6a6e343038b058be7", "_id": "6046bab736651a07ebc53809",
"is_available": true "is_available": true
}], }],
"price": 500, "price": 400,
"orig_price": 500 "orig_price": 500,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "extend", "name": "extend",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "extend", "id": "extend",
"_id": "5ff79fc6a6e343038b058bf4", "_id": "6046bab736651a07ebc53816",
"is_available": true "is_available": true
}], }],
"price": 700, "price": 500,
"orig_price": 700 "orig_price": 700,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "alice", "name": "alice",
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "alice", "id": "alice",
"_id": "5ff79fc6a6e343038b058c0e", "_id": "6046bab736651a07ebc537fe",
"is_available": true "is_available": true
}], }],
"orig_price": 500, "orig_price": 500,
@@ -210,7 +218,7 @@
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "alice_append_1", "id": "alice_append_1",
"_id": "5ff79fc6a6e343038b058bde", "_id": "6046bab736651a07ebc537e6",
"is_available": true "is_available": true
}], }],
"orig_price": 300, "orig_price": 300,
@@ -220,7 +228,7 @@
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "ongeki", "id": "ongeki",
"_id": "5ff79fc6a6e343038b058bea", "_id": "6046bab736651a07ebc5380c",
"is_available": true "is_available": true
}], }],
"orig_price": 400, "orig_price": 400,
@@ -230,9 +238,19 @@
"items": [{ "items": [{
"type": "pack", "type": "pack",
"id": "maimai", "id": "maimai",
"_id": "5ff79fc6a6e343038b058bf7", "_id": "6046bab736651a07ebc53819",
"is_available": true "is_available": true
}], }],
"orig_price": 400, "orig_price": 400,
"price": 400 "price": 400
}, {
"name": "chunithm_append_1",
"items": [{
"type": "pack",
"id": "chunithm_append_1",
"_id": "6046bab736651a07ebc537f2",
"is_available": true
}],
"orig_price": 300,
"price": 300
}] }]

View File

@@ -12,55 +12,55 @@
"items": [{ "items": [{
"id": "dataerror", "id": "dataerror",
"type": "single", "type": "single",
"_id": "5ff79fc6a6e343038b058beb", "_id": "6046bab736651a07ebc537f3",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "yourvoiceso", "name": "yourvoiceso",
"items": [{ "items": [{
"id": "yourvoiceso", "id": "yourvoiceso",
"type": "single", "type": "single",
"_id": "5ff79fc6a6e343038b058bf8", "_id": "6046bab736651a07ebc53800",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "crosssoul", "name": "crosssoul",
"items": [{ "items": [{
"id": "crosssoul", "id": "crosssoul",
"type": "single", "type": "single",
"_id": "5ff79fc6a6e343038b058c03", "_id": "6046bab736651a07ebc5380d",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "impurebird", "name": "impurebird",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "impurebird", "id": "impurebird",
"_id": "5ff79fc6a6e343038b058bdf", "_id": "6046bab736651a07ebc53801",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "auxesia", "name": "auxesia",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "auxesia", "id": "auxesia",
"_id": "5ff79fc6a6e343038b058bec", "_id": "6046bab736651a07ebc5380e",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -72,43 +72,43 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "modelista", "id": "modelista",
"_id": "5ff79fc6a6e343038b058c04", "_id": "6046bab736651a07ebc537f4",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "yozakurafubuki", "name": "yozakurafubuki",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "yozakurafubuki", "id": "yozakurafubuki",
"_id": "5ff79fc6a6e343038b058be0", "_id": "6046bab736651a07ebc53802",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "surrender", "name": "surrender",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "surrender", "id": "surrender",
"_id": "5ff79fc6a6e343038b058bed", "_id": "6046bab736651a07ebc5380f",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "metallicpunisher", "name": "metallicpunisher",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "metallicpunisher", "id": "metallicpunisher",
"_id": "5ff79fc6a6e343038b058c05", "_id": "6046bab736651a07ebc537f5",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -118,7 +118,7 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "carminescythe", "id": "carminescythe",
"_id": "5ff79fc6a6e343038b058be1", "_id": "6046bab736651a07ebc53803",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -128,79 +128,79 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "bethere", "id": "bethere",
"_id": "5ff79fc6a6e343038b058bee", "_id": "6046bab736651a07ebc53810",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "callmyname", "name": "callmyname",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "callmyname", "id": "callmyname",
"_id": "5ff79fc6a6e343038b058bfa", "_id": "6046bab736651a07ebc537e9",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "fallensquare", "name": "fallensquare",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "fallensquare", "id": "fallensquare",
"_id": "5ff79fc6a6e343038b058bd6", "_id": "6046bab736651a07ebc537de",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "dropdead", "name": "dropdead",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "dropdead", "id": "dropdead",
"_id": "5ff79fc6a6e343038b058be2", "_id": "6046bab736651a07ebc53804",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "alexandrite", "name": "alexandrite",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "alexandrite", "id": "alexandrite",
"_id": "5ff79fc6a6e343038b058bef", "_id": "6046bab736651a07ebc53811",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "astraltale", "name": "astraltale",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "astraltale", "id": "astraltale",
"_id": "5ff79fc6a6e343038b058c07", "_id": "6046bab736651a07ebc537f7",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "phantasia", "name": "phantasia",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "phantasia", "id": "phantasia",
"_id": "5ff79fc6a6e343038b058bd7", "_id": "6046bab736651a07ebc537df",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -210,7 +210,7 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "empireofwinter", "id": "empireofwinter",
"_id": "5ff79fc6a6e343038b058be3", "_id": "6046bab736651a07ebc53805",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -220,75 +220,79 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "libertas", "id": "libertas",
"_id": "5ff79fc6a6e343038b058bfc", "_id": "6046bab736651a07ebc537eb",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "dottodot", "name": "dottodot",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "dottodot", "id": "dottodot",
"_id": "5ff79fc6a6e343038b058bd8", "_id": "6046bab736651a07ebc537e0",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "dreadnought", "name": "dreadnought",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "dreadnought", "id": "dreadnought",
"_id": "5ff79fc6a6e343038b058bfd", "_id": "6046bab736651a07ebc537ec",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "mirzam", "name": "mirzam",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "mirzam", "id": "mirzam",
"_id": "5ff79fc6a6e343038b058bd9", "_id": "6046bab736651a07ebc537e1",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100, "orig_price": 100,
"discount_from": 1583712000000, "discount_from": 1615248000000,
"discount_to": 1584316799000 "discount_to": 1615852799000
}, { }, {
"name": "heavenlycaress", "name": "heavenlycaress",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "heavenlycaress", "id": "heavenlycaress",
"_id": "5ff79fc6a6e343038b058be5", "_id": "6046bab736651a07ebc53807",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "filament", "name": "filament",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "filament", "id": "filament",
"_id": "5ff79fc6a6e343038b058bf2", "_id": "6046bab736651a07ebc53814",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "avantraze", "name": "avantraze",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "avantraze", "id": "avantraze",
"_id": "5ff79fc6a6e343038b058bfe", "_id": "6046bab736651a07ebc537ed",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -298,17 +302,19 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "battlenoone", "id": "battlenoone",
"_id": "5ff79fc6a6e343038b058c0a", "_id": "6046bab736651a07ebc537fa",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "saikyostronger", "name": "saikyostronger",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "saikyostronger", "id": "saikyostronger",
"_id": "5ff79fc6a6e343038b058bda", "_id": "6046bab736651a07ebc537e2",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -318,67 +324,79 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "izana", "id": "izana",
"_id": "5ff79fc6a6e343038b058be6", "_id": "6046bab736651a07ebc53808",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "einherjar", "name": "einherjar",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "einherjar", "id": "einherjar",
"_id": "5ff79fc6a6e343038b058bf3", "_id": "6046bab736651a07ebc53815",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "laqryma", "name": "laqryma",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "laqryma", "id": "laqryma",
"_id": "5ff79fc6a6e343038b058bff", "_id": "6046bab736651a07ebc537ee",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "amygdata", "name": "amygdata",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "amygdata", "id": "amygdata",
"_id": "5ff79fc6a6e343038b058c0b", "_id": "6046bab736651a07ebc537fb",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "altale", "name": "altale",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "altale", "id": "altale",
"_id": "5ff79fc6a6e343038b058bdb", "_id": "6046bab736651a07ebc537e3",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "feelssoright", "name": "feelssoright",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "feelssoright", "id": "feelssoright",
"_id": "5ff79fc6a6e343038b058c00", "_id": "6046bab736651a07ebc537ef",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "scarletcage", "name": "scarletcage",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "scarletcage", "id": "scarletcage",
"_id": "5ff79fc6a6e343038b058c0c", "_id": "6046bab736651a07ebc537fc",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -388,7 +406,7 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "teriqma", "id": "teriqma",
"_id": "5ff79fc6a6e343038b058bdc", "_id": "6046bab736651a07ebc537e4",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -398,27 +416,31 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "mahoroba", "id": "mahoroba",
"_id": "5ff79fc6a6e343038b058be8", "_id": "6046bab736651a07ebc5380a",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "badtek", "name": "badtek",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "badtek", "id": "badtek",
"_id": "5ff79fc6a6e343038b058c01", "_id": "6046bab736651a07ebc537f0",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "maliciousmischance", "name": "maliciousmischance",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "maliciousmischance", "id": "maliciousmischance",
"_id": "5ff79fc6a6e343038b058c0d", "_id": "6046bab736651a07ebc53817",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -428,7 +450,7 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "buchigireberserker", "id": "buchigireberserker",
"_id": "5ff79fc6a6e343038b058bdd", "_id": "6046bab736651a07ebc537e5",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
@@ -438,17 +460,19 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "galaxyfriends", "id": "galaxyfriends",
"_id": "5ff79fc6a6e343038b058be9", "_id": "6046bab736651a07ebc5380b",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 50,
"orig_price": 100 "orig_price": 100,
"discount_from": 1615248000000,
"discount_to": 1615852799000
}, { }, {
"name": "xeraphinite", "name": "xeraphinite",
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "xeraphinite", "id": "xeraphinite",
"_id": "5ff79fc6a6e343038b058bf6", "_id": "6046bab736651a07ebc53818",
"is_available": true "is_available": true
}], }],
"orig_price": 100, "orig_price": 100,
@@ -458,9 +482,29 @@
"items": [{ "items": [{
"type": "single", "type": "single",
"id": "xanatos", "id": "xanatos",
"_id": "5ff79fc6a6e343038b058c02", "_id": "6046bab736651a07ebc537f1",
"is_available": true "is_available": true
}], }],
"price": 100, "price": 100,
"orig_price": 100 "orig_price": 100
}, {
"name": "attraqtia",
"items": [{
"type": "single",
"id": "attraqtia",
"_id": "6046bab736651a07ebc537ff",
"is_available": true
}],
"orig_price": 100,
"price": 100
}, {
"name": "gimmedablood",
"items": [{
"type": "single",
"id": "gimmedablood",
"_id": "6046bab736651a07ebc537e7",
"is_available": true
}],
"orig_price": 100,
"price": 100
}] }]

View File

View File

@@ -1,6 +1,8 @@
# encoding: utf-8
from flask import Flask, request, jsonify, make_response, send_from_directory from flask import Flask, request, jsonify, make_response, send_from_directory
from logging.config import dictConfig from logging.config import dictConfig
import configparser from setting import Config
import base64 import base64
import server.auth import server.auth
import server.info import server.info
@@ -12,6 +14,7 @@ import server.arcworld
import server.arcdownload import server.arcdownload
import server.arcpurchase import server.arcpurchase
import os import os
import sys
app = Flask(__name__) app = Flask(__name__)
@@ -87,253 +90,185 @@ def login():
id_pwd = headers['Authorization'] id_pwd = headers['Authorization']
id_pwd = base64.b64decode(id_pwd[6:]).decode() id_pwd = base64.b64decode(id_pwd[6:]).decode()
name, password = id_pwd.split(':', 1) name, password = id_pwd.split(':', 1)
if 'DeviceId' in headers:
device_id = headers['DeviceId']
else:
device_id = 'low_version'
try: token, error_code = server.auth.arc_login(name, password, device_id)
token, error_code = server.auth.arc_login(name, password) if not error_code:
if not error_code: r = {"success": True, "token_type": "Bearer"}
r = {"success": True, "token_type": "Bearer"} r['access_token'] = token
r['access_token'] = token return jsonify(r)
return jsonify(r) else:
else: return error_return(error_code)
return error_return(error_code)
except:
return error_return(108)
@app.route('/latte/13/user/', methods=['POST']) # 注册接口 @app.route('/latte/13/user/', methods=['POST']) # 注册接口
def register(): def register():
name = request.form['name'] name = request.form['name']
password = request.form['password'] password = request.form['password']
try: if 'device_id' in request.form:
user_id, token, error_code = server.auth.arc_register(name, password) device_id = request.form['device_id']
if user_id is not None: else:
r = {"success": True, "value": { device_id = 'low_version'
'user_id': user_id, 'access_token': token}}
return jsonify(r) user_id, token, error_code = server.auth.arc_register(
else: name, password, device_id)
return error_return(error_code) # 应该是101用户名被占用毕竟电子邮箱、设备号没记录 if user_id is not None:
except: r = {"success": True, "value": {
return error_return(108) 'user_id': user_id, 'access_token': token}}
return jsonify(r)
else:
return error_return(error_code) # 应该是101用户名被占用毕竟电子邮箱没记录
# 集成式请求,没想到什么好办法处理,就先这样写着 # 集成式请求,没想到什么好办法处理,就先这样写着
@app.route('/latte/13/compose/aggregate', methods=['GET']) @app.route('/latte/13/compose/aggregate', methods=['GET'])
def aggregate(): @server.auth.auth_required(request)
def aggregate(user_id):
calls = request.args.get('calls') calls = request.args.get('calls')
headers = request.headers if calls == '[{ "endpoint": "/user/me", "id": 0 }]': # 极其沙雕的判断我猜get的参数就两种
token = headers['Authorization'] r = server.info.arc_aggregate_small(user_id)
token = token[7:] else:
try: r = server.info.arc_aggregate_big(user_id)
user_id = server.auth.token_get_id(token) return jsonify(r)
if user_id is not None:
if calls == '[{ "endpoint": "/user/me", "id": 0 }]': # 极其沙雕的判断我猜get的参数就两种
r = server.info.arc_aggregate_small(user_id)
else:
r = server.info.arc_aggregate_big(user_id)
return jsonify(r)
else:
return error_return(108)
except:
return error_return(108)
@app.route('/latte/13/user/me/character', methods=['POST']) # 角色切换 @app.route('/latte/13/user/me/character', methods=['POST']) # 角色切换
def character_change(): @server.auth.auth_required(request)
headers = request.headers def character_change(user_id):
token = headers['Authorization']
token = token[7:]
character_id = request.form['character'] character_id = request.form['character']
skill_sealed = request.form['skill_sealed'] skill_sealed = request.form['skill_sealed']
try:
user_id = server.auth.token_get_id(token) flag = server.setme.change_char(user_id, character_id, skill_sealed)
if user_id is not None: if flag:
flag = server.setme.change_char( return jsonify({
user_id, character_id, skill_sealed) "success": True,
if flag: "value": {
return jsonify({ "user_id": user_id,
"success": True, "character": character_id
"value": { }
"user_id": user_id, })
"character": character_id else:
}
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108) return error_return(108)
@app.route('/latte/<path:path>/toggle_uncap', methods=['POST']) # 角色觉醒切换 @app.route('/latte/<path:path>/toggle_uncap', methods=['POST']) # 角色觉醒切换
def character_uncap(path): @server.auth.auth_required(request)
character_id = int(path[22:]) def character_uncap(user_id, path):
headers = request.headers while '//' in path:
token = headers['Authorization'] path = path.replace('//', '/')
token = token[7:] character_id = int(path[21:])
try: r = server.setme.change_char_uncap(user_id, character_id)
user_id = server.auth.token_get_id(token) if r is not None:
if user_id is not None: return jsonify({
r = server.setme.change_char_uncap(user_id, character_id) "success": True,
if r is not None: "value": {
return jsonify({ "user_id": user_id,
"success": True, "character": [r]
"value": { }
"user_id": user_id, })
"character": [r] else:
}
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108) return error_return(108)
@app.route('/latte/13/friend/me/add', methods=['POST']) # 加好友 @app.route('/latte/13/friend/me/add', methods=['POST']) # 加好友
def add_friend(): @server.auth.auth_required(request)
headers = request.headers def add_friend(user_id):
token = headers['Authorization']
token = token[7:]
friend_code = request.form['friend_code'] friend_code = request.form['friend_code']
try: friend_id = server.auth.code_get_id(friend_code)
user_id = server.auth.token_get_id(token) if friend_id is not None:
friend_id = server.auth.code_get_id(friend_code) r = server.setme.arc_add_friend(user_id, friend_id)
if user_id is not None and friend_id is not None: if r is not None and r != 602 and r != 604:
r = server.setme.arc_add_friend(user_id, friend_id) return jsonify({
if r is not None and r != 602 and r != 604: "success": True,
return jsonify({ "value": {
"success": True, "user_id": user_id,
"value": { "updatedAt": "2020-09-07T07:32:12.740Z",
"user_id": user_id, "createdAt": "2020-09-06T10:05:18.471Z",
"updatedAt": "2020-09-07T07:32:12.740Z", "friends": r
"createdAt": "2020-09-06T10:05:18.471Z", }
"friends": r })
}
})
else:
if r is not None:
return error_return(r)
else:
return error_return(108)
else: else:
if friend_id is None: if r is not None:
return error_return(401) return error_return(r)
else: else:
return error_return(108) return error_return(108)
except: else:
return error_return(108) return error_return(401)
@app.route('/latte/13/friend/me/delete', methods=['POST']) # 删好友 @app.route('/latte/13/friend/me/delete', methods=['POST']) # 删好友
def delete_friend(): @server.auth.auth_required(request)
headers = request.headers def delete_friend(user_id):
token = headers['Authorization']
token = token[7:]
friend_id = int(request.form['friend_id']) friend_id = int(request.form['friend_id'])
try: if friend_id is not None:
user_id = server.auth.token_get_id(token) r = server.setme.arc_delete_friend(user_id, friend_id)
if user_id is not None and friend_id is not None: if r is not None:
r = server.setme.arc_delete_friend(user_id, friend_id) return jsonify({
if r is not None: "success": True,
return jsonify({ "value": {
"success": True, "user_id": user_id,
"value": { "updatedAt": "2020-09-07T07:32:12.740Z",
"user_id": user_id, "createdAt": "2020-09-06T10:05:18.471Z",
"updatedAt": "2020-09-07T07:32:12.740Z", "friends": r
"createdAt": "2020-09-06T10:05:18.471Z", }
"friends": r })
}
})
else:
return error_return(108)
else: else:
if friend_id is None: return error_return(108)
return error_return(401) else:
else: return error_return(401)
return error_return(108)
except:
return error_return(108)
@app.route('/latte/13/score/song/friend', methods=['GET']) # 好友排名默认最多50 @app.route('/latte/13/score/song/friend', methods=['GET']) # 好友排名默认最多50
def song_score_friend(): @server.auth.auth_required(request)
def song_score_friend(user_id):
song_id = request.args.get('song_id') song_id = request.args.get('song_id')
difficulty = request.args.get('difficulty') difficulty = request.args.get('difficulty')
headers = request.headers r = server.arcscore.arc_score_friend(user_id, song_id, difficulty)
token = headers['Authorization'] if r is not None:
token = token[7:] return jsonify({
try: "success": True,
user_id = server.auth.token_get_id(token) "value": r
if user_id is not None: })
r = server.arcscore.arc_score_friend(user_id, song_id, difficulty) else:
if r is not None:
return jsonify({
"success": True,
"value": r
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108) return error_return(108)
@app.route('/latte/13/score/song/me', methods=['GET']) # 我的排名默认最多20 @app.route('/latte/13/score/song/me', methods=['GET']) # 我的排名默认最多20
def song_score_me(): @server.auth.auth_required(request)
def song_score_me(user_id):
song_id = request.args.get('song_id') song_id = request.args.get('song_id')
difficulty = request.args.get('difficulty') difficulty = request.args.get('difficulty')
headers = request.headers r = server.arcscore.arc_score_me(user_id, song_id, difficulty)
token = headers['Authorization'] if r is not None:
token = token[7:] return jsonify({
try: "success": True,
user_id = server.auth.token_get_id(token) "value": r
if user_id is not None: })
r = server.arcscore.arc_score_me(user_id, song_id, difficulty) else:
if r is not None:
return jsonify({
"success": True,
"value": r
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108) return error_return(108)
@app.route('/latte/13/score/song', methods=['GET']) # TOP20 @app.route('/latte/13/score/song', methods=['GET']) # TOP20
def song_score_top(): @server.auth.auth_required(request)
def song_score_top(user_id):
song_id = request.args.get('song_id') song_id = request.args.get('song_id')
difficulty = request.args.get('difficulty') difficulty = request.args.get('difficulty')
headers = request.headers r = server.arcscore.arc_score_top(song_id, difficulty)
token = headers['Authorization'] if r is not None:
token = token[7:] return jsonify({
try: "success": True,
user_id = server.auth.token_get_id(token) "value": r
if user_id is not None: })
r = server.arcscore.arc_score_top(song_id, difficulty) else:
if r is not None:
return jsonify({
"success": True,
"value": r
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108) return error_return(108)
@app.route('/latte/13/score/song', methods=['POST']) # 成绩上传 @app.route('/latte/13/score/song', methods=['POST']) # 成绩上传
def song_score_post(): @server.auth.auth_required(request)
headers = request.headers def song_score_post(user_id):
token = headers['Authorization']
token = token[7:]
song_token = request.form['song_token'] song_token = request.form['song_token']
song_hash = request.form['song_hash'] song_hash = request.form['song_hash']
song_id = request.form['song_id'] song_id = request.form['song_id']
@@ -349,31 +284,24 @@ def song_score_post():
clear_type = int(request.form['clear_type']) clear_type = int(request.form['clear_type'])
submission_hash = request.form['submission_hash'] submission_hash = request.form['submission_hash']
try: # 增加成绩校验
user_id = server.auth.token_get_id(token) if not server.arcscore.arc_score_check(user_id, song_id, difficulty, score, shiny_perfect_count, perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type, song_token, song_hash, submission_hash):
if user_id is not None: return error_return(107)
# 增加成绩校验
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 is not None:
if re: if re:
return jsonify({ return jsonify({
"success": True, "success": True,
"value": re "value": re
}) })
else:
return jsonify({
"success": True,
"value": {"user_rating": r}
})
else:
return error_return(108)
else: else:
return error_return(108) return jsonify({
except: "success": True,
"value": {"user_rating": r}
})
else:
return error_return(108) return error_return(108)
@@ -389,56 +317,36 @@ def score_token():
# 世界模式成绩上传所需的token无验证 # 世界模式成绩上传所需的token无验证
@app.route('/latte/13/score/token/world', methods=['GET']) @app.route('/latte/13/score/token/world', methods=['GET'])
def score_token_world(): @server.auth.auth_required(request)
headers = request.headers def score_token_world(user_id):
token = headers['Authorization']
token = token[7:]
args = request.args args = request.args
try: server.arcworld.play_world_song(user_id, args)
user_id = server.auth.token_get_id(token) return jsonify({
if user_id: "success": True,
server.arcworld.play_world_song(user_id, args) "value": {
return jsonify({ "stamina": 12,
"success": True, "max_stamina_ts": 1599547603825,
"value": { "token": "13145201919810"
"stamina": 12, }
"max_stamina_ts": 1599547603825, })
"token": "13145201919810"
}
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/latte/13/user/me/save', methods=['GET']) # 从云端同步 @app.route('/latte/13/user/me/save', methods=['GET']) # 从云端同步
def cloud_get(): @server.auth.auth_required(request)
headers = request.headers def cloud_get(user_id):
token = headers['Authorization'] r = server.arcscore.arc_all_get(user_id)
token = token[7:] if r is not None:
try: return jsonify({
user_id = server.auth.token_get_id(token) "success": True,
if user_id is not None: "value": r
r = server.arcscore.arc_all_get(user_id) })
if r is not None: else:
return jsonify({
"success": True,
"value": r
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108) return error_return(108)
@app.route('/latte/13/user/me/save', methods=['POST']) # 向云端同步 @app.route('/latte/13/user/me/save', methods=['POST']) # 向云端同步
def cloud_post(): @server.auth.auth_required(request)
headers = request.headers def cloud_post(user_id):
token = headers['Authorization']
token = token[7:]
scores_data = request.form['scores_data'] scores_data = request.form['scores_data']
clearlamps_data = request.form['clearlamps_data'] clearlamps_data = request.form['clearlamps_data']
clearedsongs_data = request.form['clearedsongs_data'] clearedsongs_data = request.form['clearedsongs_data']
@@ -446,99 +354,76 @@ def cloud_post():
installid_data = request.form['installid_data'] installid_data = request.form['installid_data']
devicemodelname_data = request.form['devicemodelname_data'] devicemodelname_data = request.form['devicemodelname_data']
story_data = request.form['story_data'] story_data = request.form['story_data']
try:
user_id = server.auth.token_get_id(token) server.arcscore.arc_all_post(user_id, scores_data, clearlamps_data, clearedsongs_data,
if user_id is not None: unlocklist_data, installid_data, devicemodelname_data, story_data)
server.arcscore.arc_all_post(user_id, scores_data, clearlamps_data, clearedsongs_data, return jsonify({
unlocklist_data, installid_data, devicemodelname_data, story_data) "success": True,
return jsonify({ "value": {
"success": True, "user_id": user_id
"value": { }
"user_id": user_id })
}
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/latte/13/purchase/me/redeem', methods=['POST']) # 兑换码 @app.route('/latte/13/purchase/me/redeem', methods=['POST']) # 兑换码
def redeem(): @server.auth.auth_required(request)
headers = request.headers def redeem(user_id):
token = headers['Authorization']
token = token[7:]
code = request.form['code'] code = request.form['code']
try: fragment, error_code = server.arcpurchase.claim_user_redeem(
user_id = server.auth.token_get_id(token) user_id, code)
if user_id is not None: if not error_code:
fragment, error_code = server.arcpurchase.claim_user_redeem( if fragment > 0:
user_id, code) return jsonify({
if not error_code: "success": True,
if fragment > 0: "value": {"coupon": "fragment"+str(fragment)}
return jsonify({ })
"success": True,
"value": {"coupon": "fragment"+str(fragment)}
})
else:
return jsonify({
"success": True,
"value": {"coupon": ""}
})
else:
return error_return(error_code)
else: else:
return error_return(108) return jsonify({
except: "success": True,
return error_return(108) "value": {"coupon": ""}
})
else:
return error_return(error_code)
# 礼物确认 # 礼物确认
@app.route('/latte/13/present/me/claim/<present_id>', methods=['POST']) @app.route('/latte/13/present/me/claim/<present_id>', methods=['POST'])
def claim_present(present_id): @server.auth.auth_required(request)
headers = request.headers def claim_present(user_id, present_id):
token = headers['Authorization'] flag = server.arcpurchase.claim_user_present(user_id, present_id)
token = token[7:] if flag:
try: return jsonify({
user_id = server.auth.token_get_id(token) "success": True
if user_id is not None: })
flag = server.arcpurchase.claim_user_present(user_id, present_id) else:
if flag:
return jsonify({
"success": True
})
else:
return error_return(108)
else:
return error_return(108)
except:
return error_return(108) return error_return(108)
# 购买,为了world模式boost一下 @app.route('/latte/13/purchase/me/item', methods=['POST']) # 购买world模式boost
@app.route('/latte/13/purchase/me/item', methods=['POST']) @server.auth.auth_required(request)
def item(): def prog_boost(user_id):
return jsonify({ re = {"success": False}
"success": True if 'item_id' in request.form:
}) if request.form['item_id'] == 'prog_boost_300':
ticket, error_code = server.arcpurchase.get_prog_boost(user_id)
if error_code:
return error_return(error_code)
re = {
"success": True,
"value": {'ticket': ticket}
}
return jsonify(re)
@app.route('/latte/13/purchase/me/pack', methods=['POST']) # 曲包和单曲购买 @app.route('/latte/13/purchase/me/pack', methods=['POST']) # 曲包和单曲购买
def pack(): @server.auth.auth_required(request)
headers = request.headers def pack(user_id):
token = headers['Authorization'] if 'pack_id' in request.form:
token = token[7:] return jsonify(server.arcpurchase.buy_pack(user_id, request.form['pack_id']))
try: if 'single_id' in request.form:
user_id = server.auth.token_get_id(token) return jsonify(server.arcpurchase.buy_single(user_id, request.form['single_id']))
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
}) })
@@ -553,102 +438,65 @@ def single():
@app.route('/latte/13/world/map/me', methods=['GET']) # 获得世界模式信息,所有地图 @app.route('/latte/13/world/map/me', methods=['GET']) # 获得世界模式信息,所有地图
def world_all(): @server.auth.auth_required(request)
headers = request.headers def world_all(user_id):
token = headers['Authorization'] return jsonify({
token = token[7:] "success": True,
try: "value": {
"current_map": server.arcworld.get_current_map(user_id),
user_id = server.auth.token_get_id(token) "user_id": user_id,
if user_id: "maps": server.arcworld.get_world_all(user_id)
return jsonify({ }
"success": True, })
"value": {
"current_map": server.arcworld.get_current_map(user_id),
"user_id": user_id,
"maps": server.arcworld.get_world_all(user_id)
}
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/latte/13/world/map/me/', methods=['POST']) # 进入地图 @app.route('/latte/13/world/map/me/', methods=['POST']) # 进入地图
def world_in(): @server.auth.auth_required(request)
headers = request.headers def world_in(user_id):
token = headers['Authorization']
token = token[7:]
map_id = request.form['map_id'] map_id = request.form['map_id']
try: return jsonify({
user_id = server.auth.token_get_id(token) "success": True,
if user_id: "value": server.arcworld.get_user_world(user_id, map_id)
return jsonify({ })
"success": True,
"value": server.arcworld.get_user_world(user_id, map_id)
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/latte/13/world/map/me/<map_id>', methods=['GET']) # 获得单个地图完整信息 @app.route('/latte/13/world/map/me/<map_id>', methods=['GET']) # 获得单个地图完整信息
def world_one(map_id): @server.auth.auth_required(request)
headers = request.headers def world_one(user_id, map_id):
token = headers['Authorization'] server.arcworld.change_user_current_map(user_id, map_id)
token = token[7:] return jsonify({
try: "success": True,
user_id = server.auth.token_get_id(token) "value": {
if user_id: "user_id": user_id,
server.arcworld.change_user_current_map(user_id, map_id) "current_map": map_id,
return jsonify({ "maps": [server.arcworld.get_user_world_info(user_id, map_id)]
"success": True, }
"value": { })
"user_id": user_id,
"current_map": map_id,
"maps": [server.arcworld.get_user_world_info(user_id, map_id)]
}
})
else:
return error_return(108)
except:
return error_return(108)
@app.route('/latte/13/serve/download/me/song', methods=['GET']) # 歌曲下载 @app.route('/latte/13/serve/download/me/song', methods=['GET']) # 歌曲下载
def download_song(): @server.auth.auth_required(request)
headers = request.headers def download_song(user_id):
token = headers['Authorization']
token = token[7:]
song_ids = request.args.getlist('sid') song_ids = request.args.getlist('sid')
try: if server.arcdownload.is_able_download(user_id):
user_id = server.auth.token_get_id(token) re = {}
if user_id: if not song_ids:
if server.arcdownload.is_able_download(user_id): re = server.arcdownload.get_all_songs(user_id)
re = {}
if not song_ids:
re = server.arcdownload.get_all_songs(user_id)
else:
re = server.arcdownload.get_some_songs(user_id, song_ids)
return jsonify({
"success": True,
"value": re
})
else:
return error_return(903)
else: else:
return error_return(108) re = server.arcdownload.get_some_songs(user_id, song_ids)
except:
return error_return(108) return jsonify({
"success": True,
"value": re
})
else:
return error_return(903)
@app.route('/download/<path:file_path>', methods=['GET']) # 下载 @app.route('/download/<path:file_path>', methods=['GET']) # 下载
def download(file_path): def download(file_path):
t = request.args.get('t')
try: try:
t = request.args.get('t')
message = server.arcdownload.is_token_able_download(t) message = server.arcdownload.is_token_able_download(t)
if message == 0: if message == 0:
path = os.path.join('./database/songs', file_path) path = os.path.join('./database/songs', file_path)
@@ -663,45 +511,64 @@ def download(file_path):
@app.route('/latte/<path:path>', methods=['POST']) # 三个设置,写在最后降低优先级 @app.route('/latte/<path:path>', methods=['POST']) # 三个设置,写在最后降低优先级
def sys_set(path): @server.auth.auth_required(request)
def sys_set(user_id, path):
set_arg = path[10:] set_arg = path[10:]
headers = request.headers
token = headers['Authorization']
token = token[7:]
value = request.form['value'] value = request.form['value']
server.setme.arc_sys_set(user_id, value, set_arg)
try: r = server.info.arc_aggregate_small(user_id)
user_id = server.auth.token_get_id(token) r['value'] = r['value'][0]['value']
if user_id is not None: return jsonify(r)
server.setme.arc_sys_set(user_id, value, set_arg)
r = server.info.arc_aggregate_small(user_id)
r['value'] = r['value'][0]['value']
return jsonify(r)
else:
return error_return(108)
except:
return error_return(108)
def main(): def main():
config = configparser.ConfigParser() os.chdir(sys.path[0]) # 更改工作路径,以便于愉快使用相对路径
path = r'setting.ini' app.config.from_mapping(SECRET_KEY=Config.SECRET_KEY)
config.read(path, encoding="utf-8") app.config['SESSION_TYPE'] = 'filesystem'
HOST = config.get('CONFIG', 'HOST')
PORT = config.get('CONFIG', 'PORT')
app.config.from_mapping(SECRET_KEY='1145141919810')
app.register_blueprint(web.login.bp) app.register_blueprint(web.login.bp)
app.register_blueprint(web.index.bp) app.register_blueprint(web.index.bp)
dictConfig({ log_dict = {
'version': 1, 'version': 1,
'formatters': {'default': {
'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
}},
'root': { 'root': {
'level': 'INFO' 'level': 'INFO',
'handlers': ['wsgi', 'error_file']
},
'handlers': {
'wsgi': {
'class': 'logging.StreamHandler',
'stream': 'ext://flask.logging.wsgi_errors_stream',
'formatter': 'default'
},
"error_file": {
"class": "logging.handlers.RotatingFileHandler",
"maxBytes": 1024 * 1024,
"backupCount": 1,
"encoding": "utf-8",
"level": "ERROR",
"formatter": "default",
"filename": "./log/error.log"
}
},
'formatters': {
'default': {
'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
}
} }
}) }
if Config.ALLOW_LOG_INFO:
log_dict['root']['handlers'] = ['wsgi', 'info_file', 'error_file']
log_dict['handlers']['info_file'] = {
"class": "logging.handlers.RotatingFileHandler",
"maxBytes": 1024 * 1024,
"backupCount": 1,
"encoding": "utf-8",
"level": "INFO",
"formatter": "default",
"filename": "./log/info.log"
}
dictConfig(log_dict)
app.logger.info("Start to initialize data in 'songfile' table...") app.logger.info("Start to initialize data in 'songfile' table...")
try: try:
@@ -713,7 +580,7 @@ def main():
else: else:
app.logger.info('Complete!') app.logger.info('Complete!')
app.run(HOST, PORT) app.run(Config.HOST, Config.PORT)
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -1 +1 @@
python main.py python -B main.py

View File

@@ -2,10 +2,12 @@ import os
import hashlib import hashlib
from flask import url_for from flask import url_for
import sqlite3 import sqlite3
from server.sql import Connect
import time import time
from setting import Config
time_limit = 3000 # 每个玩家24小时下载次数限制 time_limit = Config.DOWNLOAD_TIMES_LIMIT # 每个玩家24小时下载次数限制
time_gap_limit = 1000 # 下载链接有效秒数 time_gap_limit = Config.DOWNLOAD_TIME_GAP_LIMIT # 下载链接有效秒数
def get_file_md5(file_path): def get_file_md5(file_path):
@@ -13,13 +15,13 @@ def get_file_md5(file_path):
if not os.path.isfile(file_path): if not os.path.isfile(file_path):
return None return None
myhash = hashlib.md5() myhash = hashlib.md5()
f = open(file_path, 'rb') with open(file_path, 'rb') as f:
while True: while True:
b = f.read(8096) b = f.read(8096)
if not b: if not b:
break break
myhash.update(b) myhash.update(b)
f.close()
return myhash.hexdigest() return myhash.hexdigest()
@@ -71,74 +73,63 @@ 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') with Connect() as c:
c = conn.cursor() for i in dir_list:
for i in dir_list: if os.path.isdir(os.path.join(file_dir, i)):
if os.path.isdir(os.path.join(file_dir, i)): re.update(get_one_song(c, user_id, i, file_dir))
re.update(get_one_song(c, user_id, i, file_dir))
conn.commit()
conn.close()
return re return re
def get_some_songs(user_id, song_ids): def get_some_songs(user_id, song_ids):
# 获取一些歌的下载链接,返回字典 # 获取一些歌的下载链接,返回字典
re = {} re = {}
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() for song_id in song_ids:
for song_id in song_ids: re.update(get_one_song(c, user_id, song_id))
re.update(get_one_song(c, user_id, song_id))
conn.commit()
conn.close()
return re return re
def is_token_able_download(t): def is_token_able_download(t):
# token是否可以下载返回错误码0即可以 # token是否可以下载返回错误码0即可以
errorcode = 0 errorcode = 108
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() c.execute('''select * from download_token where token = :t limit 1''',
c.execute('''select * from download_token where token = :t limit 1''', {'t': t})
{'t': t}) x = c.fetchone()
x = c.fetchone() now = int(time.time())
now = int(time.time()) if x and now - x[4] <= time_gap_limit:
if x and now - x[4] <= time_gap_limit: c.execute(
c.execute( '''select count(*) from user_download where user_id = :a''', {'a': x[0]})
'''select count(*) from user_download where user_id = :a''', {'a': x[0]}) y = c.fetchone()
y = c.fetchone() if y and y[0] <= time_limit:
if y and y[0] <= time_limit: c.execute('''insert into user_download values(:a,:b,:c)''', {
c.execute('''insert into user_download values(:a,:b,:c)''', { 'a': x[0], 'b': x[3], 'c': now})
'a': x[0], 'b': x[3], 'c': now}) errorcode = 0
else:
errorcode = 903
else: else:
errorcode = 903 errorcode = 108
else:
errorcode = 108
conn.commit()
conn.close()
return errorcode return errorcode
def is_able_download(user_id): def is_able_download(user_id):
# 是否可以下载,返回布尔值 # 是否可以下载,返回布尔值
f = True f = False
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() now = int(time.time())
now = int(time.time()) c.execute(
c.execute( '''delete from user_download where user_id = :a and time <= :b''', {'a': user_id, 'b': now - 24*3600})
'''delete from user_download where user_id = :a and time <= :b''', {'a': user_id, 'b': now - 24*3600}) c.execute(
c.execute( '''select count(*) from user_download where user_id = :a''', {'a': user_id})
'''select count(*) from user_download where user_id = :a''', {'a': user_id}) y = c.fetchone()
y = c.fetchone() if y and y[0] <= time_limit:
if y and y[0] <= time_limit: f = True
pass else:
else: f = False
f = False
conn.commit()
conn.close()
return f return f

View File

@@ -1,4 +1,4 @@
import sqlite3 from server.sql import Connect
import time import time
import json import json
@@ -41,87 +41,91 @@ def get_item(c, type='pack'):
def get_single_purchase(): def get_single_purchase():
# main里面没开数据库这里写一下代替 # main里面没开数据库这里写一下代替
conn = sqlite3.connect('./database/arcaea_database.db') re = []
c = conn.cursor() with Connect() as c:
re = get_item(c, type='single') re = get_item(c, type='single')
conn.commit()
conn.close()
return re return re
def buy_item(c, user_id, price):
# 购买接口,返回成功与否标识符和剩余源点数
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:
return False, ticket
c.execute('''update user set ticket = :b where user_id = :a''',
{'a': user_id, 'b': ticket-price})
return True, ticket - price
def buy_pack(user_id, pack_id): def buy_pack(user_id, pack_id):
# 曲包购买,返回字典 # 曲包购买,返回字典
conn = sqlite3.connect('./database/arcaea_database.db') re = {"success": False}
c = conn.cursor() with Connect() as c:
c.execute('''select price from item where item_id = :a''', {'a': pack_id}) c.execute('''select price from item where item_id = :a''',
price = c.fetchone() {'a': pack_id})
if price: price = c.fetchone()
price = price[0] if price:
else: price = price[0]
price = 0 else:
price = 0
c.execute('''select ticket from user where user_id = :a''', {'a': user_id}) flag, ticket = buy_item(c, user_id, price)
ticket = c.fetchone()
if ticket:
ticket = ticket[0]
else:
ticket = 0
if ticket < price: if flag:
conn.commit() c.execute('''insert into user_item values(:a,:b,'pack')''',
conn.close() {'a': user_id, 'b': pack_id})
return {
"success": False
}
c.execute('''update user set ticket = :b where user_id = :a''', re = {"success": True}
{'a': user_id, 'b': ticket-price})
c.execute('''insert into user_item values(:a,:b,'pack')''',
{'a': user_id, 'b': pack_id})
conn.commit() return re
conn.close()
return {
"success": True
}
def buy_single(user_id, single_id): def buy_single(user_id, single_id):
# 单曲购买,返回字典 # 单曲购买,返回字典
conn = sqlite3.connect('./database/arcaea_database.db') re = {"success": False}
c = conn.cursor() with Connect() as c:
c.execute('''select price from item where item_id = :a''', c.execute('''select price from item where item_id = :a''',
{'a': single_id}) {'a': single_id})
price = c.fetchone() price = c.fetchone()
if price: if price:
price = price[0] price = price[0]
else:
price = 0
flag, ticket = buy_item(c, user_id, price)
if flag:
c.execute('''insert into user_item values(:a,:b,'single')''',
{'a': user_id, 'b': single_id})
re = {"success": True}
return re
def get_prog_boost(user_id):
# 世界模式源韵强化扣50源点返回剩余源点数
ticket = -1
with Connect() as c:
flag, ticket = buy_item(c, user_id, 50)
if flag:
c.execute('''update user set prog_boost = 1 where user_id = :a''', {
'a': user_id})
if ticket >= 0:
return ticket, None
else: else:
price = 0 return 0, 108
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
}
def get_user_present(c, user_id): def get_user_present(c, user_id):
@@ -146,82 +150,70 @@ def get_user_present(c, user_id):
def claim_user_present(user_id, present_id): def claim_user_present(user_id, present_id):
# 确认并删除用户奖励,返回成功与否的布尔值 # 确认并删除用户奖励,返回成功与否的布尔值
flag = False flag = False
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() c.execute('''select exists(select * from user_present where user_id=:a and present_id=:b)''',
c.execute('''select exists(select * from user_present where user_id=:a and present_id=:b)''',
{'a': user_id, 'b': present_id})
if c.fetchone() == (1,):
flag = True
c.execute('''delete from user_present where user_id=:a and present_id=:b''',
{'a': user_id, 'b': present_id}) {'a': user_id, 'b': present_id})
c.execute('''select * from present where present_id=:b''', if c.fetchone() == (1,):
{'b': present_id}) c.execute('''delete from user_present where user_id=:a and present_id=:b''',
x = c.fetchone() {'a': user_id, 'b': present_id})
now = int(time.time() * 1000) c.execute('''select * from present where present_id=:b''',
if now <= int(x[1]): {'b': present_id})
# 处理memory x = c.fetchone()
items = json.loads(x[2]) now = int(time.time() * 1000)
for i in items: if now <= int(x[1]):
if i['id'] == 'memory': # 处理memory
c.execute('''select ticket from user where user_id=:a''', { items = json.loads(x[2])
'a': user_id}) for i in items:
ticket = int(c.fetchone()[0]) if i['id'] == 'memory':
ticket += int(i['amount']) c.execute('''select ticket from user where user_id=:a''', {
c.execute('''update user set ticket=:b where user_id=:a''', { 'a': user_id})
'a': user_id, 'b': ticket}) ticket = int(c.fetchone()[0])
ticket += int(i['amount'])
c.execute('''update user set ticket=:b where user_id=:a''', {
'a': user_id, 'b': ticket})
flag = True
else:
# 过期
flag = False
else:
# 过期
flag = False
conn.commit()
conn.close()
return flag return flag
def claim_user_redeem(user_id, code): def claim_user_redeem(user_id, code):
# 处理兑换码,返回碎片数量和错误码 # 处理兑换码,返回碎片数量和错误码
fragment = 0 fragment = 0
conn = sqlite3.connect('./database/arcaea_database.db') error_code = 108
c = conn.cursor() with Connect() as c:
c.execute('''select * from redeem where code=:a''', {'a': code}) c.execute('''select * from redeem where code=:a''', {'a': code})
x = c.fetchone() x = c.fetchone()
if not x: if not x:
conn.commit() return 0, 504
conn.close()
return 0, 504
if x[2] == 0: # 一次性 if x[2] == 0: # 一次性
c.execute( c.execute(
'''select exists(select * from user_redeem where code=:a)''', {'a': code}) '''select exists(select * from user_redeem where code=:a)''', {'a': code})
if c.fetchone() == (1,): if c.fetchone() == (1,):
conn.commit() return 0, 505
conn.close() elif x[2] == 1: # 每个玩家一次
return 0, 505 c.execute('''select exists(select * from user_redeem where code=:a and user_id=:b)''',
elif x[2] == 1: # 每个玩家一次 {'a': code, 'b': user_id})
c.execute('''select exists(select * from user_redeem where code=:a and user_id=:b)''', if c.fetchone() == (1,):
return 0, 506
c.execute('''insert into user_redeem values(:b,:a)''',
{'a': code, 'b': user_id}) {'a': code, 'b': user_id})
if c.fetchone() == (1,):
conn.commit()
conn.close()
return 0, 506
c.execute('''insert into user_redeem values(:b,:a)''', items = json.loads(x[1])
{'a': code, 'b': user_id}) for i in items:
if i['type'] == 'fragment':
fragment = i['amount']
if i['type'] == 'memory':
c.execute('''select ticket from user where user_id=:a''', {
'a': user_id})
ticket = int(c.fetchone()[0])
ticket += int(i['amount'])
c.execute('''update user set ticket=:b where user_id=:a''', {
'a': user_id, 'b': ticket})
error_code = None
items = json.loads(x[1]) return fragment, error_code
for i in items:
if i['type'] == 'fragment':
fragment = i['amount']
if i['type'] == 'memory':
c.execute('''select ticket from user where user_id=:a''', {
'a': user_id})
ticket = int(c.fetchone()[0])
ticket += int(i['amount'])
c.execute('''update user set ticket=:b where user_id=:a''', {
'a': user_id, 'b': ticket})
conn.commit()
conn.close()
return fragment, None

View File

@@ -1,4 +1,4 @@
import sqlite3 from server.sql import Connect
import time import time
import json import json
import server.arcworld import server.arcworld
@@ -80,144 +80,131 @@ def get_score(c, user_id, song_id, difficulty):
def arc_score_friend(user_id, song_id, difficulty, limit=50): def arc_score_friend(user_id, song_id, difficulty, limit=50):
# 得到用户好友分数表默认最大50个 # 得到用户好友分数表默认最大50个
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select user_id from best_score where user_id in (select :user_id union select user_id_other from friend where user_id_me = :user_id) and song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit''', {
'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty, 'limit': limit})
x = c.fetchall()
r = [] r = []
if x != []: with Connect() as c:
rank = 0 c.execute('''select user_id from best_score where user_id in (select :user_id union select user_id_other from friend where user_id_me = :user_id) and song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit''', {
for i in x: 'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty, 'limit': limit})
rank += 1 x = c.fetchall()
y = get_score(c, i[0], song_id, difficulty) if x != []:
y['rank'] = rank rank = 0
r.append(y) for i in x:
rank += 1
y = get_score(c, i[0], song_id, difficulty)
y['rank'] = rank
r.append(y)
conn.commit()
conn.close()
return r return r
def arc_score_top(song_id, difficulty, limit=20): def arc_score_top(song_id, difficulty, limit=20):
# 得到top分数表默认最多20个如果是负数则全部查询 # 得到top分数表默认最多20个如果是负数则全部查询
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
if limit >= 0:
c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit''', {
'song_id': song_id, 'difficulty': difficulty, 'limit': limit})
else:
c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC''', {
'song_id': song_id, 'difficulty': difficulty})
x = c.fetchall()
r = [] r = []
if x != []: with Connect() as c:
rank = 0 if limit >= 0:
for i in x: c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit''', {
rank += 1 'song_id': song_id, 'difficulty': difficulty, 'limit': limit})
y = get_score(c, i[0], song_id, difficulty) else:
y['rank'] = rank c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC''', {
r.append(y) 'song_id': song_id, 'difficulty': difficulty})
x = c.fetchall()
if x != []:
rank = 0
for i in x:
rank += 1
y = get_score(c, i[0], song_id, difficulty)
y['rank'] = rank
r.append(y)
conn.commit()
conn.close()
return r return r
def arc_score_me(user_id, song_id, difficulty, limit=20): def arc_score_me(user_id, song_id, difficulty, limit=20):
# 得到用户的排名默认最大20个 # 得到用户的排名默认最大20个
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
r = [] r = []
c.execute('''select exists(select * from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty)''', { with Connect() as c:
'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty}) c.execute('''select exists(select * from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty)''', {
if c.fetchone() == (1,):
c.execute('''select count(*) from best_score where song_id = :song_id and difficulty = :difficulty and (score>(select score from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty) or (score>(select score from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty) and time_played > (select time_played from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty)) )''', {
'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty}) 'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty})
x = c.fetchone() if c.fetchone() == (1,):
myrank = int(x[0]) + 1 c.execute('''select count(*) from best_score where song_id = :song_id and difficulty = :difficulty and (score>(select score from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty) or (score>(select score from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty) and time_played > (select time_played from best_score where user_id = :user_id and song_id = :song_id and difficulty = :difficulty)) )''', {
if myrank <= 4: # 排名在前4 'user_id': user_id, 'song_id': song_id, 'difficulty': difficulty})
conn.commit() x = c.fetchone()
conn.close() myrank = int(x[0]) + 1
return arc_score_top(song_id, difficulty, limit) if myrank <= 4: # 排名在前4
elif myrank >= 5 and myrank <= 9999 - limit + 4: # 万名内前面有4个人 return arc_score_top(song_id, difficulty, limit)
c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', { elif myrank >= 5 and myrank <= 9999 - limit + 4: # 万名内前面有4个人
'song_id': song_id, 'difficulty': difficulty, 'limit': limit, 'offset': myrank - 5}) c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', {
x = c.fetchall() 'song_id': song_id, 'difficulty': difficulty, 'limit': limit, 'offset': myrank - 5})
if x != []: x = c.fetchall()
rank = myrank - 5 if x != []:
for i in x: rank = myrank - 5
rank += 1 for i in x:
y = get_score(c, i[0], song_id, difficulty) rank += 1
y['rank'] = rank y = get_score(c, i[0], song_id, difficulty)
r.append(y) y['rank'] = rank
r.append(y)
elif myrank >= 10000: # 万名外 elif myrank >= 10000: # 万名外
c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', { c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', {
'song_id': song_id, 'difficulty': difficulty, 'limit': limit - 1, 'offset': 9999-limit}) 'song_id': song_id, 'difficulty': difficulty, 'limit': limit - 1, 'offset': 9999-limit})
x = c.fetchall() x = c.fetchall()
if x != []: if x != []:
rank = 9999 - limit rank = 9999 - limit
for i in x: for i in x:
rank += 1 rank += 1
y = get_score(c, i[0], song_id, difficulty) y = get_score(c, i[0], song_id, difficulty)
y['rank'] = rank y['rank'] = rank
r.append(y) r.append(y)
y = get_score(c, user_id, song_id, difficulty) y = get_score(c, user_id, song_id, difficulty)
y['rank'] = -1 y['rank'] = -1
r.append(y)
else:
c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', {
'song_id': song_id, 'difficulty': difficulty, 'limit': limit, 'offset': 9998-limit})
x = c.fetchall()
if x != []:
rank = 9998 - limit
for i in x:
rank += 1
y = get_score(c, i[0], song_id, difficulty)
y['rank'] = rank
r.append(y) r.append(y)
else:
c.execute('''select user_id from best_score where song_id = :song_id and difficulty = :difficulty order by score DESC, time_played DESC limit :limit offset :offset''', {
'song_id': song_id, 'difficulty': difficulty, 'limit': limit, 'offset': 9998-limit})
x = c.fetchall()
if x != []:
rank = 9998 - limit
for i in x:
rank += 1
y = get_score(c, i[0], song_id, difficulty)
y['rank'] = rank
r.append(y)
conn.commit()
conn.close()
return r return r
def get_one_ptt(song_id, difficulty, score: int) -> float: def get_one_ptt(song_id, difficulty, score: int) -> float:
# 单曲ptt计算ptt为负说明没铺面定数数据 # 单曲ptt计算ptt为负说明没铺面定数数据
conn = sqlite3.connect('./database/arcsong.db') ptt = -10
c = conn.cursor() with Connect('./database/arcsong.db') as c:
if difficulty == 0: if difficulty == 0:
c.execute('''select rating_pst from songs where sid = :sid;''', { c.execute('''select rating_pst from songs where sid = :sid;''', {
'sid': song_id}) 'sid': song_id})
elif difficulty == 1: elif difficulty == 1:
c.execute('''select rating_prs from songs where sid = :sid;''', { c.execute('''select rating_prs from songs where sid = :sid;''', {
'sid': song_id}) 'sid': song_id})
elif difficulty == 2: elif difficulty == 2:
c.execute('''select rating_ftr from songs where sid = :sid;''', { c.execute('''select rating_ftr from songs where sid = :sid;''', {
'sid': song_id}) 'sid': song_id})
elif difficulty == 3: elif difficulty == 3:
c.execute('''select rating_byn from songs where sid = :sid;''', { c.execute('''select rating_byn from songs where sid = :sid;''', {
'sid': song_id}) 'sid': song_id})
x = c.fetchone() x = c.fetchone()
defnum = -10 # 没在库里的全部当做定数-10 defnum = -10 # 没在库里的全部当做定数-10
if x is not None and x != '': if x is not None and x != '':
defnum = float(x[0]) / 10 defnum = float(x[0]) / 10
if defnum <= 0: if defnum <= 0:
defnum = -10 # 缺少难度的当做定数-10 defnum = -10 # 缺少难度的当做定数-10
if score >= 10000000: if score >= 10000000:
ptt = defnum + 2 ptt = defnum + 2
elif score < 9800000: elif score < 9800000:
ptt = defnum + (score-9500000) / 300000 ptt = defnum + (score-9500000) / 300000
if ptt < 0 and defnum != -10: if ptt < 0 and defnum != -10:
ptt = 0 ptt = 0
else: else:
ptt = defnum + 1 + (score-9800000) / 200000 ptt = defnum + 1 + (score-9800000) / 200000
conn.commit()
conn.close()
return ptt return ptt
@@ -255,8 +242,9 @@ def get_song_state(x):
return 0 return 0
def get_user_ptt(c, user_id) -> int: def get_user_ptt_float(c, user_id) -> float:
# 总ptt计算 # 总ptt计算,返回浮点数
sumr = 0 sumr = 0
c.execute('''select rating from best_score where user_id = :a order by rating DESC limit 30''', { c.execute('''select rating from best_score where user_id = :a order by rating DESC limit 30''', {
'a': user_id}) 'a': user_id})
@@ -285,8 +273,13 @@ def get_user_ptt(c, user_id) -> int:
sumr += r30[i] sumr += r30[i]
songs.append(s30[i]) songs.append(s30[i])
i += 1 i += 1
return sumr/40
return int(sumr/40*100)
def get_user_ptt(c, user_id) -> int:
# 总ptt计算返回4位整数向下取整
return int(get_user_ptt_float(c, user_id)*100)
def update_recent30(c, user_id, song_id, rating, is_protected): def update_recent30(c, user_id, song_id, rating, is_protected):
@@ -346,7 +339,7 @@ def update_recent30(c, user_id, song_id, rating, is_protected):
b.append(x[i+1]) b.append(x[i+1])
if is_protected: if is_protected:
ptt_pre = get_user_ptt(c, user_id) ptt_pre = get_user_ptt_float(c, user_id)
a_pre = [x for x in a] a_pre = [x for x in a]
b_pre = [x for x in b] b_pre = [x for x in b]
@@ -359,7 +352,7 @@ def update_recent30(c, user_id, song_id, rating, is_protected):
insert_r30table(c, user_id, a, b) insert_r30table(c, user_id, a, b)
if is_protected: if is_protected:
ptt = get_user_ptt(c, user_id) ptt = get_user_ptt_float(c, user_id)
if ptt < ptt_pre: if ptt < ptt_pre:
# 触发保护 # 触发保护
if song_id in b_pre: if song_id in b_pre:
@@ -375,172 +368,175 @@ def update_recent30(c, user_id, song_id, rating, is_protected):
def arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count, perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type): def arc_score_post(user_id, song_id, difficulty, score, shiny_perfect_count, perfect_count, near_count, miss_count, health, modifier, beyond_gauge, clear_type):
# 分数上传返回变化后的ptt和世界模式变化 # 分数上传返回变化后的ptt和世界模式变化
ptt = None
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
rating = get_one_ptt(song_id, difficulty, score)
if rating < 0: # 没数据不会向recent30里记入
unrank_flag = True
rating = 0
else:
unrank_flag = False
now = int(time.time() * 1000)
# recent 更新
c.execute('''update user set song_id = :b, difficulty = :c, score = :d, shiny_perfect_count = :e, perfect_count = :f, near_count = :g, miss_count = :h, health = :i, modifier = :j, clear_type = :k, rating = :l, time_played = :m where user_id = :a''', {
'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': clear_type, 'l': rating, 'm': now})
# 成绩录入
c.execute('''select score, best_clear_type from best_score where user_id = :a and song_id = :b and difficulty = :c''', {
'a': user_id, 'b': song_id, 'c': difficulty})
now = int(now // 1000)
x = c.fetchone()
if x is None:
first_protect_flag = True # 初见保护
c.execute('''insert into best_score values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n)''', {
'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': now, 'l': clear_type, 'm': clear_type, 'n': rating})
else:
first_protect_flag = False
if get_song_state(clear_type) > get_song_state(int(x[1])): # 状态更新
c.execute('''update best_score set best_clear_type = :a where user_id = :b and song_id = :c and difficulty = :d''', {
'a': clear_type, 'b': user_id, 'c': song_id, 'd': difficulty})
if score >= int(x[0]): # 成绩更新
c.execute('''update best_score set score = :d, shiny_perfect_count = :e, perfect_count = :f, near_count = :g, miss_count = :h, health = :i, modifier = :j, clear_type = :k, rating = :l, time_played = :m where user_id = :a and song_id = :b and difficulty = :c ''', {
'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': clear_type, 'l': rating, 'm': now})
if not unrank_flag:
# recent30 更新
if health == -1 or int(score) >= 9800000 or first_protect_flag:
update_recent30(c, user_id, song_id+str(difficulty), rating, True)
else:
update_recent30(c, user_id, song_id+str(difficulty), rating, False)
# 总PTT更新
ptt = get_user_ptt(c, user_id)
c.execute('''update user set rating_ptt = :a where user_id = :b''', {
'a': ptt, 'b': user_id})
# 世界模式判断
c.execute('''select stamina_multiply,fragment_multiply,prog_boost_multiply from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', {
'a': user_id, 'b': song_id, 'c': difficulty})
x = c.fetchone()
re = None re = None
if x: with Connect() as c:
stamina_multiply = x[0] rating = get_one_ptt(song_id, difficulty, score)
fragment_multiply = x[1] if rating < 0: # 没数据不会向recent30里记入
prog_boost_multiply = x[2] unrank_flag = True
step_times = stamina_multiply * fragment_multiply / \ rating = 0
100 * (prog_boost_multiply+100)/100 else:
exp_times = stamina_multiply * (prog_boost_multiply+100)/100 unrank_flag = False
c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', { now = int(time.time() * 1000)
# recent 更新
c.execute('''update user set song_id = :b, difficulty = :c, score = :d, shiny_perfect_count = :e, perfect_count = :f, near_count = :g, miss_count = :h, health = :i, modifier = :j, clear_type = :k, rating = :l, time_played = :m where user_id = :a''', {
'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': clear_type, 'l': rating, 'm': now})
# 成绩录入
c.execute('''select score, best_clear_type from best_score where user_id = :a and song_id = :b and difficulty = :c''', {
'a': user_id, 'b': song_id, 'c': difficulty}) 'a': user_id, 'b': song_id, 'c': difficulty})
c.execute('''select character_id,frag,prog,overdrive from user_char where user_id = :a and character_id = (select character_id from user where user_id=:a)''', { now = int(now // 1000)
'a': user_id}) x = c.fetchone()
y = c.fetchone() if x is None:
if y: first_protect_flag = True # 初见保护
character_id = y[0] c.execute('''insert into best_score values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n)''', {
flag = float(y[1]) 'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': now, 'l': clear_type, 'm': clear_type, 'n': rating})
prog = float(y[2])
overdrive = float(y[3])
else: else:
character_id = 0 first_protect_flag = False
flag = 0 if get_song_state(clear_type) > get_song_state(int(x[1])): # 状态更新
prog = 0 c.execute('''update best_score set best_clear_type = :a where user_id = :b and song_id = :c and difficulty = :d''', {
overdrive = 0 'a': clear_type, 'b': user_id, 'c': song_id, 'd': difficulty})
if score >= int(x[0]): # 成绩更新
c.execute('''select current_map from user where user_id = :a''', { c.execute('''update best_score set score = :d, shiny_perfect_count = :e, perfect_count = :f, near_count = :g, miss_count = :h, health = :i, modifier = :j, clear_type = :k, rating = :l, time_played = :m where user_id = :a and song_id = :b and difficulty = :c ''', {
'a': user_id}) 'a': user_id, 'b': song_id, 'c': difficulty, 'd': score, 'e': shiny_perfect_count, 'f': perfect_count, 'g': near_count, 'h': miss_count, 'i': health, 'j': modifier, 'k': clear_type, 'l': rating, 'm': now})
map_id = c.fetchone()[0] if not unrank_flag:
# recent30 更新
if beyond_gauge == 0: # 是否是beyond挑战 if health == -1 or int(score) >= 9800000 or first_protect_flag:
base_step = 2.5 + 2.45*rating**0.5 update_recent30(c, user_id, song_id +
step = base_step * (prog/50) * step_times str(difficulty), rating, True)
else:
info = server.arcworld.get_world_info(map_id)
if clear_type == 0:
base_step = 8/9 + (rating/1.3)**0.5
else: else:
base_step = 8/3 + (rating/1.3)**0.5 update_recent30(c, user_id, song_id +
str(difficulty), rating, False)
if character_id in info['character_affinity']: # 总PTT更新
affinity_multiplier = info['affinity_multiplier'][info['character_affinity'].index( ptt = get_user_ptt(c, user_id)
character_id)] c.execute('''update user set rating_ptt = :a where user_id = :b''', {
'a': ptt, 'b': user_id})
# 世界模式判断
c.execute('''select stamina_multiply,fragment_multiply,prog_boost_multiply from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', {
'a': user_id, 'b': song_id, 'c': difficulty})
x = c.fetchone()
re = None
if x:
stamina_multiply = x[0]
fragment_multiply = x[1]
prog_boost_multiply = x[2]
step_times = stamina_multiply * fragment_multiply / \
100 * (prog_boost_multiply+100)/100
exp_times = stamina_multiply * (prog_boost_multiply+100)/100
if prog_boost_multiply != 0:
c.execute('''update user set prog_boost = 0 where user_id = :a''', {
'a': user_id})
c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', {
'a': user_id, 'b': song_id, 'c': difficulty})
c.execute('''select character_id,frag,prog,overdrive from user_char where user_id = :a and character_id = (select character_id from user where user_id=:a)''', {
'a': user_id})
y = c.fetchone()
if y:
character_id = y[0]
flag = float(y[1])
prog = float(y[2])
overdrive = float(y[3])
else: else:
affinity_multiplier = 1 character_id = 0
flag = 0
prog = 0
overdrive = 0
step = base_step * (prog/50) * step_times * affinity_multiplier c.execute('''select current_map from user where user_id = :a''', {
'a': user_id})
map_id = c.fetchone()[0]
c.execute('''select * from user_world where user_id = :a and map_id =:b''', if beyond_gauge == 0: # 是否是beyond挑战
{'a': user_id, 'b': map_id}) base_step = 2.5 + 2.45*rating**0.5
y = c.fetchone() step = base_step * (prog/50) * step_times
rewards, steps, curr_position, curr_capture, info = server.arcworld.climb_step( else:
user_id, map_id, step, y[3], y[2]) info = server.arcworld.get_world_info(map_id)
if clear_type == 0:
base_step = 8/9 + (rating/1.3)**0.5
else:
base_step = 8/3 + (rating/1.3)**0.5
if beyond_gauge == 0: if character_id in info['character_affinity']:
re = { affinity_multiplier = info['affinity_multiplier'][info['character_affinity'].index(
"rewards": rewards, character_id)]
"exp": 25000, else:
"level": 30, affinity_multiplier = 1
"base_progress": base_step,
"progress": step,
"user_map": {
"user_id": user_id,
"curr_position": curr_position,
"curr_capture": curr_capture,
"is_locked": int2b(y[4]),
"map_id": map_id,
"prev_capture": y[3],
"prev_position": y[2],
"beyond_health": info['beyond_health'],
"steps": steps
},
"char_stats": {
"character_id": character_id,
"frag": flag,
"prog": prog,
"overdrive": overdrive
},
"current_stamina": 12,
"max_stamina_ts": 1586274871917,
"user_rating": ptt
}
else:
re = {
"rewards": rewards,
"exp": 25000,
"level": 30,
"base_progress": base_step,
"progress": step,
"user_map": {
"user_id": user_id,
"curr_position": curr_position,
"curr_capture": curr_capture,
"is_locked": int2b(y[4]),
"map_id": map_id,
"prev_capture": y[3],
"prev_position": y[2],
"beyond_health": info['beyond_health'],
"step_count": len(steps)
},
"char_stats": {
"character_id": character_id,
"frag": flag,
"prog": prog,
"overdrive": overdrive
},
"current_stamina": 12,
"max_stamina_ts": 1586274871917,
"user_rating": ptt
}
if stamina_multiply != 1: step = base_step * (prog/50) * step_times * affinity_multiplier
re['stamina_multiply'] = stamina_multiply
if fragment_multiply != 100:
re['fragment_multiply'] = fragment_multiply
if prog_boost_multiply != 0:
re['prog_boost_multiply'] = prog_boost_multiply
if curr_position == info['step_count']-1 and info['is_repeatable']: # 循环图判断 c.execute('''select * from user_world where user_id = :a and map_id =:b''',
curr_position = 0 {'a': user_id, 'b': map_id})
c.execute('''update user_world set curr_position=:a, curr_capture=:b where user_id=:c and map_id=:d''', { y = c.fetchone()
'a': curr_position, 'b': curr_capture, 'c': user_id, 'd': map_id}) rewards, steps, curr_position, curr_capture, info = server.arcworld.climb_step(
conn.commit() user_id, map_id, step, y[3], y[2])
conn.close()
if beyond_gauge == 0:
re = {
"rewards": rewards,
"exp": 25000,
"level": 30,
"base_progress": base_step,
"progress": step,
"user_map": {
"user_id": user_id,
"curr_position": curr_position,
"curr_capture": curr_capture,
"is_locked": int2b(y[4]),
"map_id": map_id,
"prev_capture": y[3],
"prev_position": y[2],
"beyond_health": info['beyond_health'],
"steps": steps
},
"char_stats": {
"character_id": character_id,
"frag": flag,
"prog": prog,
"overdrive": overdrive
},
"current_stamina": 12,
"max_stamina_ts": 1586274871917,
"user_rating": ptt
}
else:
re = {
"rewards": rewards,
"exp": 25000,
"level": 30,
"base_progress": base_step,
"progress": step,
"user_map": {
"user_id": user_id,
"curr_position": curr_position,
"curr_capture": curr_capture,
"is_locked": int2b(y[4]),
"map_id": map_id,
"prev_capture": y[3],
"prev_position": y[2],
"beyond_health": info['beyond_health'],
"step_count": len(steps)
},
"char_stats": {
"character_id": character_id,
"frag": flag,
"prog": prog,
"overdrive": overdrive
},
"current_stamina": 12,
"max_stamina_ts": 1586274871917,
"user_rating": ptt
}
if stamina_multiply != 1:
re['stamina_multiply'] = stamina_multiply
if fragment_multiply != 100:
re['fragment_multiply'] = fragment_multiply
if prog_boost_multiply != 0:
re['prog_boost_multiply'] = prog_boost_multiply
if curr_position == info['step_count']-1 and info['is_repeatable']: # 循环图判断
curr_position = 0
c.execute('''update user_world set curr_position=:a, curr_capture=:b where user_id=:c and map_id=:d''', {
'a': curr_position, 'b': curr_capture, 'c': user_id, 'd': map_id})
return ptt, re return ptt, re
@@ -569,24 +565,16 @@ def arc_score_check(user_id, song_id, difficulty, score, shiny_perfect_count, pe
def arc_all_post(user_id, scores_data, clearlamps_data, clearedsongs_data, unlocklist_data, installid_data, devicemodelname_data, story_data): def arc_all_post(user_id, scores_data, clearlamps_data, clearedsongs_data, unlocklist_data, installid_data, devicemodelname_data, story_data):
# 向云端同步,无返回 # 向云端同步,无返回
with Connect() as c:
conn = sqlite3.connect('./database/arcaea_database.db') now = int(time.time() * 1000)
c = conn.cursor() c.execute('''delete from user_save where user_id=:a''', {'a': user_id})
now = int(time.time() * 1000) c.execute('''insert into user_save values(:a,:b,:c,:d,:e,:f,:g,:h,:i)''', {
c.execute('''delete from user_save where user_id=:a''', {'a': user_id}) 'a': user_id, 'b': scores_data, 'c': clearlamps_data, 'd': clearedsongs_data, 'e': unlocklist_data, 'f': installid_data, 'g': devicemodelname_data, 'h': story_data, 'i': now})
c.execute('''insert into user_save values(:a,:b,:c,:d,:e,:f,:g,:h,:i)''', {
'a': user_id, 'b': scores_data, 'c': clearlamps_data, 'd': clearedsongs_data, 'e': unlocklist_data, 'f': installid_data, 'g': devicemodelname_data, 'h': story_data, 'i': now})
conn.commit()
conn.close()
return None return None
def arc_all_get(user_id): def arc_all_get(user_id):
# 从云端同步,返回字典 # 从云端同步,返回字典
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select * from user_save where user_id=:a''', {'a': user_id})
x = c.fetchone()
scores_data = [] scores_data = []
clearlamps_data = [] clearlamps_data = []
@@ -595,57 +583,24 @@ def arc_all_get(user_id):
installid_data = '' installid_data = ''
devicemodelname_data = '' devicemodelname_data = ''
# story_data = [] # story_data = []
createdAt = 0
if x: with Connect() as c:
scores_data = json.loads(x[1])[""] c.execute('''select * from user_save where user_id=:a''',
clearlamps_data = json.loads(x[2])[""] {'a': user_id})
clearedsongs_data = json.loads(x[3])[""] x = c.fetchone()
# unlocklist_data = json.loads(x[4])[""]
installid_data = json.loads(x[5])["val"]
devicemodelname_data = json.loads(x[6])["val"]
# story_data = json.loads(x[7])[""]
if x[8]:
createdAt = int(x[8])
else:
createdAt = 0
# c.execute('''select * from best_score where user_id = :a''', if x:
# {'a': user_id}) scores_data = json.loads(x[1])[""]
# x = c.fetchall() clearlamps_data = json.loads(x[2])[""]
# song_1 = [] clearedsongs_data = json.loads(x[3])[""]
# song_2 = [] # unlocklist_data = json.loads(x[4])[""]
# song_3 = [] installid_data = json.loads(x[5])["val"]
# if x != []: devicemodelname_data = json.loads(x[6])["val"]
# for i in x: # story_data = json.loads(x[7])[""]
# if i[11] != 0: if x[8]:
# song_1.append({ createdAt = int(x[8])
# "grade": get_song_grade(i[3]),
# "difficulty": i[2],
# "song_id": i[1]
# })
# song_2.append({
# "ct": 0,
# "clear_type": i[11],
# "difficulty": i[2],
# "song_id": i[1]
# })
# song_3.append({
# "ct": 0,
# "time_played": i[10],
# "modifier": i[9],
# "health": i[8],
# "miss_count": i[7],
# "near_count": i[6],
# "perfect_count": i[5],
# "shiny_perfect_count": i[4],
# "score": i[3],
# "difficulty": i[2],
# "version": 1,
# "song_id": i[1]
# })
conn.commit()
conn.close()
return { return {
"user_id": user_id, "user_id": user_id,
"story": { "story": {
@@ -949,7 +904,23 @@ def arc_all_get(user_id):
"mi": 6, "mi": 6,
"c": True, "c": True,
"r": True "r": True
}]}, }, {
"ma": 8,
"mi": 1,
"c": True,
"r": True
}, {
"ma": 8,
"mi": 2,
"c": True,
"r": True
}, {
"ma": 8,
"mi": 3,
"c": True,
"r": True
}]
},
"devicemodelname": { "devicemodelname": {
"val": devicemodelname_data "val": devicemodelname_data
}, },
@@ -1021,9 +992,6 @@ def arc_all_get(user_id):
}, { }, {
"unlock_key": "rugie|2|0", "unlock_key": "rugie|2|0",
"complete": 1 "complete": 1
}, {
"unlock_key": "rugie|1|0",
"complete": 1
}, { }, {
"unlock_key": "rise|2|0", "unlock_key": "rise|2|0",
"complete": 1 "complete": 1
@@ -1123,6 +1091,9 @@ def arc_all_get(user_id):
}, { }, {
"unlock_key": "lucifer|1|0", "unlock_key": "lucifer|1|0",
"complete": 1 "complete": 1
}, {
"unlock_key": "lostdesire|2|0",
"complete": 1
}, { }, {
"unlock_key": "tiemedowngently|2|0", "unlock_key": "tiemedowngently|2|0",
"complete": 1 "complete": 1
@@ -1141,9 +1112,6 @@ def arc_all_get(user_id):
}, { }, {
"unlock_key": "infinityheaven|1|0", "unlock_key": "infinityheaven|1|0",
"complete": 1 "complete": 1
}, {
"unlock_key": "lostdesire|2|0",
"complete": 1
}, { }, {
"unlock_key": "ignotus|2|0", "unlock_key": "ignotus|2|0",
"complete": 1 "complete": 1
@@ -1270,6 +1238,15 @@ def arc_all_get(user_id):
}, { }, {
"unlock_key": "flyburg|2|0", "unlock_key": "flyburg|2|0",
"complete": 1 "complete": 1
}, {
"unlock_key": "oracle|2|0",
"complete": 1
}, {
"unlock_key": "clotho|2|0",
"complete": 1
}, {
"unlock_key": "gou|2|0",
"complete": 1
}, { }, {
"unlock_key": "felis|2|0", "unlock_key": "felis|2|0",
"complete": 1 "complete": 1
@@ -1384,12 +1361,6 @@ def arc_all_get(user_id):
}, { }, {
"unlock_key": "cyberneciacatharsis|2|0", "unlock_key": "cyberneciacatharsis|2|0",
"complete": 1 "complete": 1
}, {
"unlock_key": "oracle|2|0",
"complete": 1
}, {
"unlock_key": "clotho|2|0",
"complete": 1
}, { }, {
"unlock_key": "ignotus|1|0", "unlock_key": "ignotus|1|0",
"complete": 1 "complete": 1
@@ -1510,6 +1481,12 @@ def arc_all_get(user_id):
}, { }, {
"unlock_key": "lethaeus|2|0", "unlock_key": "lethaeus|2|0",
"complete": 1 "complete": 1
}, {
"unlock_key": "rugie|1|0",
"complete": 1
}, {
"unlock_key": "gou|1|0",
"complete": 1
}, { }, {
"unlock_key": "sheriruth|1|0", "unlock_key": "sheriruth|1|0",
"complete": 1 "complete": 1

View File

@@ -1,5 +1,5 @@
import json import json
import sqlite3 from server.sql import Connect
import os import os
@@ -23,64 +23,17 @@ def get_world_name(file_dir='./database/map'):
def get_world_info(map_id): def get_world_info(map_id):
# 读取json文件内容返回字典 # 读取json文件内容返回字典
f = open('./database/map/'+map_id+'.json', 'r') world_info = {}
world_info = json.load(f) with open('./database/map/'+map_id+'.json', 'r') as f:
f.close() world_info = json.load(f)
return world_info return world_info
def get_user_world_info(user_id, map_id): def get_user_world_info(user_id, map_id):
# 读取json文件内容加上用户信息返回字典 # 读取json文件内容加上用户信息返回字典
info = get_world_info(map_id) info = get_world_info(map_id)
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor()
c.execute('''select * from user_world where map_id = :a and user_id = :b''',
{'a': map_id, 'b': user_id})
x = c.fetchone()
if x:
info['curr_position'] = x[2]
info['curr_capture'] = x[3]
info['is_locked'] = int2b(x[4])
else:
c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
'a': user_id, 'b': map_id})
conn.commit()
conn.close()
return info
def get_current_map(user_id):
# 得到user的当前图返回字符串
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select current_map from user where user_id = :a''',
{'a': user_id})
x = c.fetchone()
re = ''
if x:
re = x[0]
conn.commit()
conn.close()
return re
def get_world_all(user_id):
# 读取所有地图信息并处理,返回字典列表
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
worlds = get_world_name()
re = []
for map_id in worlds:
info = get_world_info(map_id)
steps = info['steps']
del info['steps']
rewards = []
for step in steps:
if 'items' in step:
rewards.append(
{'items': step['items'], 'position': step['position']})
info['rewards'] = rewards
c.execute('''select * from user_world where map_id = :a and user_id = :b''', c.execute('''select * from user_world where map_id = :a and user_id = :b''',
{'a': map_id, 'b': user_id}) {'a': map_id, 'b': user_id})
x = c.fetchone() x = c.fetchone()
@@ -90,75 +43,110 @@ def get_world_all(user_id):
info['is_locked'] = int2b(x[4]) info['is_locked'] = int2b(x[4])
else: else:
c.execute('''insert into user_world values(:a,:b,0,0,0)''', { c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
'a': user_id, 'b': map_id}) 'a': user_id, 'b': map_id})
re.append(info) return info
def get_current_map(user_id):
# 得到user的当前图返回字符串
re = ''
with Connect() as c:
c.execute('''select current_map from user where user_id = :a''',
{'a': user_id})
x = c.fetchone()
if x:
re = x[0]
return re
def get_world_all(user_id):
# 读取所有地图信息并处理,返回字典列表
re = []
with Connect() as c:
worlds = get_world_name()
for map_id in worlds:
info = get_world_info(map_id)
steps = info['steps']
del info['steps']
rewards = []
for step in steps:
if 'items' in step:
rewards.append(
{'items': step['items'], 'position': step['position']})
info['rewards'] = rewards
c.execute('''select * from user_world where map_id = :a and user_id = :b''',
{'a': map_id, 'b': user_id})
x = c.fetchone()
if x:
info['curr_position'] = x[2]
info['curr_capture'] = x[3]
info['is_locked'] = int2b(x[4])
else:
c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
'a': user_id, 'b': map_id})
re.append(info)
conn.commit()
conn.close()
return re return re
def get_user_world(user_id, map_id): def get_user_world(user_id, map_id):
# 获取用户图信息,返回字典 # 获取用户图信息,返回字典
conn = sqlite3.connect('./database/arcaea_database.db') re = {}
c = conn.cursor() with Connect() as c:
c.execute('''select * from user_world where map_id = :a and user_id = :b''', c.execute('''select * from user_world where map_id = :a and user_id = :b''',
{'a': map_id, 'b': user_id}) {'a': map_id, 'b': user_id})
x = c.fetchone() x = c.fetchone()
re = { re = {
"user_id": user_id, "user_id": user_id,
"curr_position": 0, "curr_position": 0,
"curr_capture": 0, "curr_capture": 0,
"is_locked": False, "is_locked": False,
"map_id": map_id "map_id": map_id
} }
if x: if x:
re['curr_position'] = x[2] re['curr_position'] = x[2]
re['curr_capture'] = x[3] re['curr_capture'] = x[3]
re['is_locked'] = int2b(x[4]) re['is_locked'] = int2b(x[4])
else: else:
c.execute('''insert into user_world values(:a,:b,0,0,0)''', { c.execute('''insert into user_world values(:a,:b,0,0,0)''', {
'a': user_id, 'b': map_id}) 'a': user_id, 'b': map_id})
conn.commit()
conn.close()
return re return re
def change_user_current_map(user_id, map_id): def change_user_current_map(user_id, map_id):
# 改变用户当前图 # 改变用户当前图
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() c.execute('''update user set current_map = :a where user_id=:b''', {
c.execute('''update user set current_map = :a where user_id=:b''', { 'a': map_id, 'b': user_id})
'a': map_id, 'b': user_id})
conn.commit()
conn.close()
return None return None
def play_world_song(user_id, args): def play_world_song(user_id, args):
# 声明是世界模式的打歌,并且记录加成信息 # 声明是世界模式的打歌,并且记录加成信息
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() stamina_multiply = 1
fragment_multiply = 100
prog_boost_multiply = 0
if 'stamina_multiply' in args:
stamina_multiply = int(args['stamina_multiply'])
if 'fragment_multiply' in args:
fragment_multiply = int(args['fragment_multiply'])
if 'prog_boost_multiply' in args:
c.execute('''select prog_boost from user where user_id=:a''', {
'a': user_id})
x = c.fetchone()
if x and x[0] == 1:
prog_boost_multiply = 300
stamina_multiply = 1 c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', {
fragment_multiply = 100 'a': user_id, 'b': args['song_id'], 'c': args['difficulty']})
prog_boost_multiply = 0 c.execute('''insert into world_songplay values(:a,:b,:c,:d,:e,:f)''', {
if 'stamina_multiply' in args: 'a': user_id, 'b': args['song_id'], 'c': args['difficulty'], 'd': stamina_multiply, 'e': fragment_multiply, 'f': prog_boost_multiply})
stamina_multiply = int(args['stamina_multiply'])
if 'fragment_multiply' in args:
fragment_multiply = int(args['fragment_multiply'])
if 'prog_boost_multiply' in args:
prog_boost_multiply = int(args['prog_boost_multiply'])
c.execute('''delete from world_songplay where user_id=:a and song_id=:b and difficulty=:c''', {
'a': user_id, 'b': args['song_id'], 'c': args['difficulty']})
c.execute('''insert into world_songplay values(:a,:b,:c,:d,:e,:f)''', {
'a': user_id, 'b': args['song_id'], 'c': args['difficulty'], 'd': stamina_multiply, 'e': fragment_multiply, 'f': prog_boost_multiply})
conn.commit()
conn.close()
return None return None

View File

@@ -1,53 +1,71 @@
import sqlite3
import hashlib import hashlib
import time import time
import server.arcworld import server.arcworld
from server.sql import Connect
import functools
from setting import Config
def arc_login(name: str, password: str) -> str: # 登录判断 def arc_login(name: str, password: str, device_id: str): # 登录判断
# 查询数据库中的user表验证账号密码返回并记录token多返回个error code # 查询数据库中的user表验证账号密码返回并记录token多返回个error code
# token采用user_id和时间戳连接后hash生成真的是瞎想的没用bear # token采用user_id和时间戳连接后hash生成真的是瞎想的没用bear
# 密码和token的加密方式为 SHA-256 # 密码和token的加密方式为 SHA-256
conn = sqlite3.connect('./database/arcaea_database.db') error_code = 108
c = conn.cursor()
error_code = None
token = None token = None
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest() with Connect() as c:
c.execute('''select user_id, password from user where name = :name''', { hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
'name': name}) c.execute('''select user_id, password from user where name = :name''', {
x = c.fetchone() 'name': name})
if x is not None: x = c.fetchone()
if x[1] == '': if x is not None:
# 账号封禁 if x[1] == '':
error_code = 106 # 账号封禁
elif x[1] == hash_pwd: error_code = 106
user_id = str(x[0]) elif x[1] == hash_pwd:
now = int(time.time() * 1000) user_id = str(x[0])
token = hashlib.sha256( now = int(time.time() * 1000)
(user_id + str(now)).encode("utf8")).hexdigest() token = hashlib.sha256(
c.execute( (user_id + str(now)).encode("utf8")).hexdigest()
'''select exists(select * from login where user_id = :user_id)''', {"user_id": user_id}) c.execute(
'''select login_device from login where user_id = :user_id''', {"user_id": user_id})
y = c.fetchall()
if y:
device_list = []
for i in y:
if i[0]:
device_list.append(i[0])
else:
device_list.append('')
if c.fetchone() == (1,): # 删掉多余token should_delete_num = len(
c.execute('''delete from login where user_id = :user_id''', device_list) + 1 - Config.LOGIN_DEVICE_NUMBER_LIMIT
{'user_id': user_id})
c.execute('''insert into login(access_token, user_id) values(:access_token, :user_id)''', { if not Config.ALLOW_LOGIN_SAME_DEVICE:
'user_id': user_id, 'access_token': token}) if device_id in device_list: # 对相同设备进行删除
c.execute('''delete from login where login_device=:a''', {
'a': device_id})
should_delete_num = len(
device_list) + 1 - device_list.count(device_id) - Config.LOGIN_DEVICE_NUMBER_LIMIT
if should_delete_num >= 1: # 删掉多余token
c.execute('''delete from login where rowid in (select rowid from login where user_id=:user_id limit :a);''',
{'user_id': user_id, 'a': int(should_delete_num)})
c.execute('''insert into login(access_token, user_id, login_device) values(:access_token, :user_id, :device_id)''', {
'user_id': user_id, 'access_token': token, 'device_id': device_id})
error_code = None
else:
# 密码错误
error_code = 104
else: else:
# 密码错误 # 用户名错误
error_code = 104 error_code = 104
else:
# 用户名错误
error_code = 104
conn.commit()
conn.close()
return token, error_code return token, error_code
def arc_register(name: str, password: str): # 注册 def arc_register(name: str, password: str, device_id: str): # 注册
# 账号注册只记录hash密码和用户名生成user_id和user_code自动登录返回token # 账号注册只记录hash密码和用户名生成user_id和user_code自动登录返回token
# token和密码的处理同登录部分 # token和密码的处理同登录部分
@@ -81,68 +99,83 @@ def arc_register(name: str, password: str): # 注册
c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', { c.execute('''insert into user_char values(:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o)''', {
'a': user_id, 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]}) 'a': user_id, 'b': i[0], 'c': i[2], 'd': i[3], 'e': i[4], 'f': i[5], 'g': i[6], 'h': i[7], 'i': i[8], 'j': i[9], 'k': i[10], 'l': i[11], 'm': i[12], 'n': i[14], 'o': i[15]})
conn = sqlite3.connect('./database/arcaea_database.db') user_id = None
c = conn.cursor() token = None
hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest() error_code = 108
c.execute( with Connect() as c:
'''select exists(select * from user where name = :name)''', {'name': name}) hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
if c.fetchone() == (0,): c.execute(
user_code = build_user_code(c) '''select exists(select * from user where name = :name)''', {'name': name})
user_id = build_user_id(c) if c.fetchone() == (0,):
now = int(time.time() * 1000) user_code = build_user_code(c)
c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt, user_id = build_user_id(c)
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket) now = int(time.time() * 1000)
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '', 0) c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt,
''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd}) character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket, prog_boost)
c.execute('''insert into recent30(user_id) values(:user_id)''', { values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '', :memories, 0)
'user_id': user_id}) ''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd, 'memories': Config.DEFAULT_MEMORIES})
c.execute('''insert into recent30(user_id) values(:user_id)''', {
'user_id': user_id})
token = hashlib.sha256( token = hashlib.sha256(
(str(user_id) + str(now)).encode("utf8")).hexdigest() (str(user_id) + str(now)).encode("utf8")).hexdigest()
c.execute('''insert into login(access_token, user_id) values(:access_token, :user_id)''', { c.execute('''insert into login(access_token, user_id, login_device) values(:access_token, :user_id, :device_id)''', {
'user_id': user_id, 'access_token': token}) 'user_id': user_id, 'access_token': token, 'device_id': device_id})
insert_user_char(c, user_id) insert_user_char(c, user_id)
conn.commit() error_code = 0
conn.close() else:
return user_id, token, 0 error_code = 101
else:
conn.commit() return user_id, token, error_code
conn.close()
return None, None, 101
def token_get_id(token: str): def token_get_id(token: str):
# 用token获取id没有考虑不同用户token相同情况说不定会有bug # 用token获取id没有考虑不同用户token相同情况说不定会有bug
conn = sqlite3.connect('./database/arcaea_database.db') user_id = None
c = conn.cursor() with Connect() as c:
c.execute('''select user_id from login where access_token = :token''', { c.execute('''select user_id from login where access_token = :token''', {
'token': token}) 'token': token})
x = c.fetchone() x = c.fetchone()
if x is not None: if x is not None:
conn.commit() user_id = x[0]
conn.close()
return x[0] return user_id
else:
conn.commit()
conn.close()
return None
def code_get_id(user_code): def code_get_id(user_code):
# 用user_code获取id # 用user_code获取id
conn = sqlite3.connect('./database/arcaea_database.db') user_id = None
c = conn.cursor()
c.execute('''select user_id from user where user_code = :a''', with Connect() as c:
{'a': user_code}) c.execute('''select user_id from user where user_code = :a''',
x = c.fetchone() {'a': user_code})
if x is not None: x = c.fetchone()
conn.commit() if x is not None:
conn.close() user_id = x[0]
return x[0]
else: return user_id
conn.commit()
conn.close()
return None def auth_required(request):
# arcaea登录验证写成了修饰器
def decorator(view):
@functools.wraps(view)
def wrapped_view(*args, **kwargs):
user_id = None
with Connect() as c:
headers = request.headers
token = headers['Authorization']
token = token[7:]
user_id = token_get_id(token)
if user_id is not None:
return view(user_id, *args, **kwargs)
else:
return '''{"success":false,"error_code":108}'''
return wrapped_view
return decorator

View File

@@ -1,7 +1,8 @@
import sqlite3 from server.sql import Connect
import server.arcworld import server.arcworld
import server.arcpurchase import server.arcpurchase
import time import time
from setting import Config
def int2b(x): def int2b(x):
@@ -170,8 +171,11 @@ def get_value_0(c, user_id):
characters = [] characters = []
for i in user_character: for i in user_character:
characters.append(i['character_id']) characters.append(i['character_id'])
prog_boost = 0
if x[27] and x[27] != 0:
prog_boost = 300
r = {"is_aprilfools": False, r = {"is_aprilfools": Config.IS_APRILFOOLS,
"curr_available_maps": [], "curr_available_maps": [],
"character_stats": user_character, "character_stats": user_character,
"friends": get_user_friend(c, user_id), "friends": get_user_friend(c, user_id),
@@ -189,15 +193,14 @@ def get_value_0(c, user_id):
"is_locked_name_duplicate": False, "is_locked_name_duplicate": False,
"is_skill_sealed": int2b(x[7]), "is_skill_sealed": int2b(x[7]),
"current_map": x[25], "current_map": x[25],
"prog_boost": 0, "prog_boost": prog_boost,
"next_fragstam_ts": -1, "next_fragstam_ts": -1,
"max_stamina_ts": 1586274871917, "max_stamina_ts": 1586274871917,
"stamina": 12, "stamina": 12,
"world_unlocks": ["scenery_chap1", "scenery_chap2", "scenery_chap3", "scenery_chap4", "scenery_chap5"], "world_unlocks": ["scenery_chap1", "scenery_chap2", "scenery_chap3", "scenery_chap4", "scenery_chap5"],
"world_songs": ["babaroque", "shadesoflight", "kanagawa", "lucifer", "anokumene", "ignotus", "rabbitintheblackroom", "qualia", "redandblue", "bookmaker", "darakunosono", "espebranch", "blacklotus", "givemeanightmare", "vividtheory", "onefr", "gekka", "vexaria3", "infinityheaven3", "fairytale3", "goodtek3", "suomi", "rugie", "faintlight", "harutopia", "goodtek", "dreaminattraction", "syro", "diode", "freefall", "grimheart", "blaster", "cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight", "lapis", "solitarydream", "lumia3", "purpleverse", "moonheart3"], "world_songs": ["babaroque", "shadesoflight", "kanagawa", "lucifer", "anokumene", "ignotus", "rabbitintheblackroom", "qualia", "redandblue", "bookmaker", "darakunosono", "espebranch", "blacklotus", "givemeanightmare", "vividtheory", "onefr", "gekka", "vexaria3", "infinityheaven3", "fairytale3", "goodtek3", "suomi", "rugie", "faintlight", "harutopia", "goodtek", "dreaminattraction", "syro", "diode", "freefall", "grimheart", "blaster", "cyberneciacatharsis", "monochromeprincess", "revixy", "vector", "supernova", "nhelv", "purgatorium3", "dement3", "crossover", "guardina", "axiumcrisis", "worldvanquisher", "sheriruth", "pragmatism", "gloryroad", "etherstrike", "corpssansorganes", "lostdesire", "blrink", "essenceoftwilight", "lapis", "solitarydream", "lumia3", "purpleverse", "moonheart3", "glow", "enchantedlove", "take"],
"singles": get_user_singles(c, user_id), # ["dataerror", "yourvoiceso", "crosssoul", "impurebird", "auxesia", "modelista", "yozakurafubuki", "surrender", "metallicpunisher", "carminescythe", "bethere", "callmyname", "fallensquare", "dropdead", "alexandrite", "astraltale", "phantasia", "empireofwinter", "libertas", "dottodot", "dreadnought", "mirzam", "heavenlycaress", "filament", "avantraze", "battlenoone", "saikyostronger", "izana", "einherjar", "laqryma", "amygdata", "altale", "feelssoright", "scarletcage", "teriqma", "mahoroba", "badtek", "maliciousmischance", "buchigireberserker", "galaxyfriends", "xeraphinite", "xanatos"] "singles": get_user_singles(c, user_id),
"packs": get_user_packs(c, user_id), "packs": get_user_packs(c, user_id),
# ["vs", "extend", "dynamix", "prelude", "core", "yugamu", "omatsuri", "zettai", "mirai", "shiawase", "chunithm", "nijuusei", "groovecoaster", "rei", "tonesphere", "lanota"]
"characters": characters, "characters": characters,
"cores": [], "cores": [],
"recent_score": get_recent_score(c, user_id), "recent_score": get_recent_score(c, user_id),
@@ -211,148 +214,143 @@ def get_value_0(c, user_id):
def arc_aggregate_small(user_id): def arc_aggregate_small(user_id):
# 返回用户数据 # 返回用户数据
conn = sqlite3.connect('./database/arcaea_database.db') r = {"success": False}
c = conn.cursor() with Connect() as c:
r = {"success": True, r = {"success": True,
"value": [{ "value": [{
"id": 0, "id": 0,
"value": get_value_0(c, user_id) "value": get_value_0(c, user_id)
}]} }]}
conn.commit()
conn.close()
return r return r
def arc_aggregate_big(user_id): def arc_aggregate_big(user_id):
# 返回用户数据和地图歌曲信息 # 返回用户数据和地图歌曲信息
r = {"success": False}
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() r = {"success": True,
r = {"success": True, "value": [{
"value": [{ "id": 0,
"id": 0, "value": get_value_0(c, user_id)
"value": get_value_0(c, user_id) }, {
}, { "id": 1,
"id": 1, "value": server.arcpurchase.get_item(c, 'pack')
"value": server.arcpurchase.get_item(c, 'pack') }, {
}, { "id": 2,
"id": 2, "value": {}
"value": {} }, {
}, { "id": 3,
"id": 3, "value": {
"value": { "max_stamina": 12,
"max_stamina": 12, "stamina_recover_tick": 1800000,
"stamina_recover_tick": 1800000, "core_exp": 250,
"core_exp": 250, "curr_ts": int(time.time())*1000,
"curr_ts": int(time.time())*1000, "level_steps": [{
"level_steps": [{ "level": 1,
"level": 1, "level_exp": 0
"level_exp": 0 }, {
}, { "level": 2,
"level": 2, "level_exp": 50
"level_exp": 50 }, {
}, { "level": 3,
"level": 3, "level_exp": 100
"level_exp": 100 }, {
}, { "level": 4,
"level": 4, "level_exp": 150
"level_exp": 150 }, {
}, { "level": 5,
"level": 5, "level_exp": 200
"level_exp": 200 }, {
}, { "level": 6,
"level": 6, "level_exp": 300
"level_exp": 300 }, {
}, { "level": 7,
"level": 7, "level_exp": 450
"level_exp": 450 }, {
}, { "level": 8,
"level": 8, "level_exp": 650
"level_exp": 650 }, {
}, { "level": 9,
"level": 9, "level_exp": 900
"level_exp": 900 }, {
}, { "level": 10,
"level": 10, "level_exp": 1200
"level_exp": 1200 }, {
}, { "level": 11,
"level": 11, "level_exp": 1600
"level_exp": 1600 }, {
}, { "level": 12,
"level": 12, "level_exp": 2100
"level_exp": 2100 }, {
}, { "level": 13,
"level": 13, "level_exp": 2700
"level_exp": 2700 }, {
}, { "level": 14,
"level": 14, "level_exp": 3400
"level_exp": 3400 }, {
}, { "level": 15,
"level": 15, "level_exp": 4200
"level_exp": 4200 }, {
}, { "level": 16,
"level": 16, "level_exp": 5100
"level_exp": 5100 }, {
}, { "level": 17,
"level": 17, "level_exp": 6100
"level_exp": 6100 }, {
}, { "level": 18,
"level": 18, "level_exp": 7200
"level_exp": 7200 }, {
}, { "level": 19,
"level": 19, "level_exp": 8500
"level_exp": 8500 }, {
}, { "level": 20,
"level": 20, "level_exp": 10000
"level_exp": 10000 }, {
}, { "level": 21,
"level": 21, "level_exp": 11500
"level_exp": 11500 }, {
}, { "level": 22,
"level": 22, "level_exp": 13000
"level_exp": 13000 }, {
}, { "level": 23,
"level": 23, "level_exp": 14500
"level_exp": 14500 }, {
}, { "level": 24,
"level": 24, "level_exp": 16000
"level_exp": 16000 }, {
}, { "level": 25,
"level": 25, "level_exp": 17500
"level_exp": 17500 }, {
}, { "level": 26,
"level": 26, "level_exp": 19000
"level_exp": 19000 }, {
}, { "level": 27,
"level": 27, "level_exp": 20500
"level_exp": 20500 }, {
}, { "level": 28,
"level": 28, "level_exp": 22000
"level_exp": 22000 }, {
}, { "level": 29,
"level": 29, "level_exp": 23500
"level_exp": 23500 }, {
}, { "level": 30,
"level": 30, "level_exp": 25000
"level_exp": 25000 }],
}], "world_ranking_enabled": False,
"world_ranking_enabled": False, "is_byd_chapter_unlocked": True
"is_byd_chapter_unlocked": True }
}, {
"id": 4,
"value": server.arcpurchase.get_user_present(c, user_id)
}, {
"id": 5,
"value": {
"current_map": server.arcworld.get_current_map(user_id),
"user_id": user_id,
"maps": server.arcworld.get_world_all(user_id)
}
} }
}, { ]}
"id": 4,
"value": server.arcpurchase.get_user_present(c, user_id)
}, {
"id": 5,
"value": {
"current_map": server.arcworld.get_current_map(user_id),
"user_id": user_id,
"maps": server.arcworld.get_world_all(user_id)
}
}
]}
conn.commit()
conn.close()
return r return r

View File

@@ -1,4 +1,4 @@
import sqlite3 from server.sql import Connect
import server.info import server.info
@@ -20,98 +20,90 @@ def int2b(x):
def change_char(user_id, character_id, skill_sealed): def change_char(user_id, character_id, skill_sealed):
# 角色改变,包括技能封印的改变,返回成功与否的布尔值 # 角色改变,包括技能封印的改变,返回成功与否的布尔值
conn = sqlite3.connect('./database/arcaea_database.db') re = False
c = conn.cursor()
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
{'a': user_id, 'b': character_id})
x = c.fetchone()
if x is not None:
if skill_sealed == 'false':
skill_sealed = False
else:
skill_sealed = True
c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', {
'a': b2int(skill_sealed), 'b': character_id, 'c': x[0], 'd': x[1], 'e': user_id})
conn.commit() with Connect() as c:
conn.close() c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
return True {'a': user_id, 'b': character_id})
x = c.fetchone()
if x is not None:
if skill_sealed == 'false':
skill_sealed = False
else:
skill_sealed = True
c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', {
'a': b2int(skill_sealed), 'b': character_id, 'c': x[0], 'd': x[1], 'e': user_id})
conn.commit() re = True
conn.close()
return False return re
def change_char_uncap(user_id, character_id): def change_char_uncap(user_id, character_id):
# 角色觉醒改变,返回字典 # 角色觉醒改变,返回字典
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
{'a': user_id, 'b': character_id})
x = c.fetchone()
r = None r = None
if x is not None and x[0] == 1: with Connect() as c:
c.execute('''update user set is_char_uncapped_override = :a where user_id = :b''', { c.execute('''select is_uncapped, is_uncapped_override from user_char where user_id = :a and character_id = :b''',
'a': b2int(x[1] == 0), 'b': user_id})
c.execute('''update user_char set is_uncapped_override = :a where user_id = :b and character_id = :c''', {
'a': b2int(x[1] == 0), 'b': user_id, 'c': character_id})
c.execute('''select * from user_char where user_id = :a and character_id = :b''',
{'a': user_id, 'b': character_id}) {'a': user_id, 'b': character_id})
y = c.fetchone() x = c.fetchone()
c.execute(
'''select name from character where character_id = :x''', {'x': y[1]}) if x is not None and x[0] == 1:
z = c.fetchone() c.execute('''update user set is_char_uncapped_override = :a where user_id = :b''', {
if z is not None: 'a': b2int(x[1] == 0), 'b': user_id})
char_name = z[0] c.execute('''update user_char set is_uncapped_override = :a where user_id = :b and character_id = :c''', {
if y is not None: 'a': b2int(x[1] == 0), 'b': user_id, 'c': character_id})
r = { c.execute('''select * from user_char where user_id = :a and character_id = :b''',
"is_uncapped_override": int2b(y[14]), {'a': user_id, 'b': character_id})
"is_uncapped": int2b(y[13]), y = c.fetchone()
"uncap_cores": [], c.execute(
"char_type": y[12], '''select name from character where character_id = :x''', {'x': y[1]})
"skill_id_uncap": y[11], z = c.fetchone()
"skill_requires_uncap": int2b(y[10]), if z is not None:
"skill_unlock_level": y[9], char_name = z[0]
"skill_id": y[8], if y is not None:
"overdrive": y[7], r = {
"prog": y[6], "is_uncapped_override": int2b(y[14]),
"frag": y[5], "is_uncapped": int2b(y[13]),
"level_exp": y[4], "uncap_cores": [],
"exp": y[3], "char_type": y[12],
"level": y[2], "skill_id_uncap": y[11],
"name": char_name, "skill_requires_uncap": int2b(y[10]),
"character_id": y[1] "skill_unlock_level": y[9],
} "skill_id": y[8],
"overdrive": y[7],
"prog": y[6],
"frag": y[5],
"level_exp": y[4],
"exp": y[3],
"level": y[2],
"name": char_name,
"character_id": y[1]
}
conn.commit()
conn.close()
return r return r
def arc_sys_set(user_id, value, set_arg): def arc_sys_set(user_id, value, set_arg):
# 三个设置PTT隐藏、体力满通知、最爱角色无返回 # 三个设置PTT隐藏、体力满通知、最爱角色无返回
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() if 'favorite_character' in set_arg:
if 'favorite_character' in set_arg: value = int(value)
value = int(value) c.execute('''update user set favorite_character = :a where user_id = :b''', {
c.execute('''update user set favorite_character = :a where user_id = :b''', { 'a': value, 'b': user_id})
'a': value, 'b': user_id})
else:
if value == 'false':
value = False
else: else:
value = True if value == 'false':
value = False
else:
value = True
if 'is_hide_rating' in set_arg: if 'is_hide_rating' in set_arg:
c.execute('''update user set is_hide_rating = :a where user_id = :b''', { c.execute('''update user set is_hide_rating = :a where user_id = :b''', {
'a': b2int(value), 'b': user_id}) 'a': b2int(value), 'b': user_id})
if 'max_stamina_notification_enabled' in set_arg: if 'max_stamina_notification_enabled' in set_arg:
c.execute('''update user set max_stamina_notification_enabled = :a where user_id = :b''', { c.execute('''update user set max_stamina_notification_enabled = :a where user_id = :b''', {
'a': b2int(value), 'b': user_id}) 'a': b2int(value), 'b': user_id})
conn.commit()
conn.close()
return None return None
@@ -119,37 +111,32 @@ def arc_add_friend(user_id, friend_id):
# 加好友返回好友列表或者是错误码602、604 # 加好友返回好友列表或者是错误码602、604
if user_id == friend_id: if user_id == friend_id:
return 604 return 604
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
{'x': user_id, 'y': friend_id})
r = None r = None
if c.fetchone() == (0,): with Connect() as c:
c.execute('''insert into friend values(:a, :b)''', c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
{'a': user_id, 'b': friend_id}) {'x': user_id, 'y': friend_id})
r = server.info.get_user_friend(c, user_id) if c.fetchone() == (0,):
c.execute('''insert into friend values(:a, :b)''',
{'a': user_id, 'b': friend_id})
r = server.info.get_user_friend(c, user_id)
else:
r = 602
else:
return 602
conn.commit()
conn.close()
return r return r
def arc_delete_friend(user_id, friend_id): def arc_delete_friend(user_id, friend_id):
# 删好友,返回好友列表 # 删好友,返回好友列表
conn = sqlite3.connect('./database/arcaea_database.db')
c = conn.cursor()
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
{'x': user_id, 'y': friend_id})
r = None r = None
if c.fetchone() == (1,): with Connect() as c:
c.execute('''delete from friend where user_id_me = :x and user_id_other = :y''',
c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
{'x': user_id, 'y': friend_id}) {'x': user_id, 'y': friend_id})
if c.fetchone() == (1,):
c.execute('''delete from friend where user_id_me = :x and user_id_other = :y''',
{'x': user_id, 'y': friend_id})
r = server.info.get_user_friend(c, user_id) r = server.info.get_user_friend(c, user_id)
conn.commit()
conn.close()
return r return r

View File

@@ -0,0 +1,31 @@
import sqlite3
from flask import current_app
import traceback
class Connect():
# 数据库连接类,上下文管理
def __init__(self, file_path='./database/arcaea_database.db'):
"""
数据库连接默认连接arcaea_database.db
接受:文件路径
返回sqlite3连接操作对象
"""
self.file_path = file_path
def __enter__(self):
self.conn = sqlite3.connect(self.file_path)
self.c = self.conn.cursor()
return self.c
def __exit__(self, exc_type, exc_val, exc_tb):
if self.conn:
self.conn.commit()
self.conn.close()
if exc_type is not None:
current_app.logger.error(
traceback.format_exception(exc_type, exc_val, exc_tb))
return True

View File

@@ -1,7 +0,0 @@
[CONFIG]
HOST = 192.168.1.113
PORT = 80
[WEB]
USERNAME = admin
PASSWORD = admin

97
latest version/setting.py Normal file
View File

@@ -0,0 +1,97 @@
class Config():
'''
This is the setting file. You can change some parameters here.
'''
'''
--------------------
主机的地址和端口号
Host and port of your server
'''
HOST = '192.168.1.101'
PORT = '80'
'''
--------------------
'''
'''
--------------------
愚人节模式开关
Switch of April Fool's Day
'''
IS_APRILFOOLS = True
'''
--------------------
'''
'''
--------------------
Web后台管理页面的用户名和密码
Username and password of web background management page
'''
USERNAME = 'admin'
PASSWORD = 'admin'
'''
--------------------
'''
'''
--------------------
Web后台管理页面的session秘钥如果不知道是什么请不要修改
Session key of web background management page
If you don't know what it is, please don't modify it.
'''
SECRET_KEY = '1145141919810'
'''
--------------------
'''
'''
--------------------
玩家歌曲下载的24小时次数限制每个文件算一次
Player's song download limit times in 24 hours, once per file
'''
DOWNLOAD_TIMES_LIMIT = 3000
'''
歌曲下载链接的有效时长,单位:秒
Effective duration of song download link, unit: seconds
'''
DOWNLOAD_TIME_GAP_LIMIT = 1000
'''
--------------------
'''
'''
--------------------
Arcaea登录的最大允许设备数量最小值为1
The maximum number of devices allowed to log in Arcaea, minimum: 1
'''
LOGIN_DEVICE_NUMBER_LIMIT = 1
'''
是否允许同设备多应用共存登录
If logging in from multiple applications on the same device is allowed
'''
ALLOW_LOGIN_SAME_DEVICE = False
'''
--------------------
'''
'''
--------------------
是否记录详细的服务器日志
If recording detailed server logs is enabled
'''
ALLOW_LOG_INFO = False
'''
--------------------
'''
'''
--------------------
用户注册时的默认记忆源点数量
The default amount of memories at the time of user registration
'''
DEFAULT_MEMORIES = 0
'''
--------------------
'''

View File

@@ -11,6 +11,9 @@
<div class="name">{{user['name']}} <div class="name">{{user['name']}}
<span class="rank">UID: {{user['user_id']}}</span> <span class="rank">UID: {{user['user_id']}}</span>
<span class="rank">User code: {{user['user_code']}}</span> <span class="rank">User code: {{user['user_code']}}</span>
{% if user['ban_flag'] %}
<span class="rank">Banned</span>
{% endif %}
</div> </div>
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div> <div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
<div class="ptt">PTT: {{'%0.2f'|format(user['rating_ptt']/100|float)}}</div> <div class="ptt">PTT: {{'%0.2f'|format(user['rating_ptt']/100|float)}}</div>

View File

@@ -22,6 +22,9 @@
<div class="name">{{user['name']}} <div class="name">{{user['name']}}
<span class="rank">UID: {{user['user_id']}}</span> <span class="rank">UID: {{user['user_id']}}</span>
<span class="rank">User code: {{user['user_code']}}</span> <span class="rank">User code: {{user['user_code']}}</span>
{% if user['ban_flag'] %}
<span class="rank">Banned</span>
{% endif %}
</div> </div>
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div> <div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
<div class="ptt">Memories: {{user['ticket']}}</div> <div class="ptt">Memories: {{user['ticket']}}</div>

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,8 @@
from flask import (Blueprint, flash, g, redirect, from flask import (Blueprint, flash, g, redirect,
render_template, request, session, url_for) render_template, request, session, url_for)
import functools import functools
import configparser from setting import Config
import hashlib
bp = Blueprint('login', __name__, url_prefix='/web') bp = Blueprint('login', __name__, url_prefix='/web')
@@ -15,18 +16,16 @@ def login():
password = request.form['password'] password = request.form['password']
error = None error = None
config = configparser.ConfigParser() if username != Config.USERNAME or password != Config.PASSWORD:
path = r'setting.ini'
config.read(path, encoding="utf-8")
USERNAME = config.get('WEB', 'USERNAME')
PASSWORD = config.get('WEB', 'PASSWORD')
if username != USERNAME and password != PASSWORD:
error = '错误的用户名或密码 Incorrect username or password.' error = '错误的用户名或密码 Incorrect username or password.'
if error is None: if error is None:
session.clear() session.clear()
session['user_id'] = USERNAME + PASSWORD hash_session = username + \
hashlib.sha256(password.encode("utf8")).hexdigest()
hash_session = hashlib.sha256(
hash_session.encode("utf8")).hexdigest()
session['user_id'] = hash_session
return redirect(url_for('index.index')) return redirect(url_for('index.index'))
flash(error) flash(error)
@@ -48,16 +47,14 @@ def login_required(view):
def wrapped_view(**kwargs): def wrapped_view(**kwargs):
x = session.get('user_id') x = session.get('user_id')
config = configparser.ConfigParser() hash_session = Config.USERNAME + \
path = r'setting.ini' hashlib.sha256(Config.PASSWORD.encode("utf8")).hexdigest()
config.read(path, encoding="utf-8") hash_session = hashlib.sha256(hash_session.encode("utf8")).hexdigest()
USERNAME = config.get('WEB', 'USERNAME')
PASSWORD = config.get('WEB', 'PASSWORD')
if x != USERNAME + PASSWORD: if x != hash_session:
return redirect(url_for('login.login')) return redirect(url_for('login.login'))
g.user = {'user_id': x, 'username': USERNAME} g.user = {'user_id': x, 'username': Config.USERNAME}
return view(**kwargs) return view(**kwargs)
return wrapped_view return wrapped_view

View File

@@ -1,5 +1,5 @@
import os import os
import sqlite3 from server.sql import Connect
import time import time
import json import json
import server.arcscore import server.arcscore
@@ -179,46 +179,34 @@ def update_database():
# 对于arcaea_datebase.db更新一些表并用character数据更新user_char # 对于arcaea_datebase.db更新一些表并用character数据更新user_char
# 对于arcsong.db更新songs # 对于arcsong.db更新songs
if os.path.isfile("database/old_arcaea_database.db") and os.path.isfile("database/arcaea_database.db"): if os.path.isfile("database/old_arcaea_database.db") and os.path.isfile("database/arcaea_database.db"):
conn1 = sqlite3.connect('./database/old_arcaea_database.db') with Connect('./database/old_arcaea_database.db') as c1:
c1 = conn1.cursor() with Connect() as c2:
conn2 = sqlite3.connect('./database/arcaea_database.db')
c2 = conn2.cursor()
update_one_table(c1, c2, 'user') update_one_table(c1, c2, 'user')
update_one_table(c1, c2, 'friend') update_one_table(c1, c2, 'friend')
update_one_table(c1, c2, 'best_score') update_one_table(c1, c2, 'best_score')
update_one_table(c1, c2, 'recent30') update_one_table(c1, c2, 'recent30')
update_one_table(c1, c2, 'user_world') update_one_table(c1, c2, 'user_world')
update_one_table(c1, c2, 'item') update_one_table(c1, c2, 'item')
update_one_table(c1, c2, 'user_item') update_one_table(c1, c2, 'user_item')
update_one_table(c1, c2, 'user_save') update_one_table(c1, c2, 'user_save')
update_one_table(c1, c2, 'login') update_one_table(c1, c2, 'login')
update_one_table(c1, c2, 'present') update_one_table(c1, c2, 'present')
update_one_table(c1, c2, 'user_present') update_one_table(c1, c2, 'user_present')
update_one_table(c1, c2, 'redeem') update_one_table(c1, c2, 'redeem')
update_one_table(c1, c2, 'user_redeem') update_one_table(c1, c2, 'user_redeem')
update_user_char(c2) update_user_char(c2)
conn1.commit()
conn1.close()
conn2.commit()
conn2.close()
os.remove('database/old_arcaea_database.db') os.remove('database/old_arcaea_database.db')
# songs # songs
if os.path.isfile("database/old_arcsong.db") and os.path.isfile("database/arcsong.db"): if os.path.isfile("database/old_arcsong.db") and os.path.isfile("database/arcsong.db"):
conn1 = sqlite3.connect('./database/old_arcsong.db') with Connect('./database/old_arcsong.db') as c1:
c1 = conn1.cursor() with Connect('./database/arcsong.db') as c2:
conn2 = sqlite3.connect('./database/arcsong.db')
c2 = conn2.cursor()
update_one_table(c1, c2, 'songs') update_one_table(c1, c2, 'songs')
conn1.commit()
conn1.close()
conn2.commit()
conn2.close()
os.remove('database/old_arcsong.db') os.remove('database/old_arcsong.db')
@@ -257,34 +245,31 @@ def unlock_user_item(c, user_id):
def get_all_item(): def get_all_item():
# 所有购买数据查询 # 所有购买数据查询
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() c.execute('''select * from item''')
c.execute('''select * from item''') x = c.fetchall()
x = c.fetchall() re = []
re = [] if x:
if x: for i in x:
for i in x: discount_from = None
discount_from = None discount_to = None
discount_to = None
if i[5] and i[5] >= 0: if i[5] and i[5] >= 0:
discount_from = time.strftime( discount_from = time.strftime(
"%Y-%m-%d %H:%M:%S", time.localtime(int(i[5])/1000)) "%Y-%m-%d %H:%M:%S", time.localtime(int(i[5])/1000))
if i[6] and i[6] >= 0: if i[6] and i[6] >= 0:
discount_to = time.strftime( discount_to = time.strftime(
"%Y-%m-%d %H:%M:%S", time.localtime(int(i[6])//1000)) "%Y-%m-%d %H:%M:%S", time.localtime(int(i[6])//1000))
re.append({'item_id': i[0], re.append({'item_id': i[0],
'type': i[1], 'type': i[1],
'is_available': int2b(i[2]), 'is_available': int2b(i[2]),
'price': i[3], 'price': i[3],
'orig_price': i[4], 'orig_price': i[4],
'discount_from': discount_from, 'discount_from': discount_from,
'discount_to': discount_to 'discount_to': discount_to
}) })
conn.commit()
conn.close()
return re return re
@@ -346,19 +331,16 @@ def add_one_present(present_id, expire_ts, description, items):
# 添加一个奖励 # 添加一个奖励
message = None message = None
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() c.execute(
c.execute( '''select exists(select * from present where present_id=:a)''', {'a': present_id})
'''select exists(select * from present where present_id=:a)''', {'a': present_id}) if c.fetchone() == (0,):
if c.fetchone() == (0,): c.execute('''insert into present values(:a,:b,:c,:d)''', {
c.execute('''insert into present values(:a,:b,:c,:d)''', { 'a': present_id, 'b': expire_ts, 'c': items, 'd': description})
'a': present_id, 'b': expire_ts, 'c': items, 'd': description}) message = '添加成功 Successfully add it.'
message = '添加成功 Successfully add it.' else:
else: message = '奖励已存在 The present exists.'
message = '奖励已存在 The present exists.'
conn.commit()
conn.close()
return message return message
@@ -366,21 +348,18 @@ def delete_one_present(present_id):
# 删除一个奖励 # 删除一个奖励
message = None message = None
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() c.execute(
c.execute( '''select exists(select * from present where present_id=:a)''', {'a': present_id})
'''select exists(select * from present where present_id=:a)''', {'a': present_id}) if c.fetchone() == (1,):
if c.fetchone() == (1,): c.execute('''delete from present where present_id = :a''',
c.execute('''delete from present where present_id = :a''', {'a': present_id})
{'a': present_id}) c.execute('''delete from user_present where present_id =:a''', {
c.execute('''delete from user_present where present_id =:a''', { 'a': present_id})
'a': present_id}) message = '删除成功 Successfully delete it.'
message = '删除成功 Successfully delete it.' else:
else: message = '奖励不存在 The present does not exist.'
message = '奖励不存在 The present does not exist.'
conn.commit()
conn.close()
return message return message
@@ -423,19 +402,16 @@ def add_one_redeem(code, redeem_type, items):
# 添加一个兑换码 # 添加一个兑换码
message = None message = None
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() c.execute(
c.execute( '''select exists(select * from redeem where code=:a)''', {'a': code})
'''select exists(select * from redeem where code=:a)''', {'a': code}) if c.fetchone() == (0,):
if c.fetchone() == (0,): c.execute('''insert into redeem values(:a,:b,:c)''', {
c.execute('''insert into redeem values(:a,:b,:c)''', { 'a': code, 'b': items, 'c': redeem_type})
'a': code, 'b': items, 'c': redeem_type}) message = '添加成功 Successfully add it.'
message = '添加成功 Successfully add it.' else:
else: message = '兑换码已存在 The redeem code exists.'
message = '兑换码已存在 The redeem code exists.'
conn.commit()
conn.close()
return message return message
@@ -443,21 +419,19 @@ def add_some_random_redeem(amount, redeem_type, items):
# 随机生成一堆10位的兑换码 # 随机生成一堆10位的兑换码
message = None message = None
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() i = 1
i = 0 while i <= amount:
while i <= amount: code = random_str()
code = random_str() c.execute(
c.execute( '''select exists(select * from redeem where code=:a)''', {'a': code})
'''select exists(select * from redeem where code=:a)''', {'a': code}) if c.fetchone() == (0,):
if c.fetchone() == (0,): c.execute('''insert into redeem values(:a,:b,:c)''',
c.execute('''insert into redeem values(:a,:b,:c)''', {'a': code, 'b': items, 'c': redeem_type})
{'a': code, 'b': items, 'c': redeem_type}) i += 1
i += 1
message = '添加成功 Successfully add it.'
message = '添加成功 Successfully add it.'
conn.commit()
conn.close()
return message return message
@@ -465,19 +439,17 @@ def delete_one_redeem(code):
# 删除一个兑换码 # 删除一个兑换码
message = None message = None
conn = sqlite3.connect('./database/arcaea_database.db') with Connect() as c:
c = conn.cursor() c.execute(
c.execute( '''select exists(select * from redeem where code=:a)''', {'a': code})
'''select exists(select * from redeem where code=:a)''', {'a': code}) if c.fetchone() == (1,):
if c.fetchone() == (1,): c.execute('''delete from redeem where code = :a''', {'a': code})
c.execute('''delete from redeem where code = :a''', {'a': code}) c.execute(
c.execute('''delete from user_redeem where code =:a''', {'a': code}) '''delete from user_redeem where code =:a''', {'a': code})
message = '删除成功 Successfully delete it.' message = '删除成功 Successfully delete it.'
else: else:
message = '兑换码不存在 The redeem code does not exist.' message = '兑换码不存在 The redeem code does not exist.'
conn.commit()
conn.close()
return message return message

View File

@@ -49,6 +49,10 @@ def get_user(c, user_id):
if x[20]: if x[20]:
time_played = time.strftime('%Y-%m-%d %H:%M:%S', time_played = time.strftime('%Y-%m-%d %H:%M:%S',
time.localtime(int(x[20])//1000)) time.localtime(int(x[20])//1000))
if x[2] == '':
ban_flag = True
else:
ban_flag = False
r = {'name': x[1], r = {'name': x[1],
'user_id': user_id, 'user_id': user_id,
@@ -65,7 +69,8 @@ def get_user(c, user_id):
'time_played': time_played, 'time_played': time_played,
'clear_type': x[21], 'clear_type': x[21],
'rating': x[22], 'rating': x[22],
'ticket': x[26] 'ticket': x[26],
'ban_flag': ban_flag
} }
return r return r