meraki-analytics / cassiopeia

An all-inclusive Python framework for the Riot Games League of Legends API. Cass focuses on making the data easy and fun to work with, while providing all the tools necessary to create a website or do data analysis.
MIT License
552 stars 135 forks source link

Problem to get_match_history #359

Closed deadTaste closed 3 years ago

deadTaste commented 3 years ago

Hello, I ran into a problem while trying to get information on games. Maybe it's because of some standard updated libraries? Below is the request code and error:

import cassiopeia as cass from icecream import ic from cassiopeia import Season, Queue, Summoner

gamer = Summoner(name="Agurin", region="EUW") ic(gamer.id) ic(gamer.level) ic(gamer.name) ic(gamer.exists)

match_history = cass.get_match_history(summoner=gamer, queues={Queue.ranked_solo_fives}, seasons={Season.season_9}) ic(match_history)


Making call: https://euw1.api.riotgames.com/lol/summoner/v4/summoners/by-name/Agurin ic| gamer.id: 'iURguE78Q9LMsTpAO13dgHm3BEsV5AY-4Ec_NiS_vi2nYg0' ic| gamer.level: 545 ic| gamer.name: 'Agurin' ic| gamer.exists: True Traceback (most recent call last): File "E:\Python\lib\site-packages\datapipelines\sources.py", line 69, in wrapper return call(self, query, context=context) File "E:\Python\lib\site-packages\datapipelines\queries.py", line 326, in wrapped return method(self, query, context) File "E:\Python\lib\site-packages\cassiopeia\datastores\ghost.py", line 470, in get_match_history generator = MatchHistory.from_generator(generator=generator, summoner=summoner, File "E:\Python\lib\site-packages\cassiopeia\core\match.py", line 334, in from_generator CassiopeiaLazyList.init(self, generator=generator, kwargs) File "E:\Python\lib\site-packages\cassiopeia\core\common.py", line 336, in init self.init(kwargs) File "E:\Python\lib\site-packages\cassiopeia\core\match.py", line 285, in init begin_time = begin_time.timestamp 1000 TypeError: unsupported operand type(s) for : 'method' and 'int'

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "E:/GitFolder/my_proj/main.py", line 97, in match_history = cass.get_match_history(summoner=gamer, queues={Queue.ranked_solo_fives}, seasons={Season.season_9}) File "E:\Python\lib\site-packages\cassiopeia\cassiopeia.py", line 70, in get_match_history return MatchHistory(summoner=summoner, begin_index=begin_index, end_index=end_index, begin_time=begin_time, end_time=end_time, queues=queues, seasons=seasons, champions=champions) File "E:\Python\lib\site-packages\cassiopeia\core\common.py", line 214, in call return pipeline.get(cls, query=query) File "E:\Python\lib\site-packages\datapipelines\pipelines.py", line 459, in get return handler.get(query, context) File "E:\Python\lib\site-packages\datapipelines\pipelines.py", line 185, in get result = self._source.get(self._source_type, deepcopy(query), context) File "E:\Python\lib\site-packages\datapipelines\sources.py", line 71, in wrapper raise DataSource.unsupported(type) datapipelines.common.UnsupportedError: The type "MatchHistory" is not supported by this DataSource!

Process finished with exit code 1

jjmaldonis commented 3 years ago

Ahh, the Riot API doesn't support data that far back. Riot deletes match data more than two years old, and timeline data more than one year old. The Riot API also barely supports the season parameter, so you're much better off using begin-time and end-time. Cass has a Patch object to help identify those dates.

deadTaste commented 3 years ago

Well, I decided to try using the example match_collection.py in which I changed the line patch = Patch.from_str ("8.9", region = region) to patch = Patch.from_str ("11.2", region = region) and the result is generally the same. Maybe I'm doing something wrong?

Making call: https://cdn.merakianalytics.com/riot/lol/resources/patches.json ic| patch: <cassiopeia.core.patch.Patch object at 0x00000238434F77F0> Making call: https://ru.api.riotgames.com/lol/summoner/v4/summoners/by-name/deadTaste Making call: https://ru.api.riotgames.com/lol/summoner/v4/summoners/RJb6-3Zwf8YBgGgxk-J3HMod_IJryf6uyMNzlGdn3r64ctc Traceback (most recent call last): File "E:/GitFolder/my_proj/timeline.py", line 59, in collect_matches() File "E:/GitFolder/my_proj/timeline.py", line 38, in collect_matches matches = filter_match_history(new_summoner, patch) File "E:/GitFolder/my_projtimeline.py", line 15, in filter_match_history match_history = MatchHistory(summoner=summoner, queues={Queue.ranked_solo_fives}, begin_time=patch.start, end_time=end_time) File "E:\Python\lib\site-packages\cassiopeia\core\common.py", line 211, in call query = cls.get_query_from_kwargs(**kwargs) File "E:\Python\lib\site-packages\cassiopeia\core\match.py", line 309, in get_query_from_kwargs begin_time = begin_time.timestamp 1000 TypeError: unsupported operand type(s) for : 'method' and 'int'

Process finished with exit code 1

jjmaldonis commented 3 years ago

You are getting a very different error message this time, and it looks like it has something to do with your code specifically. I would recommend hopping on the Riot API discord server and asking some questions there, they can get you up and running for sure.

deadTaste commented 3 years ago

Thanks for the answer, but I do not understand how the Riot API discord server can help to solve the issue. That kind of functionality works. A problem arises when an attempt is made to retrieve match data. The error is generated in the Сass library

jjmaldonis commented 3 years ago

The reason I directed you to the Riot API discord is because they have plenty of experience with using Cass, so you can not only get direct help from them about the Riot API, but also about Cass. I am also active on that discord and could have looked at your issue in more detail there.

Second, the error message above indicates that you're passing the wrong variable into the code, which isn't an issue with Cass but rather an issue with your code. I can't help you with that since I can't see your code -- you'd need to paste it here, which is the first thing people on the Riot API discord will ask you to do.

Third, as far as I know nothing in the last three years has changed with the match history endpoint, so I think it's very unlikely that something is wrong with Cass in this regard. It's always possible that something has changed, but typically we know about it before hand or hear about it immediately on the Riot API discord.

To make sure, I started up Cass and checked the match_collection.py script, and made the changes you mentioned. It works correctly on my computer with no issues. Below is a full copy of the code I used, minus my API key.

I'm going to close this issue because I don't think Cass is having any errors. And really, the Riot API discord can be very helpful with stuff like this, and I hope the code code clarifies the issues you're running into.

import random
from sortedcontainers import SortedList
import arrow

import cassiopeia as cass
from cassiopeia.core import Summoner, MatchHistory, Match
from cassiopeia import Queue, Patch

cass.set_riot_api_key("...")

def filter_match_history(summoner, patch):
    end_time = patch.end
    if end_time is None:
        end_time = arrow.now()
    match_history = MatchHistory(summoner=summoner, queues={Queue.aram}, begin_time=patch.start, end_time=end_time)
    return match_history

def collect_matches():
    initial_summoner_name = "Agurin"
    region = "EUW"

    summoner = Summoner(name=initial_summoner_name, region=region)
    patch = Patch.from_str("11.2", region=region)

    unpulled_summoner_ids = SortedList([summoner.id])
    pulled_summoner_ids = SortedList()

    unpulled_match_ids = SortedList()
    pulled_match_ids = SortedList()

    while unpulled_summoner_ids:
        # Get a random summoner from our list of unpulled summoners and pull their match history
        new_summoner_id = random.choice(unpulled_summoner_ids)
        new_summoner = Summoner(id=new_summoner_id, region=region)
        matches = filter_match_history(new_summoner, patch)
        unpulled_match_ids.update([match.id for match in matches])
        unpulled_summoner_ids.remove(new_summoner_id)
        pulled_summoner_ids.add(new_summoner_id)

        while unpulled_match_ids:
            # Get a random match from our list of matches
            new_match_id = random.choice(unpulled_match_ids)
            new_match = Match(id=new_match_id, region=region)
            for participant in new_match.participants:
                if participant.summoner.id not in pulled_summoner_ids and participant.summoner.id not in unpulled_summoner_ids:
                    unpulled_summoner_ids.add(participant.summoner.id)
            # The above lines will trigger the match to load its data by iterating over all the participants.
            # If you have a database in your datapipeline, the match will automatically be stored in it.
            unpulled_match_ids.remove(new_match_id)
            pulled_match_ids.add(new_match_id)

if __name__ == "__main__":
    collect_matches()
deadTaste commented 3 years ago

Thanks a lot

jjmaldonis commented 3 years ago

Okay so you were right, this is largely a Cass issue - sorry about that. It looks like Rob helped you out in the discord as well. It turns out that Arrow, a python library that Cass uses, recently upgraded to 1.0 and made breaking changes in their API. It worked fine on my computer because I didn't have Arrow 1.0.

We've pinned the Arrow version to < 1.0 in the requirements file, so that will work for now, and we'll get a backwards and forwards compatible fix in sometime soon.