def games_next() -> FlaskResponse:
    next_args = {}
    share_settings = None
    if 'username' in request.args:
        username = request.args['username']
        next_args['username'] = username
        user, share_settings = resolve_public_user(username)
        if not user:
            return 'Share link not found', 404
    elif 'sharekey' in request.args:
        sharekey = request.args['sharekey']
        next_args['sharekey'] = request.args['sharekey']
        user, share_settings = resolve_share_key(sharekey)
        if not user:
            return 'Share link not found', 404
    else:
        if check_authentication() is None:
            user = session.user
        else:
            return 'Not logged in', 403

    sessions, season, include_quickplay, last_evaluated = get_sessions(
        user, share_settings=share_settings)

    if last_evaluated:
        next_args['last_evaluated'] = last_evaluated
        next_from = url_for('overwatch.games_list.games_next', **next_args)
    else:
        next_from = None

    return render_template(
        'overwatch/games_list/sessions_page.html',
        sessions=sessions,
        next_from=next_from,
    )
def games_next() -> FlaskResponse:
    next_args = {}
    share_settings = None
    if 'username' in request.args:
        username = request.args['username']
        next_args['username'] = username
        user = resolve_public_user(username)
        if not user:
            return 'Share link not found', 404
    else:
        if check_authentication() is None:
            user = session.user
        else:
            return 'Not logged in', 403

    sessions, last_evaluated = get_sessions(user)

    if last_evaluated:
        next_args['last_evaluated'] = last_evaluated
        next_from = url_for('valorant.games_list.games_next', **next_args)
    else:
        next_from = None

    return render_template(
        'valorant/games_list/sessions_page.html',
        sessions=sessions,
        next_from=next_from,
        OLDEST_SUPPORTED_GAME_VERSION=OLDEST_SUPPORTED_GAME_VERSION,
    )
Example #3
0
def context_processor():
    from overtrack_web.lib.context_processors import processors as lib_context_processors
    from overtrack_web.lib.session import session
    processors = dict(lib_context_processors)
    processors['user'] = session.user if check_authentication(
    ) is None else None
    return processors
Example #4
0
def login():
    if 'next' in request.args:
        next_ = request.args['next']
        if check_authentication() is None:
            return redirect(next_)
    else:
        next_ = request.host_url

    return render_template(
        'login.html',
        login_twitch='https://api2.overtrack.gg/login/twitch?next=' + next_,
        login_bnet='https://api2.overtrack.gg/login/battlenet?next=' + next_)
Example #5
0
def game(key: str):
    summary = OverwatchGameSummary.get(key)

    game = load_game(summary)
    game.timestamp = summary.time

    summary_dict = summary.asdict()
    summary_dict['key'] = (
        summary.key,
        f'https://overtrack-overwatch-games.s3.amazonaws.com/{summary.key}.json'
    )

    if check_authentication() is None and session.user.superuser:
        try:
            frames_url = urlparse(summary.frames_uri)
            signed_url = s3.generate_presigned_url('get_object',
                                                   Params={
                                                       'Bucket':
                                                       frames_url.netloc,
                                                       'Key':
                                                       frames_url.path[1:]
                                                   })
            summary_dict['frames_uri'] = (summary.frames_uri, signed_url)
        except:
            pass

    game_dict = {}
    for f in fields(game):
        if not is_dataclass(getattr(game, f.name)):
            game_dict[f.name] = getattr(game, f.name)
    game_dict['key'] = (
        summary.key,
        f'https://overtrack-overwatch-games.s3.amazonaws.com/{summary.key}.json'
    )

    return render_template(
        'overwatch/game/game.html',
        summary=summary,
        game=game,
        summary_dict=summary_dict,
        game_dict=game_dict,
        all_stats=asdict(game.stats.stats['all heroes'])
        if 'all heroes' in game.stats.stats else {},
        OLDEST_SUPPORTED_GAME_VERSION=OLDEST_SUPPORTED_GAME_VERSION,
    )
def games_pagination() -> FlaskResponse:
    public = 'username' in request.args
    if public:
        try:
            user = User.username_index.get(request.args['username'].lower())
        except User.DoesNotExist:
            user = None
        if not user or (not user.apex_games_public and not is_superuser()):
            return 'User not found or games not public', 404
    else:
        if check_authentication() is None:
            user = session.user
        else:
            return 'Not logged in', 403
    games_it, is_ranked, season = get_games(user, limit=PAGINATION_SIZE)
    games, next_from = paginate(games_it,
                                username=user.username if public else None)
    return render_template_string(
        '''{% import 'apex/games_list/games_page.html' as games_page with context %}
           {{ games_page.next_page(games, next_from) }}''',
        games=games,
        is_ranked=is_ranked,
        next_from=next_from,
    )
Example #7
0
def game(key: str):
    try:
        summary = OverwatchGameSummary.get(key)
    except OverwatchGameSummary.DoesNotExist:
        return 'Game does not exist', 404

    if summary.player_name and summary.result != 'UNKNOWN':
        title = f'{summary.player_name}\'s {summary.result} on {summary.map}'
    elif summary.player_name:
        title = f'{summary.player_name}\'s game on {summary.map}'
    else:
        title = f'{key.split("/", 1)[0]}\'s game on {summary.map}'

    if not summary.game_version or summary.game_version < OLDEST_SUPPORTED_GAME_VERSION or 'legacy' in request.args:
        return render_template(
            'overwatch/game/legacy_game.html',
            title=title,
            legacy_base=LEGACY_URL,
            legacy_scripts=legacy_scripts,
            legacy_stylesheet=legacy_stylesheet,
        )

    if not summary.viewable and not(check_authentication() is None and session.superuser):
        return 'Please subscribe to view game details', 403

    if summary.game_type == 'custom' and (check_authentication() is not None or (not session.superuser and session.user_id != summary.user_id)):
        return 'Custom games are restricted to being viewed by their owner', 403

    game, metadata = load_game(summary)
    game.timestamp = summary.time

    if game.teams.owner and game.result != 'UNKNOWN':
        title = f'{game.teams.owner.name}\'s {game.result} on {game.map.name}'
    elif game.teams.owner:
        title = f'{game.teams.owner.name}\'s game on {game.map.name}'

    dev_info = get_dev_info(summary, game, metadata)

    imagehash = hashlib.md5(str((game.result, game.start_sr, game.end_sr)).encode()).hexdigest()

    try:
        tfs = game.teamfights
        stat_totals = {
            'eliminations.during_fights': len(tfs.eliminations_during_fights),
            'deaths.during_fights': len(tfs.eliminations_during_fights) + len(tfs.suicides_during_fights),
            'killfeed_assists.during_fights': len(tfs.killfeed_assists_during_fights),
            'first_elims': len(tfs.first_bloods),
            'first_deaths': len(tfs.first_bloods),
            'eliminations.outside_fights': len(tfs.eliminations_outside_fights),
            'deaths.outside_fights': len(tfs.eliminations_outside_fights) + len(tfs.suicides_outside_fights),
            'killfeed_assists.outside_fights': len(tfs.killfeed_assists_outside_fights),
            'fight_starts_missed': len(tfs.teamfights),
            'times_staggered': len(tfs.teamfights),
        }
    except AttributeError:
        stat_totals = {}

    return render_template(
        'overwatch/game/game.html',

        title=title,
        meta=Meta(
            title=title,
            image_url=url_for('overwatch.game.game_card_png', key=key, _external=True) + f'?_cachebust={imagehash}',
            twitter_image_url=url_for('overwatch.game.game_card_png', key=key, _external=True) + f'?height=190&_cachebust={imagehash}',
            summary_large_image=True,
            colour=COLOURS.get(game.result, 'gray')
        ),

        # show_stats=show_stats,
        stat_totals=stat_totals,
        # get_top_heroes=get_top_heroes,
        # get_hero_color=get_hero_color,
        # get_hero_image=get_hero_image,
        # process_stat=process_stat,

        summary=summary,
        game=game,

        show_edit=check_authentication() is None and (summary.user_id == session.user_id or session.superuser),

        dev_info=dev_info,

        OLDEST_SUPPORTED_GAME_VERSION=OLDEST_SUPPORTED_GAME_VERSION,
    )
Example #8
0
def get_dev_info(summary, game, metatada):
    if check_authentication() is not None or not session.user.superuser:
        return None

    summary_dict = summary.asdict()
    summary_dict['key'] = (summary.key, f'https://overtrack-overwatch-games.s3.amazonaws.com/{summary.key}.json')
    log_id = summary_dict['log_id']
    if log_id and len(log_id) == 3 and all(log_id):
        summary_dict['log_id'] = (
            ' '.join(log_id),
            (
                f'https://us-west-2.console.aws.amazon.com/cloudwatch/home?region=us-west-2#logEventViewer:'
                f'group={log_id[0]};'
                f'stream={log_id[1]};'
                f'start={log_id[2]}'
            )
        )
    try:
        frames_url = urlparse(summary.frames_uri)
        # noinspection PyNoneFunctionAssignment
        signed_url = s3.generate_presigned_url(
            'get_object',
            Params={
                'Bucket': frames_url.netloc,
                'Key': frames_url.path[1:]
            }
        )
        summary_dict['frames_uri'] = (summary.frames_uri, signed_url)
    except:
        pass

    def _quickdump(val):
        if not isinstance(val, (tuple, str)) and isinstance(val, collections.Sequence):
            return f'... {len(val)} items'
        else:
            rep = repr(val)
            if len(rep) < 50:
                return rep
            else:
                return rep[:50 - 3] + '...'

    game_dict = {}
    extras = {
        'metadata': metatada.items(),
    }
    for f in fields(game):
        if f.name == 'images':
            game_dict['images'] = ''
            for image in game.images:
                game_dict['\u00a0' * 6 + '.' + image] = (game.images[image].rsplit('/', 1)[-1], game.images[image])
        elif not is_dataclass(getattr(game, f.name)):
            game_dict[f.name] = getattr(game, f.name)
        else:
            dc = getattr(game, f.name)
            dc_data = []
            extras[f'Game.{f.name}'] = dc_data
            for ff in fields(dc):
                val = getattr(getattr(game, f.name), ff.name)
                if is_dataclass(val):
                    dc_data.append((ff.name, ''))
                    for fff in fields(val):
                        dc_data.append(('\u00a0' * 6 + '.' + fff.name, _quickdump(getattr(val, fff.name))))
                elif isinstance(val, list) and len(val) <= 6:
                    dc_data.append((ff.name, ''))
                    for i, v in enumerate(val):
                        dc_data.append(('\u00a0' * 6 + '.' + str(i), _quickdump(v)))
                else:
                    dc_data.append((ff.name, _quickdump(val)))

    game_dict['key'] = (summary.key, f'https://overtrack-overwatch-games.s3.amazonaws.com/{summary.key}.json')

    return {
        'Summary': list(summary_dict.items()),
        'Game': list(game_dict.items()),
        'Extras': extras,
    }
Example #9
0
def root():
    if check_authentication() is None:
        return redirect(url_for('apex.games_list.games_list'), code=307)
    else:
        return welcome()
Example #10
0
def game(key: str):
    try:
        summary = ApexGameSummary.get(key)
    except ApexGameSummary.DoesNotExist:
        return 'Game does not exist', 404
    logger.info(f'Fetching {summary.url}')

    try:
        url = urlparse(summary.url)
        game_object = s3.get_object(Bucket=url.netloc.split('.')[0],
                                    Key=url.path[1:])
        game_data = json.loads(game_object['Body'].read())
    except:
        game_object = None
        logger.exception('Failed to fetch game data from S3 - trying HTTP')
        r = requests.get(summary.url)
        r.raise_for_status()
        game_data = r.json()

    game_data = compat_game_data(game_data)
    game = referenced_typedload.load(game_data, ApexGame)

    # used for link previews
    og_description = make_game_description(summary, divider='\n')
    meta = Meta(
        title=
        f'{game.squad.player.name} placed #{summary.placed}',  # TODO: find another way of getting the name,
        description=og_description,
        colour={
            1: '#ffdf00',
            2: '#ef20ff',
            3: '#d95ff'
        }.get(summary.placed, '#992e26'),
        image_url=image_url(game.squad.player.champion))

    scrim_details = None
    if summary.scrims and summary.match_id and game.match_id:
        champion_name = (game.champion or
                         {}).get('ocr_name') or summary.match_id.split('/')[1]
        matching_games = []
        for match_id in game.match_ids:
            logger.info(
                f'Checking for matching scrims with match_id={match_id}')
            for other_game in ApexGameSummary.match_id_index.query(
                    match_id,
                (ApexGameSummary.scrims == summary.scrims
                 )  # & (ApexGameSummary.key != summary.key)
            ):
                if not any(
                        any(other_game.key == g.key for g in gs)
                        for gs in matching_games):
                    for gamesets in matching_games:
                        if any(g.placed == other_game.placed
                               for g in gamesets):
                            gamesets.append(other_game)
                            break
                    else:
                        matching_games.append([other_game])

        # TODO: dedupe
        # for g in matching_games:
        #     g.player_name = ' / '.join(filter(None, [g.player_name] + list(g.squadmate_names or ())))
        scrim_details = ScrimDetails(
            champion_name,
            'Mendo Scrims (Beta)',
            sorted(matching_games, key=lambda gs: gs[0].placed),
        )
    logger.info(f'Scrim details: {scrim_details}')

    if logs and check_authentication(
    ) is None and session.superuser and game_object:
        try:
            admin_data = get_admin_data(summary, game_object)
        except:
            logger.exception('Failed to get admin data for game')
            admin_data = None
    else:
        admin_data = None

    return render_template('apex/game/game.html',
                           summary=summary,
                           game=game,
                           is_ranked=summary.rank is not None,
                           scrim_details=scrim_details,
                           meta=meta,
                           admin_data=admin_data)
Example #11
0
def root():
    if check_authentication() is None:
        return games()
    else:
        return welcome()
Example #12
0
def winrates() -> FlaskResponse:
    if check_authentication() is None:
        user = session.user
    else:
        user = None
    return render_winrates(user)
Example #13
0
def check_superuser() -> bool:
    if check_authentication() is None:
        return session.user.superuser
    else:
        return False
Example #14
0
def get_dev_info(summary, game, metatada):
    if check_authentication() is not None or not session.user.superuser:
        return None

    summary_dict = summary.asdict()
    summary_dict['key'] = (
        summary.key,
        f'https://overtrack-valorant-games.s3.amazonaws.com/{summary.key}.json'
    )
    log = metatada.get('log')
    if log:
        metatada['log'] = (
            ' '.join(log.split(':', 3)[2].split(';')),
            log,
        )

    try:
        frames_url = urlparse(summary.frames_uri)
        # noinspection PyNoneFunctionAssignment
        signed_url = s3.generate_presigned_url('get_object',
                                               Params={
                                                   'Bucket': frames_url.netloc,
                                                   'Key': frames_url.path[1:]
                                               })
        summary_dict['frames_uri'] = (summary.frames_uri, signed_url)
    except:
        pass

    def _quickdump(val):
        if not isinstance(val, (tuple, str)) and isinstance(
                val, collections.Sequence):
            return f'... {len(val)} items'
        else:
            rep = repr(val)
            if len(rep) < 50:
                return rep
            else:
                return rep[:50 - 3] + '...'

    game_dict = {}
    extras = {
        'metadata': metatada.items(),
    }
    for f in fields(game):
        if f.name == 'images':
            game_dict['images'] = ''
            for image in game.images:
                game_dict['\u00a0' * 6 + '.' +
                          image] = (game.images[image].rsplit('/', 1)[-1],
                                    game.images[image])
        elif not is_dataclass(getattr(game, f.name)):
            game_dict[f.name] = getattr(game, f.name)
        else:
            dc = getattr(game, f.name)
            dc_data = []
            extras[f'Game.{f.name}'] = dc_data
            for ff in fields(dc):
                val = getattr(getattr(game, f.name), ff.name)
                if is_dataclass(val):
                    dc_data.append((ff.name, ''))
                    for fff in fields(val):
                        dc_data.append(('\u00a0' * 6 + '.' + fff.name,
                                        _quickdump(getattr(val, fff.name))))
                elif isinstance(val, list) and len(val) <= 6:
                    dc_data.append((ff.name, ''))
                    for i, v in enumerate(val):
                        dc_data.append(
                            ('\u00a0' * 6 + '.' + str(i), _quickdump(v)))
                else:
                    dc_data.append((ff.name, _quickdump(val)))

    extras['kills'] = []
    for r in game.rounds:
        extras['kills'].append((f'Round\u00a0{r.index}', ''))
        for i, k in enumerate(r.kills):
            extras['kills'].append(('\u00a0' * 6 + f'{i}', repr(k)))
    game_dict['key'] = (
        summary.key,
        f'https://overtrack-valorant-games.s3.amazonaws.com/{summary.key}.json'
    )
    if game_dict.get('vod'):
        game_dict['vod'] = (game_dict['vod'], game_dict['vod'])

    return {
        'Summary': list(summary_dict.items()),
        'Game': list(game_dict.items()),
        'Extras': extras,
    }
def games_list() -> FlaskResponse:
    if check_authentication() is None:
        return render_games_list(session.user)
    else:
        return public_profiles_directory()