def store_data(info): """Store validated data in the database.""" # Check if user exists team = Teams.query.get(info['team_id']) if team is None: # Create new team new_team = Teams(info['team_id']) new_team.token = info['token'] new_team.bot_id = info['bot_id'] new_team.bot_token = info['bot_token'] # Store new user report_event('team_added', info) DB.session.add(new_team) else: # Update team info team.token = info['token'] team.bot_id = info['bot_id'] team.bot_token = info['bot_token'] report_event('team_updated', info) # Update DB DB.session.commit() return
def store_data(info): """Store validated data in the database.""" # Check if user exists team = Teams.query.get(info['team_id']) if team is None: # Create new team new_team = Teams(team_id=info['team_id'], token=info['token'], bot_id=info['bot_id'], bot_token=info['bot_token']) # Store new user report_event('team_added', info) DB.session.add(new_team) else: # Update team info team.token = info['token'] team.bot_id = info['bot_id'] team.bot_token = info['bot_token'] report_event('team_updated', info) # Update DB DB.session.commit()
def is_valid_token(token): """Check that the team has a valid token.""" # Set auth object auth = Auth(token) try: # Make request result = auth.test() except Error as err: # Check for auth errors report_event(str(err), { 'token': token }) return False # Check for further errors if not result.successful: report_event('token_invalid', { 'token': token, 'result': result.__dict__ }) return False # Return successful return True
def send_roll(team, roll, args): """Post the roll to Slack.""" # Set up chat object chat = Chat(team.bot_token) try: # Attempt to post message chat.post_message(args['channel_id'], roll, username='******', icon_emoji=':game_die:') except Error as err: report_event(str(err), { 'team': team.__dict__, 'roll': roll, 'args': args }) # Check specifically for channel errors if str(err) == 'channel_not_found': err_msg = "{0} is not authorized to post in this channel.".format( 'The {0} bot'.format(PROJECT_INFO['name_full'])) err_msg += ' Please invite it to join this channel and try again.' return err_msg # Report any other errors return '{0} encountered an error: {1}'.format( PROJECT_INFO['name_full'], str(err)) # Return no errors return None
def get_token(code): """Request a token from the Slack API.""" # Set OAuth access object oauth = OAuth() try: # Attempt to make request result = oauth.access(client_id=PROJECT_INFO['client_id'], client_secret=PROJECT_INFO['client_secret'], redirect_uri=PROJECT_INFO['valid_url'], code=code) except Error as err: report_event('oauth_error', {'code': code, 'error': str(err)}) abort(400) if not result.successful: report_event('oauth_unsuccessful', { 'code': code, 'result': result.__dict__ }) abort(400) # Setup return info info = { 'token': result.body['access_token'], 'team_id': result.body['team_id'], 'bot_id': result.body['bot']['bot_user_id'], 'bot_token': result.body['bot']['bot_access_token'] } # Return info return info
def home(): """Render app homepage template.""" if request.method == 'POST': report_event('post_request', request.form.to_dict()) return roll.make_roll(request.form.to_dict()) else: return render_template('index.html', project=PROJECT_INFO, allowed_commands=ALLOWED_COMMANDS)
def home(): """Render app homepage template.""" if request.method == 'POST': report_event('post_request', request.form.to_dict()) return roll.make_roll(request.form.to_dict()) else: return render_template( 'index.html', project=PROJECT_INFO, allowed_commands=ALLOWED_COMMANDS )
def validate_return(args): """Run data validation functions.""" # Make sure we have args if not args['state'] or not args['code']: report_event('missing_args', args) abort(400) # Validate state validate_state(args['state']) # Get access token and info token_info = get_token(args['code']) # Set up storage methods store_data(token_info) # Set success url redirect_url = '{0}?success=1'.format(PROJECT_INFO['base_url']) # Return successful return redirect_url
def validate_return(args): """Wrapper function for data validation functions.""" # Make sure we have args if not args['state'] or not args['code']: report_event('missing_args', args) abort(400) # Validate state validate_state(args['state']) # Get access token and info token_info = get_token(args['code']) # Set up storage methods store_data(token_info) # Set success url redirect_url = '{0}?success=1'.format(PROJECT_INFO['base_url']) # Return successful return redirect_url
def validate_state(state): """Validate state token returned by authentication.""" try: # Attempt to decode state state_token = GENERATOR.loads( state, max_age=timedelta(minutes=60).total_seconds()) except SignatureExpired: # Token has expired report_event('token_expired', {'state': state}) abort(400) except BadSignature: # Token is not authorized report_event('token_not_authorized', {'state': state}) abort(401) if state_token != PROJECT_INFO['client_id']: # Token is not authorized report_event('token_not_valid', { 'state': state, 'state_token': state_token }) abort(401) # Return success return
def validate_state(state): """Validate state token returned by authentication.""" try: # Attempt to decode state state_token = GENERATOR.loads( state, max_age=timedelta(minutes=60).total_seconds() ) except SignatureExpired: # Token has expired report_event('token_expired', { 'state': state }) abort(400) except BadSignature: # Token is not authorized report_event('token_not_authorized', { 'state': state }) abort(401) if state_token != PROJECT_INFO['client_id']: # Token is not authorized report_event('token_not_valid', { 'state': state, 'state_token': state_token }) abort(401) # Return success return
def get_token(code): """Request a token from the Slack API.""" # Set OAuth access object oauth = OAuth() try: # Attempt to make request result = oauth.access( client_id=PROJECT_INFO['client_id'], client_secret=PROJECT_INFO['client_secret'], redirect_uri=PROJECT_INFO['valid_url'], code=code ) except Error as err: report_event('oauth_error', { 'code': code, 'error': str(err) }) abort(400) if not result.successful: report_event('oauth_unsuccessful', { 'code': code, 'result': result.__dict__ }) abort(400) # Setup return info info = { 'token': result.body['access_token'], 'team_id': result.body['team_id'], 'bot_id': result.body['bot']['bot_user_id'], 'bot_token': result.body['bot']['bot_access_token'] } # Return info return info
def send_roll(team, roll, args): """Post the roll to Slack.""" # Set up chat object chat = Chat(team.bot_token) try: # Attempt to post message chat.post_message( args['channel_id'], roll, username='******', icon_emoji=':game_die:' ) except Error as err: report_event(str(err), { 'team': team.__dict__, 'roll': roll, 'args': args }) # Check specifically for channel errors if str(err) == 'channel_not_found': err_msg = "{0} is not authorized to post in this channel.".format( 'The {0} bot'.format(PROJECT_INFO['name_full']) ) err_msg += ' Please invite it to join this channel and try again.' return err_msg # Report any other errors return '{0} encountered an error: {1}'.format( PROJECT_INFO['name_full'], str(err) ) # Return successful return
def make_roll(args): """Run dice roll functions.""" # Reset global error tracker global ERRORS ERRORS = [] # Make sure this is a valid slash command if args['command'] not in ALLOWED_COMMANDS: report_event('command_not_allowed', args) return '"{0}" is not an allowed command'.format(args['command']) # Set global command value to access later global COMMAND COMMAND = args['command'] # Check to see if team has authenticated with the app team = get_team(args) # If the user, team token, and bot token are not valid, let them know if (not team or not is_valid_token(team.token) or not is_valid_token(team.bot_token)): report_event('auth_error', {'args': args, 'team': team.__dict__}) return AUTH_ERROR # If there's no input, use the default roll dice_roll = 'd6' if not args['text'] else args['text'] # Get parser parser = get_parser() # Parse args result = parser.parse_args([dice_roll]) # Report any errors from parser if ERRORS: report_event('parser_errors', {'errors': ERRORS}) return ERRORS[0] # Get requested flip roll = do_roll(result, args['user_name']) # Post flip as user err = send_roll(team, roll, args) # If there were problems posting, report it if err is not None: return err # Return successful return ('', 204)
def __call__(self, parser, namespace, values, option_string=None): """Validate flip arguments and stores them to namespace.""" dice_roll = values.lower() # Check for help if dice_roll in ['help', 'version']: parser.print_help(dice_roll) return # Set defaults count = 1 sides = 6 modifier = None modifier_count = None hit = None # Parse the roll result = re.match( r'(?P<count>\d+)?d(?P<sides>\d+)' + r'(?:(?P<mod>[-+])(?P<mod_count>\d+))?' + r'(?:\s(?P<hit>hit)(?P<hit_count>\d+)?)?', dice_roll, re.I) # Check that roll is valid if result is None: report_event('roll_invalid', {'roll': dice_roll}) parser.error("'{0}' is not a valid roll format".format(dice_roll)) else: # Get the number of dice if result.group('count') is not None: count = int(result.group('count')) # Set 100 count max if count > 100: count = 100 # Set 1 count min if count < 1: count = 1 # Get the number of sides if result.group('sides') is not None: sides = int(result.group('sides')) # Set 100 side max if sides > 100: sides = 100 # Set 2 side min if sides < 2: sides = 2 # Get the modifiers if result.group('mod') is not None: # Check that we have a number with the modifier if result.group('mod_count') is None: report_event('roll_modifier_invalid', {'roll': dice_roll}) parser.error( "'{0}' is not a valid roll format".format(dice_roll)) # Set modifier data modifier = result.group('mod') modifier_count = int(result.group('mod_count')) # Set 100 modifier max if modifier_count > 100: modifier_count = 100 # Get the hit if result.group('hit') is not None: # Set default hit to 5 as per Shadowrun mechanics hit = 5 # See if we have a hit threshold if result.group('hit_count') is not None: hit = int(result.group('hit_count')) # Set max hit to 100 if hit > 100: hit = 100 # Make sure we have enough sides if hit > sides: report_event('roll_hit_invalid', {'roll': dice_roll}) parser.error("Hit threshold '{0}' is too big".format(hit)) # Set values setattr(namespace, 'count', count) setattr(namespace, 'sides', sides) setattr(namespace, 'modifier', modifier) setattr(namespace, 'modifier_count', modifier_count) setattr(namespace, 'hit', hit) # Exit call return
def make_roll(args): """Wrapper function for roll functions.""" # Reset global error traker global ERRORS ERRORS = [] print args # Make sure this is a valid slash command if args['command'] not in ALLOWED_COMMANDS: report_event('command_not_allowed', args) return '"{0}" is not an allowed command'.format(args['command']) else: # Set global command value to access later global COMMAND COMMAND = args['command'] # Check to see if team has authenticated with the app team = get_team(args) # If the user, team token, and bot token are not valid, let them know if ( not team or not is_valid_token(team.token) or not is_valid_token(team.bot_token) ): report_event('auth_error', { 'args': args, 'team': team.__dict__ }) return AUTH_ERROR # If there's no input, use the default roll if not args['text']: dice_roll = 'd6' else: dice_roll = args['text'] # Get parser parser = get_parser() # Parse args result = parser.parse_args([dice_roll]) # Report any errors from parser if len(ERRORS) > 0: report_event('parser_errors', { 'errors': ERRORS }) return ERRORS[0] # Get requested flip roll = do_roll(result, args['user_name']) # Post flip as user err = send_roll(team, roll, args) # If there were problems posting, report it if err is not None: return err # Return successful return ('', 204)
def __call__(self, parser, namespace, values, option_string=None): """Validate flip arguments and stores them to namespace.""" dice_roll = values.lower() # Check for help if dice_roll in ['help', 'version']: parser.print_help(dice_roll) return # Set defaults count = 1 sides = 6 modifier = None modifier_count = None # Parse the roll result = re.match(r'(\d+)?d(\d+)(?:([-+])(\d+))?', dice_roll, re.I) # Check that roll is valid if result is None: report_event('roll_invalid', { 'roll': dice_roll }) parser.error( "'{0}' is not a recognized roll format".format( dice_roll.encode('utf-8') ) ) else: # Get the number of dice if result.group(1) is not None: count = int(result.group(1)) # Set 100 count max if count > 100: count = 100 # Set 1 count min if count < 1: count = 1 # Get the number of sides if result.group(2) is not None: sides = int(result.group(2)) # Set 100 side max if sides > 100: sides = 100 # Set 4 side min if sides < 4: sides = 4 # Get the modifiers if result.group(3) is not None: if result.group(4) is None: report_event('roll_modifier_invalid', { 'roll': dice_roll }) parser.error( "'{0}' is not a recognized roll format".format( dice_roll.encode('utf-8') ) ) modifier = result.group(3) modifier_count = int(result.group(4)) # Set values setattr(namespace, 'count', count) setattr(namespace, 'sides', sides) setattr(namespace, 'modifier', modifier) setattr(namespace, 'modifier_count', modifier_count) return