async def get_teams_info(self, ctx, tournament, players_spreadsheet, match_info, retry=False): """Returns ally and enemy team info""" try: team1_info = TeamInfo.from_team_name(players_spreadsheet, match_info.team1.get()) team2_info = TeamInfo.from_team_name(players_spreadsheet, match_info.team2.get()) except tosurnament.SpreadsheetHttpError as e: await self.on_cog_command_error(ctx, e) return None, None if players_spreadsheet.range_team_name: team_captain_role = tosurnament.get_role( ctx.guild.roles, tournament.team_captain_role_id, "Team Captain") if team_captain_role and not tosurnament.get_role( ctx.author.roles, tournament.team_captain_role_id, "Team Captain"): raise tosurnament.NotRequiredRole(team_captain_role.name) if self.get_player_in_team(ctx.author, team1_info): return team1_info, team2_info if self.get_player_in_team(ctx.author, team2_info): return team2_info, team1_info raise tosurnament.InvalidMatch()
async def get_player_role_for_bracket(self, guild, tournament, user, user_name, player_role): """Gives the player role of the bracket to the user, if he is a player of this bracket.""" bracket = tournament.current_bracket try: is_player, team_info = await self.is_a_player(bracket, user_name) except HttpError as e: raise tosurnament.SpreadsheetHttpError(e.code, e.operation, bracket.name, "players") if not is_player: return False roles_to_give = [player_role] bracket_role = tosurnament.get_role(guild.roles, bracket.role_id, bracket.name) if bracket_role: roles_to_give.append(bracket_role) if team_info: team_name = team_info.team_name.value team_role = tosurnament.get_role(guild.roles, None, team_name) if not team_role: try: team_role = await guild.create_role(name=team_name, mentionable=False) except discord.InvalidArgument: raise tosurnament.InvalidRoleName(team_name) if team_role: roles_to_give.append(team_role) if team_name == team_info.players[0].value: team_captain_role = tosurnament.get_role( guild.roles, tournament.team_captain_role_id, "Team Captain") if team_captain_role: roles_to_give.append(team_captain_role) await user.add_roles(*roles_to_give) return True
async def get_player_role_for_user(self, guild, user, channel=None): """Gives the corresponding player role to the user.""" tournament = self.get_tournament(guild.id) player_role_id = tournament.player_role_id if tosurnament.get_role(user.roles, player_role_id, "Player"): raise tosurnament.UserAlreadyPlayer() try: tosurnament_user = self.get_verified_user(user.id) user_name = tosurnament_user.osu_name except (tosurnament.UserNotLinked, tosurnament.UserNotVerified): user_name = user.display_name roles = guild.roles player_role = tosurnament.get_role(roles, player_role_id, "Player") if not player_role: raise tosurnament.RoleDoesNotExist("Player") got_role = False for bracket in tournament.brackets: tournament.current_bracket_id = bracket.id try: got_role |= await self.get_player_role_for_bracket( guild, tournament, user, user_name, player_role, ) except Exception as e: if channel: await self.on_cog_command_error(channel, "get_player_role", e) return got_role
async def register( self, ctx, timezone: str = ""): # TODO handle teams + multiples brackets """Registers the player to the tournament.""" verified_user = self.get_verified_user(ctx.author.id) tournament = self.get_tournament(ctx.guild.id) if len(tournament.brackets) != 1: await self.send_reply(ctx, "not_supported_yet") return bracket = tournament.current_bracket if bracket.registration_end_date: registration_end_date = datetime.datetime.strptime( bracket.registration_end_date, tosurnament.DATABASE_DATE_FORMAT) if datetime.datetime.now() > registration_end_date: raise tosurnament.RegistrationEnded() players_spreadsheet = await bracket.get_players_spreadsheet() if not players_spreadsheet: raise tosurnament.NoSpreadsheet("players") if players_spreadsheet.range_team_name: await self.send_reply(ctx, "not_supported_yet") return if players_spreadsheet.range_timezone: if not timezone: raise commands.UserInputError() if not re.match(r"(UTC)?[-\+]([0-9]|1[0-4])(:[0-5][0-9])?$", timezone, re.IGNORECASE): raise tosurnament.InvalidTimezone(timezone) timezone = "UTC" + re.sub( r"^UTC", "", timezone, flags=re.IGNORECASE) osu_user = osu.get_user(verified_user.osu_id, m=tournament.game_mode) if not osu_user: raise tosurnament.UserNotFound(verified_user.osu_id) team_info = TeamInfo.get_first_blank_fields(players_spreadsheet) player_info = team_info.players[0] player_info.name.set(osu_user.name) player_info.discord.set(str(ctx.author)) player_info.discord_id.set(ctx.author.id) player_info.rank.set(str(osu_user.rank)) player_info.bws_rank.set(str(osu_user.rank)) player_info.osu_id.set(str(osu_user.id)) player_info.pp.set(str(int(float(osu_user.pp)))) player_info.country.set(str(osu_user.country)) team_info.timezone.set(timezone) self.add_update_spreadsheet_background_task(players_spreadsheet) roles_to_give = [ tosurnament.get_role(ctx.guild.roles, tournament.player_role_id, "Player") ] roles_to_give.append( tosurnament.get_role(ctx.guild.roles, bracket.role_id, bracket.name)) await ctx.author.add_roles(*filter(None, roles_to_give)) try: await ctx.author.edit(nick=osu_user.name) except (discord.Forbidden, discord.HTTPException): pass await self.send_reply(ctx, "success")
async def get_player_role_for_bracket(self, guild, tournament, member, player_role): """Gives the player role of the bracket to the user, if he is a player of this bracket.""" bracket = tournament.current_bracket team_infos, _ = await self.get_all_teams_infos_and_roles( guild, await bracket.get_players_spreadsheet()) for team_info in team_infos: player = self.get_player_in_team(member, team_info) if not player: continue roles_to_give = [player_role] team_name = team_info.team_name.get() team_role = tosurnament.get_role(guild.roles, None, team_name) if not team_role: try: team_role = await guild.create_role(name=team_name, mentionable=False) except discord.InvalidArgument: raise tosurnament.InvalidRoleName(team_name) if team_role: roles_to_give.append(team_role) if player.is_captain: team_captain_role = tosurnament.get_role( guild.roles, tournament.team_captain_role_id, "Team Captain") if team_captain_role: roles_to_give.append(team_captain_role) await member.add_roles(*roles_to_give) return True return False
async def step8_remove_player_role(self, ctx, error_channel, tournament, challonge_tournament, loser_participant): if challonge_tournament.state == "group_stages_underway": for match in challonge_tournament.matches: if not match.state == "complete": return self.send_reply(error_channel, "post_result", "group_stages_complete") elif challonge_tournament.state == "underway": matches = challonge.get_participant_with_matches(challonge_tournament.id, loser_participant.id) for match in matches: if not match.state == "complete": return bracket = tournament.current_bracket try: team_info = TeamInfo.from_team_name(bracket.players_spreadsheet, loser_participant.name) player_role = tosurnament.get_role(ctx.guild.roles, tournament.player_role_id, "Player") roles_to_remove = [player_role] bracket_role = tosurnament.get_role(ctx.guild.roles, bracket.role_id, bracket.name) if bracket_role: roles_to_remove.append(bracket_role) team_name = team_info.team_name.value team_role = tosurnament.get_role(ctx.guild.roles, None, team_name) if team_role: roles_to_remove.append(team_role) if team_info.discord[0]: member = ctx.guild.get_member_named(team_info.discord[0]) if member: member.remove_roles(*roles_to_remove) for player_cell in team_info.players: member = ctx.guild.get_member_named(player_cell.value) if member: member.remove_roles(*roles_to_remove) except Exception: return
async def fill_matches_info_for_roles(self, ctx, tournament, bracket, user_details): user_name = user_details.name team_name = None has_bracket_role = False bracket_role = tosurnament.get_role(ctx.guild.roles, bracket.role_id) if not bracket_role or tosurnament.get_role(ctx.author.roles, bracket.role_id): has_bracket_role = True if user_details.player: team_name = await self.find_player_identification( ctx, bracket, user_name) matches_data = await self.get_next_matches_info_for_bracket( tournament, bracket) for match_info, match_date in matches_data: if (user_details.player and has_bracket_role and team_name and (match_info.team1.has_value(team_name) or match_info.team2.has_value(team_name))): user_details.player.taken_matches.append( (bracket.name, match_info, match_date)) for referee_cell in match_info.referees: if user_details.referee and referee_cell.has_value(user_name): user_details.referee.taken_matches.append( (bracket.name, match_info, match_date)) for streamer_cell in match_info.streamers: if user_details.streamer and streamer_cell.has_value( user_name): user_details.streamer.taken_matches.append( (bracket.name, match_info, match_date)) for commentator_cell in match_info.commentators: if user_details.commentator and commentator_cell.has_value( user_name): user_details.commentator.taken_matches.append( (bracket.name, match_info, match_date))
async def give_player_role(self, guild, tournament): player_role = tosurnament.get_role(guild.roles, tournament.player_role_id, "Player") if not player_role: return for bracket in tournament.brackets: players_spreadsheet = await bracket.get_players_spreadsheet( retry=True, force_sync=True) if not players_spreadsheet: continue bracket_role = tosurnament.get_role(guild.roles, bracket.role_id, bracket.name) team_infos, team_roles = await self.get_all_teams_infos_and_roles( guild, players_spreadsheet) for team_info_index, team_info in enumerate(team_infos): team_role = None if players_spreadsheet.range_team_name: team_role = team_roles[team_info_index] if not team_role: team_role = await guild.create_role( name=team_info.team_name.get(), mentionable=False) for player in team_info.players: user = tosurnament.UserAbstraction.get_from_player_info( self.bot, player, guild) member = user.get_member(guild) if member: try: await member.add_roles(*filter( None, [player_role, bracket_role, team_role])) await member.edit(nick=player.name.get()) except Exception: continue
async def give_player_role(self, guild, tournament): # TODO: better player_role = tosurnament.get_role(guild.roles, tournament.player_role_id, "Player") if not player_role: return for bracket in tournament.brackets: players_spreadsheet = bracket.players_spreadsheet if not players_spreadsheet: continue bracket_role = tosurnament.get_role(guild.roles, bracket.role_id, bracket.name) await players_spreadsheet.get_spreadsheet() if players_spreadsheet.range_team_name: team_name_cells = players_spreadsheet.spreadsheet.get_cells_with_value_in_range( players_spreadsheet.range_team_name) for team_name_cell in team_name_cells: team_info = TeamInfo.from_team_name( players_spreadsheet, team_name_cell.value) team_name = team_info.team_name.value team_role = tosurnament.get_role(guild.roles, None, team_name) if not team_role: team_role = await guild.create_role(name=team_name, mentionable=False) for i, player_cell in enumerate(team_info.players): player_name = player_cell.value if not player_name: continue discord_tag = None if len(team_info.discord ) > i and team_info.discord[i].value: discord_tag = team_info.discord[i].value user = tosurnament.UserAbstraction.get_from_osu_name( self.bot, player_name, discord_tag) member = user.get_member(guild) if not member: member = guild.get_member_named(user.name) if member: await member.add_roles(*filter( None, [player_role, bracket_role, team_role])) else: team_cells = players_spreadsheet.spreadsheet.get_cells_with_value_in_range( players_spreadsheet.range_team) for cell in team_cells: try: team_info = TeamInfo.from_player_name( players_spreadsheet, cell.value) if team_info.discord[0].value: user = guild.get_member_named( team_info.discord[0].value) else: user = guild.get_member_named( team_info.team_name.value) if user: await user.add_roles( *filter(None, [player_role, bracket_role])) except Exception: continue
async def clear_player_role(self, ctx, bracket_index: int = None, remove_player_role: bool = True): """Removes the player role of users not present in the challonge.""" tournament = self.get_tournament(ctx.guild.id) brackets = tournament.brackets if len(brackets) != 1: if bracket_index is None: brackets_string = "" for i, bracket in enumerate(brackets): brackets_string += str(i + 1) + ": `" + bracket.name + "`\n" await self.send_reply(ctx, ctx.command.name, "default", brackets_string) return elif bracket_index <= 0 or bracket_index > len(brackets): raise commands.UserInputError() bracket_index -= 1 else: bracket_index = 0 bracket = brackets[bracket_index] if not bracket.challonge: raise tosurnament.NoChallonge(bracket.name) player_role = tosurnament.get_role(ctx.guild.roles, tournament.player_role_id, "Player") bracket_role = tosurnament.get_role(ctx.guild.roles, bracket.role_id, bracket.name) team_captain_role = tosurnament.get_role(ctx.guild.roles, tournament.team_captain_role_id, "Team Captain") if remove_player_role: roles_to_removes = list(filter(None, [player_role, bracket_role, team_captain_role])) else: roles_to_removes = list(filter(None, [bracket_role, team_captain_role])) challonge_tournament = challonge.get_tournament(bracket.challonge) participants = [participant.name for participant in challonge_tournament.participants] participants_lower = [participant.lower() for participant in participants] players_spreadsheet = bracket.players_spreadsheet teams_info = [] if players_spreadsheet: await players_spreadsheet.get_spreadsheet() if players_spreadsheet.range_team_name: team_cells = players_spreadsheet.spreadsheet.get_cells_with_value_in_range( players_spreadsheet.range_team_name ) else: team_cells = players_spreadsheet.spreadsheet.get_cells_with_value_in_range( players_spreadsheet.range_team ) teams_info = [] for cell in team_cells: try: team_info = TeamInfo.from_team_name(players_spreadsheet, cell.value) except Exception: continue if players_spreadsheet.range_team_name: if team_role := tosurnament.get_role(ctx.guild.roles, None, team_info.team_name.value): roles_to_removes.append(team_role) teams_info.append(team_info)
async def allow_next_reschedule(self, ctx, match_id: str, allowed_hours: int = 24): """Allows a match to be reschedule without any time constraint applied.""" tournament = self.get_tournament(ctx.guild.id) tosurnament_guild = self.get_guild(ctx.guild.id) admin_role = tosurnament.get_role(ctx.author.roles, tosurnament_guild.admin_role_id) referee_role = tosurnament.get_role(ctx.author.roles, tournament.referee_role_id, "Referee") if not admin_role and not ctx.guild.owner == ctx.author and not referee_role: raise tosurnament.NotRequiredRole("Referee") match_found = False for bracket in tournament.brackets: schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: continue await schedules_spreadsheet.get_spreadsheet() try: match_info = MatchInfo.from_id(schedules_spreadsheet, match_id) except (tosurnament.SpreadsheetHttpError, InvalidWorksheet) as e: await self.on_cog_command_error(ctx, ctx.command.name, e) continue except MatchIdNotFound as e: self.bot.info(str(type(e)) + ": " + str(e)) continue match_found = True if admin_role or ctx.guild.owner == ctx.author: break user = tosurnament.UserAbstraction.get_from_ctx(ctx) is_referee_of_match = False for referee_cell in match_info.referees: if referee_cell.has_value(user.name): is_referee_of_match = True break if not is_referee_of_match: raise tosurnament.NotRefereeOfMatch() if not match_found: raise MatchIdNotFound(match_id) team1 = await self.get_team_mention(ctx.guild, bracket.players_spreadsheet, match_info.team1.value) team2 = await self.get_team_mention(ctx.guild, bracket.players_spreadsheet, match_info.team2.value) allowed_reschedule = AllowedReschedule(tournament_id=tournament.id, match_id=match_id, allowed_hours=allowed_hours) self.bot.session.add(allowed_reschedule) await self.send_reply(ctx, ctx.command.name, "success", match_id, allowed_hours, team1, team2)
async def register( self, ctx, osu_link: str, timezone: str = ""): # TODO handle teams + multiples brackets """Registers the player to the tournament.""" tournament = self.get_tournament(ctx.guild.id) if len(tournament.brackets) != 1: await self.send_reply(ctx, ctx.command.name, "not_supported_yet") return bracket = tournament.current_bracket players_spreadsheet = bracket.players_spreadsheet if players_spreadsheet.range_timezone: if not timezone: raise commands.MissingRequiredArgument("timezone") if not re.match(r"(UTC)?[-\+]([0-9]|1[0-4])$", timezone, re.IGNORECASE): raise InvalidTimezone(timezone) timezone = "UTC" + re.sub( r"^UTC", "", timezone, flags=re.IGNORECASE) if players_spreadsheet.range_team_name: await self.send_reply(ctx, ctx.command.name, "not_supported_yet") return await players_spreadsheet.get_spreadsheet() team_info = TeamInfo.get_first_blank_fields(players_spreadsheet) osu_name = osu.get_from_string(osu_link) osu_user = osu.get_user(osu_name) if not osu_user: raise tosurnament.UserNotFound(osu_name) team_info.players[0].value = osu_user.name team_info.discord[0].value = str(ctx.author) team_info.discord_ids[0].value = str(ctx.author.id) team_info.ranks[0].value = str(osu_user.rank) team_info.bws_ranks[0].value = str(osu_user.rank) # TODO team_info.osu_ids[0].value = str(osu_user.id) team_info.pps[0].value = str(int(float(osu_user.pp))) team_info.timezones[0].value = timezone self.add_update_spreadsheet_background_task(players_spreadsheet) roles_to_give = [ tosurnament.get_role(ctx.guild.roles, tournament.player_role_id, "Player") ] roles_to_give.append( tosurnament.get_role(ctx.guild.roles, bracket.role_id, bracket.name)) await ctx.author.add_roles(*filter(None, roles_to_give)) try: await ctx.author.edit(nick=osu_user.name) except (discord.Forbidden, discord.HTTPException): pass await self.send_reply(ctx, ctx.command.name, "success")
async def clear_player_role(self, ctx, *, number: int = None): """Removes the player role of users not present in the challonge.""" # TODO improve to handle teams, bracket roles, team captain role # TODO and remove special code for nik's tournament and handle challonge error tournament = self.get_tournament(ctx.guild.id) player_role = tosurnament.get_role(ctx.guild.roles, tournament.player_role_id, "Player") if not player_role: return for bracket in tournament.brackets: players_spreadsheet = bracket.players_spreadsheet if not bracket.challonge or not players_spreadsheet: continue challonge_tournament = challonge.get_tournament(tournament.current_bracket.challonge) participants = [participant.name for participant in challonge_tournament.participants] team_cells = players_spreadsheet.worksheet.get_cells_with_value_in_range(players_spreadsheet.range_team) teams_info = [] for cell in team_cells: try: team_info = TeamInfo.from_player_name(players_spreadsheet, cell.value) teams_info.append(team_info) except Exception: continue players_found = [] users_role_not_removed = [] n_roles_removed = 0 for member in ctx.guild.members: member_id = str(member) if player_name := self.is_player_in_challonge(member_id, teams_info, participants): players_found.append(player_name) else: try: user = ctx.guild.get_member_named(member_id) if user and tosurnament.get_role(user.roles, player_role.id, "Player"): await user.remove_roles(player_role) n_roles_removed += 1 except Exception: users_role_not_removed.append(member_id) continue success_extra = "" players_not_found = "\n".join(list(set(participants) - set(players_found))) if players_not_found: success_extra += self.get_string(ctx.command.name, "players_not_found", players_not_found) if users_role_not_removed: success_extra += self.get_string( ctx.command.name, "users_role_not_removed", "\n".join(users_role_not_removed) ) await self.send_reply( ctx, ctx.command.name, "success", bracket.name, n_roles_removed, len(players_found), success_extra, )
async def reschedule(self, ctx, match_id: str, *, date: str): """Allows players to reschedule their matches.""" tournament = self.get_tournament(ctx.guild.id) try: new_date = tournament.parse_date(date, prefer_dates_from="future") except ValueError: raise commands.UserInputError() if not new_date: raise commands.UserInputError() skip_deadline_validation = False allowed_reschedule_match_ids = [ allowed_reschedule.match_id.upper() for allowed_reschedule in self.bot.session.query(AllowedReschedule).where( AllowedReschedule.tournament_id == tournament.id).all() ] if match_id.upper() in allowed_reschedule_match_ids: skip_deadline_validation = True user = tosurnament.UserAbstraction.get_from_ctx(ctx) bracket_role_present = False for bracket in tournament.brackets: bracket_role = tosurnament.get_role(ctx.guild.roles, bracket.role_id) if bracket_role and not tosurnament.get_role( ctx.author.roles, bracket.role_id): bracket_role_present = True continue schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: continue await schedules_spreadsheet.get_spreadsheet() players_spreadsheet = bracket.players_spreadsheet if players_spreadsheet: await players_spreadsheet.get_spreadsheet() if await self.reschedule_for_bracket( ctx, tournament, bracket, schedules_spreadsheet, players_spreadsheet, match_id, new_date, user, skip_deadline_validation, ): return if bracket_role_present: raise tosurnament.InvalidMatchIdOrNoBracketRole() raise tosurnament.InvalidMatchId()
async def get_teams_info(self, ctx, tournament, players_spreadsheet, match_info, user): """Returns ally and enemy team info""" try: team1_info = TeamInfo.from_team_name(players_spreadsheet, match_info.team1.value) team2_info = TeamInfo.from_team_name(players_spreadsheet, match_info.team2.value) except tosurnament.SpreadsheetHttpError as e: await self.on_cog_command_error(ctx, ctx.command.name, e) return None, None if players_spreadsheet.range_team_name: team_captain_role = tosurnament.get_role( ctx.guild.roles, tournament.team_captain_role_id, "Team Captain") if team_captain_role: if not tosurnament.get_role(ctx.author.roles, tournament.team_captain_role_id, "Team Captain"): raise tosurnament.NotRequiredRole(team_captain_role.name) if user.verified: if user.name in [ cell.value.lower() for cell in team1_info.players ]: return team1_info, team2_info elif user.name in [ cell.value.lower() for cell in team2_info.players ]: return team2_info, team1_info if str(ctx.author) in [ cell.value for cell in team1_info.discord ]: return team1_info, team2_info elif str(ctx.author) in [ cell.value for cell in team2_info.discord ]: return team2_info, team1_info raise tosurnament.InvalidMatch() if user.verified: if user.name == team1_info.players[0].value: return team1_info, team2_info elif user.name == team2_info.players[0].value: return team2_info, team1_info if str(ctx.author) == team1_info.discord[0].value: return team1_info, team2_info elif str(ctx.author) == team2_info.discord[0].value: return team2_info, team1_info raise tosurnament.InvalidMatch()
async def reaction_on_reschedule_message(self, ctx, emoji, reschedule_message): """Reschedules a match or denies the reschedule.""" if str(ctx.author.id) != reschedule_message.opponent_user_id: return try: tournament = self.get_tournament(ctx.guild.id) tournament.current_bracket_id = reschedule_message.bracket_id if not tournament.current_bracket: raise tosurnament.UnknownError("Bracket not found") if emoji.name == "👍": await self.agree_to_reschedule(ctx, reschedule_message, tournament) else: self.bot.session.delete(reschedule_message) ally_to_mention = None if reschedule_message.ally_team_role_id: ally_to_mention = tosurnament.get_role( ctx.guild.roles, reschedule_message.ally_team_role_id) if not ally_to_mention: ally_to_mention = ctx.guild.get_member( int(reschedule_message.ally_user_id)) if ally_to_mention: await self.send_reply(ctx, "refused", ally_to_mention.mention, reschedule_message.match_id) else: raise tosurnament.OpponentNotFound(ctx.author.mention) except Exception as e: await self.on_cog_command_error(ctx, e)
async def reaction_on_match_notification(self, ctx, emoji, match_notification): """Allows a referee to take a match from its notification.""" tournament = tosurnament_api.get_tournament( match_notification.tournament_id) if not tournament: self.bot.session.delete(match_notification) return referee_role = tosurnament.get_role(ctx.author.roles, tournament.referee_role_id, "Referee") if not referee_role: return bracket = tosurnament_api.get_bracket(tournament.id, match_notification.bracket_id) if not bracket: self.bot.session.delete(match_notification) return try: await self.take_or_drop_match_in_spreadsheets( [match_notification.match_id], tosurnament.UserDetails.get_as_referee(self.bot, ctx.author), True, await bracket.get_schedules_spreadsheet(), await bracket.get_qualifiers_spreadsheet(), ) # TODO if return of function not empty send error except Exception as e: await self.on_cog_command_error(ctx, e) return ctx.command.name = "player_match_notification" if match_notification.notification_type == 1: ctx.command.name = "referee_match_notification" elif match_notification.notification_type == 2: ctx.command.name = "qualifier_match_notification" match_notification_message = await ctx.channel.fetch_message( match_notification.message_id_int) if match_notification.notification_type == 2: await match_notification_message.edit(content=self.get_string( ctx, "edited", match_notification.match_id, match_notification.teams_mentions, referee_role.mention, match_notification.date_info, ctx.author.mention, )) else: await match_notification_message.edit(content=self.get_string( ctx, "edited", match_notification.match_id, match_notification.team1_mention, match_notification.team2_mention, referee_role.mention, match_notification.date_info, ctx.author.mention, )) self.bot.session.delete(match_notification)
async def fill_matches_info_for_roles(self, ctx, tournament, bracket, user_details): user_name = user_details.name team_name = None if user_details.player: bracket_role = tosurnament.get_role(ctx.guild.roles, bracket.role_id) if not bracket_role or tosurnament.get_role( ctx.author.roles, bracket.role_id): team_name = await self.find_team_name_of_member(ctx, bracket) matches_data = await self.get_next_matches_info_for_bracket( tournament, bracket) for match_info, match_date in matches_data: if isinstance(match_info, MatchInfo): if team_name and (match_info.team1.has_value(team_name) or match_info.team2.has_value(team_name)): user_details.player.taken_matches.append( (bracket.name, match_info, match_date)) if user_details.referee: for referee_cell in match_info.referees: if referee_cell.has_value(user_name): user_details.referee.taken_matches.append( (bracket.name, match_info, match_date)) break if user_details.streamer: for streamer_cell in match_info.streamers: if streamer_cell.has_value(user_name): user_details.streamer.taken_matches.append( (bracket.name, match_info, match_date)) break if user_details.commentator: for commentator_cell in match_info.commentators: if commentator_cell.has_value(user_name): user_details.commentator.taken_matches.append( (bracket.name, match_info, match_date)) break else: if team_name: for team_cell in match_info.teams: if team_cell.has_value(team_name): user_details.player.taken_matches.append( (bracket.name, match_info, match_date)) if user_details.referee and match_info.referee and match_info.referee.has_value( user_name): user_details.referee.taken_matches.append( (bracket.name, match_info, match_date))
async def step8_remove_player_role(self, ctx, error_channel, tournament, challonge_tournament, loser_participant): if challonge_tournament.state == "group_stages_underway": for match in challonge_tournament.matches: if not match.state == "complete": return await self.send_reply(ctx, "group_stage_complete", channel=error_channel) elif challonge_tournament.state == "underway": matches = challonge.get_matches_of_participant( challonge_tournament.id, loser_participant.id) for match in matches: if not match.state == "complete": return bracket = tournament.current_bracket players_spreadsheet = await bracket.get_players_spreadsheet() if not players_spreadsheet: return try: team_info = TeamInfo.from_team_name(players_spreadsheet, loser_participant.name) player_role = tosurnament.get_role(ctx.guild.roles, tournament.player_role_id, "Player") roles_to_remove = [player_role] bracket_role = tosurnament.get_role(ctx.guild.roles, bracket.role_id, bracket.name) if bracket_role: roles_to_remove.append(bracket_role) team_role = tosurnament.get_role(ctx.guild.roles, None, team_info.team_name) if team_role: roles_to_remove.append(team_role) for player in team_info.players: user = tosurnament.UserAbstraction.get_from_player_info( self.bot, player, ctx.guild) member = user.get_member(ctx.guild) if member: await member.remove_roles(*roles_to_remove) except Exception: return
async def reaction_on_match_notification(self, message_id, emoji, guild, channel, user): """Allows a referee to take a match from its notification.""" if emoji.name != "💪": return match_notification = (self.bot.session.query(MatchNotification).where( MatchNotification.message_id_hash == message_id).first()) if not match_notification or match_notification.in_use: return tournament = self.bot.session.query(Tournament).where( Tournament.id == match_notification.tournament_id).first() if not tournament: self.bot.session.delete(match_notification) return referee_role = tosurnament.get_role(user.roles, tournament.referee_role_id, "Referee") if not referee_role: return match_notification.in_use = True self.bot.session.update(match_notification) bracket = self.bot.session.query(Bracket).where( Bracket.id == match_notification.bracket_id).first() if not bracket: self.bot.session.delete(match_notification) return try: await self.take_or_drop_match_in_spreadsheets( [match_notification.match_id], tosurnament.UserDetails.get_as_referee(self.bot, user), True, set(), bracket.schedules_spreadsheet, ) # TODO if not write_cells send error except Exception as e: match_notification.in_use = False self.bot.session.update(match_notification) await self.on_cog_command_error(channel, "take_match", e) return command_name = "player_match_notification" if match_notification.notification_type == 1: command_name = "referee_match_notification" match_notification_message = await channel.fetch_message( match_notification.message_id) await match_notification_message.edit(content=self.get_string( command_name, "edited", match_notification.match_id, match_notification.team1_mention, match_notification.team2_mention, referee_role.mention, match_notification.date_info, user.mention, )) self.bot.session.delete(match_notification)
async def get_player_role_for_user(self, ctx, guild, member): """Gives the corresponding player role to the user.""" tournament = self.get_tournament(guild.id) player_role_id = tournament.player_role_id if tosurnament.get_role(member.roles, player_role_id, "Player"): raise tosurnament.UserAlreadyPlayer() player_role = tosurnament.get_role(guild.roles, player_role_id, "Player") if not player_role: raise tosurnament.RoleDoesNotExist("Player") got_role = False for bracket in tournament.brackets: tournament.current_bracket_id = bracket.id try: got_role |= await self.get_player_role_for_bracket( guild, tournament, member, player_role) except Exception as e: if ctx: await self.on_cog_command_error(ctx, e) return got_role
def cog_check(self, ctx): """Check function called before any command of the cog.""" if not ctx.guild: raise commands.NoPrivateMessage() if ctx.guild.owner == ctx.author: return True guild = self.get_guild(ctx.guild.id) if not guild or not guild.admin_role_id: raise tosurnament.NotBotAdmin() if not tosurnament.get_role(ctx.author.roles, guild.admin_role_id): raise tosurnament.NotBotAdmin() return True
def cog_check(self, ctx): if ctx.guild is None: raise commands.NoPrivateMessage() role_name = "Referee" tournament = self.get_tournament(ctx.guild.id) role_id = tournament.get_role_id(role_name) role = tosurnament.get_role(ctx.guild.roles, role_id, role_name) if not role: raise tosurnament.RoleDoesNotExist(role_name) if role in ctx.author.roles: return True raise tosurnament.NotRequiredRole(role.name)
def get_referees_mentions_of_match(self, ctx, match_info): referees_to_ping, _ = self.find_staff_to_ping(ctx.guild, match_info.referees) referees_mentions = " / ".join( [referee.mention for referee in referees_to_ping]) if not referees_mentions: tosurnament_guild = self.get_guild(ctx.guild.id) admin_role = tosurnament.get_role(ctx.guild.roles, tosurnament_guild.admin_role_id) if admin_role: referees_mentions = admin_role.mention else: referees_mentions = self.get_string(ctx, "no_admin_role") return referees_mentions
async def reaction_on_reschedule_message(self, message_id, emoji, guild, channel, user): """Reschedules a match or denies the reschedule.""" reschedule_message = (self.bot.session.query(RescheduleMessage).where( RescheduleMessage.message_id == message_id).first()) if not reschedule_message or reschedule_message.in_use: return if user.id != reschedule_message.opponent_user_id: return reschedule_message.in_use = True self.bot.session.update(reschedule_message) bracket = None try: tournament = self.get_tournament(guild.id) tournament.current_bracket_id = reschedule_message.bracket_id if not tournament.current_bracket: raise tosurnament.UnknownError("Bracket not found") if emoji.name == "👍": await self.agree_to_reschedule(reschedule_message, guild, channel, user, tournament) elif emoji.name == "👎": self.bot.session.delete(reschedule_message) ally_to_mention = None if reschedule_message.ally_team_role_id: ally_to_mention = tosurnament.get_role( guild.roles, reschedule_message.ally_team_role_id) if not ally_to_mention: ally_to_mention = guild.get_member( reschedule_message.ally_user_id) if ally_to_mention: await self.send_reply( channel, "reschedule", "refused", ally_to_mention.mention, reschedule_message.match_id, ) else: raise tosurnament.OpponentNotFound(user.mention) else: reschedule_message.in_use = False self.bot.session.update(reschedule_message) except Exception as e: reschedule_message.in_use = False self.bot.session.update(reschedule_message) await self.reaction_on_reschedule_message_handler( channel, e, bracket)
async def referee_match_notification(self, guild, tournament, bracket, channel, match_info, delta, match_date): if list(filter(None, [cell for cell in match_info.referees])): return if not (delta.days == 0 and delta.seconds >= 20700 and delta.seconds < 21600): return referee_role = tosurnament.get_role(guild.roles, tournament.referee_role_id, "Referee") if referee_role: referee = referee_role.mention else: referee = self.get_simple_string(guild, "referee") match_date_str = self.get_pretty_date_for_guild( guild, tournament, match_date) team1 = escape_markdown(match_info.team1.get()) team2 = escape_markdown(match_info.team2.get()) message = await self.send_reply_in_bg_task( guild, channel, "referee_match_notification", "notification", match_info.match_id.get(), team1, team2, referee, match_date_str, ) match_notification = MatchNotification( message_id_int=message.id, message_id=message.id, tournament_id=tournament.id, bracket_id=bracket.id, match_id=match_info.match_id.get(), team1_mention=team1, team2_mention=team2, date_info=match_date_str, notification_type=1, ) self.bot.session.add(match_notification) try: await message.add_reaction("😱") await message.add_reaction("💪") except Exception as e: self.bot.info(str(type(e)) + ": " + str(e))
async def get_team_mention(self, guild, players_spreadsheet, team_name): if not players_spreadsheet: return escape_markdown(team_name) try: team_info = TeamInfo.from_team_name(players_spreadsheet, team_name) if players_spreadsheet.range_team_name: team_role = tosurnament.get_role(guild.roles, None, team_name) if team_role: return team_role.mention user = tosurnament.UserAbstraction.get_from_player_info( self.bot, team_info.get_team_captain(), guild) member = user.get_member(guild) if member: return member.mention return escape_markdown(team_name) except Exception as e: self.bot.info(str(type(e)) + ": " + str(e)) return escape_markdown(team_name)
async def reaction_on_match_notification(self, message_id, emoji, guild, channel, user): """Allows a referee to take a match from its notification.""" match_notification = ( self.bot.session.query(MatchNotification).where(MatchNotification.message_id_hash == message_id).first() ) if not match_notification or match_notification.in_use: return tournament = self.bot.session.query(Tournament).where(Tournament.id == match_notification.tournament_id).first() if not tournament: self.bot.session.delete(match_notification) return if not tosurnament.get_role(user.roles, tournament.referee_role_id, "Referee"): return match_notification.in_use = True self.bot.session.update(match_notification) bracket = self.bot.session.query(Bracket).where(Bracket.id == match_notification.bracket_id).first() if not bracket: self.bot.session.delete(match_notification) return try: await self.take_or_drop_match( guild.id, user, channel, [match_notification.match_id], True, tosurnament.UserRoles.get_as_referee() ) except Exception as e: match_notification.in_use = False self.bot.session.update(match_notification) await self.on_cog_command_error(channel, "take_match", e) return command_name = "player_match_notification" if match_notification.notification_type == 1: command_name = "referee_match_notification" match_notification_message = await channel.fetch_message(match_notification.message_id) await match_notification_message.edit( content=self.get_string( command_name, "edited", match_notification.match_id, match_notification.team1_mention, match_notification.team2_mention, user.mention, match_notification.date_info, ) ) self.bot.session.delete(match_notification)
async def give_player_role(self, guild): tournament = self.get_tournament(guild.id) player_role = tosurnament.get_role(guild.roles, tournament.player_role_id, "Player") if not player_role: return for bracket in tournament.brackets: players_spreadsheet = bracket.players_spreadsheet if not players_spreadsheet: continue if players_spreadsheet.range_team_name: team_name_cells = players_spreadsheet.worksheet.get_cells_with_value_in_range( players_spreadsheet.range_team_name) team_info = None for team_name_cell in team_name_cells: team_info = TeamInfo.from_team_name( players_spreadsheet, team_name_cell.value) if not team_info: continue for player_cell in team_info.players: user = guild.get_member_named(player_cell.value) if user: await user.add_roles(player_role) else: team_cells = players_spreadsheet.worksheet.get_cells_with_value_in_range( players_spreadsheet.range_team) for cell in team_cells: try: team_info = TeamInfo.from_player_name( players_spreadsheet, cell.value) if team_info.discord[0]: user = guild.get_member_named(team_info.discord[0]) else: user = guild.get_member_named( team_info.team_name.value) if user: await user.add_roles(player_role) except Exception: continue
async def referee_match_notification(self, guild, tournament, bracket, channel, match_info, delta, match_date): if not list(filter(None, [cell.value for cell in match_info.referees])): if delta.days == 0 and delta.seconds >= 20700 and delta.seconds < 21600: referee_role = tosurnament.get_role(guild.roles, tournament.referee_role_id, "Referee") if referee_role: referee = referee_role.mention else: referee = "Referees" match_date_str = match_date.strftime(tosurnament.PRETTY_DATE_FORMAT) team1 = escape_markdown(match_info.team1.value) team2 = escape_markdown(match_info.team2.value) message = await self.send_reply( channel, "referee_match_notification", "notification", match_info.match_id.value, team1, team2, referee, match_date_str, ) match_notification = MatchNotification( message_id_hash=message.id, message_id=message.id, tournament_id=tournament.id, bracket_id=bracket.id, match_id=match_info.match_id.value, team1_mention=team1, team2_mention=team2, date_info=match_date_str, notification_type=1, ) self.bot.session.add(match_notification) try: await message.add_reaction("😱") await message.add_reaction("💪") except Exception: return