mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2025-12-14 08:06:23 +08:00
Update to v1.6
This commit is contained in:
15
README.md
15
README.md
@@ -20,7 +20,8 @@ This is a small local Arcaea server based on Python and Flask, which can simulat
|
||||
- 自定义歌曲下载 Customizable songs download
|
||||
- 全角色立绘 All character drawings
|
||||
- 角色技能 Character skills
|
||||
- 全剧情解锁 Unlock all the storys
|
||||
- 自定义角色属性 Customizable characters attributes
|
||||
- 全剧情解锁 Unlock all the stories
|
||||
- 后台查分 Background search scores
|
||||
- 后台自定义歌曲定数 Customize chart consts in the background
|
||||
- 成绩校验 Score check
|
||||
@@ -29,6 +30,7 @@ This is a small local Arcaea server based on Python and Flask, which can simulat
|
||||
- 角色数值 Character characteristic value
|
||||
- 购买 Purchase
|
||||
- 歌曲解锁、曲包解锁 Songs unlocking and music packs unlocking
|
||||
- 数据同步的时间和设备记录 The record of time and device for data synchronization
|
||||
- 服务器安全性保证 Server security assurance
|
||||
|
||||
可能有问题 There may be problems:
|
||||
@@ -51,10 +53,13 @@ It is just so interesting. What it can do is under exploration.
|
||||
>
|
||||
> Tips: When updating, please keep the original database in case of data loss.
|
||||
|
||||
### Version 1.5
|
||||
- 仍然适用于Arcaea 3.2.2版本 Still for Arcaea 3.2.2
|
||||
- 新增了角色技能 Add character skills.
|
||||
- 新增了分数校验系统 Add score check system.
|
||||
### Version 1.6
|
||||
- 适用于Arcaea 3.2.3版本 For Arcaea 3.2.3
|
||||
- 更新了歌曲数据库 Update the song database.
|
||||
- 新增了自定义角色属性 Add customizable characters attributes.
|
||||
- 用户的记忆源点可以修改了,但仍然没有实际用途 The users' memories can be modified, but still is of no practical use.
|
||||
- 网页端安全性增强,用户名及密码可修改 The security of webpage is enhanced, and the username and password can be modified now.
|
||||
- 改进了数据库更新方式,可以一定程度上应对数据表结构修改 The method of database updating is improved, which can deal with the modification of data table structure to some extent.
|
||||
|
||||
## 运行环境与依赖 Running environment and requirements
|
||||
- Windows操作系统 Windows operating system
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -31,7 +31,8 @@ clear_type int,
|
||||
rating real,
|
||||
favorite_character int,
|
||||
max_stamina_notification_enabled int,
|
||||
current_map text
|
||||
current_map text,
|
||||
ticket int
|
||||
);''')
|
||||
c.execute('''create table if not exists login(access_token text,
|
||||
user_id int,
|
||||
@@ -243,8 +244,8 @@ def arc_register(name: str, password: str):
|
||||
user_id = build_user_id(c)
|
||||
now = int(time.time() * 1000)
|
||||
c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt,
|
||||
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map)
|
||||
values(:user_id, :name, :password, :join_date, :user_code, 1250, 1, 0, 1, 0, 0, -1, 0, '')
|
||||
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket)
|
||||
values(:user_id, :name, :password, :join_date, :user_code, 1250, 1, 0, 1, 0, 0, -1, 0, '', 114514)
|
||||
''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd})
|
||||
c.execute('''insert into recent30(user_id) values(:user_id)''', {
|
||||
'user_id': user_id})
|
||||
|
||||
@@ -81,8 +81,8 @@ def arc_register(name: str, password: str): # 注册
|
||||
user_id = build_user_id(c)
|
||||
now = int(time.time() * 1000)
|
||||
c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt,
|
||||
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map)
|
||||
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '')
|
||||
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket)
|
||||
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '', 114514)
|
||||
''', {'user_code': user_code, 'user_id': user_id, 'join_date': now, 'name': name, 'password': hash_pwd})
|
||||
c.execute('''insert into recent30(user_id) values(:user_id)''', {
|
||||
'user_id': user_id})
|
||||
|
||||
@@ -139,7 +139,7 @@ def get_value_0(c, user_id):
|
||||
"name": x[1],
|
||||
"user_code": x[4],
|
||||
"display_name": x[1],
|
||||
"ticket": 114514,
|
||||
"ticket": x[26],
|
||||
"character": x[6],
|
||||
"is_locked_name_duplicate": False,
|
||||
"is_skill_sealed": int2b(x[7]),
|
||||
@@ -149,8 +149,8 @@ def get_value_0(c, user_id):
|
||||
"max_stamina_ts": 1586274871917,
|
||||
"stamina": 12,
|
||||
"world_unlocks": [],
|
||||
"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"],
|
||||
"singles": ["dataerror", "yourvoiceso", "crosssoul", "impurebird", "auxesia", "modelista", "yozakurafubuki", "surrender", "metallicpunisher", "carminescythe", "bethere", "callmyname", "fallensquare", "dropdead", "alexandrite", "astraltale", "phantasia", "empireofwinter", "libertas", "dottodot", "dreadnought", "mirzam", "heavenlycaress", "filament", "avantraze", "battlenoone", "saikyostronger", "izana", "einherjar", "laqryma", "amygdata", "altale", "feelssoright", "scarletcage", "teriqma", "mahoroba", "badtek", "maliciousmischance", "buchigireberserker", "galaxyfriends", "buchigireberserker2", "xeraphinite"],
|
||||
"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"],
|
||||
"singles": ["dataerror", "yourvoiceso", "crosssoul", "impurebird", "auxesia", "modelista", "yozakurafubuki", "surrender", "metallicpunisher", "carminescythe", "bethere", "callmyname", "fallensquare", "dropdead", "alexandrite", "astraltale", "phantasia", "empireofwinter", "libertas", "dottodot", "dreadnought", "mirzam", "heavenlycaress", "filament", "avantraze", "battlenoone", "saikyostronger", "izana", "einherjar", "laqryma", "amygdata", "altale", "feelssoright", "scarletcage", "teriqma", "mahoroba", "badtek", "maliciousmischance", "buchigireberserker", "galaxyfriends", "buchigireberserker2", "xeraphinite", "xanatos"],
|
||||
"packs": ["vs", "extend", "dynamix", "prelude", "core", "yugamu", "omatsuri", "zettai", "mirai", "shiawase", "chunithm", "nijuusei", "groovecoaster", "rei", "tonesphere", "lanota"],
|
||||
"characters": characters,
|
||||
"cores": [],
|
||||
@@ -180,7 +180,6 @@ def arc_aggregate_small(user_id):
|
||||
|
||||
def arc_aggregate_big(user_id):
|
||||
# 返回用户数据和地图歌曲信息
|
||||
# 因为没有整理地图和曲包数据(不需要世界模式),所以直接复制了
|
||||
|
||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||
c = conn.cursor()
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
[CONFIG]
|
||||
HOST = 192.168.1.113
|
||||
PORT = 80
|
||||
PORT = 80
|
||||
|
||||
[WEB]
|
||||
USERNAME = admin
|
||||
PASSWORD = admin
|
||||
@@ -210,8 +210,28 @@ input[type=submit] {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.footer{
|
||||
.footer {
|
||||
font-size: 0.5em;
|
||||
color: grey;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.char-item {
|
||||
margin-bottom: 10px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.char-name {
|
||||
font-size: 1.3em;
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.char-id {
|
||||
font-size: 1em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.char-num {
|
||||
font-size: 1em;
|
||||
}
|
||||
59
latest version/templates/web/allchar.html
Normal file
59
latest version/templates/web/allchar.html
Normal file
@@ -0,0 +1,59 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block header %}
|
||||
<h1>{% block title %}All characters{% endblock %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if posts %}<br />
|
||||
{% for char in posts %}
|
||||
|
||||
<div class="char-item">
|
||||
<span>Id: </span>
|
||||
<span class="char-id">{{char['character_id']}}</span>
|
||||
<br />
|
||||
|
||||
<span>Name: </span>
|
||||
<span class="char-name">{{char['name']}}</span>
|
||||
<br />
|
||||
|
||||
<span>Level: </span>
|
||||
<span class="char-num">{{char['level']}}</span>
|
||||
<br />
|
||||
|
||||
<span>Frag: </span>
|
||||
<span class="char-num">{{char['frag']}}</span>
|
||||
<br />
|
||||
|
||||
<span>Prog: </span>
|
||||
<span class="char-num">{{char['prog']}}</span>
|
||||
<br />
|
||||
|
||||
<span>Overdrive: </span>
|
||||
<span class="char-num">{{char['overdrive']}}</span>
|
||||
<br />
|
||||
|
||||
<span>Skill id: </span>
|
||||
<span class="char-num">{{char['skill_id']}}</span>
|
||||
<br />
|
||||
|
||||
<span>Uncapped skill id: </span>
|
||||
<span class="char-num">{{char['skill_id_uncap']}}</span>
|
||||
<br />
|
||||
|
||||
<span>Is uncapped: </span>
|
||||
<span class="char-num">{{char['is_uncapped']}}</span>
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
{% if not loop.last %}
|
||||
<br />
|
||||
<hr />
|
||||
<br />
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -14,6 +14,7 @@
|
||||
</div>
|
||||
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
|
||||
<div class="ptt">PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}</div>
|
||||
<div class="ptt">Memories: {{user['ticket']}}</div>
|
||||
<div>
|
||||
<div>Recent plays: </div>
|
||||
<div>
|
||||
|
||||
55
latest version/templates/web/changechar.html
Normal file
55
latest version/templates/web/changechar.html
Normal file
@@ -0,0 +1,55 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block header %}
|
||||
<h1>{% block title %}Change the characters{% endblock %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form action="/web/changesong/editchar" method="post">
|
||||
<div class="title">Edit the character</div>
|
||||
<label for="id">ID of the character</label>
|
||||
<input name="id" id="sid" required>
|
||||
|
||||
<label for="level">Level</label>
|
||||
<input name="level" id="level">
|
||||
|
||||
<label for="frag">Frag</label>
|
||||
<input name="frag" id="frag">
|
||||
|
||||
<label for="prog">Prog</label>
|
||||
<input name="prog" id="prog">
|
||||
|
||||
<label for="overdrive">Overdrive</label>
|
||||
<input name="overdrive" id="overdrive">
|
||||
|
||||
<div>
|
||||
<select name="skill_id">
|
||||
<option value="">Skill id</option>
|
||||
{% for skill_id in skill_ids %}
|
||||
<option value={{ skill_id }}>{{ skill_id }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<select name="skill_id_uncap">
|
||||
<option value="">Uncapped skill id</option>
|
||||
{% for skill_id in skill_ids %}
|
||||
<option value={{ skill_id }}>{{ skill_id }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<br />
|
||||
<div class="content">如果某些不需要修改,留空即可</div>
|
||||
<div class="content">If some things do not need to be modified, leave it blank.</div>
|
||||
<div class="content">更新时角色数据表不会同步</div>
|
||||
<div class="content">The character table will not be synchronized when updated.</div>
|
||||
<input type="submit" value="Edit">
|
||||
</form>
|
||||
<br />
|
||||
<hr />
|
||||
<form action="/web/changesong/updatechar" method="post">
|
||||
<div class="title">Update the character</div>
|
||||
<div class="content">更新所有用户拥有的角色</div>
|
||||
<div class="content">Update all users' characters.</div>
|
||||
<input type="submit" value="Update">
|
||||
</form>
|
||||
{% endblock %}
|
||||
28
latest version/templates/web/changeuser.html
Normal file
28
latest version/templates/web/changeuser.html
Normal file
@@ -0,0 +1,28 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block header %}
|
||||
<h1>{% block title %}Change user information{% endblock %}</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form action="/web/changeuser/edituser" method="post">
|
||||
<div class="title">Edit the user</div>
|
||||
<label for="name">Arcaea Username</label>
|
||||
<input name="name" id="name">
|
||||
or<br />
|
||||
<label for="user_code">Arcaea User Code</label>
|
||||
<input name="user_code" id="user_code">
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<label for="ticket">Memories</label>
|
||||
<input name="ticket" id="ticket">
|
||||
|
||||
|
||||
<br />
|
||||
<div class="content">如果某些不需要修改,留空即可</div>
|
||||
<div class="content">If some things do not need to be modified, leave it blank.</div>
|
||||
<div class="content">目前只支持修改记忆源点</div>
|
||||
<div class="content">At present, only memories can be modified.</div>
|
||||
<input type="submit" value="Edit">
|
||||
</form>
|
||||
{% endblock %}
|
||||
@@ -14,11 +14,14 @@
|
||||
<a href="{{ url_for('index.single_player_ptt') }}">单个玩家PTT详情查询 Single player ptt</a></br></br>
|
||||
<a href="{{ url_for('index.all_player') }}">所有玩家信息查询 All players</a></br></br>
|
||||
<a href="{{ url_for('index.all_song') }}">铺面信息查询 All songs</a></br></br>
|
||||
<a href="{{ url_for('index.all_character') }}">角色信息查询 All characters</a></br></br>
|
||||
<a href="{{ url_for('index.single_chart_top') }}">单个铺面排行榜查询 Single song chart tops</a>
|
||||
<hr>
|
||||
<h1>系统方面 System</h1>
|
||||
<a href="{{ url_for('index.update_database') }}">数据库更新 Update databases</a></br></br>
|
||||
<a href="{{ url_for('index.change_song') }}">歌曲修改 Change the songs</a>
|
||||
<a href="{{ url_for('index.change_song') }}">歌曲修改 Change the songs</a></br></br>
|
||||
<a href="{{ url_for('index.change_character') }}">角色修改 Change the characters</a></br></br>
|
||||
<a href="{{ url_for('index.change_user') }}">用户信息修改 Change user information</a>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
@@ -24,6 +24,7 @@
|
||||
<span class="rank">User code: {{user['user_code']}}</span>
|
||||
</div>
|
||||
<div class="join-date">注册于 Registered in: {{user['join_date']}}</div>
|
||||
<div class="ptt">Memories: {{user['ticket']}}</div>
|
||||
<div class="ptt">PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}</div>
|
||||
<div class="ptt">Best 30 PTT: {{bestptt}}</div>
|
||||
<div class="ptt">Recent 10 PTT: {{recentptt}}</div>
|
||||
|
||||
@@ -157,7 +157,8 @@ def all_player():
|
||||
'miss_count': i[17],
|
||||
'time_played': time_played,
|
||||
'clear_type': i[21],
|
||||
'rating': i[22]
|
||||
'rating': i[22],
|
||||
'ticket': i[26]
|
||||
})
|
||||
else:
|
||||
error = '没有玩家数据 No player data.'
|
||||
@@ -358,3 +359,213 @@ def delete_song():
|
||||
flash(error)
|
||||
|
||||
return redirect(url_for('index.change_song'))
|
||||
|
||||
|
||||
@bp.route('/allchar', methods=['GET'])
|
||||
@login_required
|
||||
def all_character():
|
||||
# 所有角色数据
|
||||
|
||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||
c = conn.cursor()
|
||||
c.execute('''select * from character''')
|
||||
x = c.fetchall()
|
||||
error = None
|
||||
if x:
|
||||
posts = []
|
||||
for i in x:
|
||||
posts.append({'character_id': i[0],
|
||||
'name': i[1],
|
||||
'level': i[2],
|
||||
'frag': i[5],
|
||||
'prog': i[6],
|
||||
'overdrive': i[7],
|
||||
'skill_id': i[8],
|
||||
'skill_id_uncap': i[11],
|
||||
'char_type': i[12],
|
||||
'is_uncapped': i[14] == 1
|
||||
})
|
||||
else:
|
||||
error = '没有角色数据 No character data.'
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
if error:
|
||||
flash(error)
|
||||
return render_template('web/allchar.html')
|
||||
else:
|
||||
return render_template('web/allchar.html', posts=posts)
|
||||
|
||||
|
||||
@bp.route('/changechar', methods=['GET'])
|
||||
@login_required
|
||||
def change_character():
|
||||
# 修改角色数据
|
||||
skill_ids = ['No_skill', 'gauge_easy', 'note_mirror', 'gauge_hard', 'frag_plus_10_pack_stellights', 'gauge_easy|frag_plus_15_pst&prs', 'gauge_hard|fail_frag_minus_100', 'frag_plus_5_side_light', 'visual_hide_hp', 'frag_plus_5_side_conflict', 'challenge_fullcombo_0gauge', 'gauge_overflow', 'gauge_easy|note_mirror', 'note_mirror', 'visual_tomato_pack_tonesphere',
|
||||
'frag_rng_ayu', 'gaugestart_30|gaugegain_70', 'combo_100-frag_1', 'audio_gcemptyhit_pack_groovecoaster', 'gauge_saya', 'gauge_chuni', 'kantandeshou', 'gauge_haruna', 'frags_nono', 'gauge_pandora', 'gauge_regulus', 'omatsuri_daynight', 'sometimes(note_mirror|frag_plus_5)', 'scoreclear_aa|visual_scoregauge', 'gauge_tempest', 'gauge_hard', 'gauge_ilith_summer', 'frags_kou', 'visual_ink', 'shirabe_entry_fee', 'frags_yume']
|
||||
return render_template('web/changechar.html', skill_ids=skill_ids)
|
||||
|
||||
|
||||
@bp.route('/changesong/editchar', methods=['POST'])
|
||||
@login_required
|
||||
def edit_char():
|
||||
# 修改角色数据
|
||||
|
||||
error = None
|
||||
|
||||
try:
|
||||
character_id = int(request.form['id'])
|
||||
level = request.form['level']
|
||||
frag = request.form['frag']
|
||||
prog = request.form['prog']
|
||||
overdrive = request.form['overdrive']
|
||||
skill_id = request.form['skill_id']
|
||||
skill_id_uncap = request.form['skill_id_uncap']
|
||||
if level:
|
||||
level = int(level)
|
||||
else:
|
||||
level = None
|
||||
if frag:
|
||||
frag = float(frag)
|
||||
else:
|
||||
frag = None
|
||||
if prog:
|
||||
prog = float(prog)
|
||||
else:
|
||||
prog = None
|
||||
if overdrive:
|
||||
overdrive = float(overdrive)
|
||||
else:
|
||||
overdrive = None
|
||||
except:
|
||||
error = '数据错误 Wrong data.'
|
||||
flash(error)
|
||||
return redirect(url_for('index.change_character'))
|
||||
|
||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||
c = conn.cursor()
|
||||
c.execute(
|
||||
'''select exists(select * from character where character_id=:a)''', {'a': character_id})
|
||||
if c.fetchone() == (1,):
|
||||
if not level and not frag and not prog and not overdrive and not skill_id and not skill_id_uncap:
|
||||
error = '无修改 No change.'
|
||||
else:
|
||||
|
||||
sql = '''update character set level_exp=25000'''
|
||||
sql_dict = {'character_id': character_id}
|
||||
if level:
|
||||
sql += ', level = :level'
|
||||
sql_dict['level'] = level
|
||||
if frag:
|
||||
sql += ', frag = :frag'
|
||||
sql_dict['frag'] = frag
|
||||
if prog:
|
||||
sql += ', prog = :prog'
|
||||
sql_dict['prog'] = prog
|
||||
if overdrive:
|
||||
sql += ', overdrive = :overdrive'
|
||||
sql_dict['overdrive'] = overdrive
|
||||
if skill_id:
|
||||
sql += ', skill_id = :skill_id'
|
||||
if skill_id == 'No_skill':
|
||||
sql_dict['skill_id'] = ''
|
||||
else:
|
||||
sql_dict['skill_id'] = skill_id
|
||||
if skill_id_uncap:
|
||||
sql += ', skill_id_uncap = :skill_id_uncap'
|
||||
if skill_id_uncap == 'No_skill':
|
||||
sql_dict['skill_id_uncap'] = ''
|
||||
else:
|
||||
sql_dict['skill_id_uncap'] = skill_id_uncap
|
||||
sql += ' where character_id = :character_id'
|
||||
c.execute(sql, sql_dict)
|
||||
flash('角色修改成功 Successfully edit the character.')
|
||||
else:
|
||||
error = '角色不存在 The character does not exist.'
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
if error:
|
||||
flash(error)
|
||||
|
||||
return redirect(url_for('index.change_character'))
|
||||
|
||||
|
||||
@bp.route('/changesong/updatechar', methods=['POST'])
|
||||
@login_required
|
||||
def update_character():
|
||||
# 更新角色数据
|
||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||
c = conn.cursor()
|
||||
web.system.update_user_char(c)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
flash('数据更新成功 Success update data.')
|
||||
return redirect(url_for('index.change_character'))
|
||||
|
||||
|
||||
@bp.route('/changeuser', methods=['GET'])
|
||||
@login_required
|
||||
def change_user():
|
||||
# 修改用户信息
|
||||
|
||||
return render_template('web/changeuser.html')
|
||||
|
||||
|
||||
@bp.route('/changeuser/edituser', methods=['POST'])
|
||||
@login_required
|
||||
def edit_user():
|
||||
# 修改用户数据
|
||||
|
||||
error = None
|
||||
name = request.form['name']
|
||||
user_code = request.form['user_code']
|
||||
|
||||
if name or user_code:
|
||||
conn = sqlite3.connect('./database/arcaea_database.db')
|
||||
c = conn.cursor()
|
||||
if user_code:
|
||||
c.execute('''select user_id from user where user_code=:a''', {
|
||||
'a': user_code})
|
||||
else:
|
||||
c.execute(
|
||||
'''select user_id from user where name=:a''', {'a': name})
|
||||
|
||||
user_id = c.fetchone()
|
||||
posts = []
|
||||
if user_id:
|
||||
user_id = user_id[0]
|
||||
try:
|
||||
ticket = request.form['ticket']
|
||||
if ticket:
|
||||
ticket = int(ticket)
|
||||
else:
|
||||
ticket = None
|
||||
except:
|
||||
error = '数据错误 Wrong data.'
|
||||
flash(error)
|
||||
return redirect(url_for('index.change_user'))
|
||||
|
||||
if not ticket:
|
||||
error = '无修改 No change.'
|
||||
else:
|
||||
sql = '''update user set ticket = :ticket where user_id = :user_id'''
|
||||
sql_dict = {'ticket': ticket, 'user_id': user_id}
|
||||
c.execute(sql, sql_dict)
|
||||
flash('用户信息修改成功 Successfully edit the user information.')
|
||||
|
||||
else:
|
||||
error = '玩家不存在 The player does not exist.'
|
||||
|
||||
else:
|
||||
error = '输入为空 Null Input.'
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
if error:
|
||||
flash(error)
|
||||
|
||||
return redirect(url_for('index.change_user'))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
from flask import (Blueprint, flash, g, redirect,
|
||||
render_template, request, session, url_for)
|
||||
import functools
|
||||
import configparser
|
||||
|
||||
bp = Blueprint('login', __name__, url_prefix='/web')
|
||||
|
||||
@@ -14,12 +15,18 @@ def login():
|
||||
password = request.form['password']
|
||||
error = None
|
||||
|
||||
if username != 'admin' and password != 'admin':
|
||||
config = configparser.ConfigParser()
|
||||
path = r'setting.ini'
|
||||
config.read(path, encoding="utf-8")
|
||||
USERNAME = config.get('WEB', 'USERNAME')
|
||||
PASSWORD = config.get('WEB', 'PASSWORD')
|
||||
|
||||
if username != USERNAME and password != PASSWORD:
|
||||
error = '错误的用户名或密码 Incorrect username or password.'
|
||||
|
||||
if error is None:
|
||||
session.clear()
|
||||
session['user_id'] = 'admin'
|
||||
session['user_id'] = USERNAME + PASSWORD
|
||||
return redirect(url_for('index.index'))
|
||||
|
||||
flash(error)
|
||||
@@ -40,11 +47,17 @@ def login_required(view):
|
||||
@functools.wraps(view)
|
||||
def wrapped_view(**kwargs):
|
||||
x = session.get('user_id')
|
||||
# 少用户存在验证
|
||||
if x is None:
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
path = r'setting.ini'
|
||||
config.read(path, encoding="utf-8")
|
||||
USERNAME = config.get('WEB', 'USERNAME')
|
||||
PASSWORD = config.get('WEB', 'PASSWORD')
|
||||
|
||||
if x != USERNAME + PASSWORD:
|
||||
return redirect(url_for('login.login'))
|
||||
|
||||
g.user = {'user_id': x, 'username': 'admin'}
|
||||
g.user = {'user_id': x, 'username': USERNAME}
|
||||
return view(**kwargs)
|
||||
|
||||
return wrapped_view
|
||||
|
||||
@@ -2,6 +2,111 @@ import os
|
||||
import sqlite3
|
||||
|
||||
|
||||
def get_table_info(c, table_name):
|
||||
# 得到表结构,返回主键列表和字段名列表
|
||||
pk = []
|
||||
name = []
|
||||
|
||||
c.execute('''pragma table_info ("'''+table_name+'''")''')
|
||||
x = c.fetchall()
|
||||
if x:
|
||||
for i in x:
|
||||
name.append(i[1])
|
||||
if i[5] != 0:
|
||||
pk.append(i[1])
|
||||
|
||||
return pk, name
|
||||
|
||||
|
||||
def get_sql_select_table(table_name, get_field, where_field=[], where_value=[]):
|
||||
# sql语句拼接,select ... from ... where ...
|
||||
sql = 'select '
|
||||
sql_dict = {}
|
||||
if len(get_field) >= 2:
|
||||
sql += get_field[0]
|
||||
for i in range(1, len(get_field)):
|
||||
sql += ',' + get_field[i]
|
||||
sql += ' from ' + table_name
|
||||
elif len(get_field) == 1:
|
||||
sql += get_field[0] + ' from ' + table_name
|
||||
else:
|
||||
sql += '* from ' + table_name
|
||||
|
||||
if where_field and where_value:
|
||||
sql += ' where '
|
||||
sql += where_field[0] + '=:' + where_field[0]
|
||||
sql_dict[where_field[0]] = where_value[0]
|
||||
if len(where_field) >= 1:
|
||||
for i in range(1, len(where_field)):
|
||||
sql_dict[where_field[i]] = where_value[i]
|
||||
sql += ' and ' + where_field[i] + '=:' + where_field[i]
|
||||
|
||||
sql += ' order by rowid'
|
||||
return sql, sql_dict
|
||||
|
||||
|
||||
def get_sql_insert_table(table_name, field, value):
|
||||
# sql语句拼接,insert into ...(...) values(...)
|
||||
sql = 'insert into ' + table_name + '('
|
||||
sql_dict = {}
|
||||
sql2 = ''
|
||||
if len(field) >= 2:
|
||||
sql += field[0]
|
||||
sql2 += ':' + field[0]
|
||||
sql_dict[field[0]] = value[0]
|
||||
for i in range(1, len(field)):
|
||||
sql += ',' + field[i]
|
||||
sql2 += ', :' + field[i]
|
||||
sql_dict[field[i]] = value[i]
|
||||
|
||||
sql += ') values('
|
||||
|
||||
elif len(field) == 1:
|
||||
sql += field[0] + ') values('
|
||||
sql2 += ':' + field[0]
|
||||
sql_dict[field[0]] = value[0]
|
||||
|
||||
else:
|
||||
return 'error', {}
|
||||
|
||||
sql += sql2 + ')'
|
||||
|
||||
return sql, sql_dict
|
||||
|
||||
|
||||
def update_one_table(c1, c2, table_name):
|
||||
# 从c1向c2更新数据表,c2中存在的信息不变
|
||||
db1_pk, db1_name = get_table_info(c1, table_name)
|
||||
db2_pk, db2_name = get_table_info(c2, table_name)
|
||||
if db1_pk != db2_pk:
|
||||
return 'error'
|
||||
|
||||
field = []
|
||||
for i in db1_name:
|
||||
if i in db2_name:
|
||||
field.append(i)
|
||||
|
||||
sql, sql_dict = get_sql_select_table(table_name, db1_pk)
|
||||
c1.execute(sql)
|
||||
x = c1.fetchall()
|
||||
sql, sql_dict = get_sql_select_table(table_name, field)
|
||||
c1.execute(sql)
|
||||
y = c1.fetchall()
|
||||
if x:
|
||||
for i in range(0, len(x)):
|
||||
sql, sql_dict = get_sql_select_table(
|
||||
table_name, [], db1_pk, list(x[i]))
|
||||
sql = 'select exists(' + sql + ')'
|
||||
c2.execute(sql, sql_dict)
|
||||
|
||||
if c2.fetchone() == (0,):
|
||||
sql, sql_dict = get_sql_insert_table(
|
||||
table_name, field, list(y[i]))
|
||||
c2.execute(sql, sql_dict)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def update_user_char(c):
|
||||
# 用character数据更新user_char
|
||||
c.execute('''select * from character''')
|
||||
@@ -27,62 +132,14 @@ def update_database():
|
||||
conn2 = sqlite3.connect('./database/arcaea_database.db')
|
||||
c2 = conn2.cursor()
|
||||
|
||||
# user
|
||||
c1.execute('''select * from user''')
|
||||
x = c1.fetchall()
|
||||
if x:
|
||||
for i in x:
|
||||
c2.execute(
|
||||
'''select exists(select * from user where user_id=:a)''', {'a': i[0]})
|
||||
if c2.fetchone() == (0,):
|
||||
c2.execute('''insert into user values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25)''', {
|
||||
'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25]})
|
||||
|
||||
# friend
|
||||
c1.execute('''select * from friend''')
|
||||
x = c1.fetchall()
|
||||
if x:
|
||||
for i in x:
|
||||
c2.execute(
|
||||
'''select exists(select * from friend where user_id_me=:a and user_id_other=:b)''', {'a': i[0], 'b': i[1]})
|
||||
if c2.fetchone() == (0,):
|
||||
c2.execute('''insert into friend values(:a,:b)''', {
|
||||
'a': i[0], 'b': i[1]})
|
||||
|
||||
# best_score
|
||||
c1.execute('''select * from best_score''')
|
||||
x = c1.fetchall()
|
||||
if x:
|
||||
for i in x:
|
||||
c2.execute('''select exists(select * from best_score where user_id=:a and song_id=:b and difficulty=:c)''', {
|
||||
'a': i[0], 'b': i[1], 'c': i[2]})
|
||||
if c2.fetchone() == (0,):
|
||||
c2.execute('''insert into best_score values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13)''', {
|
||||
'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13]})
|
||||
|
||||
# recent30
|
||||
c1.execute('''select * from recent30''')
|
||||
x = c1.fetchall()
|
||||
if x:
|
||||
for i in x:
|
||||
c2.execute(
|
||||
'''select exists(select * from recent30 where user_id=:a)''', {'a': i[0]})
|
||||
if c2.fetchone() == (0,):
|
||||
c2.execute('''insert into recent30 values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27,:a28,:a29,:a30,:a31,:a32,:a33,:a34,:a35,:a36,:a37,:a38,:a39,:a40,:a41,:a42,:a43,:a44,:a45,:a46,:a47,:a48,:a49,:a50,:a51,:a52,:a53,:a54,:a55,:a56,:a57,:a58,:a59,:a60)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[
|
||||
18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27], 'a28': i[28], 'a29': i[29], 'a30': i[30], 'a31': i[31], 'a32': i[32], 'a33': i[33], 'a34': i[34], 'a35': i[35], 'a36': i[36], 'a37': i[37], 'a38': i[38], 'a39': i[39], 'a40': i[40], 'a41': i[41], 'a42': i[42], 'a43': i[43], 'a44': i[44], 'a45': i[45], 'a46': i[46], 'a47': i[47], 'a48': i[48], 'a49': i[49], 'a50': i[50], 'a51': i[51], 'a52': i[52], 'a53': i[53], 'a54': i[54], 'a55': i[55], 'a56': i[56], 'a57': i[57], 'a58': i[58], 'a59': i[59], 'a60': i[60]})
|
||||
|
||||
# user_world
|
||||
c1.execute('''select * from user_world''')
|
||||
x = c1.fetchall()
|
||||
if x:
|
||||
for i in x:
|
||||
c2.execute(
|
||||
'''select exists(select * from user_world where user_id=:a and map_id=:b)''', {'a': i[0], 'b': i[1]})
|
||||
if c2.fetchone() == (0,):
|
||||
c2.execute('''insert into user_world values(:a0,:a1,:a2,:a3,:a4)''', {
|
||||
'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4]})
|
||||
update_one_table(c1, c2, 'user')
|
||||
update_one_table(c1, c2, 'friend')
|
||||
update_one_table(c1, c2, 'best_score')
|
||||
update_one_table(c1, c2, 'recent30')
|
||||
update_one_table(c1, c2, 'user_world')
|
||||
|
||||
update_user_char(c2)
|
||||
|
||||
conn1.commit()
|
||||
conn1.close()
|
||||
conn2.commit()
|
||||
@@ -96,15 +153,7 @@ def update_database():
|
||||
conn2 = sqlite3.connect('./database/arcsong.db')
|
||||
c2 = conn2.cursor()
|
||||
|
||||
c1.execute('''select * from songs''')
|
||||
x = c1.fetchall()
|
||||
if x:
|
||||
for i in x:
|
||||
c2.execute(
|
||||
'''select exists(select * from songs where sid=:a)''', {'a': i[0]})
|
||||
if c2.fetchone() == (0,):
|
||||
c2.execute('''insert into songs values(:a0,:a1,:a2,:a3,:a4,:a5,:a6,:a7,:a8,:a9,:a10,:a11,:a12,:a13,:a14,:a15,:a16,:a17,:a18,:a19,:a20,:a21,:a22,:a23,:a24,:a25,:a26,:a27)''', {'a0': i[0], 'a1': i[1], 'a2': i[2], 'a3': i[3], 'a4': i[4], 'a5': i[5], 'a6': i[6], 'a7': i[7], 'a8': i[
|
||||
8], 'a9': i[9], 'a10': i[10], 'a11': i[11], 'a12': i[12], 'a13': i[13], 'a14': i[14], 'a15': i[15], 'a16': i[16], 'a17': i[17], 'a18': i[18], 'a19': i[19], 'a20': i[20], 'a21': i[21], 'a22': i[22], 'a23': i[23], 'a24': i[24], 'a25': i[25], 'a26': i[26], 'a27': i[27]})
|
||||
update_one_table(c1, c2, 'songs')
|
||||
|
||||
conn1.commit()
|
||||
conn1.close()
|
||||
|
||||
@@ -64,7 +64,8 @@ def get_user(c, user_id):
|
||||
'miss_count': x[17],
|
||||
'time_played': time_played,
|
||||
'clear_type': x[21],
|
||||
'rating': x[22]
|
||||
'rating': x[22],
|
||||
'ticket': x[26]
|
||||
}
|
||||
|
||||
return r
|
||||
|
||||
Reference in New Issue
Block a user