tybug / ossapi

The definitive python wrapper for the osu! api.
https://tybug.github.io/ossapi/
GNU Affero General Public License v3.0
80 stars 17 forks source link

Invalid GameMode 123 #48

Closed reinum closed 2 years ago

reinum commented 2 years ago

Im trying to make automatic clip bot, that scrapes user replays, downloads .osr, and does other shit.

I tried to use ossapi to scrape and download a replay, but as soon as Im trying to download a replay, it throws ValueError: 123 is not a valid GameMode.

Code:

from ossapi import OssapiV2
api = OssapiV2("app id", "app key", "redirect url")
import requests
import base64

def get_replay(userid):
    """This function gets the latest replay.

Returns None if no new recent replays are made.
Else it returns the replay."""

    # gets the 30th top play pp
    wtp = api.user_scores(userid, "best", limit=30)[-1].pp
    # gets the last 10 scores
    scores = score = api.user_scores(userid, "recent", limit=10)
    # opens the replays.txt, so we dont process replays that have been already rendered and shit
    rendered = open("replays.txt").read().splitlines()
    for cn in range(0, 60):
        score = scores[cn] # grabs score
        pp = score.pp # gets pp
        if pp == None: # loved maps return None PP, so i change it to 0 if its none to make it work normally
            pp = 0
        score_id = score.id # score id
        print(wtp, pp, score.pp, cn, score.id) # debugging, ignore

        # checks if the score pp is more than 30th top play, and isnt rendered
        if pp >= wtp and score_id not in rendered:
            api.download_score(mode="osu", score_id=score.id)
            print("found")
            break

# call
get_replay(11917029)
tybug commented 2 years ago

I can't reproduce given your script, possibly because the score has passed out of the user's recent plays. Can you narrow this down to a single score id which results in this error when api.download_score(mode="osu", score_id) is called?

reinum commented 2 years ago

Oh, sorry, I forgot. The score ID is 19403445646.

tybug commented 2 years ago

That score...doesn't exist? https://osu.ppy.sh/scores/osu/19403445646

tybug commented 2 years ago

I think I see what happened here - you called api.download_score with a nonexistent score id. The api returns a response of b'{"error":null}', which we blindly feed to osrparse. We should check the response for an error and raise before trying to parse the replay.

For now, this is an error on your end ;)

reinum commented 2 years ago

How is this possible though? The value score.id returned that...?

reinum commented 2 years ago

I will find the score ID using the osu website, and ill try to download the replay with that ID through ossapi / osrparse. I will let you know if it threw an error, or something

tybug commented 2 years ago

You want score.best_id, not score.id. I'm not entirely sure what the difference is (and it's not documented anywhere), but I suspect score.best_id increments once per replay set and score.best_id increments once per stored (top 1k) replay set.

reinum commented 2 years ago

Oh. Why is this so confusing lol

reinum commented 2 years ago

Now its throwing AttributeError: module 'osrparse' has no attribute 'parse_replay'... what?

tybug commented 2 years ago

Are you using osrparse 6.x.x and the latest version of ossapi? pip install -U ossapi, pip install -U osrparse.

reinum commented 2 years ago

oh... yeah i had out of date ossapi, lol but its throwing ValueError: 123 is not a valid GameMode again... what is going on??

from ossapi import *
api = OssapiV2("id", "secret", "url")
print(api.download_score(mode="osu", score_id=4056787666))

https://osu.ppy.sh/scores/osu/4056787666

tybug commented 2 years ago

That replay isn't downloadable, so of course you can't download it.

I think I take back what I said about id vs best_id - I still don't understand the distinction, but it's clear that even when best_id is available, the replay isn't always downloadable (see above).

What I would recommend is continue to use score.best_id, but check score.replay before trying to download. If score.replay is False, the score isn't downloadable and you should skip it. Otherwise, you can download it as normal.

tybug commented 2 years ago

I'm going to consider the only actionable part of this issue (confusing error messages) closed with 6c6b265a4ba6b9c429df5a08580b6fc34fd6f66e.