168 lines
5.3 KiB
Python
168 lines
5.3 KiB
Python
import random
|
|
from copy import deepcopy
|
|
from typing import Dict, List, Optional, Union, Tuple, Any
|
|
|
|
from core.utils.http import get_url
|
|
|
|
|
|
def get_cover_len5_id(mid) -> str:
|
|
mid = int(mid)
|
|
if mid > 10000 and mid <= 11000:
|
|
mid -= 10000
|
|
return f'{mid:05d}'
|
|
|
|
|
|
def cross(checker: List[Any], elem: Optional[Union[Any, List[Any]]], diff):
|
|
ret = False
|
|
diff_ret = []
|
|
if not elem or elem is Ellipsis:
|
|
return True, diff
|
|
if isinstance(elem, List):
|
|
for _j in (range(len(checker)) if diff is Ellipsis else diff):
|
|
if _j >= len(checker):
|
|
continue
|
|
__e = checker[_j]
|
|
if __e in elem:
|
|
diff_ret.append(_j)
|
|
ret = True
|
|
elif isinstance(elem, Tuple):
|
|
for _j in (range(len(checker)) if diff is Ellipsis else diff):
|
|
if _j >= len(checker):
|
|
continue
|
|
__e = checker[_j]
|
|
if elem[0] <= __e <= elem[1]:
|
|
diff_ret.append(_j)
|
|
ret = True
|
|
else:
|
|
for _j in (range(len(checker)) if diff is Ellipsis else diff):
|
|
if _j >= len(checker):
|
|
continue
|
|
__e = checker[_j]
|
|
if elem == __e:
|
|
return True, [_j]
|
|
return ret, diff_ret
|
|
|
|
|
|
def in_or_equal(checker: Any, elem: Optional[Union[Any, List[Any]]]):
|
|
if elem is Ellipsis:
|
|
return True
|
|
if isinstance(elem, List):
|
|
return checker in elem
|
|
elif isinstance(elem, Tuple):
|
|
return elem[0] <= checker <= elem[1]
|
|
else:
|
|
return checker == elem
|
|
|
|
|
|
class Chart(Dict):
|
|
tap: Optional[int] = None
|
|
slide: Optional[int] = None
|
|
hold: Optional[int] = None
|
|
touch: Optional[int] = None
|
|
brk: Optional[int] = None
|
|
charter: Optional[int] = None
|
|
|
|
def __getattribute__(self, item):
|
|
if item == 'tap':
|
|
return self['notes'][0]
|
|
elif item == 'hold':
|
|
return self['notes'][1]
|
|
elif item == 'slide':
|
|
return self['notes'][2]
|
|
elif item == 'touch':
|
|
return self['notes'][3] if len(self['notes']) == 5 else 0
|
|
elif item == 'brk':
|
|
return self['notes'][-1]
|
|
elif item == 'charter':
|
|
return self['charter']
|
|
return super().__getattribute__(item)
|
|
|
|
|
|
class Music(Dict):
|
|
id: Optional[str] = None
|
|
title: Optional[str] = None
|
|
ds: Optional[List[float]] = None
|
|
level: Optional[List[str]] = None
|
|
genre: Optional[str] = None
|
|
type: Optional[str] = None
|
|
bpm: Optional[float] = None
|
|
version: Optional[str] = None
|
|
charts: Optional[Chart] = None
|
|
release_date: Optional[str] = None
|
|
artist: Optional[str] = None
|
|
|
|
diff: List[int] = []
|
|
|
|
def __getattribute__(self, item):
|
|
if item in {'genre', 'artist', 'release_date', 'bpm', 'version'}:
|
|
if item == 'version':
|
|
return self['basic_info']['from']
|
|
return self['basic_info'][item]
|
|
elif item in self:
|
|
return self[item]
|
|
return super().__getattribute__(item)
|
|
|
|
|
|
class MusicList(List[Music]):
|
|
def by_id(self, music_id: str) -> Optional[Music]:
|
|
for music in self:
|
|
if music.id == music_id:
|
|
return music
|
|
return None
|
|
|
|
def by_title(self, music_title: str) -> Optional[Music]:
|
|
for music in self:
|
|
if music.title == music_title:
|
|
return music
|
|
return None
|
|
|
|
def random(self):
|
|
return random.choice(self)
|
|
|
|
def filter(self,
|
|
*,
|
|
level: Optional[Union[str, List[str]]] = ...,
|
|
ds: Optional[Union[float, List[float], Tuple[float, float]]] = ...,
|
|
title_search: Optional[str] = ...,
|
|
genre: Optional[Union[str, List[str]]] = ...,
|
|
bpm: Optional[Union[float, List[float], Tuple[float, float]]] = ...,
|
|
type: Optional[Union[str, List[str]]] = ...,
|
|
diff: List[int] = ...,
|
|
):
|
|
new_list = MusicList()
|
|
for music in self:
|
|
diff2 = diff
|
|
music = deepcopy(music)
|
|
ret, diff2 = cross(music.level, level, diff2)
|
|
if not ret:
|
|
continue
|
|
ret, diff2 = cross(music.ds, ds, diff2)
|
|
if not ret:
|
|
continue
|
|
if not in_or_equal(music.genre, genre):
|
|
continue
|
|
if not in_or_equal(music.type, type):
|
|
continue
|
|
if not in_or_equal(music.bpm, bpm):
|
|
continue
|
|
if title_search is not Ellipsis and title_search.lower() not in music.title.lower():
|
|
continue
|
|
music.diff = diff2
|
|
new_list.append(music)
|
|
return new_list
|
|
|
|
|
|
class TotalList:
|
|
def __init__(self):
|
|
self.total_list = None
|
|
|
|
async def get(self):
|
|
if self.total_list is None:
|
|
obj = await get_url('https://www.diving-fish.com/api/maimaidxprober/music_data', 200, fmt='json')
|
|
total_list: MusicList = MusicList(obj)
|
|
for __i in range(len(total_list)):
|
|
total_list[__i] = Music(total_list[__i])
|
|
for __j in range(len(total_list[__i].charts)):
|
|
total_list[__i].charts[__j] = Chart(total_list[__i].charts[__j])
|
|
self.total_list = total_list
|
|
return self.total_list
|