From dfcbb6f9c0d5299fdb3e3dfb4e7c5c8d687bc374 Mon Sep 17 00:00:00 2001 From: Lost-MSth Date: Fri, 27 Nov 2020 21:35:35 +0800 Subject: [PATCH] Update to v1.7 close #1 close #2 --- README.md | 28 +- latest version/database/arcaea_database.db | Bin 77824 -> 118784 bytes latest version/database/arcsong.db | Bin 106496 -> 106496 bytes .../database/database_initialize.py | 124 +++-- latest version/database/map/byd_lumia.json | 70 +++ latest version/database/packs.json | 198 ++++++++ latest version/database/singles.json | 466 ++++++++++++++++++ latest version/main.py | 108 ++-- latest version/server/arcdownload.py | 91 +++- latest version/server/arcpurchase.py | 122 +++++ latest version/server/arcscore.py | 13 +- latest version/server/info.py | 228 ++------- latest version/static/favicon.ico | Bin 0 -> 16958 bytes latest version/templates/web/allitem.html | 51 ++ latest version/templates/web/allplayer.html | 2 +- latest version/templates/web/changeitem.html | 41 ++ latest version/templates/web/changeuser.html | 9 + .../templates/web/changeuserpurchase.html | 44 ++ latest version/templates/web/index.html | 5 +- .../templates/web/singleplayerptt.html | 2 +- latest version/web/index.py | 244 ++++++++- latest version/web/system.py | 85 +++- 22 files changed, 1635 insertions(+), 296 deletions(-) create mode 100644 latest version/database/map/byd_lumia.json create mode 100644 latest version/database/packs.json create mode 100644 latest version/database/singles.json create mode 100644 latest version/server/arcpurchase.py create mode 100644 latest version/static/favicon.ico create mode 100644 latest version/templates/web/allitem.html create mode 100644 latest version/templates/web/changeitem.html create mode 100644 latest version/templates/web/changeuserpurchase.html diff --git a/README.md b/README.md index a37533f..ece4729 100644 --- a/README.md +++ b/README.md @@ -18,23 +18,24 @@ This is a small local Arcaea server based on Python and Flask, which can simulat - 爬梯 Climbing steps - 自定义世界模式 Customizable World Mode - 自定义歌曲下载 Customizable songs download +- 单曲和曲包购买(没啥用) Single songs and song packs purchase(useless) - 全角色立绘 All character drawings - 角色技能 Character skills - 自定义角色属性 Customizable characters attributes - 全剧情解锁 Unlock all the stories -- 后台查分 Background search scores -- 后台自定义歌曲定数 Customize chart consts in the background +- 后台查询 Background search +- 后台自定义信息 Customize some things in the background - 成绩校验 Score check +- 下载校验 Download check 没有以下 We don't have: - 角色数值 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: - Recent 30 +- 一些歌曲的解锁 Some Songs' unlocking ## 说明 Statement 只是很有趣,用处探索中。 @@ -53,13 +54,16 @@ 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.6 -- 适用于Arcaea 3.2.3版本 For Arcaea 3.2.3 +### Version 1.7 +- 仍然适用于Arcaea 3.2.3版本 Still 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. +- 新增了购买系统,包括单曲购买和曲包购买 Add purchase system, including single purchase and pack purchase. +- 后台查询与修改项目增多 Increase background query and modification items. +- 新增用户下载量限制和下载校验 Add user download limit and download verification. +- 新增了**梦**的语音 Add the voice of **Yume**. +- 新增了网站图标 Add a favicon. +- 尝试解锁了所有的场景 Try to unlock all the scenes. +- 修复了一些Bug Fix some bugs. ## 运行环境与依赖 Running environment and requirements - Windows操作系统 Windows operating system @@ -81,7 +85,9 @@ It is just so interesting. What it can do is under exploration. ## 鸣谢 Thanks 歌曲数据库来自 Using song database from -[BotArcAPI releases](https://github.com/TheSnowfield/BotArcAPI/releases) +[BotArcAPI releases](https://github.com/TheSnowfield/BotArcAPI/releases) + +网站图标来自 Using favicon from [black fate - てんてん - pixiv](https://www.pixiv.net/artworks/82374369) ## 联系方式 Contact 如有必要,可以联系本人 Contact me if necessary diff --git a/latest version/database/arcaea_database.db b/latest version/database/arcaea_database.db index 3b927d31e5d3a218426afbfade81c7f823192d46..147e9b6bccf77af5cf523c1b9d83f8da26f0d1aa 100644 GIT binary patch delta 6520 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 f@f^c5x5w*%qwHTMti$mg<|O', methods=['POST']) +def claim_present(present_id): + return jsonify({ + "success": True + }) + + +# 购买,为了world模式boost一下 @app.route('/coffee/12/purchase/me/item', methods=['POST']) def item(): return jsonify({ @@ -445,27 +477,32 @@ def item(): }) -@app.route('/coffee/12/purchase/me/pack', methods=['POST']) # 购买,自然没有用 +@app.route('/coffee/12/purchase/me/pack', methods=['POST']) # 曲包和单曲购买 def pack(): + headers = request.headers + token = headers['Authorization'] + token = token[7:] + try: + user_id = server.auth.token_get_id(token) + if user_id: + if 'pack_id' in request.form: + return jsonify(server.arcpurchase.buy_pack(user_id, request.form['pack_id'])) + if 'single_id' in request.form: + return jsonify(server.arcpurchase.buy_single(user_id, request.form['single_id'])) + else: + return error_return(108) + except: + return error_return(108) return jsonify({ "success": True }) -@app.route('/coffee/12/purchase/bundle/single', methods=['GET']) # 单曲购买,自然没有用 +@app.route('/coffee/12/purchase/bundle/single', methods=['GET']) # 单曲购买信息获取 def single(): return jsonify({ "success": True, - "value": [{ - "name": "testsingle", - "items": [{ - "id": "testsingle", - "type": "single", - "is_available": False - }], - "price": 100, - "orig_price": 100 - }] + "value": server.arcpurchase.get_single_purchase() }) @@ -475,6 +512,7 @@ def world_all(): token = headers['Authorization'] token = token[7:] try: + user_id = server.auth.token_get_id(token) if user_id: return jsonify({ @@ -539,21 +577,22 @@ def download_song(): token = headers['Authorization'] token = token[7:] song_ids = request.args.getlist('sid') - try: user_id = server.auth.token_get_id(token) if user_id: - re = {} - if not song_ids: - re = server.arcdownload.get_all_songs() - else: - for song_id in song_ids: - re.update(server.arcdownload.get_one_song(song_id)) + if server.arcdownload.is_able_download(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 - }) + return jsonify({ + "success": True, + "value": re + }) + else: + return error_return(903) else: return error_return(108) except: @@ -562,12 +601,17 @@ def download_song(): @app.route('/download/', methods=['GET']) # 下载 def download(file_path): + t = request.args.get('t') try: - path = os.path.join('./database/songs', file_path) - if os.path.isfile(path) and not('../' in path or '..\\' in path): - return send_from_directory('./database/songs', file_path, as_attachment=True) + message = server.arcdownload.is_token_able_download(t) + if message == 0: + path = os.path.join('./database/songs', file_path) + if os.path.isfile(path) and not('../' in path or '..\\' in path): + return send_from_directory('./database/songs', file_path, as_attachment=True) + else: + return error_return(109) else: - return error_return(109) + return error_return(message) except: return error_return(108) diff --git a/latest version/server/arcdownload.py b/latest version/server/arcdownload.py index 4ed2da7..3c7127c 100644 --- a/latest version/server/arcdownload.py +++ b/latest version/server/arcdownload.py @@ -1,6 +1,11 @@ import os import hashlib from flask import url_for +import sqlite3 +import time + +time_limit = 3000 # 每个玩家24小时下载次数限制 +time_gap_limit = 1000 # 下载链接有效秒数 def get_file_md5(file_path): @@ -18,31 +23,105 @@ def get_file_md5(file_path): return myhash.hexdigest() -def get_one_song(song_id, file_dir='./database/songs'): +def get_one_song(c, user_id, song_id, file_dir='./database/songs'): # 获取一首歌的下载链接,返回字典 dir_list = os.listdir(os.path.join(file_dir, song_id)) re = {} + now = int(time.time()) + c.execute('''delete from download_token where user_id=:a and song_id=:b''', { + 'a': user_id, 'b': song_id}) + for i in dir_list: if os.path.isfile(os.path.join(file_dir, song_id, i)) and i in ['0.aff', '1.aff', '2.aff', '3.aff', 'base.ogg']: + token = hashlib.md5( + (str(user_id) + song_id + i + str(now)).encode(encoding='UTF-8')).hexdigest() + token = token[:8] + if i == 'base.ogg': re['audio'] = {"checksum": get_file_md5(os.path.join(file_dir, song_id, 'base.ogg')), - "url": url_for('download', file_path=song_id+'/base.ogg', _external=True)} + "url": url_for('download', file_path=song_id+'/base.ogg', t=token, _external=True)} else: if 'chart' not in re: re['chart'] = {} - re['chart'][i[0]] = {"checksum": get_file_md5(os.path.join(file_dir, song_id, i)), - "url": url_for('download', file_path=song_id+'/'+i, _external=True)} + "url": url_for('download', file_path=song_id+'/'+i, t=token, _external=True)} + + c.execute('''insert into download_token values(:a,:b,:c,:d,:e)''', { + 'a': user_id, 'b': song_id, 'c': i, 'd': token, 'e': now}) return {song_id: re} -def get_all_songs(file_dir='./database/songs'): +def get_all_songs(user_id, file_dir='./database/songs'): # 获取所有歌的下载链接,返回字典 dir_list = os.listdir(file_dir) re = {} + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() for i in dir_list: if os.path.isdir(os.path.join(file_dir, i)): - re.update(get_one_song(i)) + re.update(get_one_song(c, user_id, i)) + + conn.commit() + conn.close() + return re + +def get_some_songs(user_id, song_ids): + # 获取一些歌的下载链接,返回字典 + re = {} + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + for song_id in song_ids: + re.update(get_one_song(c, user_id, song_id)) + + conn.commit() + conn.close() return re + + +def is_token_able_download(t): + # token是否可以下载,返回错误码,0即可以 + errorcode = 0 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select * from download_token where token = :t limit 1''', + {'t': t}) + x = c.fetchone() + now = int(time.time()) + if x and now - x[4] <= time_gap_limit: + c.execute( + '''select count(*) from user_download where user_id = :a''', {'a': x[0]}) + y = c.fetchone() + if y and y[0] <= time_limit: + c.execute('''insert into user_download values(:a,:b,:c)''', { + 'a': x[0], 'b': x[3], 'c': now}) + else: + errorcode = 903 + else: + errorcode = 108 + + conn.commit() + conn.close() + return errorcode + + +def is_able_download(user_id): + # 是否可以下载,返回布尔值 + f = True + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + now = int(time.time()) + c.execute( + '''delete from user_download where user_id = :a and time <= :b''', {'a': user_id, 'b': now - 24*3600}) + c.execute( + '''select count(*) from user_download where user_id = :a''', {'a': user_id}) + y = c.fetchone() + if y and y[0] <= time_limit: + pass + else: + f = False + + conn.commit() + conn.close() + return f diff --git a/latest version/server/arcpurchase.py b/latest version/server/arcpurchase.py new file mode 100644 index 0000000..6580a9d --- /dev/null +++ b/latest version/server/arcpurchase.py @@ -0,0 +1,122 @@ +import sqlite3 + + +def int2b(x): + # int与布尔值转换 + if x is None or x == 0: + return False + else: + return True + + +def get_item(c, type='pack'): + # 读取packs内容,返回字典列表 + c.execute('''select * from item where type = :a''', {'a': type}) + x = c.fetchall() + if not x: + return [] + + re = [] + for i in x: + r = {"name": i[0], + "items": [{ + "type": i[1], + "id": i[0], + "is_available": int2b(i[2]) + }], + "price": i[3], + "orig_price": i[4]} + + if i[5] > 0: + r['discount_from'] = i[5] + if i[6] > 0: + r['discount_to'] = i[6] + + re.append(r) + + return re + + +def get_single_purchase(): + # main里面没开数据库,这里写一下代替 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + re = get_item(c, type='single') + conn.commit() + conn.close() + return re + + +def buy_pack(user_id, pack_id): + # 曲包购买,返回字典 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select price from item where item_id = :a''', {'a': pack_id}) + price = c.fetchone() + if price: + price = price[0] + else: + price = 0 + + c.execute('''select ticket from user where user_id = :a''', {'a': user_id}) + ticket = c.fetchone() + if ticket: + ticket = ticket[0] + else: + ticket = 0 + + if ticket < price: + conn.commit() + conn.close() + return { + "success": False + } + + c.execute('''update user set ticket = :b where user_id = :a''', + {'a': user_id, 'b': ticket-price}) + c.execute('''insert into user_item values(:a,:b,'pack')''', + {'a': user_id, 'b': pack_id}) + + conn.commit() + conn.close() + return { + "success": True + } + + +def buy_single(user_id, single_id): + # 单曲购买,返回字典 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select price from item where item_id = :a''', + {'a': single_id}) + price = c.fetchone() + if price: + price = price[0] + else: + price = 0 + + c.execute('''select ticket from user where user_id = :a''', {'a': user_id}) + ticket = c.fetchone() + if ticket: + ticket = ticket[0] + else: + ticket = 0 + + if ticket < price: + conn.commit() + conn.close() + return { + "success": False + } + + c.execute('''update user set ticket = :b where user_id = :a''', + {'a': user_id, 'b': ticket-price}) + c.execute('''insert into user_item values(:a,:b,'single')''', + {'a': user_id, 'b': single_id}) + + conn.commit() + conn.close() + return { + "success": True + } diff --git a/latest version/server/arcscore.py b/latest version/server/arcscore.py index 8cf87fa..43f5e39 100644 --- a/latest version/server/arcscore.py +++ b/latest version/server/arcscore.py @@ -1390,7 +1390,18 @@ def arc_all_get(user_id): }, { "complete": 1, "unlock_key": "dreaminattraction|1|0" - }] + }, { + "complete": 1, + "unlock_key": "buchigireberserker|2|0" + }, { + "complete": 1, + "unlock_key": "gothiveofra|2|0" + }, { + "complete": 1, + "unlock_key": "gothiveofra|1|0" + } + + ] }, "clearedsongs": { "": song_1 }, diff --git a/latest version/server/info.py b/latest version/server/info.py index 4fd5074..93b2aec 100644 --- a/latest version/server/info.py +++ b/latest version/server/info.py @@ -1,5 +1,7 @@ import sqlite3 import server.arcworld +import server.arcpurchase +import time def int2b(x): @@ -56,7 +58,7 @@ def get_user_character(c, user_id): y = c.fetchone() if y is not None: char_name = y[0] - s.append({ + char = { "is_uncapped_override": int2b(i[14]), "is_uncapped": int2b(i[13]), "uncap_cores": [], @@ -73,7 +75,10 @@ def get_user_character(c, user_id): "level": i[2], "name": char_name, "character_id": i[1] - }) + } + if i[1] == 21: + char["voice"] = [0, 1, 2, 3, 100, 1000, 1001] + s.append(char) return s else: @@ -115,6 +120,34 @@ def get_user_friend(c, user_id): return s +def get_user_singles(c, user_id): + # 得到用户的单曲,返回列表 + c.execute('''select * from user_item where user_id = :user_id and type = "single"''', + {'user_id': user_id}) + x = c.fetchall() + if not x: + return [] + + re = [] + for i in x: + re.append(i[1]) + return re + + +def get_user_packs(c, user_id): + # 得到用户的曲包,返回列表 + c.execute('''select * from user_item where user_id = :user_id and type = "pack"''', + {'user_id': user_id}) + x = c.fetchall() + if not x: + return [] + + re = [] + for i in x: + re.append(i[1]) + return re + + def get_value_0(c, user_id): # 构造value id=0的数据,返回字典 c.execute('''select * from user where user_id = :x''', {'x': user_id}) @@ -148,10 +181,11 @@ def get_value_0(c, user_id): "next_fragstam_ts": -1, "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", "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"], + "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"], + "singles": get_user_singles(c, user_id), # ["dataerror", "yourvoiceso", "crosssoul", "impurebird", "auxesia", "modelista", "yozakurafubuki", "surrender", "metallicpunisher", "carminescythe", "bethere", "callmyname", "fallensquare", "dropdead", "alexandrite", "astraltale", "phantasia", "empireofwinter", "libertas", "dottodot", "dreadnought", "mirzam", "heavenlycaress", "filament", "avantraze", "battlenoone", "saikyostronger", "izana", "einherjar", "laqryma", "amygdata", "altale", "feelssoright", "scarletcage", "teriqma", "mahoroba", "badtek", "maliciousmischance", "buchigireberserker", "galaxyfriends", "xeraphinite", "xanatos"] + "packs": get_user_packs(c, user_id), + # ["vs", "extend", "dynamix", "prelude", "core", "yugamu", "omatsuri", "zettai", "mirai", "shiawase", "chunithm", "nijuusei", "groovecoaster", "rei", "tonesphere", "lanota"] "characters": characters, "cores": [], "recent_score": get_recent_score(c, user_id), @@ -189,185 +223,7 @@ def arc_aggregate_big(user_id): "value": get_value_0(c, user_id) }, { "id": 1, - "value": [{ - "name": "core", - "items": [{ - "id": "core", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "shiawase", - "items": [{ - "id": "shiawase", - "type": "pack", - "is_available": True - }, { - "id": "kou", - "type": "character", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1552089600000, - "discount_to": 1552694399000 - }, { - "name": "dynamix", - "items": [{ - "id": "dynamix", - "type": "pack", - "is_available": True - }, { - "id": "sapphire", - "type": "character", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "mirai", - "items": [{ - "id": "mirai", - "type": "pack", - "is_available": True - }, { - "id": "lethe", - "type": "character", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1552089600000, - "discount_to": 1552694399000 - }, { - "name": "yugamu", - "items": [{ - "id": "yugamu", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "lanota", - "items": [{ - "id": "lanota", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "nijuusei", - "items": [{ - "id": "nijuusei", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "rei", - "items": [{ - "id": "rei", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "tonesphere", - "items": [{ - "id": "tonesphere", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "groovecoaster", - "items": [{ - "id": "groovecoaster", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "zettai", - "items": [{ - "id": "zettai", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500, - "discount_from": 1583712000000, - "discount_to": 1584316799000 - }, { - "name": "chunithm", - "items": [{ - "id": "chunithm", - "type": "pack", - "is_available": True - }], - "price": 300, - "orig_price": 300 - }, { - "name": "prelude", - "items": [{ - "id": "prelude", - "type": "pack", - "is_available": True - }], - "price": 400, - "orig_price": 400 - }, { - "name": "omatsuri", - "items": [{ - "id": "omatsuri", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500 - }, { - "name": "vs", - "items": [{ - "id": "vs", - "type": "pack", - "is_available": True - }], - "price": 500, - "orig_price": 500 - }, { - "name": "extend", - "items": [{ - "id": "extend", - "type": "pack", - "is_available": True - }], - "price": 700, - "orig_price": 700 - }] + "value": server.arcpurchase.get_item(c, 'pack') }, { "id": 2, "value": {} @@ -377,7 +233,7 @@ def arc_aggregate_big(user_id): "max_stamina": 12, "stamina_recover_tick": 1800000, "core_exp": 250, - "curr_ts": 1599547606825, + "curr_ts": int(time.time())*1000, "level_steps": [{ "level": 1, "level_exp": 0 diff --git a/latest version/static/favicon.ico b/latest version/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..0120be6660c2f35c904255251ff473846bedacc3 GIT binary patch literal 16958 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 boxlExFxBG}7^(4Z{~v(=|MCBu9{7I%MrA-M literal 0 HcmV?d00001 diff --git a/latest version/templates/web/allitem.html b/latest version/templates/web/allitem.html new file mode 100644 index 0000000..06d74cf --- /dev/null +++ b/latest version/templates/web/allitem.html @@ -0,0 +1,51 @@ +{% extends 'base.html' %} +{% block header %} +

{% block title %}All items{% endblock %}

+{% endblock %} + +{% block content %} +{% if posts %}
+{% for item in posts %} + +
+ Id: + {{item['item_id']}} +
+ + Type: + {{item['type']}} +
+ + Is available: + {{item['is_available']}} +
+ + Price: + {{item['price']}} +
+ + Original price: + {{item['orig_price']}} +
+ + Discount from: + {{item['discount_from']}} +
+ + Discount to: + {{item['discount_to']}} +
+ + + + +
+{% if not loop.last %} +
+
+
+{% endif %} +{% endfor %} + +{% endif %} +{% endblock %} \ No newline at end of file diff --git a/latest version/templates/web/allplayer.html b/latest version/templates/web/allplayer.html index 61e4157..3a9fd94 100644 --- a/latest version/templates/web/allplayer.html +++ b/latest version/templates/web/allplayer.html @@ -13,7 +13,7 @@

{% block title %}All players{% endblock %}

User code: {{user['user_code']}}
注册于 Registered in: {{user['join_date']}}
-
PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}
+
PTT: {{'%0.2f'|format(user['rating_ptt']/100|float)}}
Memories: {{user['ticket']}}
Recent plays:
diff --git a/latest version/templates/web/changeitem.html b/latest version/templates/web/changeitem.html new file mode 100644 index 0000000..c91d57a --- /dev/null +++ b/latest version/templates/web/changeitem.html @@ -0,0 +1,41 @@ +{% extends 'base.html' %} +{% block header %} +

{% block title %}Change the items{% endblock %}

+{% endblock %} + +{% block content %} +
+
Change the item
+ + + +
+ +
+
+
可修改项 Modifiable items:
+
+
+
+ +
+ +
+ + + + + + + + +
如果某些不需要修改,留空即可
+
If some things do not need to be modified, leave it blank.
+
时间填写是一个HTML5控件
+
Time filling is an HTML5 control.
+ +
+{% endblock %} \ No newline at end of file diff --git a/latest version/templates/web/changeuser.html b/latest version/templates/web/changeuser.html index ba2d56e..1b731e2 100644 --- a/latest version/templates/web/changeuser.html +++ b/latest version/templates/web/changeuser.html @@ -25,4 +25,13 @@

{% block title %}Change user information{% endblock %}

At present, only memories can be modified.
+
+
+
+
Edit all the users
+ + + + +
{% endblock %} \ No newline at end of file diff --git a/latest version/templates/web/changeuserpurchase.html b/latest version/templates/web/changeuserpurchase.html new file mode 100644 index 0000000..95c06e4 --- /dev/null +++ b/latest version/templates/web/changeuserpurchase.html @@ -0,0 +1,44 @@ +{% extends 'base.html' %} +{% block header %} +

{% block title %}Change user purchase information{% endblock %}

+{% endblock %} + +{% block content %} +
+
Edit the user
+ + + or
+ + +
+
+ +
对所有单曲和曲包的操作 Operation to all singles and packs: +
+
+ +
+ +
+ + +
+ +
+
+
+
+
Edit all the users
+
+
对所有单曲和曲包的操作 Operation to all singles and packs: +
+
+ +
+ +
+
+ +
+{% endblock %} \ No newline at end of file diff --git a/latest version/templates/web/index.html b/latest version/templates/web/index.html index 2aa8848..1f37a2f 100644 --- a/latest version/templates/web/index.html +++ b/latest version/templates/web/index.html @@ -15,13 +15,16 @@

游戏方面 Game

所有玩家信息查询 All players

铺面信息查询 All songs

角色信息查询 All characters

+购买信息查询 All items

单个铺面排行榜查询 Single song chart tops

系统方面 System

数据库更新 Update databases

歌曲修改 Change the songs

角色修改 Change the characters

-用户信息修改 Change user information +购买信息修改 Change the items

+用户信息修改 Change user information

+用户购买信息修改 Change user purchase information {% endblock %} \ No newline at end of file diff --git a/latest version/templates/web/singleplayerptt.html b/latest version/templates/web/singleplayerptt.html index 2b6d471..ddf9045 100644 --- a/latest version/templates/web/singleplayerptt.html +++ b/latest version/templates/web/singleplayerptt.html @@ -25,7 +25,7 @@

{% block title %}Single player ptt{% endblock %}

注册于 Registered in: {{user['join_date']}}
Memories: {{user['ticket']}}
-
PTT: {{user['rating_ptt']//100 ~ '.' ~ user['rating_ptt']%100}}
+
PTT: {{'%0.2f'|format(user['rating_ptt']/100|float)}}
Best 30 PTT: {{bestptt}}
Recent 10 PTT: {{recentptt}}
diff --git a/latest version/web/index.py b/latest version/web/index.py index 8cc2740..101c0a2 100644 --- a/latest version/web/index.py +++ b/latest version/web/index.py @@ -447,31 +447,31 @@ def edit_char(): 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: + if level is None and frag is None and prog is None and overdrive is None and skill_id is None and skill_id_uncap is None: error = '无修改 No change.' else: sql = '''update character set level_exp=25000''' sql_dict = {'character_id': character_id} - if level: + if level is not None: sql += ', level = :level' sql_dict['level'] = level - if frag: + if frag is not None: sql += ', frag = :frag' sql_dict['frag'] = frag - if prog: + if prog is not None: sql += ', prog = :prog' sql_dict['prog'] = prog - if overdrive: + if overdrive is not None: sql += ', overdrive = :overdrive' sql_dict['overdrive'] = overdrive - if skill_id: + if skill_id is not None: sql += ', skill_id = :skill_id' if skill_id == 'No_skill': sql_dict['skill_id'] = '' else: sql_dict['skill_id'] = skill_id - if skill_id_uncap: + if skill_id_uncap is not None: sql += ', skill_id_uncap = :skill_id_uncap' if skill_id_uncap == 'No_skill': sql_dict['skill_id_uncap'] = '' @@ -520,12 +520,42 @@ def edit_user(): # 修改用户数据 error = None - name = request.form['name'] - user_code = request.form['user_code'] + flag = True + name = None + user_code = None + try: + ticket = request.form['ticket'] + if ticket: + ticket = int(ticket) + else: + ticket = None + except: + error = '数据错误 Wrong data.' + flash(error) + return redirect(url_for('index.change_user')) + + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + + # 全修改 + if 'name' not in request.form and 'user_code' not in request.form: + flag = False + if not ticket: + error = '无修改 No change.' + else: + sql = '''update user set ticket = :ticket''' + sql_dict = {'ticket': ticket} + c.execute(sql, sql_dict) + flash("全部用户信息修改成功 Successfully edit all the users' information.") + + else: + name = request.form['name'] + user_code = request.form['user_code'] + + # 指定修改 if name or user_code: - 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}) @@ -537,16 +567,6 @@ def edit_user(): 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.' @@ -560,12 +580,190 @@ def edit_user(): error = '玩家不存在 The player does not exist.' else: - error = '输入为空 Null Input.' + if flag: + error = '输入为空 Null Input.' conn.commit() conn.close() - if error: flash(error) return redirect(url_for('index.change_user')) + + +@bp.route('/changeuserpurchase', methods=['GET']) +@login_required +def change_user_purchase(): + # 修改用户购买 + + return render_template('web/changeuserpurchase.html') + + +@bp.route('/changeuserpurchase/edituser', methods=['POST']) +@login_required +def edit_user_purchase(): + # 修改用户购买 + + error = None + flag = True + name = None + user_code = None + try: + method = request.form['method'] + except: + flash('输入为空 Null Input.') + return redirect(url_for('index.change_user_purchase')) + + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + + # 全修改 + if 'name' not in request.form and 'user_code' not in request.form: + flag = False + if method == '0': + web.system.unlock_all_user_item(c) + else: + c.execute('''delete from user_item''') + + flash("全部用户购买信息修改成功 Successfully edit all the users' purchase information.") + + else: + name = request.form['name'] + user_code = request.form['user_code'] + + # 指定修改 + if name or user_code: + + if user_code: + c.execute('''select user_id from user where user_code=:a''', { + 'a': user_code}) + else: + c.execute( + '''select user_id from user where name=:a''', {'a': name}) + + user_id = c.fetchone() + posts = [] + if user_id: + user_id = user_id[0] + + if method == '0': + web.system.unlock_user_item(c, user_id) + else: + c.execute('''delete from user_item where user_id=:a''', { + 'a': user_id}) + flash('用户购买信息修改成功 Successfully edit the user purchase information.') + + else: + error = '玩家不存在 The player does not exist.' + + else: + if flag: + error = '输入为空 Null Input.' + + conn.commit() + conn.close() + if error: + flash(error) + + return redirect(url_for('index.change_user_purchase')) + + +@bp.route('/allitem', methods=['GET']) +@login_required +def all_item(): + # 所有购买数据 + + error = None + posts = web.system.get_all_item() + if not posts: + error = '没有购买数据 No item data.' + + if error: + flash(error) + return redirect(url_for('index.all_item')) + else: + return render_template('web/allitem.html', posts=posts) + + +@bp.route('/changeitem', methods=['GET', 'POST']) +@login_required +def change_item(): + # 修改购买信息 + + error = None + if request.method == 'POST': + try: + item_id = request.form['item_id'] + item_type = request.form['type'] + price = request.form['price'] + orig_price = request.form['orig_price'] + discount_from = request.form['discount_from'] + discount_to = request.form['discount_to'] + try: + is_available = request.form['is_available'] + if is_available: + is_available = int(is_available) + else: + is_available = None + except: + is_available = None + + if price: + price = int(price) + else: + price = None + if orig_price: + orig_price = int(orig_price) + else: + orig_price = None + if discount_from: + discount_from = int(time.mktime(time.strptime(discount_from, "%Y-%m-%dT%H:%M"))) * 1000 + else: + discount_from = None + if discount_to: + discount_to = int(time.mktime(time.strptime(discount_to, "%Y-%m-%dT%H:%M"))) * 1000 + else: + discount_to = None + except: + error = '数据错误 Wrong data.' + flash(error) + return redirect(url_for('index.change_item')) + + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute( + '''select exists(select * from item where item_id=:a and type=:b)''', {'a': item_id, 'b': item_type}) + if c.fetchone() == (1,): + if is_available is None and price is None and orig_price is None and not discount_from and not discount_to: + error = '无修改 No change.' + else: + sql = '''update item set type=:type''' + sql_dict = {'item_id': item_id, 'type': item_type} + if price is not None: + sql += ', price = :price' + sql_dict['price'] = price + if orig_price is not None: + sql += ', orig_price = :orig_price' + sql_dict['orig_price'] = orig_price + if discount_from is not None: + sql += ', discount_from = :discount_from' + sql_dict['discount_from'] = discount_from + if discount_to is not None: + sql += ', discount_to = :discount_to' + sql_dict['discount_to'] = discount_to + if is_available is not None: + sql += ', is_available = :is_available' + sql_dict['is_available'] = is_available + + sql += ' where item_id = :item_id and type = :type' + c.execute(sql, sql_dict) + flash('购买项目修改成功 Successfully edit the item.') + else: + error = '购买项目不存在 The item does not exist.' + + conn.commit() + conn.close() + if error: + flash(error) + + return render_template('web/changeitem.html') diff --git a/latest version/web/system.py b/latest version/web/system.py index 1b1e34c..d0b2355 100644 --- a/latest version/web/system.py +++ b/latest version/web/system.py @@ -1,5 +1,14 @@ import os import sqlite3 +import time + + +def int2b(x): + # int与布尔值转换 + if x is None or x == 0: + return False + else: + return True def get_table_info(c, table_name): @@ -76,6 +85,13 @@ def get_sql_insert_table(table_name, field, value): def update_one_table(c1, c2, table_name): # 从c1向c2更新数据表,c2中存在的信息不变 + c1.execute( + '''select * from sqlite_master where type = 'table' and name = :a''', {'a': table_name}) + c2.execute( + '''select * from sqlite_master where type = 'table' and name = :a''', {'a': table_name}) + if not c1.fetchone() or not c2.fetchone(): + return 'error' + db1_pk, db1_name = get_table_info(c1, table_name) db2_pk, db2_name = get_table_info(c2, table_name) if db1_pk != db2_pk: @@ -124,7 +140,7 @@ def update_user_char(c): def update_database(): # 将old数据库不存在数据加入到新数据库上,并删除old数据库 - # 对于arcaea_datebase.db,更新best_score,friend,recent30,user,user_world并用character数据更新user_char + # 对于arcaea_datebase.db,更新best_score,friend,recent30,user,user_world, user_item并用character数据更新user_char # 对于arcsong.db,更新songs 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') @@ -137,6 +153,7 @@ def update_database(): update_one_table(c1, c2, 'best_score') update_one_table(c1, c2, 'recent30') update_one_table(c1, c2, 'user_world') + update_one_table(c1, c2, 'user_item') update_user_char(c2) @@ -160,3 +177,69 @@ def update_database(): conn2.commit() conn2.close() os.remove('database/old_arcsong.db') + + +def unlock_all_user_item(c): + # 解锁所有用户购买 + + c.execute('''select user_id from user''') + x = c.fetchall() + c.execute('''select item_id, type from item''') + y = c.fetchall() + c.execute('''delete from user_item''') + if x and y: + for i in x: + for j in y: + c.execute('''insert into user_item values(:a,:b,:c)''', { + 'a': i[0], 'b': j[0], 'c': j[1]}) + + return + + +def unlock_user_item(c, user_id): + # 解锁用户购买 + + c.execute('''select item_id, type from item''') + y = c.fetchall() + + for j in y: + c.execute('''select exists(select * from user_item where user_id=:a and item_id=:b and type=:c)''', { + 'a': user_id, 'b': j[0], 'c': j[1]}) + if c.fetchone() == (0,): + c.execute('''insert into user_item values(:a,:b,:c)''', { + 'a': user_id, 'b': j[0], 'c': j[1]}) + + return + + +def get_all_item(): + # 所有购买数据查询 + conn = sqlite3.connect('./database/arcaea_database.db') + c = conn.cursor() + c.execute('''select * from item''') + x = c.fetchall() + re = [] + if x: + for i in x: + discount_from = None + discount_to = None + + if i[5] and i[5] >= 0: + discount_from = time.strftime( + "%Y-%m-%d %H:%M:%S", time.localtime(int(i[5])/1000)) + if i[6] and i[6] >= 0: + discount_to = time.strftime( + "%Y-%m-%d %H:%M:%S", time.localtime(int(i[6])//1000)) + + re.append({'item_id': i[0], + 'type': i[1], + 'is_available': int2b(i[2]), + 'price': i[3], + 'orig_price': i[4], + 'discount_from': discount_from, + 'discount_to': discount_to + }) + + conn.commit() + conn.close() + return re