def get_response( self, body ): body_type = body.get( 'type' ) # Currently 5 types: verifylogin, gamelist, categories, gamecategories # and submitrun if body_type is None: return self.get_fail_response( "No type given." ) elif body_type == 'verifylogin': ( valid, response ) = self.verify_login( body ) return response elif body_type == 'gamelist': return self.get_fail_response( "Type [" + body_type + "] currently" + " not supported dynamically, but " + "you can find a static JSON " + "response at " + "https://www.dropbox.com/s/" + "xnvsmx3mt0i4nbv/gamelist.json?dl" + "=0" ) elif body_type == 'categories': return self.get_fail_response( "Type [" + body_type + "] currently" + " not supported dynamically, but " + "you can find a static JSON " + "response at " + "https://www.dropbox.com/s/" + "irdj4xakh72g541/categories.json?" + "dl=0" ) elif body_type == 'modgamelist': # First, verify login credentials and that we are a mod ( valid, response ) = self.verify_mod_login( body ) if not valid: return response # Note that this is a different type of gamelist than the one # generated in games.py categories = self.get_categories( ) if categories == self.OVER_QUOTA_ERROR: return self.get_fail_response( "PB Tracker is currently " + "experiencing an over " + "quota downtime period." ) d = dict( ) for game in categories.keys( ): d[ util.get_code( game ) ] = game return self.get_success_response( data=d ) elif body_type == 'modcategories': # First, verify login credentials and that we are a mod ( valid, response ) = self.verify_mod_login( body ) if not valid: return response categories = self.get_categories( ) if categories == self.OVER_QUOTA_ERROR: return self.get_fail_response( "PB Tracker is currently " + "experiencing an over " + "quota downtime period." ) d = dict( ) for game, categorylist in categories.iteritems( ): game_code = util.get_code( game ) for category in categorylist: category_code = util.get_code( category ) d[ game_code + ':' + category_code ] = ( game + ' - ' + category ) return self.get_success_response( data=d ) elif body_type == 'gamecategories': return self.get_fail_response( "Type [" + body_type + "] currently" + " not supported, sorry." ) # game_code = body.get( 'game' ) # game_model = self.get_game_model( game_code ) # if game_code is None: # return self.get_fail_response( 'No game specified' ) # elif game_model is None: # return self.get_fail_response( 'Unknown game [' # + game_code + '].' ) # TODO: elif game_model == self.OVER_QUOTA_ERROR: # else: # d = dict( ) # gameinfolist = json.loads( game_model.info ) # for gameinfo in gameinfolist: # category = gameinfo['category'] # d[ util.get_code( category ) ] = category # return self.get_success_response( data=d ) elif body_type == 'submitrun': # First, verify login credentials ( valid, response ) = self.verify_login( body ) if not valid: return response # Grab the params from the body username = body.get( 'username' ) game_code = body.get( 'game' ) category_code = body.get( 'category' ) version = body.get( 'version' ) time = body.get( 'runtime' ) video = body.get( 'video' ) notes = body.get( 'comment' ) splits = body.get( 'splits' ) # Make sure the game and category exist (can't handle new games # and categories just yet) if game_code is None: return self.get_fail_response( 'No game given' ) game_model = self.get_game_model( game_code ) if game_model is None: return self.get_fail_response( 'Unknown game [' + game_code + '].' ) if game_model == self.OVER_QUOTA_ERROR: return self.get_fail_response( 'PB Tracker is currently over ' + "quota. Please try again " + "later." ) if category_code is None: return self.get_fail_response( 'No category specified' ) gameinfolist = json.loads( game_model.info ) category = None for gameinfo in gameinfolist: if category_code == util.get_code( gameinfo['category'] ): category = gameinfo['category'] break if category is None: return self.get_fail_response( 'Unknown category [' + category_code + '] for game [' + game_code + '].' ) # Parse the time into seconds and ensure it is valid if time is None: return self.get_fail_response( 'No runtime given' ) ( seconds, time_error ) = util.timestr_to_seconds( time ) if seconds is None: return self.get_fail_response( 'Bad runtime [' + time + '] given: ' + time_error ) # Ensure standard format time = util.seconds_to_timestr( seconds ) # Make sure that the notes are not too long if notes is not None and len( notes ) > 140: return self.get_fail_response( 'Comment is too long; must be ' + 'at most 140 characters.' ) # Figure out current date in user's local timezone user = self.get_runner( util.get_code( username ) ) if user == self.OVER_QUOTA_ERROR: return False, self.get_fail_response( "PB Tracker is currently " + "experiencing an over " + "quota limit down time " + "period." ) if user.timezone: tz = pytz.timezone( user.timezone ) local_today = datetime.now( pytz.utc ).astimezone( tz ) else: # UTC by default local_today = datetime.now( pytz.utc ) date = local_today.date( ) # Load up the needed parameters and put a new run params = dict( user=user, game=game_model.game, game_code=game_code, game_model=game_model, category=category, category_found=True, seconds=seconds, time=time, video=video, version=version, notes=notes, valid=True, date=date, datestr=date.strftime( "%m/%d/%Y" ), is_bkt=False ) if self.put_new_run( params ): return self.get_success_response( ) else: if params.get( 'video_error' ): return self.get_fail_response( 'Bad video link [' + video + ']: ' + params[ 'video_error' ] ) else: return self.get_fail_response( 'Sorry, an unknown error ' + 'occurred.' ) return self.get_fail_response( "Unknown type [" + body_type + "]." )
def get_response( self, body ): body_type = body.get( 'type' ) # Currently 5 types: verifylogin, gamelist, categories, gamecategories # and submitrun if body_type is None: return self.get_fail_response( "No type given." ) elif body_type == 'verifylogin': ( valid, response ) = self.verify_login( body ) return response elif body_type == 'gamelist': # Note that this is a different type of gamelist than the one # generated in games.py categories = self.get_categories( ) d = dict( ) for game in categories.keys( ): d[ util.get_code( game ) ] = game return self.get_success_response( data=d ) elif body_type == 'categories': categories = self.get_categories( ) d = dict( ) for game, categorylist in categories.iteritems( ): game_code = util.get_code( game ) for category in categorylist: category_code = util.get_code( category ) d[ game_code + ':' + category_code ] = ( game + ' - ' + category ) return self.get_success_response( data=d ) elif body_type == 'gamecategories': game_code = body.get( 'game' ) game_model = self.get_game_model( game_code ) if game_code is None: return self.get_fail_response( 'No game specified' ) elif game_model is None: return self.get_fail_response( 'Unknown game [' + game_code + '].' ) else: d = dict( ) gameinfolist = json.loads( game_model.info ) for gameinfo in gameinfolist: category = gameinfo['category'] d[ util.get_code( category ) ] = category return self.get_success_response( data=d ) elif body_type == 'submitrun': # First, verify login credentials ( valid, response ) = self.verify_login( body ) if not valid: return response # Grab the params from the body username = body.get( 'username' ) game_code = body.get( 'game' ) category_code = body.get( 'category' ) version = body.get( 'version' ) time = body.get( 'runtime' ) video = body.get( 'video' ) notes = body.get( 'comment' ) splits = body.get( 'splits' ) # Make sure the game and category exist (can't handle new games # and categories just yet) if game_code is None: return self.get_fail_response( 'No game given' ) game_model = self.get_game_model( game_code ) if game_model is None: return self.get_fail_response( 'Unknown game [' + game_code + '].' ) if category_code is None: return self.get_fail_response( 'No category specified' ) gameinfolist = json.loads( game_model.info ) category = None for gameinfo in gameinfolist: if category_code == util.get_code( gameinfo['category'] ): category = gameinfo['category'] break if category is None: return self.get_fail_response( 'Unknown category [' + category_code + '] for game [' + game_code + '].' ) # Parse the time into seconds and ensure it is valid if time is None: return self.get_fail_response( 'No runtime given' ) ( seconds, time_error ) = util.timestr_to_seconds( time ) if seconds is None: return self.get_fail_response( 'Bad runtime [' + time + '] given: ' + time_error ) # Ensure standard format time = util.seconds_to_timestr( seconds ) # Make sure that the notes are not too long if notes is not None and len( notes ) > 140: return self.get_fail_response( 'Comment is too long; must be ' + 'at most 140 characters.' ) # Figure out current date in user's local timezone user = self.get_runner( util.get_code( username ) ) if user.timezone: tz = pytz.timezone( user.timezone ) local_today = datetime.now( pytz.utc ).astimezone( tz ) else: # UTC by default local_today = datetime.now( pytz.utc ) date = local_today.date( ) # Load up the needed parameters and put a new run params = dict( user=user, game=game_model.game, game_code=game_code, game_model=game_model, category=category, category_found=True, seconds=seconds, time=time, video=video, version=version, notes=notes, valid=True, date=date, datestr=date.strftime( "%m/%d/%Y" ), is_bkt=False ) if self.put_new_run( params ): return self.get_success_response( ) else: if params.get( 'video_error' ): return self.get_fail_response( 'Bad video link [' + video + ']: ' + params[ 'video_error' ] ) else: return self.get_fail_response( 'Sorry, an unknown error ' + 'occurred.' ) return self.get_fail_response( "Unknown type [" + body_type + "]." )
def post(self): user = self.get_user() if not user: self.redirect("/") return game = self.request.get('game') category = self.request.get('category') time = self.request.get('time') datestr = self.request.get('date') video = self.request.get('video') version = self.request.get('version') notes = self.request.get('notes') is_bkt = self.request.get('bkt', default_value="no") if is_bkt == "yes": is_bkt = True else: is_bkt = False run_id = self.request.get('edit') params = dict(user=user, game=game, category=category, time=time, datestr=datestr, video=video, version=version, notes=notes, run_id=run_id, is_bkt=is_bkt) valid = True # Make sure the game doesn't already exist under a similar name game_code = util.get_code(game) game_model = self.get_game_model(game_code) if not game_code: params['game_error'] = "Game cannot be blank" valid = False elif game_model is not None and game != game_model.game: params['game_error'] = ("Game already exists under [" + game_model.game + "] (case sensitive)." + " Hit submit again to confirm.") params['game'] = game_model.game valid = False elif not games.valid_game_or_category(game): params['game_error'] = ("Game name must not use any 'funny'" + " characters and can be up to 100 " + "characters long") valid = False params['game_code'] = game_code params['game_model'] = game_model # Make sure the category doesn't already exist under a similar name category_code = util.get_code(category) category_found = False if not category_code: params['category_error'] = "Category cannot be blank" valid = False elif game_model is not None: infolist = json.loads(game_model.info) for info in infolist: if category_code == util.get_code(info['category']): category_found = True if category != info['category']: params['category_error'] = ( "Category already exists " + "under [" + info['category'] + "] " + "(case sensitive). " + "Hit submit again to " + "confirm.") params['category'] = info['category'] valid = False break if not category_found and not games.valid_game_or_category(category): params['category_error'] = ("Category must not use any 'funny'" + " characters and can be up to 100 " + "characters long") valid = False params['category_found'] = category_found # Parse the time into seconds, ensure it is valid (seconds, time_error) = util.timestr_to_seconds(time) if seconds is None: params['time_error'] = "Invalid time: " + time_error params['seconds'] = -1 valid = False else: time = util.seconds_to_timestr(seconds) # Enforce standard form params['time'] = time params['seconds'] = seconds # Parse the date, ensure it is valid (params['date'], params['date_error']) = util.datestr_to_date(datestr) if params['date_error']: params['date_error'] = "Invalid date: " + params['date_error'] valid = False # Check that if this is a best known time, then it beats the old # best known time. if is_bkt and game_model is not None: gameinfolist = json.loads(game_model.info) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if (gameinfo.get('bk_seconds') is not None and gameinfo['bk_seconds'] <= seconds): s = ("This time does not beat current best known " + "time of " + util.seconds_to_timestr( gameinfo.get('bk_seconds')) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)") params['bkt_error'] = s params['is_bkt'] = False valid = False break # Check that if this is not the best known time, then it doesn't beat # the old best known time if not is_bkt and game_model is not None: gameinfolist = json.loads(game_model.info) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if (gameinfo.get('bk_seconds') is not None and seconds < gameinfo['bk_seconds']): s = ( "This time beats the current best known time of " + util.seconds_to_timestr(gameinfo.get('bk_seconds')) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)") params['bkt_error'] = s params['is_bkt'] = True valid = False break # Make sure that the notes are not too long if len(notes) > 140: params['notes_error'] = "Notes must be at most 140 characters" valid = False params['valid'] = valid if run_id: success = self.put_existing_run(params) else: success = self.put_new_run(params) if success: self.redirect("/runner/" + util.get_code(user.username) + "?q=view-all") else: # Grab all of the games for autocompleting params['categories'] = self.get_categories() params['user'] = user self.render("submit.html", **params)
def post( self ): user = self.get_user( ) if not user: self.redirect( "/" ) return game = self.request.get( 'game' ) category = self.request.get( 'category' ) time = self.request.get( 'time' ) datestr = self.request.get( 'date' ) video = self.request.get( 'video' ) version = self.request.get( 'version' ) notes = self.request.get( 'notes' ) is_bkt = self.request.get( 'bkt', default_value="no" ) if is_bkt == "yes": is_bkt = True else: is_bkt = False run_id = self.request.get( 'edit' ) params = dict( user = user, game = game, category = category, time = time, datestr = datestr, video = video, version = version, notes = notes, run_id = run_id, is_bkt = is_bkt ) valid = True # Make sure the game doesn't already exist under a similar name game_code = util.get_code( game ) game_model = self.get_game_model( game_code ) if not game_code: params['game_error'] = "Game cannot be blank" valid = False elif game_model is not None and game != game_model.game: params['game_error'] = ( "Game already exists under [" + game_model.game + "] (case sensitive)." + " Hit submit again to confirm." ) params['game'] = game_model.game valid = False elif not valid_game_or_category( game ): params['game_error'] = ( "Game name must not use any 'funny'" + " characters and can be up to 100 " + "characters long" ) valid = False params[ 'game_code' ] = game_code params[ 'game_model' ] = game_model # Make sure the category doesn't already exist under a similar name category_code = util.get_code( category ) category_found = False if not category_code: params['category_error'] = "Category cannot be blank" valid = False elif game_model is not None: infolist = json.loads( game_model.info ) for info in infolist: if category_code == util.get_code( info['category'] ): category_found = True if category != info['category']: params['category_error'] = ( "Category already exists " + "under [" + info['category'] + "] " + "(case sensitive). " + "Hit submit again to " + "confirm." ) params['category'] = info['category'] valid = False break if not category_found and not valid_game_or_category( category ): params['category_error'] = ( "Category must not use any 'funny'" + " characters and can be up to 100 " + "characters long" ) valid = False params[ 'category_found' ] = category_found # Parse the time into seconds, ensure it is valid ( seconds, time_error ) = util.timestr_to_seconds( time ) if seconds is None: params['time_error'] = "Invalid time: " + time_error params['seconds'] = -1 valid = False else: time = util.seconds_to_timestr( seconds ) # Enforce standard form params[ 'time' ] = time params[ 'seconds' ] = seconds # Parse the date, ensure it is valid ( params['date'], params['date_error'] ) = util.datestr_to_date( datestr ) if params['date_error']: params['date_error'] = "Invalid date: " + params['date_error'] valid = False # Check that if this is a best known time, that it beats the old # best known time if is_bkt and game_model is not None: gameinfolist = json.loads( game_model.info ) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if( gameinfo.get( 'bk_seconds' ) is not None and gameinfo['bk_seconds'] <= seconds ): s = ( "This time does not beat current best known " + "time of " + util.seconds_to_timestr( gameinfo.get( 'bk_seconds' ) ) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)" ) params['bkt_error'] = s params['is_bkt'] = False valid = False break # Make sure that the notes are not too long if len( notes ) > 140: params['notes_error'] = "Notes must be at most 140 characters" valid = False params['valid'] = valid if run_id: success = self.put_existing_run( params ) else: success = self.put_new_run( params ) if success: self.redirect( "/runner/" + util.get_code( user.username ) + "?q=view-all" ) else: # Grab all of the games for autocompleting params['categories'] = self.get_categories( ) params['user'] = user self.render( "submit.html", **params )
def get_response(self, body): body_type = body.get('type') # Currently 5 types: verifylogin, gamelist, categories, gamecategories # and submitrun if body_type is None: return self.get_fail_response("No type given.") elif body_type == 'verifylogin': (valid, response) = self.verify_login(body) return response elif body_type == 'gamelist': return self.get_fail_response("Type [" + body_type + "] currently" + " not supported dynamically, but " + "you can find a static JSON " + "response at " + "https://www.dropbox.com/s/" + "xnvsmx3mt0i4nbv/gamelist.json?dl" + "=0") elif body_type == 'categories': return self.get_fail_response("Type [" + body_type + "] currently" + " not supported dynamically, but " + "you can find a static JSON " + "response at " + "https://www.dropbox.com/s/" + "irdj4xakh72g541/categories.json?" + "dl=0") elif body_type == 'modgamelist': # First, verify login credentials and that we are a mod (valid, response) = self.verify_mod_login(body) if not valid: return response # Note that this is a different type of gamelist than the one # generated in games.py categories = self.get_categories() if categories == self.OVER_QUOTA_ERROR: return self.get_fail_response("PB Tracker is currently " + "experiencing an over " + "quota downtime period.") d = dict() for game in categories.keys(): d[util.get_code(game)] = game return self.get_success_response(data=d) elif body_type == 'modcategories': # First, verify login credentials and that we are a mod (valid, response) = self.verify_mod_login(body) if not valid: return response categories = self.get_categories() if categories == self.OVER_QUOTA_ERROR: return self.get_fail_response("PB Tracker is currently " + "experiencing an over " + "quota downtime period.") d = dict() for game, categorylist in categories.iteritems(): game_code = util.get_code(game) for category in categorylist: category_code = util.get_code(category) d[game_code + ':' + category_code] = (game + ' - ' + category) return self.get_success_response(data=d) elif body_type == 'gamecategories': return self.get_fail_response("Type [" + body_type + "] currently" + " not supported, sorry.") # game_code = body.get( 'game' ) # game_model = self.get_game_model( game_code ) # if game_code is None: # return self.get_fail_response( 'No game specified' ) # elif game_model is None: # return self.get_fail_response( 'Unknown game [' # + game_code + '].' ) # TODO: elif game_model == self.OVER_QUOTA_ERROR: # else: # d = dict( ) # gameinfolist = json.loads( game_model.info ) # for gameinfo in gameinfolist: # category = gameinfo['category'] # d[ util.get_code( category ) ] = category # return self.get_success_response( data=d ) elif body_type == 'submitrun': # First, verify login credentials (valid, response) = self.verify_login(body) if not valid: return response # Grab the params from the body username = body.get('username') game_code = body.get('game') category_code = body.get('category') version = body.get('version') time = body.get('runtime') video = body.get('video') notes = body.get('comment') splits = body.get('splits') # Make sure the game and category exist (can't handle new games # and categories just yet) if game_code is None: return self.get_fail_response('No game given') game_model = self.get_game_model(game_code) if game_model is None: return self.get_fail_response('Unknown game [' + game_code + '].') if game_model == self.OVER_QUOTA_ERROR: return self.get_fail_response('PB Tracker is currently over ' + "quota. Please try again " + "later.") if category_code is None: return self.get_fail_response('No category specified') gameinfolist = json.loads(game_model.info) category = None for gameinfo in gameinfolist: if category_code == util.get_code(gameinfo['category']): category = gameinfo['category'] break if category is None: return self.get_fail_response('Unknown category [' + category_code + '] for game [' + game_code + '].') # Parse the time into seconds and ensure it is valid if time is None: return self.get_fail_response('No runtime given') (seconds, time_error) = util.timestr_to_seconds(time) if seconds is None: return self.get_fail_response('Bad runtime [' + time + '] given: ' + time_error) # Ensure standard format time = util.seconds_to_timestr(seconds) # Make sure that the notes are not too long if notes is not None and len(notes) > 140: return self.get_fail_response('Comment is too long; must be ' + 'at most 140 characters.') # Figure out current date in user's local timezone user = self.get_runner(util.get_code(username)) if user == self.OVER_QUOTA_ERROR: return False, self.get_fail_response( "PB Tracker is currently " + "experiencing an over " + "quota limit down time " + "period.") if user.timezone: tz = pytz.timezone(user.timezone) local_today = datetime.now(pytz.utc).astimezone(tz) else: # UTC by default local_today = datetime.now(pytz.utc) date = local_today.date() # Load up the needed parameters and put a new run params = dict(user=user, game=game_model.game, game_code=game_code, game_model=game_model, category=category, category_found=True, seconds=seconds, time=time, video=video, version=version, notes=notes, valid=True, date=date, datestr=date.strftime("%m/%d/%Y"), is_bkt=False) if self.put_new_run(params): return self.get_success_response() else: if params.get('video_error'): return self.get_fail_response('Bad video link [' + video + ']: ' + params['video_error']) else: return self.get_fail_response('Sorry, an unknown error ' + 'occurred.') return self.get_fail_response("Unknown type [" + body_type + "].")
def post( self, game_code ): user = self.get_user( ) if user == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html" ) return return_url = self.request.get( 'from' ) if not return_url: return_url = "/" # Get the category category_code = self.request.get( 'c' ) if user is None or category_code is None: self.error( 404 ) self.render( "404.html", user=user ) return # Have to take the code of the category code because of percent # encoded plusses category_code = util.get_code( category_code ) # Check to make sure that the user has run this game game_model = self.get_game_model( game_code ) if game_model == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html", user=user ) return user_has_run = self.get_user_has_run( user.username, game_model.game ) if user_has_run == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html", user=user ) return if not user_has_run and not user.is_mod: self.error( 404 ) self.render( "404.html", user=user ) return # Find the corresponding gameinfo for this category gameinfolist = json.loads( game_model.info ) gameinfo = None for g in gameinfolist: if util.get_code( g['category'] ) == category_code: gameinfo = g break if gameinfo is None: self.error( 404 ) self.render( "404.html", user=user ) return # Get the inputs username = self.request.get( 'username' ) time = self.request.get( 'time' ) datestr = self.request.get( 'date' ) video = self.request.get( 'video' ) params = dict( user=user, game=game_model.game, game_code=game_code, category=gameinfo['category'], username=username, time=time, datestr=datestr, video=video, return_url=return_url ) # Are we updating? if gameinfo.get( 'bk_runner' ) is None: params['updating'] = False else: params['updating'] = True valid = True # Check for where we came from if return_url[ 0 : len( '/runner/' ) ] == '/runner/': params['from_runnerpage'] = True else: params['from_runnerpage'] = False if not username and not time and not datestr and not video: gameinfo['bk_runner'] = None gameinfo['bk_seconds'] = None gameinfo['bk_datestr'] = None gameinfo['bk_video'] = None date = None else: # Make sure we got a username if not username: params['username_error'] = "You must enter a runner" valid = False # Parse the time into seconds, ensure it is valid ( seconds, time_error ) = util.timestr_to_seconds( time ) if not seconds: params['time_error'] = "Invalid time: " + time_error valid = False # Parse the date, ensure it is valid ( date, date_error ) = util.datestr_to_date( datestr ) if date_error: params['date_error'] = "Invalid date: " + date_error valid = False if not valid: self.render( "updatebkt.html", **params ) return time = util.seconds_to_timestr( seconds ) # Standard format params['time'] = time # Store the best known time gameinfo['bk_runner'] = username gameinfo['bk_seconds'] = seconds gameinfo['bk_datestr'] = datestr gameinfo['bk_video'] = video gameinfo['bk_updater'] = user.username game_model.info = json.dumps( gameinfolist ) game_model.put( ) # Update game_model in memcache self.update_cache_game_model( game_code, game_model ) # Update gamepage in memcache cached_gamepages = self.get_cached_gamepages( game_model.game, category_code ) if cached_gamepages is not None: for page_num, gamepage in cached_gamepages.iteritems( ): d = gamepage['d'] d['bk_runner'] = gameinfo['bk_runner'] d['bk_time'] = util.seconds_to_timestr( gameinfo['bk_seconds'] ) d['bk_date'] = date d['bk_video'] = gameinfo['bk_video'] self.update_cache_gamepage( game_model.game, category_code, cached_gamepages ) # All dun self.redirect( return_url )
def post( self, game_code ): user = self.get_user( ) if user == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html" ) return return_url = self.request.get( 'from' ) if not return_url: return_url = "/" # Get the category category_code = self.request.get( 'c' ) if user is None or category_code is None: self.error( 404 ) self.render( "404.html", user=user ) return # Have to take the code of the category code because of percent # encoded plusses category_code = util.get_code( category_code ) # Check to make sure that the user has run this game game_model = self.get_game_model( game_code ) if game_model == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html", user=user ) return user_has_run = self.get_user_has_run( user.username, game_model.game ) if user_has_run == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html", user=user ) return if not user_has_run and not user.is_mod: self.error( 404 ) self.render( "404.html", user=user ) return # Find the corresponding gameinfo for this category gameinfolist = json.loads( game_model.info ) gameinfo = None for g in gameinfolist: if util.get_code( g['category'] ) == category_code: gameinfo = g break if gameinfo is None: self.error( 404 ) self.render( "404.html", user=user ) return # Get the inputs username = self.request.get( 'username' ) time = self.request.get( 'time' ) datestr = self.request.get( 'date' ) video = self.request.get( 'video' ) params = dict( user=user, game=game_model.game, game_code=game_code, category=gameinfo['category'], username=username, time=time, datestr=datestr, video=video, return_url=return_url ) # Are we updating? if gameinfo.get( 'bk_runner' ) is None: params['updating'] = False else: params['updating'] = True valid = True # Check for where we came from if return_url[ 0 : len( '/runner/' ) ] == '/runner/': params['from_runnerpage'] = True else: params['from_runnerpage'] = False if not username and not time and not datestr and not video: gameinfo['bk_runner'] = None gameinfo['bk_seconds'] = None gameinfo['bk_datestr'] = None gameinfo['bk_video'] = None date = None else: # Make sure we got a username if not username: params['username_error'] = "You must enter a runner" valid = False # Parse the time into seconds, ensure it is valid ( seconds, time_error ) = util.timestr_to_seconds( time ) if not seconds: params['time_error'] = "Invalid time: " + time_error valid = False # Parse the date, ensure it is valid ( date, date_error ) = util.datestr_to_date( datestr ) if date_error: params['date_error'] = "Invalid date: " + date_error valid = False if not valid: self.render( "updatebkt.html", **params ) return time = util.seconds_to_timestr( seconds ) # Standard format params['time'] = time # Store the best known time gameinfo['bk_runner'] = username gameinfo['bk_seconds'] = seconds gameinfo['bk_datestr'] = datestr gameinfo['bk_video'] = video gameinfo['bk_updater'] = user.username game_model.info = json.dumps( gameinfolist ) game_model.put( ) # Update game_model in memcache self.update_cache_game_model( game_code, game_model ) # Update gamepage in memcache gamepage = self.get_gamepage( game_model.game, no_refresh=True ) if gamepage == self.OVER_QUOTA_ERROR: self.update_cache_gamepage( game, None ) elif gamepage is not None: for d in gamepage: if d['category'] == gameinfo['category']: d['bk_runner'] = gameinfo['bk_runner'] d['bk_time'] = util.seconds_to_timestr( gameinfo['bk_seconds'] ) d['bk_date'] = date d['bk_video'] = gameinfo['bk_video'] break self.update_cache_gamepage( game_model.game, gamepage ) # All dun self.redirect( return_url )
def post( self, game_code ): user = self.get_user( ) if not user: self.redirect( "/" ) return elif user == self.OVER_QUOTA_ERROR: self.error( 403 ) self.render( "403.html" ) return category = self.request.get( 'category' ) time = self.request.get( 'time' ) datestr = self.request.get( 'date' ) video = self.request.get( 'video' ) version = self.request.get( 'version' ) notes = self.request.get( 'notes' ) is_bkt = self.request.get( 'bkt', default_value="no" ) if is_bkt == "yes": is_bkt = True else: is_bkt = False run_id = self.request.get( 'edit' ) # Have to take the code of the game code because of percent # encoded plusses game_code = util.get_code( game_code ) params = dict( user = user, game_code = game_code, category = category, time = time, datestr = datestr, video = video, version = version, notes = notes, run_id = run_id, is_bkt = is_bkt ) valid = True # Make sure the game already exists game_model = self.get_game_model( game_code ) game = '' if not game_code: params['game_error'] = "Game cannot be blank" valid = False elif game_model is None: params['game_error'] = ( "That's weird, we could not find any " + "records for that game" ) valid = False elif game_model == self.OVER_QUOTA_ERROR: params['game_error'] = ( "PB Tracker is currently over its quota" + " limit for the day. Please try again " + "tomorrow." ) valid = False else: game = game_model.game params[ 'game' ] = game params[ 'game_model' ] = game_model # Make sure the category doesn't already exist under a similar name category_code = util.get_code( category ) category_found = False if not category_code: params['category_error'] = "Category cannot be blank" valid = False elif game_model is not None: infolist = json.loads( game_model.info ) for info in infolist: if category_code == util.get_code( info['category'] ): category_found = True if category != info['category']: params['category_error'] = ( "Category already exists " + "under [" + info['category'] + "] " + "(case sensitive). " + "Hit submit again to " + "confirm." ) params['category'] = info['category'] valid = False break if not category_found and not games.valid_game_or_category( category ): params['category_error'] = ( "Category must not use any 'funny'" + " characters and can be up to 100 " + "characters long" ) valid = False params[ 'category_found' ] = category_found # Parse the time into seconds, ensure it is valid ( seconds, time_error ) = util.timestr_to_seconds( time ) if seconds is None: params['time_error'] = "Invalid time: " + time_error params['seconds'] = -1 valid = False else: time = util.seconds_to_timestr( seconds ) # Enforce standard form params[ 'time' ] = time params[ 'seconds' ] = seconds # Parse the date, ensure it is valid ( params['date'], params['date_error'] ) = util.datestr_to_date( datestr ) if params['date_error']: params['date_error'] = "Invalid date: " + params['date_error'] valid = False # Check that if this is a best known time, then it beats the old # best known time. if is_bkt and game_model is not None: gameinfolist = json.loads( game_model.info ) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if( gameinfo.get( 'bk_seconds' ) is not None and gameinfo['bk_seconds'] <= seconds ): s = ( "This time does not beat current best known " + "time of " + util.seconds_to_timestr( gameinfo.get( 'bk_seconds' ) ) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)" ) params['bkt_error'] = s params['is_bkt'] = False valid = False break # Check that if this is not the best known time, then it doesn't beat # the old best known time if not is_bkt and game_model is not None: gameinfolist = json.loads( game_model.info ) for gameinfo in gameinfolist: if gameinfo['category'] == params['category']: if( gameinfo.get( 'bk_seconds' ) is not None and seconds < gameinfo['bk_seconds'] ): s = ( "This time beats the current best known time of " + util.seconds_to_timestr( gameinfo.get( 'bk_seconds' ) ) + " by " + gameinfo['bk_runner'] + " (if best known time is incorrect, you can " + "update best known time after submission)" ) params['bkt_error'] = s params['is_bkt'] = True valid = False break # Make sure that the notes are not too long if len( notes ) > 140: params['notes_error'] = "Notes must be at most 140 characters" valid = False params['valid'] = valid if run_id: success = self.put_existing_run( params ) else: success = self.put_new_run( params ) if success: self.redirect( "/runner/" + util.get_code( user.username ) + "?q=view-all" ) elif game_model is not None: try: # Grab all of the categories for autocompleting params['categories'] = game_model.categories( ) params['user'] = user self.render( "submit.html", **params ) except DeadlineExceededError, msg: logging.error( msg ) self.error( 403 ) self.render( "deadline_exceeded.html", user=user )
def get_response(self, body): body_type = body.get('type') # Currently 5 types: verifylogin, gamelist, categories, gamecategories # and submitrun if body_type is None: return self.get_fail_response("No type given.") elif body_type == 'verifylogin': (valid, response) = self.verify_login(body) return response elif body_type == 'gamelist': # Note that this is a different type of gamelist than the one # generated in games.py categories = self.get_categories() d = dict() for game in categories.keys(): d[util.get_code(game)] = game return self.get_success_response(data=d) elif body_type == 'categories': categories = self.get_categories() d = dict() for game, categorylist in categories.iteritems(): game_code = util.get_code(game) for category in categorylist: category_code = util.get_code(category) d[game_code + ':' + category_code] = (game + ' - ' + category) return self.get_success_response(data=d) elif body_type == 'gamecategories': game_code = body.get('game') game_model = self.get_game_model(game_code) if game_code is None: return self.get_fail_response('No game specified') elif game_model is None: return self.get_fail_response('Unknown game [' + game_code + '].') else: d = dict() gameinfolist = json.loads(game_model.info) for gameinfo in gameinfolist: category = gameinfo['category'] d[util.get_code(category)] = category return self.get_success_response(data=d) elif body_type == 'submitrun': # First, verify login credentials (valid, response) = self.verify_login(body) if not valid: return response # Grab the params from the body username = body.get('username') game_code = body.get('game') category_code = body.get('category') version = body.get('version') time = body.get('runtime') video = body.get('video') notes = body.get('comment') splits = body.get('splits') # Make sure the game and category exist (can't handle new games # and categories just yet) if game_code is None: return self.get_fail_response('No game given') game_model = self.get_game_model(game_code) if game_model is None: return self.get_fail_response('Unknown game [' + game_code + '].') if category_code is None: return self.get_fail_response('No category specified') gameinfolist = json.loads(game_model.info) category = None for gameinfo in gameinfolist: if category_code == util.get_code(gameinfo['category']): category = gameinfo['category'] break if category is None: return self.get_fail_response('Unknown category [' + category_code + '] for game [' + game_code + '].') # Parse the time into seconds and ensure it is valid if time is None: return self.get_fail_response('No runtime given') (seconds, time_error) = util.timestr_to_seconds(time) if seconds is None: return self.get_fail_response('Bad runtime [' + time + '] given: ' + time_error) # Ensure standard format time = util.seconds_to_timestr(seconds) # Make sure that the notes are not too long if notes is not None and len(notes) > 140: return self.get_fail_response('Comment is too long; must be ' + 'at most 140 characters.') # Figure out current date in user's local timezone user = self.get_runner(util.get_code(username)) if user.timezone: tz = pytz.timezone(user.timezone) local_today = datetime.now(pytz.utc).astimezone(tz) else: # UTC by default local_today = datetime.now(pytz.utc) date = local_today.date() # Load up the needed parameters and put a new run params = dict(user=user, game=game_model.game, game_code=game_code, game_model=game_model, category=category, category_found=True, seconds=seconds, time=time, video=video, version=version, notes=notes, valid=True, date=date, datestr=date.strftime("%m/%d/%Y"), is_bkt=False) if self.put_new_run(params): return self.get_success_response() else: if params.get('video_error'): return self.get_fail_response('Bad video link [' + video + ']: ' + params['video_error']) else: return self.get_fail_response('Sorry, an unknown error ' + 'occurred.') return self.get_fail_response("Unknown type [" + body_type + "].")