OsuDbCollectionParser/utils/parsedb.py
2023-10-20 16:05:52 +02:00

191 lines
7.9 KiB
Python
Executable File

#!/usr/bin/env python3
import datetime
from typing import IO
from utils.readfunctions import *
from enum import Enum, auto
import json
def parse_osu_db_beatmaps(file: IO[any],beatmap_count: int,version:int) -> list[dict]:
""" This function parse the beatmaps from the osu!.db file and returns the
data as a list of dictionaries, each dictionary represent a beatmap
Args:
file (IO[any]): the osu!.db file to read from
beatmap_count (_type_): the number of beatmaps to read
version (_type_): the version of the osu!.db file
Returns:
list[dict]: a list of dictionaries, each dictionary represent a beatmap
"""
beatmaps = []
for number in range(beatmap_count):
number_of_dash = int(((number+1)/beatmap_count)*50)
string = f"[{'#'*number_of_dash}{' '*(50 - number_of_dash)}] {number+1}/{beatmap_count}"
print(string,end="\r")
beatmap = {}
if version < 20191106:
beatmap["Data byte size"] = read_int(file)
beatmap["Artist name"] = read_string(file)
beatmap["Artist name (unicode)"] = read_string(file)
beatmap["Song name"] = read_string(file)
beatmap["Song name (unicode)"] = read_string(file)
beatmap["Creator name"] = read_string(file)
beatmap["Difficulty"] = read_string(file)
beatmap["Audio file name"] = read_string(file)
beatmap["MD5 hash"] = read_string(file)
beatmap[".osu filename"] = read_string(file)
ranked_status = read_byte(file)
ranked_status_str = ""
match ranked_status:
case 0:
ranked_status_str = "unknown"
case 1:
ranked_status_str = "unsubmitted"
case 2:
ranked_status_str = "pending/wip/graveyard"
case 3:
ranked_status_str = "unused"
case 4:
ranked_status_str = "ranked"
case 5:
ranked_status_str = "approved"
case 6:
ranked_status_str = "qualified"
case 7:
ranked_status_str = "loved"
case _:
ranked_status_str = "unknown"
beatmap["Ranked status"] = ranked_status
beatmap["Ranked status text"] = ranked_status_str
beatmap["Hitcircle number"] = read_short(file)
beatmap["Slider number"] = read_short(file)
beatmap["Spinner number"] = read_short(file)
beatmap["Last modification time"] = read_long(file)
beatmap["Approach rate"] = read_byte(file) if version <20140609 else read_single(file)
beatmap["Circle size"] = read_byte(file) if version <20140609 else read_single(file)
beatmap["HP drain"] = read_byte(file) if version <20140609 else read_single(file)
beatmap["Overall difficulty"] = read_byte(file) if version <20140609 else read_single(file)
beatmap["Slider velocity"] = read_double(file)
if version >= 20140609:
beatmap["Osu!Standard stars ratings"] = []
pair_number = read_int(file)
for i in range(pair_number):
beatmap["Osu!Standard stars ratings"].append(read_int_double_pair(file))
if version >= 20140609:
beatmap["Taiko stars ratings"] = []
pair_number = read_int(file)
for i in range(pair_number):
beatmap["Taiko stars ratings"].append(read_int_double_pair(file))
if version >= 20140609:
beatmap["CTB stars ratings"] = []
pair_number = read_int(file)
for i in range(pair_number):
beatmap["CTB stars ratings"].append(read_int_double_pair(file))
if version >= 20140609:
beatmap["Mania stars ratings"] = []
pair_number = read_int(file)
for i in range(pair_number):
beatmap["Mania stars ratings"].append(read_int_double_pair(file))
beatmap["Drain time"] = read_int(file)
beatmap["Total time"] = read_int(file)
beatmap["Audio preview time"] = read_int(file)
beatmap["Timing points"] = []
timing_point_number = read_int(file)
for i in range(timing_point_number):
beatmap["Timing points"].append(read_timing_point(file))
beatmap["Difficulty ID"] = read_int(file)
beatmap["Beatmap ID"] = read_int(file)
beatmap["Thread ID"] = read_int(file)
beatmap["Standard grade"] = read_byte(file)
beatmap["Taiko grade"] = read_byte(file)
beatmap["CTB grade"] = read_byte(file)
beatmap["Mania grade"] = read_byte(file)
beatmap["Local offset"] = read_short(file)
beatmap["Stack leniency"] = read_single(file)
game_mode = read_byte(file)
beatmap["Gameplay mode"] = game_mode
game_mode_str = ""
match game_mode:
case 0:
game_mode_str = "Osu!Standard"
case 1:
game_mode_str = "Taiko"
case 2:
game_mode_str = "CTB"
case 3:
game_mode_str = "Mania"
case _:
game_mode_str = "unknown"
beatmap["Gameplay mode text"] = game_mode_str
beatmap["Song source"] = read_string(file)
beatmap["Song tags"] = read_string(file)
beatmap["Online offset"] = read_short(file)
beatmap["Font used"] = read_string(file)
beatmap["Is unplayed"] = read_bool(file)
beatmap["Last play time"] = read_long(file)
beatmap["Is osz2"] = read_bool(file)
beatmap["Folder name"] = read_string(file)
beatmap["Last check time"] = read_long(file)
beatmap["Ignore beatmap sounds"] = read_bool(file)
beatmap["Ignore beatmap skin"] = read_bool(file)
beatmap["Disable storyboard"] = read_bool(file)
beatmap["Disable video"] = read_bool(file)
beatmap["Visual override"] = read_bool(file)
if version < 20140609:
beatmap["Unknown"] = read_byte(file)
beatmap["Last modification time"] = read_int(file)
beatmap["Mania scroll speed"] = read_byte(file)
beatmaps.append(beatmap)
print(80*" ",end="\r")
return beatmaps
def parse_osu_db(filepath:str)->dict:
""" This function parse the osu!.db file and returns the data as a dictionary
Args:
filepath (str): the path to the osu!.db file
Returns:
dict: a dictionary containing the data from the osu!.db file
"""
data = {}
with open(filepath,'rb') as db_file:
version = read_int(db_file)
data["version"] = version
data['folder count'] = read_int(db_file)
data['account blocked'] = read_bool(db_file)
data['unblock date'] = read_date_time(db_file).strftime("%d/%m/%Y, %H:%M:%S")
data['username'] = read_string(db_file)
beatmap_count = read_int(db_file)
data['beatmap count'] = beatmap_count
data['beatmaps'] = parse_osu_db_beatmaps(db_file,beatmap_count,version)
data['User permissions'] = read_int(db_file)
return data
def parse_collection_db(filepath:str)->dict:
""" This function parse the collection.db file and returns the data as a dictionary
Args:
filepath (str): the path to the collection.db file
Returns:
dict: a dictionary containing the data from the collection.db file
"""
data = {}
with open(filepath,'rb') as db_file:
version = read_int(db_file)
data["version"] = version
collection_count = read_int(db_file)
data["collection count"] = collection_count
data["collections"] = []
for i in range(collection_count):
collection = {}
collection["Name"] = read_string(db_file)
beatmap_count = read_int(db_file)
collection["Beatmap count"] = beatmap_count
collection["Beatmaps"] = []
for j in range(beatmap_count):
collection["Beatmaps"].append(read_string(db_file))
data["collections"].append(collection)
return data