def default_pb(self, split_msg, sender): if Configs.get('respond to user'): user = sender else: user = Configs.get('streamer') category = self.get_category(' '.join(split_msg[1:])) if category: board = category.get_leaderboard(category.selected_subcategory) return self.get_pb_text(board, user)
def validate_boolean_settings(): for setting in [ Configs.get('speedrun.com'), Configs.get('srl results'), Configs.get('srl races'), Configs.get('print all race entrants') ]: assert ( isinstance(setting, bool) ), f"One of the boolean settings ({setting}) in Configs.py is not a bool!"
def validate_settings_file_edited(): default_stream_settings = { Configs.get('streamer'): '123_user_name', Configs.get('bot'): '123_bot__name', Configs.get('bot'): 'oauth:test123' } for setting, default_value in default_stream_settings.items(): assert ( setting != default_value ), "One of the Stream settings in Configs.py has not been filled in! Please fill in your streamer name, bot name, and the bots oauth.\
def select_dates(self, races, type): if ('bingo' in type) & ('all' not in type): if Configs.get('latest bingo version date') != '': version_date = datetime.datetime.strptime( Configs.get('latest bingo version date'), '%d-%m-%Y') races = [ race for race in races if race.get_date() >= version_date ] return races
def get_player(self, result_handler): logging.debug('Message sent by: ' + self.sender) name = self.player_name if not name: if Configs.get('respond to user'): name = self.sender else: return result_handler.player_lookup.get_SRL_player(Configs.get('streamer')) player = result_handler.player_lookup.get_SRL_player(name) if player: return player
def handle_message(self, msg, sender): split_msg = msg.split(' ') command = split_msg[0] # handle pb separately (can be either results (bingo) or src) if command in self.commands['handle_pb']: return self.handle_pb(msg, sender) elif Configs.get( 'speedrun.com') and command in self.SRC_handler.get_commands(): return self.SRC_handler.handle_message(msg, sender) elif Configs.get('srl results' ) and command in self.result_handler.get_commands(): return self.result_handler.handle_message(msg, sender)
def validate_race_types(): race_type_setting = Configs.get('default race type') assert (isinstance( race_type_setting, str)), "The default (race) result type in Configs.py is not a string!" assert ( race_type_setting in Definitions.RACE_TYPES ), f"{race_type_setting} in Configs.py is not a valid default (race) result type. Pick one from {Definitions.RACE_TYPES}."
def reset_hints(self, sender): if sender in Configs.get('editors'): if reset_hints(): return "Hints file reset to default." else: return "Hints couldn't be reset." else: return sender + "does not have the rights to use this command."
def __init__(self): super().__init__() self.commands = { 'average': ['!average', '!mean', '!median'], 'results': ['!results'], 'pb': ['!pb', '!best'], 'user_pb': ['!userpb'] } self.player_lookup = Player_lookup() self.race_type = Configs.get('default race type')
def set_srl(self, msg, sender): if sender in Configs.get('editors'): split_msg = msg.lower().split(' ') arg = split_msg[1] if arg in Definitions.RACE_TYPES: Configs.set('default race type', arg) return f'Updated default SRL race type to {arg}.' else: return f"Argument not a valid SRL race type! Choose from: {', '.join(Definitions.RACE_TYPES)}" else: return f"{sender} does not have the permissions to use this command."
def get_type(self, split_msg, result_handler): # look in arguments for word in split_msg[1:]: if word in Definitions.RACE_TYPES: return word # look in stream title type = result_handler.get_stream_title_type() # pick default if not type: return Configs.get('default race type') return type
def validate_dates(): date = Configs.get('latest bingo version date') assert (isinstance( date, str)), "The latest bingo version date in Configs.py is not a string!" try: date = datetime.strptime(date, '%d-%m-%Y') except: raise ValueError( "The latest bingo version date could not be parsed correctly. Please verify that it's in the right format DD-MM-YYYY." ) assert (date <= datetime.today() ), "Please pick a latest bingo version date that is in the past."
def get_live_race_info(self, command): if (command in self.commands['card']) & (self.live_race.type != 'bingo'): return "Current race is not a bingo. Use !race or !goal." response = '' if command in self.commands['goal'] + self.commands['card']: response = self.live_race.goal.replace('&', '&') elif command in self.commands['race']: response = self.live_race.get_race_link() if (command in self.commands['entrants']) | ( Configs.get('print all race entrants') & (command in self.commands['race'])): response = f"{response} {self.live_race.get_entrants_string()}" return response.strip()
def handle_message(self, msg, sender): split_msg = msg.lower().split(' ') command = split_msg[0] self.update_live_race(Configs.get('streamer')) if self.live_race is None: return "No active SRL or Racetime race found." def live_race_commands(): live_race_groups = ['race', 'goal', 'card', 'entrants'] return flatten( [self.commands[group] for group in live_race_groups]) # current race if command in live_race_commands(): return self.get_live_race_info(command)
def handle_pb(self, msg, sender): """In case of !pb command: decide whether to send to SRL result handler or SRC. If there's a race type involved, it goes to SRL.""" split_msg = msg.split(' ') command = split_msg[0] num_args = 1 if command == '!userpb': num_args = 2 # check in stream title if len(split_msg) <= num_args: arg = get_stream_category() # argument else: arg = ' '.join(split_msg[1:]) logging.debug( f"Comparing argument '{arg}' to race types: {Definitions.RACE_TYPES}" ) if any(type in arg for type in Definitions.RACE_TYPES): if Configs.get('srl results'): return self.result_handler.handle_message(msg, sender) if Configs.get('speedrun.com'): return self.SRC_handler.handle_message(msg, sender)
def update_live_race(self, player): # search SRL json = readjson('http://api.speedrunslive.com/races') for race in json['races']: if player.lower() in [e.lower() for e in race['entrants'].keys()]: self.live_race = LiveSRLRace(race) # if the race isn't finished, stop looking if self.live_race.state != 'Complete': return # search Racetime.gg for game in Configs.get('racetime games'): json = readjson(f'https://racetime.gg/{game}/data') for race in json['current_races']: game_json = readjson(f"https://racetime.gg{race['data_url']}") entrants = [ e['user']['name'].lower() for e in game_json['entrants'] ] if player.lower() in entrants: self.live_race = LiveRacetimeRace(game_json) self.latest_racetime_url = race['data_url'] logging.debug( f'Updated {self.live_race.platform} race {self.live_race.id}' ) # if the race isn't finished, stop looking if self.live_race.state != 'Complete': return # keep showing finished racetime races for 1 hour (after completing you can't find them in the game data anymore) if self.live_race and self.live_race.platform == 'racetime': game_json = readjson(self.live_race.get_race_link() + '/data') if game_json['ended_at']: finished_time = isodate.parse_datetime(game_json['ended_at']) now = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) if now < finished_time + datetime.timedelta(hours=1): logging.debug( f'Updated completed {self.live_race.platform} race {self.live_race.id}' ) self.live_race = LiveRacetimeRace(game_json) return self.live_race = None
def handle_pb(self, args): logging.debug("Looking up SRL result PB...") player = args.get_player(self) if player: if 'bingo' in args.type and 'all' not in args.type and Configs.get('latest bingo version date') != '': disclaimer = ' (for the latest bingo version)' else: disclaimer = '' # for bingo races, only looks at latest version pb = player.get_pb(type=args.type) if pb: return f"{player.name}'s {args.type} race pb{disclaimer} is {pb}." else: return f"No recorded {args.type} races{disclaimer} found for user {player.name}" else: "SRL user not found!"
def initalize_logger(): logger = logging.getLogger() logger.setLevel(logging.DEBUG) logger.handlers.clear() formatter = logging.Formatter( '%(asctime)s %(name)s %(levelname)s: %(message)s') if not os.path.exists('logs'): os.mkdir('logs') def add_logging_handler(handler, level): handler.setLevel(level) handler.setFormatter(formatter) logger.addHandler(handler) # console handler add_logging_handler(logging.StreamHandler(), Configs.get('console_logging_level')) # file handler (errors) add_logging_handler(logging.FileHandler("logs/ERROR.log", "a"), logging.WARNING)
def __init__(self): streamer = Configs.get('streamer') self.SRL_players = {streamer: self.find_new_SRL_player(streamer)}
def validate_string_settings(): for setting in [Configs.get('streamer'), Configs.get('bot')]: assert ( isinstance(setting, str) ), f"One of the string settings ({setting}) in Configs.py is not a string!"
def run(self): self.client.run(Configs.get('bot_oauth'))
def validate_editors(): assert (isinstance( Configs.get('editors'), list)), "The EDITORS setting in Configs.py has to be list!" assert (Configs.get('streamer') in Configs.get('editors') ), "The EDITORS list Configs.py has to contain the STREAMER!"
def validate_logging_level(): level = Configs.get('console_logging_level') assert ( level in Definitions.LOGGING_LEVELS ), f"The selected console logging level ({level}) in Advanced_settings.py is not a valid logging level! Select on from {Definitions.LOGGING_LEVELS}."
def get_srl(self, msg, sender): if sender in Configs.get('editors'): return f"SRL race type is currently set to {Configs.get('default race type')}." else: return f"{sender} does not have the permissions to use this command."
def _get_hints_path(): location = Configs.get('rando_hints_dir') if location == 'default': return Definitions.ROOT_DIR / 'RandoHints' else: return os.path.normpath(location)
def setup_and_run_irc(): connection = IRC_connection(Configs.get('streamer'), Configs.get('bot'), Configs.get('bot_oauth')) if connection.is_connected(): connection_manager = Connection_manager(connection, Responder()) connection_manager.run()
def is_bot_message(self): sender = self.sender() if not sender: return False return sender.lower() == Configs.get('bot').lower()