hash of beatmap file

This commit is contained in:
Emily 2019-03-13 06:32:21 +01:00
parent a94baeac62
commit fddb66fb86

View File

@ -7,11 +7,26 @@ from .helpers import osuMods
from .helpers import osuRanks from .helpers import osuRanks
from .helpers import typeSerializer from .helpers import typeSerializer
from io import BufferedReader
from os.path import isfile from os.path import isfile
from hashlib import md5 as _md5 from hashlib import md5 as _md5
def md5(str): def md5_str(data):
return _md5(str.encode("ascii")).hexdigest().encode() if type(data) is str:
data = data.encode("ascii")
return _md5(data).hexdigest().encode()
def md5_file(file):
if type(file) is not BufferedReader:
raise Exception("File is not a BufferedReader")
if file.mode != "rb":
raise Exception("File is not in ReadBytes mode")
hash = _md5()
for chunk in iter(lambda: file.read(4096), b""):
hash.update(chunk)
return hash.hexdigest()
class Replay: class Replay:
mode = osuModes.STANDARD # Byte mode = osuModes.STANDARD # Byte
@ -31,7 +46,7 @@ class Replay:
perfect = True # Byte perfect = True # Byte
mods = osuMods.NOMOD # Int mods = osuMods.NOMOD # Int
lifebar_graph = b"0|1," # Byte[] lifebar_graph = b"0|1," # Byte[]
timestamp = 0 # Long timestamp = 0 # Long
@ -50,58 +65,64 @@ class Replay:
for k, v in kwargs.items(): for k, v in kwargs.items():
if k in allowed_kwargs.keys(): if k in allowed_kwargs.keys():
allowed_kwargs[k](v) # Run callback func allowed_kwargs[k](v) # Run callback func
# Set validators ----------------------------------------------------------- # Set validators -----------------------------------------------------------
def set_mode(self, mode_id): def set_mode(self, mode_id):
if mode_id > 3 or mode_id < 0: if mode_id > 3 or mode_id < 0:
raise Exception("Invalid mode") raise Exception("Invalid mode")
self.mode_id = mode_id self.mode_id = mode_id
def set_osu_version(self, osu_version): def set_osu_version(self, osu_version):
if type(osu_version) is not int: if type(osu_version) is not int:
raise Exception("osu! version must be an int") raise Exception("osu! version must be an int")
self.osu_version = osu_version self.osu_version = osu_version
def set_beatmap_hash(self, md5_hash): def set_beatmap_hash(self, md5_hash):
if len(md5_hash) != 32 or len([x for x in md5_hash if x in string.hexdigits]) != 32: if len(md5_hash) != 32 or len([x for x in md5_hash if x in string.hexdigits]) != 32:
raise Exception("Invalid beatmap hash") raise Exception("Invalid beatmap hash")
self.beatmap_hash = md5_hash self.beatmap_hash = md5_hash
def set_beatmap(self, filepath):
if not isfile(filepath):
raise Exception("Beatmap file not found")
with open(filepath, "rb") as f:
self.beatmap_hash = md5_file(f)
def set_player_name(self, player_name): def set_player_name(self, player_name):
self.player_name = player_name self.player_name = player_name
def set_score_hash(self, md5_hash): def set_score_hash(self, md5_hash):
if type(md5_hash) is bytes: if type(md5_hash) is bytes:
md5_hash = md5_hash.decode() md5_hash = md5_hash.decode()
if len(md5_hash) != 32 or len([x for x in md5_hash if x in string.hexdigits]) != 32: if len(md5_hash) != 32 or len([x for x in md5_hash if x in string.hexdigits]) != 32:
raise Exception("Invalid replay hash") raise Exception("Invalid replay hash")
self.score_hash = md5_hash.encode() self.score_hash = md5_hash.encode()
def set_mods(self, mods): def set_mods(self, mods):
if mods < 0 or mods > (1 << 30) - 1: if mods < 0 or mods > (1 << 30) - 1:
raise Exception("Mods are out of range") raise Exception("Mods are out of range")
self.mods = mods self.mods = mods
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Update variables --------------------------------------------------------- # Update variables ---------------------------------------------------------
def update_perfect(self): def update_perfect(self):
m = [self.score_100s, self.score_50s, self.score_katus, self.score_miss] m = [self.score_100s, self.score_50s, self.score_katus, self.score_miss]
self.perfect = sum(m) == 0 self.perfect = sum(m) == 0
def update_score_hash(self): def update_score_hash(self):
self.set_score_hash( self.set_score_hash(
md5("%d%s%s%s%d%d" % ( md5_str("%d%s%s%s%d%d" % (
self.combo, "osu", self.player_name, self.combo, "osu", self.player_name,
self.beatmap_hash, self.score, self.get_rank() self.beatmap_hash, self.score, self.get_rank()
)) ))
) )
def update(self): def update(self):
self.update_perfect() self.update_perfect()
self.update_score_hash() self.update_score_hash()
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Get / Helpers ------------------------------------------------------------ # Get / Helpers ------------------------------------------------------------
@ -131,7 +152,7 @@ class Replay:
if r300 > .6: if r300 > .6:
return osuRanks.C return osuRanks.C
return osuRanks.D return osuRanks.D
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Write replay data -------------------------------------------------------- # Write replay data --------------------------------------------------------
@ -140,9 +161,9 @@ class Replay:
for _frame in frame: # (frames) for _frame in frame: # (frames)
self.write(_frame) self.write(_frame)
return return
self.replay_data += bytes(frame) self.replay_data += bytes(frame)
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# IO replay data ----------------------------------------------------------- # IO replay data -----------------------------------------------------------