Beispiel #1
0
 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
Beispiel #2
0
 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
Beispiel #3
0
 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()
Beispiel #4
0
 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
Beispiel #5
0
 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
Beispiel #6
0
 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
Beispiel #7
0
    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)
Beispiel #8
0
 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
Beispiel #9
0
 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")
Beispiel #10
0
    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,
            )
Beispiel #11
0
 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)
Beispiel #12
0
 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
Beispiel #13
0
    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()
Beispiel #14
0
 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