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, )
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
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_)
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, )
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, )
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, }
def root(): if check_authentication() is None: return redirect(url_for('apex.games_list.games_list'), code=307) else: return welcome()
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)
def root(): if check_authentication() is None: return games() else: return welcome()
def winrates() -> FlaskResponse: if check_authentication() is None: user = session.user else: user = None return render_winrates(user)
def check_superuser() -> bool: if check_authentication() is None: return session.user.superuser else: return False
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()