async def get_teams_infos(self, bracket, team_name1, team_name2): players_spreadsheet = bracket.players_spreadsheet if not players_spreadsheet: return None, None await players_spreadsheet.get_spreadsheet() team1_info = TeamInfo.from_team_name(players_spreadsheet, team_name1) team2_info = TeamInfo.from_team_name(players_spreadsheet, team_name2) return team1_info, team2_info
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 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 is_a_player(self, bracket, user_name): """Returns if the user is a player in the bracket and its team_info if he is.""" players_spreadsheet = bracket.players_spreadsheet if not players_spreadsheet: return False, None 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: return False, None if user_name not in [cell.value for cell in team_info.players]: return False, None return True, team_info else: team_cells = players_spreadsheet.worksheet.find_cells( players_spreadsheet.range_team, user_name) if len(team_cells) < 1: return False, None elif len(team_cells) > 1: raise tosurnament.DuplicatePlayer(user_name) return True, None
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
def find_player_identification(self, ctx, bracket, user_name): players_spreadsheet = bracket.players_spreadsheet if not players_spreadsheet: return user_name if players_spreadsheet.range_team_name: cells = players_spreadsheet.worksheet.get_cells_with_value_in_range(players_spreadsheet.range_team_name) for cell in cells: team_info = TeamInfo.get_from_team_name(cell.value) if user_name in [cell.value for cell in team_info.players]: return team_info.team_name.value else: return user_name
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 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 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 get_team_mention(self, guild, players_spreadsheet, team_name): if not players_spreadsheet: return escape_markdown(team_name) await players_spreadsheet.get_spreadsheet() 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_osu_name( self.bot, team_info.players[0].value, team_info.discord[0].value) 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 player_match_notification(self, guild, tournament, bracket, channel, match_info, delta): if delta.days == 0 and delta.seconds >= 900 and delta.seconds < 1800: team1 = match_info.team1.value team2 = match_info.team2.value players_spreadsheet = bracket.players_spreadsheet if players_spreadsheet: try: team1_info = TeamInfo.from_team_name(players_spreadsheet, team1) player = guild.get_member_named(team1_info.discord[0]) if player: team1 = player.mention else: team1 = escape_markdown(team1) except Exception: pass try: team2_info = TeamInfo.from_team_name(players_spreadsheet, team2) player = guild.get_member_named(team2_info.discord[0]) if player: team2 = player.mention else: team2 = escape_markdown(team2) except Exception: pass referee_name = match_info.referees[0].value referee_role = None if referee_name: referee = guild.get_member_named(referee_name) if referee: referee = referee.mention else: referee = referee_name else: referee_role = tosurnament.get_role(guild.roles, tournament.referee_role_id, "Referee") if referee_role: referee = ( "**No Referee** (" + referee_role.mention + ", if you want to take this match, react with :muscle:)" ) else: referee = "**No Referee** (and referee role not found)" minutes_before_match = str(int(delta.seconds / 60) + 1) message = await self.send_reply( channel, "player_match_notification", "notification", match_info.match_id.value, team1, team2, referee, minutes_before_match, ) if referee_role: 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=minutes_before_match, notification_type=0, ) self.bot.session.add(match_notification) try: await message.add_reaction("👀") if referee_role: await message.add_reaction("💪") except Exception: return
async def reschedule(self, ctx, match_id: str, *, date: str): """Allows players to reschedule their matches.""" try: new_date = dateparser.parse(date) except ValueError: raise commands.UserInputError() tournament = self.get_tournament(ctx.guild.id) 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 now = datetime.datetime.utcnow() self.validate_new_date(tournament, now, new_date, skip_deadline_validation) try: tosurnament_user = self.get_verified_user(ctx.author.id) user_name = tosurnament_user.osu_name except (tosurnament.UserNotLinked, tosurnament.UserNotVerified ): # ! Temporary for nik's tournament user_name = "" for bracket in tournament.brackets: schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: continue try: match_info = MatchInfo.from_id(schedules_spreadsheet, match_id) except tosurnament.SpreadsheetHttpError as e: await self.on_cog_command_error(ctx, ctx.command.name, e) continue except DuplicateMatchId: await self.send_reply(ctx, ctx.command.name, "duplicate_match_id", match_id) continue except (InvalidWorksheet, MatchIdNotFound): continue match_id = match_info.match_id.value players_spreadsheet = bracket.players_spreadsheet if players_spreadsheet and players_spreadsheet.range_team_name: 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) continue except (InvalidWorksheet, TeamNotFound, DuplicateTeam): continue if user_name in [cell.value for cell in team1_info.players]: team_name = team1_info.team_name.value opponent_team_name = team2_info.team_name.value opponent_team_captain_name = team2_info.players[0].value else: team_name = team2_info.team_name.value opponent_team_name = team1_info.team_name.value opponent_team_captain_name = team1_info.players[0].value else: # ! Temporary 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) continue except (InvalidWorksheet, DuplicateTeam): continue except TeamNotFound: raise tosurnament.InvalidMatch() if team1_info.discord[0] == str(ctx.author): user_name = team1_info.players[0].value opponent_team_captain = ctx.guild.get_member_named( team2_info.discord[0]) elif team2_info.discord[0] == str(ctx.author): user_name = team2_info.players[0].value opponent_team_captain = ctx.guild.get_member_named( team1_info.discord[0]) else: raise tosurnament.InvalidMatch() # ! Temporary team_name = user_name if match_info.team1.value == user_name: opponent_team_name = match_info.team2.value opponent_team_captain_name = opponent_team_name elif match_info.team2.value == user_name: opponent_team_name = match_info.team1.value opponent_team_captain_name = opponent_team_name else: raise tosurnament.InvalidMatch() previous_date = self.validate_reschedule_feasibility( tournament, schedules_spreadsheet, match_info, now, new_date, skip_deadline_validation) if not opponent_team_captain: # ! Temporary opponent_team_captain = ctx.guild.get_member_named( opponent_team_captain_name) if not opponent_team_captain: raise tosurnament.OpponentNotFound(ctx.author.mention) reschedule_message = RescheduleMessage(tournament_id=tournament.id, bracket_id=bracket.id, in_use=False) opponent_to_ping = opponent_team_captain if tournament.reschedule_ping_team: role = tosurnament.get_role(ctx.guild.roles, None, opponent_team_name) if role: opponent_to_ping = role role = tosurnament.get_role(ctx.guild.roles, None, team_name) if role: reschedule_message.ally_team_role_id = role.id reschedule_message.match_id = match_id reschedule_message.ally_user_id = ctx.author.id reschedule_message.opponent_user_id = opponent_team_captain.id previous_date_string = previous_date.strftime( tosurnament.PRETTY_DATE_FORMAT) reschedule_message.previous_date = previous_date.strftime( tosurnament.DATABASE_DATE_FORMAT) new_date_string = new_date.strftime(tosurnament.PRETTY_DATE_FORMAT) reschedule_message.new_date = new_date.strftime( tosurnament.DATABASE_DATE_FORMAT) sent_message = await self.send_reply( ctx, ctx.command.name, "success", opponent_to_ping.mention, escape_markdown(user_name), match_id, previous_date_string, new_date_string, ) reschedule_message.message_id = sent_message.id self.bot.session.add(reschedule_message) await sent_message.add_reaction("👍") await sent_message.add_reaction("👎") return raise tosurnament.InvalidMatchId()
def get_teams_infos(self, bracket, team_name1, team_name2): if not bracket.players_spreadsheet: return None, None team1_info = TeamInfo.from_team_name(bracket.players_spreadsheet, team_name1) team2_info = TeamInfo.from_team_name(bracket.players_spreadsheet, team_name2) return team1_info, team2_info