Add function to create playlists from ScoreSaber leaderboards.
This commit is contained in:
parent
387a49438a
commit
4f8ec53033
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ __pycache__/
|
|||||||
dist/
|
dist/
|
||||||
*.json
|
*.json
|
||||||
archive/
|
archive/
|
||||||
|
*.bplist
|
@ -34,4 +34,5 @@ Homepage = "https://git.satstack.dev/blee/beatsaber-playlist-tool"
|
|||||||
# https://setuptools.pypa.io/en/latest/userguide/entry_point.html
|
# https://setuptools.pypa.io/en/latest/userguide/entry_point.html
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
replay_ranked_ss = "saberlist.scoresaber:replay_ranked"
|
replay_ranked_ss = "saberlist.scoresaber:replay_ranked"
|
||||||
|
ranked_leaderboards_ss = "saberlist.scoresaber:ranked_leaderboards"
|
||||||
#replay_ranked_bl = "saberlist.beatleader:replay_ranked"
|
#replay_ranked_bl = "saberlist.beatleader:replay_ranked"
|
@ -1,7 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
from pyscoresaber import ScoreSaberAPI, ScoreSort
|
from pyscoresaber import ScoreSaberAPI, ScoreSort
|
||||||
import requests
|
|
||||||
|
|
||||||
def filter_and_sort_scores_by_stars(scores, min_stars=0.1, max_stars=float('inf')):
|
def filter_and_sort_scores_by_stars(scores, min_stars=0.1, max_stars=float('inf')):
|
||||||
# Exclude scores outside the specified star range
|
# Exclude scores outside the specified star range
|
||||||
@ -10,6 +10,35 @@ def filter_and_sort_scores_by_stars(scores, min_stars=0.1, max_stars=float('inf'
|
|||||||
sorted_scores = sorted(filtered_scores, key=lambda x: x.leaderboard.stars)
|
sorted_scores = sorted(filtered_scores, key=lambda x: x.leaderboard.stars)
|
||||||
return sorted_scores
|
return sorted_scores
|
||||||
|
|
||||||
|
# TODO: combine with scores_to_playlist()
|
||||||
|
def leaderboards_to_playlist(leaderboards: list, playlist_title: str, playlist_author: str = "SaberList Tool") -> str:
|
||||||
|
playlist = {
|
||||||
|
"playlistTitle": playlist_title,
|
||||||
|
"playlistAuthor": playlist_author,
|
||||||
|
"songs": []
|
||||||
|
}
|
||||||
|
|
||||||
|
for leaderboard in leaderboards:
|
||||||
|
song_entry = {
|
||||||
|
"hash": leaderboard.song_hash,
|
||||||
|
"songName": leaderboard.song_name,
|
||||||
|
"difficulties": [
|
||||||
|
{
|
||||||
|
"name": leaderboard.difficulty.difficulty.name.lower(),
|
||||||
|
"characteristic": leaderboard.difficulty.game_mode.name.lower()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"levelAuthorName": leaderboard.level_author_name,
|
||||||
|
"songSubName": leaderboard.song_sub_name,
|
||||||
|
"songAuthorName": leaderboard.song_author_name
|
||||||
|
}
|
||||||
|
playlist["songs"].append(song_entry)
|
||||||
|
|
||||||
|
playlist_json = json.dumps(playlist, indent=4)
|
||||||
|
with open(f"{playlist_title}.bplist", 'w') as file:
|
||||||
|
file.write(playlist_json)
|
||||||
|
return playlist_json
|
||||||
|
|
||||||
def scores_to_playlist(scores, playlist_title, playlist_author = "SaberList Tool"):
|
def scores_to_playlist(scores, playlist_title, playlist_author = "SaberList Tool"):
|
||||||
playlist = {
|
playlist = {
|
||||||
"playlistTitle": playlist_title,
|
"playlistTitle": playlist_title,
|
||||||
@ -33,7 +62,7 @@ def scores_to_playlist(scores, playlist_title, playlist_author = "SaberList Tool
|
|||||||
|
|
||||||
|
|
||||||
playlist_json = json.dumps(playlist, indent=4)
|
playlist_json = json.dumps(playlist, indent=4)
|
||||||
with open(f"{playlist_title}.json", 'w') as file:
|
with open(f"{playlist_title}.bplist", 'w') as file:
|
||||||
file.write(playlist_json)
|
file.write(playlist_json)
|
||||||
|
|
||||||
return playlist_json
|
return playlist_json
|
||||||
@ -67,3 +96,59 @@ def replay_ranked():
|
|||||||
asyncio.run(async_replay_ranked())
|
asyncio.run(async_replay_ranked())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"An error occurred: {e}")
|
print(f"An error occurred: {e}")
|
||||||
|
|
||||||
|
def ranked_leaderboards():
|
||||||
|
|
||||||
|
default_min_stars = 6.0
|
||||||
|
min_stars = float(input(f"Enter the minimum starlevel to include on the playlist (Default: {default_min_stars}): ") or default_min_stars)
|
||||||
|
default_max_stars = min_stars + 0.10
|
||||||
|
max_stars = float(input(f"Enter the maximum starlevel to include on the playlist (Default: {default_max_stars}): ") or default_max_stars)
|
||||||
|
default_title = f"SS Leaderboard {min_stars}★"
|
||||||
|
playlist_title = input(f"Enter the filename for the playlist (Default: {default_title}): ") or default_title
|
||||||
|
|
||||||
|
try:
|
||||||
|
leaderboards = asyncio.run(async_leaderboards(min_stars, max_stars))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
|
||||||
|
leaderboards_to_playlist(leaderboards, playlist_title)
|
||||||
|
|
||||||
|
async def async_leaderboards(min_stars: float, max_stars: float):
|
||||||
|
params = {
|
||||||
|
"category": 3, # sort by scores
|
||||||
|
"sort": 1, # sort ascending
|
||||||
|
"max_star": max_stars,
|
||||||
|
"min_star": min_stars,
|
||||||
|
"qualified": 0, # False
|
||||||
|
"ranked": 1 # True
|
||||||
|
}
|
||||||
|
scoresaber = ExtendedScoreSaberAPI()
|
||||||
|
await scoresaber.start()
|
||||||
|
all_leaderboards = []
|
||||||
|
try:
|
||||||
|
async for leaderboard_page in scoresaber.leaderboards_all(**params):
|
||||||
|
all_leaderboards.extend(leaderboard_page)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
finally:
|
||||||
|
await scoresaber.close()
|
||||||
|
return all_leaderboards
|
||||||
|
|
||||||
|
from math import ceil
|
||||||
|
from typing import AsyncIterable, List
|
||||||
|
|
||||||
|
from pyscoresaber.models import LeaderboardInfo
|
||||||
|
class ExtendedScoreSaberAPI(ScoreSaberAPI):
|
||||||
|
async def leaderboards_all(self, **params) -> AsyncIterable[List[LeaderboardInfo]]:
|
||||||
|
page = 1
|
||||||
|
max_page = -1
|
||||||
|
while page < max_page or max_page == -1:
|
||||||
|
try:
|
||||||
|
leaderboards = await self.leaderboards(**params, page=page)
|
||||||
|
if max_page == -1:
|
||||||
|
max_page = ceil(leaderboards.metadata.total / leaderboards.metadata.items_per_page)
|
||||||
|
yield leaderboards.leaderboards
|
||||||
|
page += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred while fetching page {page}: {e}")
|
||||||
|
break
|
||||||
|
Loading…
x
Reference in New Issue
Block a user