async def update_players_scores(self): async with self.update_players_scores_lock: db_players = self.uow.player_repo.get_players() Logger.log("task", f"Updating scores for {len(db_players)} players") for db_player in db_players: self.update_player_scores(db_player)
def mark_player_scores_sent(self, db_player, db_guild): Logger.log(db_player, f"Marking all scores as sent in {db_guild}") db_scores = self.uow.score_repo.get_unsent_scores(db_player, db_guild) for db_score in db_scores: self.uow.score_repo.mark_score_sent(db_score, db_guild)
def update_score(self, new_db_score): old_db_score = self.get_score(new_db_score.scoreId) old_db_score.rank = new_db_score.rank old_db_score.scoreId = new_db_score.scoreId old_db_score.score = new_db_score.score old_db_score.unmodififiedScore = new_db_score.unmodififiedScore old_db_score.mods = new_db_score.mods old_db_score.pp = new_db_score.pp old_db_score.weight = new_db_score.weight old_db_score.timeSet = new_db_score.timeSet old_db_score.leaderboardId = new_db_score.leaderboardId old_db_score.songHash = new_db_score.songHash old_db_score.songName = new_db_score.songName old_db_score.songSubName = new_db_score.songSubName old_db_score.songAuthorName = new_db_score.songAuthorName old_db_score.levelAuthorName = new_db_score.levelAuthorName old_db_score.difficulty = new_db_score.difficulty old_db_score.difficultyRaw = new_db_score.difficultyRaw old_db_score.maxScore = new_db_score.maxScore self._db.commit_changes() Logger.log(old_db_score, f"Updated") self.mark_score_unsent(old_db_score)
async def update_all_player_roles(self): async with self.update_all_player_roles_lock: db_guilds = self.uow.guild_repo.get_guilds() Logger.log("task", f"Updating roles for {len(db_guilds)} guilds") for db_guild in db_guilds: await self.update_guild_roles(db_guild)
def update_player(self, db_player): try: new_player = self.uow.scoresaber.get_player(db_player.playerId) self.uow.player_repo.update_player(new_player) except NotFound: Logger.log(db_player, f"Could not find at ScoreSaber")
def set_role_country_rank_requirement(self, db_role, country_rank_requirement): db_role.country_rank_requirement = country_rank_requirement self._db.commit_changes() Logger.log( db_role, f"Set country_rank_requirement to {country_rank_requirement}")
async def send_notifications(self): async with self.send_notifications_lock: db_players = self.uow.player_repo.get_players() Logger.log("task", f"Sending notifications for {len(db_players)} players") for db_player in db_players: for db_guild in db_player.guilds: await self.send_notification(db_guild, db_player)
def set_feature(self, db_guild, feature_flag, status): if not hasattr(db_guild, feature_flag): raise RuntimeError(f"{db_guild} doesn't have attribute {feature_flag}") setattr(db_guild, feature_flag, status) self._db.commit_changes() Logger.log(db_guild, f"Set {feature_flag} to {status}")
async def wrapper(self, *args, **kwargs): if not self.uow.bot.is_ready() and not self.uow.bot.running_tests: Logger.log( "Discord", f"Discord client not ready, skipping task {func.__name__}") return return await func(self, *args, **kwargs)
async def cog_before_invoke(self, ctx): Logger.log(self.qualified_name, f"{colored(ctx.author.name, 'blue')} executed command " f"{colored(ctx.message.content, 'blue')} in " f"{colored(ctx.channel.name, 'blue')} at " f"{colored(ctx.guild.name, 'blue')}") await ctx.trigger_typing()
async def remove_guild_roles(self, guild): db_guild = self.uow.guild_repo.get_guild_by_discord_id(guild.id) Logger.log(db_guild, f"Removing roles") for db_player in db_guild.players: roles = Roles(self.uow, db_guild, db_player) await roles.remove_player_roles() await roles.remove_guild_roles()
async def wrapper(self, *args, **kwargs): if not self.uow.client.is_ready(): Logger.log( self.uow.client.user.name, "Discord client not ready, skipping task update players") return return await func(self, *args, **kwargs)
async def wrapper(self, *args, **kwargs): Logger.log(func.__name__, "<===> Starting task <===>") start_time = time.process_time() res = await func(self, *args, **kwargs) Logger.log( func.__name__, "Finished task in " f"{round(time.process_time() - start_time, 2)} seconds\n") return res
async def update_guild_roles(self, db_guild): roles_class = BeatSaberUtils.get_enabled_roles(self.uow, db_guild) if len(roles_class) == 0: Logger.log("task", f"Skipping roles update for {db_guild}, no roles enabled!") return for db_player in db_guild.players: for update_role in roles_class: await update_role.update_player_role(db_player)
async def wrapper(self, ctx): if ctx.author.guild_permissions.administrator: await func(self, ctx) else: Logger.log( type(self).__name__, f"{ctx.author.name} doesn't have the necessary permission(s) to use this command. Message: {ctx.message.content}" ) await ctx.send( 'You don\'t have the necessary permission(s) to use this command!' )
def update_score_song(self, db_score): if db_score.song is None: song = self.uow.song_repo.get_song_by_hash(db_score.songHash) if song is None: try: song = self.uow.beatsaver.get_song_by_score(db_score) except NotFound: Logger.log(db_score, f"Could not find song on BeatSaver") self.uow.score_repo.add_song(db_score, song)
async def update_players_scores(self, guild=None): if guild is None: db_players = self.uow.player_repo.get_players() Logger.log("task", f'Updating scores for {len(db_players)} players') else: db_guild = self.uow.guild_repo.get_guild_by_discord_id(guild.id) db_players = db_guild.players Logger.log(db_guild, f'Updating scores for {len(db_players)} players') for db_player in db_players: self.update_player_scores(db_player)
async def update_all_player_roles(self, guild=None): if guild is None: db_guilds = self.uow.guild_repo.get_pp_guilds() Logger.log("task", f"Updating roles for {len(db_guilds)} guilds") else: db_guilds = [self.uow.guild_repo.get_guild_by_discord_id(guild.id)] Logger.log(db_guilds[0], f"Updating roles") for db_guild in db_guilds: for db_player in db_guild.players: await self.update_player_roles(db_guild, db_player)
async def remove_guild_role(self, db_role): if db_role not in self.db_guild.roles: raise RoleNotFoundException(f"{self.db_guild} doesn't have {db_role}") role = self.get_role(db_role) try: await role.delete(reason="Removing PP role (BOT)") except Exception as error: Logger.log(self.db_guild, f"Failed to remove {db_role}") raise error self.uow.guild_repo.remove_role(self.db_guild, db_role)
def request_attempt(func): attempt = 0 attempting = True last_exception = None while attempting and attempt < 6: try: result = func() attempting = False return result except ServerErrorException as error: attempt += 1 Logger.log("Server Error", str(error)) Logger.log("Server Error", f"Waiting {WAIT_SERVER_ERROR} seconds...") last_exception = error time.sleep(WAIT_SERVER_ERROR) except RateLimitedException as error: attempt += 1 Logger.log("Rate Limit", str(error)) Logger.log("Rate Limit", f"Waiting {WAIT_RATE_LIMIT} seconds...") last_exception = error time.sleep(WAIT_RATE_LIMIT) if last_exception is not None: raise last_exception
def update_player_scores(self, db_player): try: recent_scores = self.uow.scoresaber.get_recent_scores(db_player.playerId) Logger.log(db_player, f"Got {len(recent_scores)} recent scores from ScoreSaber") # Add new scores to player self.uow.player_repo.add_scores(db_player, recent_scores) # Get db scores from recent scores db_scores = self.uow.score_repo.get_scores(recent_scores) # Update song for recent scores for db_score in db_scores: self.update_score_song(db_score) except NotFoundException: Logger.log(db_player, "Could not find scores on ScoreSaber")
def get_recent_scores(self, db_player): response = Common.request( requests.get, f"{self._url}/player/{db_player.playerId}/scores/recent", timeout=self._timeout) recent_scores = response.json()["scores"] recent_score_list = [] for recent_score in recent_scores: recent_score_list.append(Score(recent_score)) Logger.log( db_player, f"Got {len(recent_score_list)} recent scores from ScoreSaber") return recent_score_list
async def remove_player_role(self, db_player, db_role): member = await self.guild.fetch_member(db_player.discord_user_id) role = self.get_role(db_role) if role not in member.roles: if db_role in db_player.roles: self.uow.player_repo.remove_role(db_player, db_role) raise RoleNotFoundException(f"{db_player} doesn't have {db_role}") try: await member.remove_roles(role, reason="Removed PP ranking (BOT)") except Exception as error: Logger.log(db_player, f"Failed to remove {db_role}") raise error self.uow.player_repo.remove_role(db_player, db_role)
def add_scores(self, db_player, new_db_scores): new_score_list = [] for new_score in new_db_scores: is_new = True for old_db_score in db_player.scores: if old_db_score.scoreId == new_score.scoreId: is_new = False if is_new: new_score_list.append(new_score) db_player.scores += new_score_list self._db.commit_changes() Logger.log(db_player, f"Added {len(new_score_list)} new scores")
def update_player(self, new_db_player): old_db_player = self.get_player_by_player_id(new_db_player.playerId) old_db_player.playerId = new_db_player.playerId old_db_player.playerName = new_db_player.playerName old_db_player.avatar = new_db_player.avatar old_db_player.rank = new_db_player.rank old_db_player.countryRank = new_db_player.countryRank old_db_player.pp = new_db_player.pp old_db_player.country = new_db_player.country old_db_player.role = new_db_player.role old_db_player.badges = new_db_player.badges old_db_player.history = new_db_player.history old_db_player.permissions = new_db_player.permissions old_db_player.inactive = new_db_player.inactive old_db_player.banned = new_db_player.banned self._db.commit_changes() Logger.log(old_db_player, f"Updated")
async def give_player_role(self, db_player, db_role): member = await self.guild.fetch_member(db_player.discord_user_id) role = self.get_role(db_role) if role not in self.guild.roles: raise RoleNotFoundException(f"{self.db_guild} doesn't have {db_role}") if role in member.roles: if db_role not in db_player.roles: self.uow.player_repo.add_role(db_player, db_role) raise AlreadyHasRoleException(f"{db_player} already has {db_role}") try: await member.add_roles(role) except Exception as error: Logger.log(db_player, f"Failed to add {db_role}") raise error self.uow.player_repo.add_role(db_player, db_role)
def update_scores_song(self): db_scores = self.uow.score_repo.get_scores_without_song() if len(db_scores) == 0: Logger.log("task", f"No song updates needed for scores") return Logger.log("task", f'Updating songs for {len(db_scores)} scores') for db_score in db_scores: self.update_score_song(db_score) Logger.log("task", f"Updated songs for {len(db_scores)} scores")
def request_attempt(func): attempt = 0 attempting = True while attempting and attempt < 6: try: result = func() attempting = False return result except ServerError as e: attempt += 1 Logger.log("Server Error", {e}) Logger.log("Server Error", f"Waiting {Common._wait_server_error} seconds...") time.sleep(Common._wait_server_error) except RateLimited as e: attempt += 1 Logger.log("Rate Limit", {e}) Logger.log("Rate Limit", f"Waiting {Common._wait_rate_limit} seconds...") time.sleep(Common._wait_rate_limit)
async def send_notifications(self, guild=None): if guild is None: db_players = self.uow.player_repo.get_players() Logger.log("task", f"Sending notifications for {len(db_players)} players") else: db_guild = self.uow.guild_repo.get_guild_by_discord_id(guild.id) db_players = db_guild.players Logger.log(db_guild, f"Sending notifications for {len(db_players)} players") for db_player in db_players: for db_guild in db_player.guilds: if db_guild.recent_scores_channel_id is None: Logger.log(db_guild, f"Missing recent scores channel, skipping!") return channel = self.uow.client.get_channel(db_guild.recent_scores_channel_id) db_scores = self.uow.score_repo.get_unsent_scores(db_player, db_guild) Logger.log(db_guild, f"{db_player} has {len(db_scores)} scores to notify") for db_score in db_scores: embed = Message.get_score_embed(db_player, db_score, db_score.song) await channel.send(embed=embed) self.uow.score_repo.mark_score_sent(db_score, db_guild)
async def send_notification(self, db_guild, db_player): if db_guild.recent_scores_channel_id is None: Logger.log(db_guild, "Missing recent scores channel, skipping!") return channel = self.uow.bot.get_channel(db_guild.recent_scores_channel_id) if channel is None: Logger.log(db_guild, "Recent scores channel not found, skipping!") return db_scores = self.uow.score_repo.get_unsent_scores(db_player, db_guild) Logger.log(db_guild, f"{db_player} has {len(db_scores)} scores to notify") for db_score in db_scores: previous_db_score = self.uow.score_repo.get_previous_score(db_score) if previous_db_score is None: # Post as new score embed = Message.get_new_score_embed(db_player, db_score, db_score.song) await channel.send(embed=embed) self.uow.score_repo.mark_score_sent(db_score, db_guild) else: # Post as improvement embed = Message.get_improvement_score_embed(db_player, previous_db_score, db_score, db_score.song) await channel.send(embed=embed) self.uow.score_repo.mark_score_sent(db_score, db_guild) # Guild snipes leaderboard if db_guild.guild_snipes: leaderboard = GuildLeaderboard(self.uow, db_guild, db_score.leaderboardId) if len(leaderboard.leaderboard_scores) > 0: guild_leaderboard_embed = Message.get_leaderboard_embed(leaderboard.get_top_scores(3)) await channel.send(embed=guild_leaderboard_embed)