refactor
This commit is contained in:
parent
45a0f516ea
commit
b6862eb429
|
@ -1,2 +1,3 @@
|
|||
__pycache__/
|
||||
data/
|
||||
test.py
|
||||
|
|
7
app.py
7
app.py
|
@ -1,7 +1,8 @@
|
|||
from flask import Flask
|
||||
from flask_restful import Api
|
||||
from loaders.KF3.kf3db import KF3DB
|
||||
from loaders.Kingdom.kingdomdb import KingdomDB
|
||||
|
||||
from modules.KF3.database import Database as KF3DB
|
||||
from modules.Kingdom.database import Database as KFKDB
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config['JSON_AS_ASCII'] = False
|
||||
|
@ -10,7 +11,7 @@ app.databases = {}
|
|||
api = Api(app)
|
||||
|
||||
KF3DB(api)
|
||||
KingdomDB(api)
|
||||
KFKDB(api)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='127.0.0.1', port=8080, debug=True)
|
|
@ -0,0 +1,56 @@
|
|||
[2024-01-23 17:41:58 +0100] [510920] [INFO] Starting gunicorn 21.2.0
|
||||
[2024-01-23 17:41:58 +0100] [510920] [INFO] Listening at: http://127.0.0.1:8081 (510920)
|
||||
[2024-01-23 17:41:58 +0100] [510920] [INFO] Using worker: sync
|
||||
[2024-01-23 17:41:58 +0100] [510926] [INFO] Booting worker with pid: 510926
|
||||
58 74870 純情色のワンピース
|
||||
[2024-01-23 17:42:44 +0100] [510920] [INFO] Handling signal: int
|
||||
[2024-01-23 17:42:44 +0100] [510926] [INFO] Worker exiting (pid: 510926)
|
||||
[2024-01-23 17:42:45 +0100] [510920] [INFO] Shutting down: Master
|
||||
[2024-01-23 17:43:05 +0100] [511070] [INFO] Starting gunicorn 21.2.0
|
||||
[2024-01-23 17:43:05 +0100] [511070] [INFO] Listening at: http://127.0.0.1:8081 (511070)
|
||||
[2024-01-23 17:43:05 +0100] [511070] [INFO] Using worker: sync
|
||||
[2024-01-23 17:43:05 +0100] [511071] [INFO] Booting worker with pid: 511071
|
||||
58 74870 純情色のワンピース
|
||||
[2024-01-23 17:44:06 +0100] [511070] [INFO] Handling signal: int
|
||||
[2024-01-23 17:44:07 +0100] [511071] [INFO] Worker exiting (pid: 511071)
|
||||
[2024-01-23 17:44:08 +0100] [511070] [INFO] Shutting down: Master
|
||||
[2024-01-23 17:52:24 +0100] [511446] [INFO] Starting gunicorn 21.2.0
|
||||
[2024-01-23 17:52:24 +0100] [511446] [INFO] Listening at: http://127.0.0.1:8081 (511446)
|
||||
[2024-01-23 17:52:24 +0100] [511446] [INFO] Using worker: sync
|
||||
[2024-01-23 17:52:24 +0100] [511447] [INFO] Booting worker with pid: 511447
|
||||
58 74870 純情色のワンピース
|
||||
[2024-01-23 17:53:01,255] ERROR in app: Exception on /KF3/Update [GET]
|
||||
Traceback (most recent call last):
|
||||
File "/home/pi/python/env/lib/python3.11/site-packages/flask/app.py", line 867, in full_dispatch_request
|
||||
rv = self.dispatch_request()
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/home/pi/python/env/lib/python3.11/site-packages/flask/app.py", line 852, in dispatch_request
|
||||
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/home/pi/python/env/lib/python3.11/site-packages/flask_restful/__init__.py", line 493, in wrapper
|
||||
return self.make_response(data, code, headers=headers)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/home/pi/python/env/lib/python3.11/site-packages/flask_restful/__init__.py", line 522, in make_response
|
||||
resp = self.representations[mediatype](data, *args, **kwargs)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/home/pi/python/env/lib/python3.11/site-packages/flask_restful/representations/json.py", line 21, in output_json
|
||||
dumped = dumps(data, **settings) + "\n"
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.11/json/__init__.py", line 231, in dumps
|
||||
return _default_encoder.encode(obj)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.11/json/encoder.py", line 200, in encode
|
||||
chunks = self.iterencode(o, _one_shot=True)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.11/json/encoder.py", line 258, in iterencode
|
||||
return _iterencode(o, 0)
|
||||
^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.11/json/encoder.py", line 180, in default
|
||||
raise TypeError(f'Object of type {o.__class__.__name__} '
|
||||
TypeError: Object of type coroutine is not JSON serializable
|
||||
/home/pi/python/env/lib/python3.11/site-packages/flask/app.py:869: RuntimeWarning: coroutine 'KF3_Update.post' was never awaited
|
||||
rv = self.handle_user_exception(e)
|
||||
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
|
||||
[2024-01-23 17:59:01 +0100] [511446] [INFO] Handling signal: int
|
||||
[2024-01-23 17:59:01 +0100] [511447] [INFO] Worker exiting (pid: 511447)
|
||||
[2024-01-23 17:59:02 +0100] [511446] [INFO] Shutting down: Master
|
|
@ -0,0 +1,6 @@
|
|||
127.0.0.1 - - [23/Jan/2024:17:43:29 +0100] "GET /KF3/Update HTTP/1.0" 200 42 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0"
|
||||
127.0.0.1 - - [23/Jan/2024:17:43:40 +0100] "GET /KF3/Update HTTP/1.0" 200 42 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0"
|
||||
127.0.0.1 - - [23/Jan/2024:17:43:41 +0100] "GET /KF3/Update HTTP/1.0" 200 42 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0"
|
||||
127.0.0.1 - - [23/Jan/2024:17:43:42 +0100] "GET /KF3/Update HTTP/1.0" 200 42 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0"
|
||||
127.0.0.1 - - [23/Jan/2024:17:44:01 +0100] "GET /KF3/Update HTTP/1.0" 200 42 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0"
|
||||
127.0.0.1 - - [23/Jan/2024:17:53:01 +0100] "GET /KF3/Update HTTP/1.0" 500 37 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/106.0.0.0"
|
|
@ -1,6 +1,6 @@
|
|||
import multiprocessing
|
||||
|
||||
workers = multiprocessing.cpu_count() # * 2 + 1
|
||||
workers = 1 # multiprocessing.cpu_count() # * 2 + 1
|
||||
bind = 'unix:flaskrest.sock'
|
||||
umask = 0o007
|
||||
reload = False
|
||||
|
@ -8,3 +8,6 @@ reload = False
|
|||
#logging
|
||||
accesslog = '-'
|
||||
errorlog = '-'
|
||||
# accesslog = 'gunicorn.log'
|
||||
# errorlog = 'gunicorn.error.log'
|
||||
# capture_output = True
|
|
@ -3,14 +3,15 @@ import json
|
|||
import platform
|
||||
import UnityPy
|
||||
from datetime import datetime
|
||||
from loaders.KF3.statCalculation import get_all_stats, fill_miracle_numbers
|
||||
from endpoints.KF3.friend import KF3_Friend
|
||||
from endpoints.KF3.friends import KF3_Friends
|
||||
from endpoints.KF3.update import KF3_Update
|
||||
|
||||
class KF3DB:
|
||||
processed_friends = {}
|
||||
from .statCalculation import get_all_stats, fill_miracle_numbers
|
||||
from .endpoints.friend import KF3_Friend
|
||||
from .endpoints.friends import KF3_Friends
|
||||
from .endpoints.item import KF3_Item
|
||||
from .endpoints.items import KF3_Items
|
||||
from .endpoints.update import KF3_Update
|
||||
|
||||
class Database:
|
||||
def __init__(self, api) -> None:
|
||||
app = api.app
|
||||
if "KF3" in app.databases:
|
||||
|
@ -21,24 +22,44 @@ class KF3DB:
|
|||
app.databases["KF3"] = self
|
||||
api.add_resource(KF3_Friend, "/KF3/Friend/<int:id>")
|
||||
api.add_resource(KF3_Friends, "/KF3/Friends")
|
||||
api.add_resource(KF3_Item, "/KF3/Item/<int:id>")
|
||||
api.add_resource(KF3_Items, "/KF3/Items")
|
||||
api.add_resource(KF3_Update, "/KF3/Update")
|
||||
|
||||
def reload_data(self):
|
||||
def unload_data(self):
|
||||
self.charaData = {}
|
||||
self.itemCommon = {}
|
||||
self.promoteData = {}
|
||||
self.promotePresetData = {}
|
||||
self.charaClothesData = {}
|
||||
self.promotePresetData = {}
|
||||
self.limitlevel_rising_status = {}
|
||||
|
||||
self.paramArts = {}
|
||||
self.paramAbilities = {}
|
||||
self.paramAbilities1 = {}
|
||||
self.paramAbilities2 = {}
|
||||
self.paramAlphaBases = {}
|
||||
self.paramWaitActions = {}
|
||||
self.paramSpecialAttacks = {}
|
||||
|
||||
self.processed_friends = {}
|
||||
|
||||
def reload_data(self):
|
||||
self.unload_data()
|
||||
|
||||
if platform.system() == "Windows":
|
||||
path = "H:\\Apache\\Katworks\\KF\\assets\\KF3\\mst\\"
|
||||
path = "H:\\Apache\\Katworks\\KF\\assets\\KF3\\cache\\"
|
||||
else:
|
||||
path = "/media/USB2/Apache/Katworks/KF/assets/KF3/mst//"
|
||||
path = "/var/www/html/Katworks/KF/assets/KF3/develop01/cache/"
|
||||
|
||||
with gzip.open(path + "CHARA_DATA.d", mode="rt", encoding="utf-8") as file:
|
||||
for entry in json.loads(file.read()):
|
||||
self.charaData[entry["id"]] = entry
|
||||
|
||||
with gzip.open(path + "ITEM_COMMON.d", mode="rt", encoding="utf-8") as file:
|
||||
for entry in json.loads(file.read()):
|
||||
self.itemCommon[entry["id"]] = entry
|
||||
|
||||
with gzip.open(path + "CHARA_PROMOTE_DATA.d", mode="rt", encoding="utf-8") as file:
|
||||
for entry in json.loads(file.read()):
|
||||
self.promoteData[entry["promoteId"]] = entry
|
||||
|
@ -55,26 +76,20 @@ class KF3DB:
|
|||
self.charaClothesData[entry["clothesPresetId"]] = []
|
||||
self.charaClothesData[entry["clothesPresetId"]].append(entry)
|
||||
|
||||
with gzip.open("data/KF3/LIMITLEVEL_RISING_STATUS.d", mode="rt", encoding="utf-8") as file:
|
||||
with gzip.open(path + "LIMITLEVEL_RISING_STATUS.d", mode="rt", encoding="utf-8") as file:
|
||||
for entry in json.loads(file.read()):
|
||||
self.limitlevel_rising_status[entry["patternId"]] = entry
|
||||
|
||||
self.parse_parameter()
|
||||
self.process_friends()
|
||||
print("Data reload finished")
|
||||
self.update_in_progress = False
|
||||
|
||||
def parse_parameter(self):
|
||||
self.paramAbilities = {}
|
||||
self.paramAbilities1 = {}
|
||||
self.paramAbilities2 = {}
|
||||
self.paramAlphaBases = {}
|
||||
self.paramArts = {}
|
||||
self.paramSpecialAttacks = {}
|
||||
self.paramWaitActions = {}
|
||||
|
||||
if platform.system() == "Windows":
|
||||
path = "H:\\Apache\\Katworks\\KF\\assets\\KF3\\assets\\"
|
||||
else:
|
||||
path = "/media/USB2/Apache/Katworks/KF/assets/KF3/assets//"
|
||||
path = "/var/www/html/Katworks/KF/assets/KF3/develop01/assets/Windows/"
|
||||
|
||||
paramAsset = UnityPy.load(path + "parameter.asset")
|
||||
for obj in paramAsset.objects:
|
||||
|
@ -101,7 +116,6 @@ class KF3DB:
|
|||
self.paramWaitActions[id] = obj.read_typetree()
|
||||
|
||||
def process_friends(self):
|
||||
self.processed_friends = {}
|
||||
for charaID in self.charaData:
|
||||
self.processed_friends[charaID] = self.process_chara(charaID)
|
||||
|
||||
|
@ -169,7 +183,11 @@ class KF3DB:
|
|||
chara["has_rainbow_trait"] = id in self.paramAbilities2
|
||||
|
||||
chara["risingStatusPatternId"] = patternId = charaData["risingStatusPatternId"]
|
||||
level_curve = self.limitlevel_rising_status[patternId] if patternId != 0 else None
|
||||
|
||||
if patternId not in self.limitlevel_rising_status:
|
||||
level_curve = None
|
||||
else:
|
||||
level_curve = self.limitlevel_rising_status[patternId] if patternId != 0 else None
|
||||
|
||||
chara["stats_min"] = get_all_stats(chara, alphaBase, max_level = False, rising_status_pattern=level_curve)
|
||||
chara["stats_max"] = get_all_stats(chara, alphaBase, max_level = True, rising_status_pattern=level_curve)
|
||||
|
@ -194,6 +212,12 @@ class KF3DB:
|
|||
|
||||
return chara
|
||||
|
||||
def get_item(self, id : int):
|
||||
if id in self.itemCommon:
|
||||
return self.itemCommon[id]
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_chara(self, id : int):
|
||||
if id in self.processed_friends:
|
||||
return self.processed_friends[id]
|
||||
|
@ -512,6 +536,15 @@ class KF3DB:
|
|||
elif cosId == 55:
|
||||
cos["name"]= "のんほいパークの服"
|
||||
|
||||
elif cosId == 56:
|
||||
cos["name"]= "なないろのはごろも"
|
||||
|
||||
elif cosId == 57:
|
||||
cos["name"]= "4周年!ハッピーラッキーTシャツ"
|
||||
|
||||
elif cosId == 58:
|
||||
cos["name"]= "純情色のワンピース"
|
||||
|
||||
else:
|
||||
print(f"{costume['clothesId']}\t{costume['id']}\t{costume['name']}")
|
||||
continue
|
|
@ -0,0 +1,213 @@
|
|||
|
||||
import base64
|
||||
import os
|
||||
import gzip
|
||||
import json
|
||||
import asyncio
|
||||
import hashlib
|
||||
import platform
|
||||
|
||||
import aiohttp
|
||||
from UnityPy import enums
|
||||
|
||||
from ..Shared.utility import divide_chunks
|
||||
from ..Shared.downloading import download_bytes, download_text
|
||||
from ..Shared.convert import convert, extract
|
||||
|
||||
servers = [
|
||||
"https://parade-mobile-stg-app.kemono-friends-3.jp/",
|
||||
"https://parade-mobile-develop01-app.kemono-friends-3.jp/",
|
||||
#"https://parade-mobile-develop02-app.kemono-friends-3.jp/paradesv/",
|
||||
#"https://parade-mobile-develop03-app.kemono-friends-3.jp/paradesv/",
|
||||
#"https://parade-mobile-develop04-app.kemono-friends-3.jp/paradesv/",
|
||||
]
|
||||
|
||||
def decode(data):
|
||||
# cut off the md5 checksum at the end and the four bytes at the start
|
||||
hash = bytearray.fromhex(data[:-(2*16)][2*4:])
|
||||
key = hashlib.md5(bytearray.fromhex(data[:2*4])).digest() # md5 the key
|
||||
# xor with the key
|
||||
for i in range(0, len(hash)):
|
||||
hash[i] = hash[i] ^ key[i % (len(key))]
|
||||
return hash.decode("utf-8")
|
||||
|
||||
def encode(text):
|
||||
hashed = hashlib.md5(text.encode()).digest()
|
||||
checksum = hashlib.md5((text + "DARAPAB ").encode()).digest()
|
||||
key = hashlib.md5(hashed[:4]).digest() # md5 the key
|
||||
# xor the data with the key
|
||||
text = bytearray(text.encode())
|
||||
for i in range(0, len(text)):
|
||||
text[i] = text[i] ^ key[i % (len(key))]
|
||||
return hashed[:4].hex() + text.hex() + checksum.hex()
|
||||
|
||||
async def download_cache(server_name, server : str):
|
||||
session = aiohttp.ClientSession()
|
||||
downloaded_files = []
|
||||
|
||||
if platform.system() == "Windows":
|
||||
path = f"D:\\Codebase\\KFKDecrypt\\assets\\KF3\\{server_name}\\cache\\"
|
||||
else:
|
||||
path = f"/var/www/html/Katworks/KF/assets/KF3/{server_name}/cache/"
|
||||
|
||||
os.makedirs(path, exist_ok=True)
|
||||
|
||||
new_mst_ver = {}
|
||||
old_mst_ver = {}
|
||||
file_path_mst = path + "mstVersion.txt"
|
||||
if os.path.exists(file_path_mst):
|
||||
with open(file_path_mst, "rt", encoding="utf-8") as file:
|
||||
old_mst_ver = dict([(entry["type"], entry["version"]) for entry in json.load(file)])
|
||||
|
||||
param = encode(json.dumps({'dmm_viewer_id':0}))
|
||||
request = await download_bytes(server + "paradesv/common/MstVersion.do?param=" + param, session)
|
||||
result = gzip.decompress(request)
|
||||
new_mst = json.loads(result)
|
||||
new_mst_ver = dict([(entry["type"], entry["version"]) for entry in new_mst["mst_ver"]])
|
||||
|
||||
for key in new_mst_ver:
|
||||
file_path_gzip = path + key + ".d"
|
||||
file_path_json = path + key + ".json"
|
||||
if os.path.exists(file_path_gzip) and os.path.exists(file_path_json) and key in old_mst_ver:
|
||||
if new_mst_ver[key] == old_mst_ver[key]:
|
||||
continue
|
||||
|
||||
downloaded_files.append(key)
|
||||
param = encode(json.dumps({'type':key, 'dmm_viewer_id':0}))
|
||||
request = await download_bytes(server + "paradesv/common/MstData.do?param=" + param, session)
|
||||
result = gzip.decompress(request)
|
||||
response = json.loads(result)
|
||||
data = base64.b64decode(response["data"])
|
||||
with open(file_path_gzip, "wb") as file:
|
||||
file.write(data)
|
||||
with open(file_path_json, "wt", encoding="utf-8") as out_file:
|
||||
data = gzip.decompress(data)
|
||||
json.dump(json.loads(data), out_file, ensure_ascii=False, indent=1)
|
||||
|
||||
old_mst_ver[key] = new_mst_ver[key]
|
||||
|
||||
with open(file_path_mst, "wt", encoding="utf-8") as file:
|
||||
new_json = [{"type":type, "version":version} for type, version in zip(old_mst_ver.keys(), old_mst_ver.values())]
|
||||
json.dump(new_json, file, ensure_ascii=False)
|
||||
|
||||
await session.close()
|
||||
return downloaded_files
|
||||
|
||||
async def download_files(server_name, asset_bundle_url, srv_platform : str):
|
||||
def parse_ab_list(filecontent : str):
|
||||
out = {}
|
||||
lines = filecontent.replace("\r\n", "\n").split('\n')
|
||||
for line in lines:
|
||||
split = line.split('\t')
|
||||
if len(split) > 1:
|
||||
out[split[0]] = split[-2]
|
||||
return out
|
||||
|
||||
async def download_file(url_assets : str, file_name : str, download_path : str, session : aiohttp.ClientSession):
|
||||
data = await download_bytes(url_assets + file_name, session)
|
||||
if data != None:
|
||||
with open(download_path + file_name, "wb") as file:
|
||||
file.write(data)
|
||||
if server_name == "develop01":
|
||||
convert_path = f"/var/www/html/Katworks/KF/assets/KF3/WebGL/assets/" + file_name
|
||||
extract_path = f"/var/www/html/Katworks/KF/assets/KF3/extracted/"
|
||||
try:
|
||||
convert(data, convert_path, enums.BuildTarget.WebGL, True)
|
||||
except:
|
||||
with open(convert_path, "wb") as file:
|
||||
file.write(data)
|
||||
if file_name.endswith(".png"):
|
||||
extract(data, extract_path)
|
||||
|
||||
session = aiohttp.ClientSession()
|
||||
path = f"/var/www/html/Katworks/KF/assets/KF3/{server_name}/assets/{srv_platform}/"
|
||||
|
||||
os.makedirs(path, exist_ok=True)
|
||||
|
||||
files_to_download = []
|
||||
url_base = asset_bundle_url + "/" + srv_platform + "/1.0.0/ja/"
|
||||
url_list = url_base + "ab_list.txt"
|
||||
url_env = url_base + "ab_env.txt"
|
||||
url_assets = url_base + "assets/"
|
||||
|
||||
file_path_env = path + "ab_env.txt"
|
||||
file_path_list = path + "ab_list.txt"
|
||||
old_ab_env = ""
|
||||
|
||||
if os.path.exists(file_path_env):
|
||||
with open(file_path_env, "rt") as file:
|
||||
old_ab_env = file.read()
|
||||
|
||||
new_ab_env = await download_text(url_env, session)
|
||||
|
||||
if new_ab_env != old_ab_env:
|
||||
old_ab_list = {}
|
||||
if os.path.exists(file_path_list):
|
||||
with open(file_path_list, "rt") as file:
|
||||
old_ab_list = parse_ab_list(file.read())
|
||||
|
||||
new_ab_list_file = await download_text(url_list, session)
|
||||
new_ab_list = parse_ab_list(new_ab_list_file)
|
||||
|
||||
for key in new_ab_list:
|
||||
file_path = path + key
|
||||
if os.path.exists(file_path) and key in old_ab_list:
|
||||
if new_ab_list[key] == old_ab_list[key]:
|
||||
continue
|
||||
|
||||
files_to_download.append(key)
|
||||
|
||||
chunked_files_to_download = list(divide_chunks(files_to_download, 5))
|
||||
|
||||
for chunk in chunked_files_to_download:
|
||||
tasks = [asyncio.create_task(download_file(url_assets, file, path, session)) for file in chunk]
|
||||
await asyncio.wait(tasks)
|
||||
print(chunk)
|
||||
print()
|
||||
|
||||
with open(file_path_env, "wt", encoding="utf-8") as file:
|
||||
file.write(new_ab_env)
|
||||
with open(file_path_list, "wt", encoding="utf-8") as file:
|
||||
file.write(new_ab_list_file)
|
||||
|
||||
await session.close()
|
||||
return files_to_download
|
||||
|
||||
async def manual():
|
||||
downloaded_cache = {}
|
||||
downloaded_files = {}
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
param = encode(json.dumps({"version":"1.0.0","dmm_viewer_id":0,"platform":1}))
|
||||
request = await download_bytes(servers[0] + "paradesv/common/GetUrl.do?param=" + param, session)
|
||||
result = gzip.decompress(request)
|
||||
response = json.loads(result)
|
||||
asset_bundle_url = response["asset_bundle_url"]
|
||||
urlName = asset_bundle_url.split("-")[2]
|
||||
|
||||
print("downloading from", servers[0])
|
||||
downloaded_cache = await download_cache(urlName, servers[0])
|
||||
downloaded_files = await download_files(urlName, asset_bundle_url, "Windows")
|
||||
|
||||
if downloaded_cache != [] and downloaded_cache != None:
|
||||
with open("/var/www/html/Katworks/KF/assets/KF3/lastUpdate_prod_cache.json", "wt", encoding="utf-8") as file:
|
||||
json.dump(downloaded_cache, file, ensure_ascii=False, indent=1)
|
||||
if downloaded_files != [] and downloaded_files != None:
|
||||
with open("/var/www/html/Katworks/KF/assets/KF3/lastUpdate_prod_files.json", "wt", encoding="utf-8") as file:
|
||||
json.dump(downloaded_files, file, ensure_ascii=False, indent=1)
|
||||
|
||||
print("downloading from", servers[1])
|
||||
asset_bundle_url = "https://parade-mobile-develop01-app.kemono-friends-3.jp/AssetBundles/0.0.0/latest"
|
||||
urlName = asset_bundle_url.split("-")[2]
|
||||
downloaded_cache = await download_cache(urlName, servers[1])
|
||||
downloaded_files = await download_files(urlName, asset_bundle_url, "Windows")
|
||||
|
||||
if downloaded_cache != [] and downloaded_cache != None:
|
||||
with open("/var/www/html/Katworks/KF/assets/KF3/lastUpdate_dev_cache.json", "wt", encoding="utf-8") as file:
|
||||
json.dump(downloaded_cache, file, ensure_ascii=False, indent=1)
|
||||
if downloaded_files != [] and downloaded_files != None:
|
||||
with open("/var/www/html/Katworks/KF/assets/KF3/lastUpdate_dev_files.json", "wt", encoding="utf-8") as file:
|
||||
json.dump(downloaded_files, file, ensure_ascii=False, indent=1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(manual())
|
|
@ -5,7 +5,9 @@ import json
|
|||
|
||||
class KF3_Friend(Resource):
|
||||
def get(self, id:int):
|
||||
db = app.databases["KF3"]
|
||||
from KF3.database import Database
|
||||
db : Database = app.databases["KF3"]
|
||||
|
||||
if "wiki" in request.args:
|
||||
result = db.get_chara_wiki(id)
|
||||
|
|
@ -5,7 +5,9 @@ from flask import request
|
|||
|
||||
class KF3_Friends(Resource):
|
||||
def get(self):
|
||||
db = app.databases["KF3"]
|
||||
from KF3.database import Database
|
||||
db : Database = app.databases["KF3"]
|
||||
|
||||
result = []
|
||||
for value in db.processed_friends.values():
|
||||
result.append({"id": value["id"], "name": value["nameEn"], "startTime" : value["startTime"], "startTimeRaw" : value["startTimeRaw"]})
|
|
@ -0,0 +1,21 @@
|
|||
from flask_restful import Resource
|
||||
from flask import current_app as app
|
||||
from flask import request_tearing_down
|
||||
import json
|
||||
|
||||
class KF3_Item(Resource):
|
||||
def get(self, id:int):
|
||||
from KF3.database import Database
|
||||
db : Database = app.databases["KF3"]
|
||||
|
||||
result = db.get_item(id)
|
||||
result = json.dumps(result, ensure_ascii=False, indent=1)
|
||||
|
||||
response = app.response_class(
|
||||
response=result,
|
||||
status=200,
|
||||
mimetype='application/json'
|
||||
)
|
||||
|
||||
response.headers.add("Access-Control-Allow-Origin", "*")
|
||||
return response
|
|
@ -0,0 +1,21 @@
|
|||
import json
|
||||
from flask_restful import Resource
|
||||
from flask import current_app as app
|
||||
|
||||
class KF3_Items(Resource):
|
||||
def get(self):
|
||||
from KF3.database import Database
|
||||
db : Database = app.databases["KF3"]
|
||||
|
||||
result = []
|
||||
for value in db.itemCommon.values():
|
||||
result.append({"id": value["id"], "name": value["name"]})
|
||||
|
||||
response = app.response_class(
|
||||
response=json.dumps(result, ensure_ascii=False, indent=1),
|
||||
status=200,
|
||||
mimetype='application/json'
|
||||
)
|
||||
response.headers.add("Access-Control-Allow-Origin", "*")
|
||||
|
||||
return response
|
|
@ -0,0 +1,36 @@
|
|||
import asyncio
|
||||
from flask_restful import Resource
|
||||
from flask import current_app as app
|
||||
from ..downloader import manual
|
||||
|
||||
class KF3_Update(Resource):
|
||||
def post(self):
|
||||
from ..database import Database
|
||||
db : Database = app.databases["KF3"]
|
||||
|
||||
if db.update_in_progress:
|
||||
response = app.response_class(
|
||||
response="update in progress",
|
||||
status=200,
|
||||
mimetype='text/plain'
|
||||
)
|
||||
else:
|
||||
self.perform_update()
|
||||
response = app.response_class(
|
||||
response="update started, reload the site in a while",
|
||||
status=200,
|
||||
mimetype='text/plain'
|
||||
)
|
||||
|
||||
response.headers.add("Access-Control-Allow-Origin", "*")
|
||||
return response
|
||||
|
||||
def get(self):
|
||||
return self.post()
|
||||
|
||||
def perform_update(self):
|
||||
from ..database import Database
|
||||
db : Database = app.databases["KF3"]
|
||||
print("Update")
|
||||
#await manual()
|
||||
db.reload_data()
|
|
@ -1,17 +1,18 @@
|
|||
import json
|
||||
import platform
|
||||
from loaders.Kingdom.numeric import numeric
|
||||
from loaders.Kingdom.kemono import clean_skill_string, calculate_stats, fill_miracle, get_awaken_materials, get_skill_materials
|
||||
from .numeric import numeric
|
||||
from .kemono import clean_skill_string, calculate_stats, fill_miracle, get_awaken_materials, get_skill_materials
|
||||
|
||||
from endpoints.Kingdom.friend import Kingdom_Friend
|
||||
from endpoints.Kingdom.friends import Kingdom_Friends
|
||||
from endpoints.Kingdom.item import Kingdom_Item
|
||||
from endpoints.Kingdom.items import Kingdom_Items
|
||||
from .endpoints.item import Kingdom_Item
|
||||
from .endpoints.items import Kingdom_Items
|
||||
from .endpoints.update import Kingdom_Update
|
||||
from .endpoints.friend import Kingdom_Friend
|
||||
from .endpoints.friends import Kingdom_Friends
|
||||
|
||||
#element 1-orange 2-blue 3-green
|
||||
#showSkillType 1-control 2-guard 3-heal 4-support 5-assault 6-aoe
|
||||
|
||||
class KingdomDB:
|
||||
class Database:
|
||||
processed_friends = {}
|
||||
item_stages = {}
|
||||
|
||||
|
@ -20,10 +21,21 @@ class KingdomDB:
|
|||
if "Kingdom" in app.databases:
|
||||
del app.databases["Kingdom"]
|
||||
|
||||
self.reload_data()
|
||||
|
||||
app.databases["Kingdom"] = self
|
||||
|
||||
api.add_resource(Kingdom_Friend, "/Kingdom/Friend/<int:id>")
|
||||
api.add_resource(Kingdom_Friends, "/Kingdom/Friends")
|
||||
api.add_resource(Kingdom_Item, "/Kingdom/Item/<int:id>")
|
||||
api.add_resource(Kingdom_Items, "/Kingdom/Items")
|
||||
api.add_resource(Kingdom_Update, "/Kingdom/Update")
|
||||
|
||||
def reload_data(self):
|
||||
if platform.system() == "Windows":
|
||||
NUMERICPATH = "H:\\Apache\\Katworks\\KF\\assets\\Kingdom1\\NumericData"
|
||||
else:
|
||||
NUMERICPATH = "/media/USB2/Apache/Katworks/KF/assets/Kingdom1/NumericData"
|
||||
NUMERICPATH = "/var/www/html/Katworks/KF/assets/Kingdom1/NumericData"
|
||||
|
||||
self.kfk_drop = numeric(NUMERICPATH +"/Drop.num", 0)
|
||||
self.kfk_combo = numeric(NUMERICPATH +"/Combo.num", 0)
|
||||
|
@ -50,12 +62,6 @@ class KingdomDB:
|
|||
self.process_friends()
|
||||
self.process_stages()
|
||||
|
||||
app.databases["Kingdom"] = self
|
||||
api.add_resource(Kingdom_Friend, "/Kingdom/Friend/<int:id>")
|
||||
api.add_resource(Kingdom_Friends, "/Kingdom/Friends")
|
||||
api.add_resource(Kingdom_Item, "/Kingdom/Item/<int:id>")
|
||||
api.add_resource(Kingdom_Items, "/Kingdom/Items")
|
||||
|
||||
def process_friends(self):
|
||||
self.processed_friends = {}
|
||||
for friend_id in self.kfk_kemono.indexed_data:
|
|
@ -3,9 +3,10 @@ from flask import current_app as app
|
|||
from flask import request
|
||||
import json
|
||||
|
||||
class KF3_Update(Resource):
|
||||
class Kingdom_Update(Resource):
|
||||
def post(self):
|
||||
db = app.databases["KF3"]
|
||||
from ..database import Database
|
||||
db : Database = app.databases["Kingdom"]
|
||||
try:
|
||||
db.reload_data()
|
||||
response = app.response_class(
|
|
@ -0,0 +1,45 @@
|
|||
import io
|
||||
import os
|
||||
import UnityPy
|
||||
from UnityPy import enums
|
||||
from UnityPy.files import ObjectReader
|
||||
from PIL import Image
|
||||
|
||||
def convert(input_path : str, output_path : str, platform = enums.BuildTarget.WebGL, enable_read = False):
|
||||
env = UnityPy.load(input_path)
|
||||
|
||||
for item in env.assets:
|
||||
item._m_target_platform = int(platform)
|
||||
|
||||
for obj in env.objects:
|
||||
if obj.type == enums.ClassIDType.Texture2D:
|
||||
convert_texture(obj, platform)
|
||||
if enable_read and obj.type == enums.ClassIDType.Mesh:
|
||||
data = obj.read()
|
||||
data.m_IsReadable = True
|
||||
data.save()
|
||||
|
||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||
with open(output_path, "wb") as f:
|
||||
f.write(env.file.save(packer="lz4"))
|
||||
|
||||
def extract(input_path : str, output_path : str):
|
||||
env = UnityPy.load(input_path)
|
||||
|
||||
for obj in env.objects:
|
||||
if obj.type == enums.ClassIDType.Texture2D:
|
||||
os.makedirs(output_path, exist_ok=True)
|
||||
data = obj.read()
|
||||
data.image.save(output_path + data.name + ".png", format="PNG")
|
||||
|
||||
def convert_texture(obj : ObjectReader, target_platform : enums.BuildTarget):
|
||||
if target_platform == enums.BuildTarget.WebGL:
|
||||
data = obj.read()
|
||||
with io.BytesIO() as output:
|
||||
data.image.save(output, format="PNG")
|
||||
if data.image.width % 4 == 0 and data.image.height % 4 == 0:
|
||||
data.m_TextureFormat = enums.TextureFormat.DXT5
|
||||
else:
|
||||
data.m_TextureFormat = enums.TextureFormat.ARGB32
|
||||
data.image = Image.open(output)
|
||||
data.save()
|
|
@ -0,0 +1,9 @@
|
|||
import aiohttp
|
||||
|
||||
async def download_bytes(url, session : aiohttp.ClientSession):
|
||||
async with session.get(url) as resp:
|
||||
return await resp.read()
|
||||
|
||||
async def download_text(url, session : aiohttp.ClientSession):
|
||||
async with session.get(url) as resp:
|
||||
return await resp.text()
|
|
@ -0,0 +1,3 @@
|
|||
def divide_chunks(l, n):
|
||||
for i in range(0, len(l), n):
|
||||
yield l[i:i + n]
|
|
@ -0,0 +1,3 @@
|
|||
Flask==3.0.0
|
||||
flask_restful==0.3.10
|
||||
UnityPy==1.10.7
|
Loading…
Reference in New Issue