Beispiel #1
0
async def stalk_toornament_team(
    toornament_team_link: str, session: aiohttp.ClientSession = None
):
    """
    Stalks all players in the given team and returns a Team Object
    :raises ServerErrorResponseError, NotFoundResponseError
    :param toornament_team_link: Link to a toornament team page
    :type toornament_team_link: str
    :param session: A session that can be reused, if none is given, a new one will be created
    :type session: aiohttp.ClientSession
    :return: team containing all players of the given team
    :rtype: Team
    """

    if session is None:
        async with aiohttp.ClientSession() as session:
            return await stalk_toornament_team(toornament_team_link, session)

    edited_url = toornament_team_link + "info"
    async with session.get(edited_url) as response:
        if response.status >= 500:
            logger.error(f"Stalking {edited_url} resulted in a server error.")
            raise ServerErrorResponseError

        # check if toornament page was valid
        if response.status == 404:
            logger.error(f"No team could be found for {edited_url}.")
            raise NotFoundResponseError

        page = await response.text()

    toornament_soup = bs4.BeautifulSoup(page, features="html.parser")

    # extract team name
    team_name = toornament_soup.select(
        "#main-container > div.layout-section.header > div > div.layout-block.header > "
        "div > div.title > div > span"
    )[0].text
    name_containers = toornament_soup.find_all(
        "div", class_="text secondary small summoner_player_id"
    )

    players = []
    for container in name_containers:
        dirty_string = container.text

        dirty_split = dirty_string.split(":")
        # In case someone decides not to enter an actual summoner name
        if len(dirty_split) == 2:
            name = dirty_split[1]
        else:
            continue
        name = name.replace("\n", "")
        name = name.strip()
        players.append(Player(name))

    return Team(team_name, players)
Beispiel #2
0
async def test_positive_stalk_player_op_gg():
    from PykeBot2.backend.stalker import op_gg_rank
    from PykeBot2.models.data_models import Player, Rank

    test_player = Player("UFF NiceToMeetMe")

    test_rank = Rank(rank_string=await op_gg_rank.stalk_player_op_gg(test_player.summoner_name))

    assert str(test_rank) == "Platinum 1"
Beispiel #3
0
async def stalk_battlefy_tournament(battlefy_url: str):
    """
    Uses undocumented Battlefy API to scrape tournament participants.
    :param battlefy_url: A valid url to a battlefy tournament.
    :type battlefy_url: str
    :return: a TeamList object containing all Teams and Players of the given tournament.
    :rtype: TeamList
    """

    # extract tournament id from url
    battlefy_url_split = battlefy_url.split("/")

    tournament_id = battlefy_url_split[5]

    # create link for http request by inserting the tournament id
    tournament_api_url = (
        f"https://dtmwra1jsgyb0.cloudfront.net/tournaments/{tournament_id}/teams?"
    )

    # make the request
    async with aiohttp.ClientSession() as session:
        async with session.get(tournament_api_url) as response:
            page = await response.text()

    # parse the data to create Team and Player Objects
    soup = bs4.BeautifulSoup(page, features="html.parser")

    json_data = json.loads(soup.text)

    # print(json.dumps(json_data, indent=4, separators=(". ", " = ")))

    teams = []

    for team in json_data:
        team_name = team["name"]
        players = []
        for player in team["players"]:
            player_name = player["inGameName"]
            player_obj = Player(player_name)
            # ranks are often not up to date so just normal rank addition for now
            # try to add rank if player stats are available
            # player_stats = player.get("stats", None)
            # if player_stats is not None:
            #    player_rank_str = player_stats["tier"] + " " + player_stats["rank"]
            #    player_rank = Rank(rank_string=player_rank_str)
            #    player_obj.rank = player_rank
            players.append(player_obj)
        new_team = Team(team_name, players)
        # calc_average_and_max_team_rank(new_team)
        teams.append(new_team)

    team_list = TeamList(battlefy_url_split[4], teams)

    return team_list
Beispiel #4
0
async def stalk_prime_league_team(prime_league_team_link: str,
                                  session: aiohttp.ClientSession = None):
    """
    :description: Uses aiohttp requests to stalk a prime league team.
    :param prime_league_team_link:
    :type prime_league_team_link:
    :param session: When a session already exits, it should be reused as much as possible for better performance.
    :type session: aiohttp.ClientSession
    :return: Team object containing all the gathered information.
    :rtype: Team
    """

    if session is None:
        async with aiohttp.ClientSession() as session:
            return await stalk_prime_league_team(prime_league_team_link,
                                                 session)

    async with session.get(prime_league_team_link) as response:
        # TODO add error handling
        page = await response.text()

    # Select Teammitglieder Container and find team name
    soup = bs4.BeautifulSoup(page, features="html.parser")
    player_container = soup.find("ul", class_="content-portrait-grid-l")

    # check if the team was deleted
    if player_container is None:
        return None

    team_container = soup.find("div", class_="content-portrait-head")
    # behind the team name is always " « League Teams « Prime League", which needs to be removed
    # this solution will fail if a team uses « in their name
    team_name = soup.title.text.split("«")[0].strip()

    # extract player names
    player_boxes = player_container.find_all("li")
    tuple_list = []
    for box in player_boxes:
        confirmed = box.find("span", class_="txt-status-positive")
        player_info = box.find(
            "span", title="League of Legends » LoL Summoner Name (EU West)")
        tuple_list.append((player_info, confirmed))

    # create Team object and filter out unconfirmed player
    player_names = []
    confirmed_check = "Bestätigter Spieler"
    for player, confirm in tuple_list:
        if confirm is not None and confirm.text == confirmed_check:
            player_obj = Player(player.text)
            player_names.append(player_obj)

    return Team(team_name, player_names)
Beispiel #5
0
async def add_player_rank(player: Player,
                          session: aiohttp.ClientSession = None):
    """
    :description: Calls stalk player op gg using the summoner name of the given Player and adds a Rank obj to the Player.
    :param player: A Player obj with a summoner name.
    :type player: Player
    :param session: When a session already exits, it should be reused as much as possible for better performance.
    :type session: aiohttp.ClientSession
    :return: None
    :rtype: None
    """
    if session is None:
        async with aiohttp.ClientSession() as session:
            return await add_player_rank(player, session)

    player.rank = Rank(
        rank_string=await stalk_player_op_gg(player.summoner_name, session))
    return
Beispiel #6
0
def parse_participants(participants: List[dict],
                       tournament_name: str) -> TeamList:
    """
    Parses the given participant list and tournament name to create a TeamList object.
    :param participants: Expects a participant list created from the toornament api.
    :type participants: list[dict]
    :param tournament_name: The name of the tournament.
    :type tournament_name: str
    :return: A TeamList object created from the given participant list and tournament name.
    :rtype: TeamList
    """
    total = {}
    for team in participants:
        total[team["id"]] = team

    teams = []
    for team_entry in total.values():
        team_name = team_entry["name"]
        team_lineup = team_entry["lineup"]
        players = []
        for lineup_entry in team_lineup:
            custom_fields = lineup_entry["custom_fields"]
            keys = custom_fields.keys()
            summoner_name_field = None
            for key in keys:
                if "summoner" in key:
                    summoner_name_field = key
                    break
            if summoner_name_field is None:
                # if summoner_name_field is private or not set, try using the name
                player_summoner_name = lineup_entry["name"]
            else:
                player_summoner_name = lineup_entry["custom_fields"][
                    summoner_name_field]

            if player_summoner_name is None:
                continue
            player = Player(player_summoner_name)
            players.append(player)
        team = Team(team_name, players)
        teams.append(team)

    team_list = TeamList(tournament_name, teams)
    return team_list
Beispiel #7
0
async def add_player_rank(player: Player, api_token: str, session=None):
    """
    :description: Calls stalk player riot using the summoner name of the given Player and adds a Rank obj to the Player.
    :param player: A Player obj with a summoner name.
    :type player: Player
    :param api_token: Valid Riot api token.
    :type api_token: str
    :param session: When a session already exits, it should be reused as much as possible for better performance.
    :type session: aiohttp.ClientSession  or RateLimiter
    :return: None
    :rtype: None
    """
    if session is None:
        async with aiohttp.ClientSession() as session:
            session = RateLimiter(session)
            return await add_player_rank(player, api_token, session)

    player.rank = Rank(rank_string=await stalk_player_riot_api(
        player.summoner_name, api_token, session))
    return