# download most played beatmaps

> Source: <https://gist.github.com/Sheppsu/920f7d751d696a1cd7b944ae90ea8786>
> Published: 2024-10-07 19:30:24+00:00

download_most_played.py

      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      
Learn more about bidirectional Unicode characters

 
    Show hidden characters

"""

Requires osu.py (https://github.com/sheppsu/osu.py)

Can install via pip with "pip install osu.py"

Also must insert your osu api (v2) client id and client secret below where it says "CLIENT_ID" and "CLIENT_SECRET." You can get a client id and client secret via your settings on the osu website, at the bottom, where it says "OAuth."

"""

from osu import Client, UserBeatmapType

import requests

import os

import time

CLIENT_ID = 0

CLIENT_SECRET = "****"

if CLIENT_ID == 0:

    print("Edit the CLIENT_ID and CLIENT_SECRET variables before running the script. Read the docstring at the top of the file for more info.")

    quit()

client = Client.from_client_credentials(CLIENT_ID, CLIENT_SECRET, None)

def get_user():

    user = input("User to fetch from (username): ").strip()

    try:

        user = client.get_user(user, key="username")

    except:

        print("Unable to find a user by that name")

        return

    return user

 

 

def get_limit():

    while True:

        try:

            return int(input("Number of beatmaps to download: ").strip())

        except ValueError:

            print("Input a valid integer")

 

 

def yield_beatmaps(user_id, limit):

    cnt = 0

    while limit-cnt > 0:

        max_limit = min(50, limit-cnt)

        for beatmap in client.get_user_beatmaps(user_id, UserBeatmapType.MOST_PLAYED, max_limit, cnt):

            yield beatmap

        cnt += max_limit

 

 

def download_beatmapset(beatmap):

    attempts = 0

    while True:

        try:

            resp = requests.get(f"https://catboy.best/d/{beatmap.beatmapset.id}")

        except Exception as exc:

            print("Failed to download: ", exc)

            print("Retrying in a second...")

            time.sleep(1)

            continue

 

        map_string = f"{beatmap.beatmapset.artist} - {beatmap.beatmapset.title} ({beatmap.beatmapset.id})"

        # returns 200, 404, or 500 according to docs

        if resp.status_code == 200:

            with open(f"beatmap_downloads/{beatmap.beatmapset.id}.osz", "wb") as f:

                for chunk in resp.iter_content(4096):

                    f.write(chunk)

            print(f"Downloaded {map_string}")

            break

        elif resp.status_code == 404:

            print(f"Unable to find {map_string}")

        elif resp.status_code == 500:

            print(f"The api returned a server error for {map_string}")

        else:

            print(f"Failed to download {map_string} (HTTP {resp.status_code}")

 

        attempts += 1

        if attempts == 3:

            break

 

        print("Trying again in a second...")

        time.sleep(1)

if not os.path.isdir("beatmap_downloads"):

    os.mkdir("beatmap_downloads")

user = get_user()

limit = get_limit()

beatmapsets_downloaded = []

for beatmap in yield_beatmaps(user.id, limit):

    if beatmap.beatmapset.id in beatmapsets_downloaded:

        continue

    beatmapsets_downloaded.append(beatmap.beatmapset.id)

 

    start = time.monotonic()

    download_beatmapset(beatmap)

    time.sleep(max(1 - (time.monotonic() - start), 0))  # stay under 1 request per second

 

print("Finished downloading!")
