async def init_post_result(self, ctx, match_id): """Allows referees to post the result of a match""" tournament = self.get_tournament(ctx.guild.id) for bracket in tournament.brackets: schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: continue try: MatchInfo.from_id(schedules_spreadsheet, match_id) except MatchIdNotFound: continue return tournament, bracket raise tosurnament.InvalidMatchId()
async def take_or_drop_match_in_spreadsheets(self, match_ids, user_details, take, left_match_ids, *schedules_spreadsheets, retry=False): """Takes or drops matches of a bracket, if possible.""" user_details.clear_matches() left_match_ids.clear() left_match_ids.update(match_ids) for schedules_spreadsheet in schedules_spreadsheets: await schedules_spreadsheet.get_spreadsheet() for match_id in left_match_ids.copy(): try: match_info = MatchInfo.from_id(schedules_spreadsheet, match_id, False) except MatchIdNotFound: continue self.take_match_for_roles(schedules_spreadsheet, match_info, user_details, take) left_match_ids.remove(match_id) if left_match_ids and not retry: return False for schedules_spreadsheet in schedules_spreadsheets: self.add_update_spreadsheet_background_task(schedules_spreadsheet) return True
async def step8_per_bracket(self, ctx, post_result_message, tournament): bracket = tournament.current_bracket schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: raise tosurnament.NoSpreadsheet("schedules") await schedules_spreadsheet.get_spreadsheet() match_info = MatchInfo.from_id(schedules_spreadsheet, post_result_message.match_id, False) if tournament.staff_channel_id: error_channel = self.bot.get_channel(tournament.staff_channel_id) else: error_channel = ctx prbuilder = await self.create_prbuilder(ctx, post_result_message, tournament, bracket, match_info, error_channel) if tournament.post_result_message: result_string = tournament.post_result_message else: result_string = self.get_string("post_result", "default") result_string = prbuilder.build(result_string, self, tournament) if bracket.challonge: await self.step8_challonge(ctx, tournament, error_channel, prbuilder) await self.step8_write_in_spreadsheet(bracket, match_info, prbuilder) post_result_channel = ctx if bracket.post_result_channel_id: post_result_channel = self.bot.get_channel( bracket.post_result_channel_id) await post_result_channel.send(result_string)
async def step7_send_message(self, channel, tournament, post_result_message): bracket = self.bot.session.query(Bracket).where( Bracket.id == post_result_message.bracket_id).first() if not bracket: self.bot.session.delete(post_result_message) raise tosurnament.NoBracket() schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: raise tosurnament.NoSpreadsheet("schedules") await schedules_spreadsheet.get_spreadsheet() match_info = MatchInfo.from_id(schedules_spreadsheet, post_result_message.match_id, False) prbuilder = await self.create_prbuilder(None, post_result_message, tournament, bracket, match_info, channel) if tournament.post_result_message: result_string = tournament.post_result_message else: result_string = self.get_string("post_result", "default") result_string = prbuilder.build(result_string, self, tournament) await self.update_post_result_setup_message(post_result_message, channel, 8) preview_message = await self.send_reply(channel, "post_result", "preview", result_string) post_result_message.preview_message_id = preview_message.id
async def get_next_matches_info_for_bracket(self, tournament, bracket): matches_data = [] schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: return matches_data await schedules_spreadsheet.get_spreadsheet() match_ids_cells = schedules_spreadsheet.spreadsheet.get_cells_with_value_in_range( schedules_spreadsheet.range_match_id) now = datetime.datetime.utcnow() matches_to_ignore = tournament.matches_to_ignore.split("\n") for match_id_cell in match_ids_cells: if match_id_cell.value in matches_to_ignore: continue match_info = MatchInfo.from_match_id_cell(schedules_spreadsheet, match_id_cell) date_format = "%d %B" if schedules_spreadsheet.date_format: date_format = schedules_spreadsheet.date_format match_date = tournament.parse_date( match_info.get_datetime(), date_formats=list(filter(None, [date_format + " %H:%M"]))) if not match_date or match_date < now: continue matches_data.append((match_info, match_date)) return matches_data
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 init_post_result(self, ctx, match_id): """Allows referees to post the result of a match""" tournament = self.get_tournament(ctx.guild.id) for bracket in tournament.brackets: schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: continue await schedules_spreadsheet.get_spreadsheet() try: MatchInfo.from_id(schedules_spreadsheet, match_id) except MatchIdNotFound: continue return tournament, bracket raise tosurnament.InvalidMatchId() post_result_message = (self.bot.session.query(PostResultMessage).where( PostResultMessage.tournament_id == tournament.id).where( PostResultMessage.referee_id == ctx.author.id).first()) if post_result_message: # TODO Raise error ctx.send( "You cannot start multiple post_result at the same time. Please finish your previous one or cancel it." )
def take_matches(self, bracket, match_ids, staff_name, user_roles, take, invalid_match_ids): """Takes or drops matches of a bracket, if possible.""" schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: return write_cells = False for match_id in match_ids: try: match_info = MatchInfo.from_id(schedules_spreadsheet, match_id, False) except MatchIdNotFound: invalid_match_ids.append(match_id) continue write_cells |= self.take_match_for_roles(schedules_spreadsheet, match_info, staff_name, user_roles, take,) return write_cells
async def get_match_infos_from_id(self, bracket, match_ids): schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: return [] await schedules_spreadsheet.get_spreadsheet() match_ids_cells = schedules_spreadsheet.spreadsheet.get_cells_with_value_in_range( schedules_spreadsheet.range_match_id) match_infos = [] for match_id_cell in match_ids_cells: if match_id_cell.value.lower() in match_ids: match_infos.append( MatchInfo.from_match_id_cell(schedules_spreadsheet, match_id_cell)) match_ids.remove(match_id_cell.value.lower()) return match_infos
async def match_notification(self, guild, tournament): player_match_notification_channel = None if tournament.match_notification_channel_id: player_match_notification_channel = self.bot.get_channel( tournament.match_notification_channel_id) staff_channel = None if tournament.staff_channel_id: staff_channel = self.bot.get_channel(tournament.staff_channel_id) if not player_match_notification_channel and not staff_channel: return matches_to_ignore = [ match_id.upper() for match_id in tournament.matches_to_ignore.split("\n") ] for bracket in tournament.brackets: schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: continue await schedules_spreadsheet.get_spreadsheet(retry=True) now = datetime.datetime.utcnow() match_ids = schedules_spreadsheet.spreadsheet.get_cells_with_value_in_range( schedules_spreadsheet.range_match_id) for match_id_cell in match_ids: if match_id_cell.value.upper() in matches_to_ignore: continue match_info = MatchInfo.from_match_id_cell( schedules_spreadsheet, match_id_cell) date_format = "%d %B" if schedules_spreadsheet.date_format: date_format = schedules_spreadsheet.date_format match_date = tournament.parse_date( match_info.get_datetime(), date_formats=list(filter(None, [date_format + " %H:%M"])), to_timezone="UTC", ) if match_date: delta = match_date - now if player_match_notification_channel: await self.player_match_notification( guild, tournament, bracket, player_match_notification_channel, match_info, delta) if staff_channel: await self.referee_match_notification( guild, tournament, bracket, staff_channel, match_info, delta, match_date)
def fill_matches_info_for_roles(self, ctx, bracket, matches_to_ignore, user_roles, user_name): team_name = None if user_roles.player: team_name = self.find_player_identification( ctx, bracket, user_name) schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: return match_ids_cells = schedules_spreadsheet.worksheet.get_cells_with_value_in_range( schedules_spreadsheet.range_match_id) now = datetime.datetime.utcnow() for match_id_cell in match_ids_cells: if match_id_cell.value in matches_to_ignore: continue match_info = MatchInfo.from_match_id_cell(schedules_spreadsheet, match_id_cell) date_format = "%d %B" if schedules_spreadsheet.date_format: date_format = schedules_spreadsheet.date_format match_date = dateparser.parse( match_info.get_datetime(), date_formats=list(filter(None, [date_format + " %H:%M"])), ) if not match_date: continue if match_date < now: continue if (user_roles.player and team_name and (match_info.team1.has_value(team_name) or match_info.team2.has_value(team_name))): user_roles.player.taken_matches.append( (bracket.name, match_info, match_date)) for referee_cell in match_info.referees: if user_roles.referee and referee_cell.has_value(user_name): user_roles.referee.taken_matches.append( (bracket.name, match_info, match_date)) for streamer_cell in match_info.streamers: if user_roles.streamer and streamer_cell.has_value(user_name): user_roles.streamer.taken_matches.append( (bracket.name, match_info, match_date)) for commentator_cell in match_info.commentators: if user_roles.commentator and commentator_cell.has_value( user_name): user_roles.commentator.taken_matches.append( (bracket.name, match_info, match_date))
def find_matches_to_notify(self, bracket): matches_info = [] now = datetime.datetime.utcnow() schedules_spreadsheet = bracket.schedules_spreadsheet match_ids = bracket.schedules_spreadsheet.worksheet.get_cells_with_value_in_range( bracket.schedules_spreadsheet.range_match_id ) for match_id_cell in match_ids: match_info = MatchInfo.from_match_id_cell(schedules_spreadsheet, match_id_cell) date_format = "%d %B" if schedules_spreadsheet.date_format: date_format = schedules_spreadsheet.date_format match_date = dateparser.parse( match_info.get_datetime(), date_formats=list(filter(None, [date_format + " %H:%M"])), ) if match_date: delta = match_date - now if delta.days == 0 and delta.seconds >= 900 and delta.seconds < 1800: matches_info.append(match_info) return matches_info
async def step7_send_message(self, ctx, tournament, post_result_message): bracket = self.bot.session.query(Bracket).where(Bracket.id == post_result_message.bracket_id).first() if not bracket: self.bot.session.delete(post_result_message) raise tosurnament.NoBracket() schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: raise tosurnament.NoSpreadsheet("schedules") match_info = MatchInfo.from_id(schedules_spreadsheet, post_result_message.match_id, False) prbuilder = await self.create_prbuilder(post_result_message, tournament, bracket, match_info, ctx) if tournament.post_result_message: result_string = tournament.post_result_message else: result_string = self.get_string("post_result", "default") result_string = prbuilder.build(result_string, self, tournament) message = await self.send_reply( ctx, "post_result", "step8", post_result_message.match_id, post_result_message.best_of, post_result_message.roll_team1, post_result_message.roll_team2, post_result_message.n_warmup, osu.build_mp_links(post_result_message.mp_links.split("\n")), post_result_message.bans_team1, post_result_message.bans_team2, post_result_message.tb_bans_team1, post_result_message.tb_bans_team2, ) post_result_message.setup_message_id = message.id post_result_message.step = 8 preview_message = await self.send_reply(ctx, "post_result", "preview", result_string) post_result_message.preview_message_id = preview_message.id return message
async def agree_to_reschedule(self, reschedule_message, guild, channel, user, tournament): """Updates the schedules spreadsheet with reschedule time.""" schedules_spreadsheet = tournament.current_bracket.schedules_spreadsheet if not schedules_spreadsheet: raise tosurnament.NoSpreadsheet(tournament.current_bracket.name, "schedules") await schedules_spreadsheet.get_spreadsheet() match_id = reschedule_message.match_id match_info = MatchInfo.from_id(schedules_spreadsheet, match_id) if reschedule_message.previous_date: previous_date = datetime.datetime.strptime( reschedule_message.previous_date, tosurnament.DATABASE_DATE_FORMAT) previous_date_string = tosurnament.get_pretty_date( tournament, previous_date) else: previous_date_string = "**No previous date**" new_date = datetime.datetime.strptime(reschedule_message.new_date, tosurnament.DATABASE_DATE_FORMAT) date_format = "%d %B" if schedules_spreadsheet.date_format: date_format = schedules_spreadsheet.date_format if schedules_spreadsheet.range_date and schedules_spreadsheet.range_time: match_info.date.value = new_date.strftime(date_format) match_info.time.value = new_date.strftime("%H:%M") elif schedules_spreadsheet.range_date: match_info.date.value = new_date.strftime(date_format + " %H:%M") elif schedules_spreadsheet.range_time: match_info.time.value = new_date.strftime(date_format + " %H:%M") else: raise tosurnament.UnknownError("No date range") self.add_update_spreadsheet_background_task(schedules_spreadsheet) 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", "accepted", ally_to_mention.mention, match_id) else: # TODO not raise raise tosurnament.OpponentNotFound(user.mention) referees_to_ping, _ = self.find_staff_to_ping(guild, match_info.referees) streamers_to_ping, _ = self.find_staff_to_ping(guild, match_info.streamers) commentators_to_ping, _ = self.find_staff_to_ping( guild, match_info.commentators) new_date_string = tosurnament.get_pretty_date(tournament, new_date) staff_channel = None if tournament.staff_channel_id: staff_channel = self.bot.get_channel(tournament.staff_channel_id) if referees_to_ping + streamers_to_ping + commentators_to_ping: if staff_channel: to_channel = staff_channel else: to_channel = channel sent_message = await self.send_reply( to_channel, "reschedule", "staff_notification", match_id, match_info.team1.value, match_info.team2.value, previous_date_string, new_date_string, " / ".join([referee.mention for referee in referees_to_ping]), " / ".join( [streamer.mention for streamer in streamers_to_ping]), " / ".join([ commentator.mention for commentator in commentators_to_ping ]), ) staff_reschedule_message = StaffRescheduleMessage( tournament_id=reschedule_message.tournament_id, bracket_id=tournament.current_bracket.id, message_id=sent_message.id, team1=match_info.team1.value, team2=match_info.team2.value, match_id=match_id, previous_date=reschedule_message.previous_date, new_date=reschedule_message.new_date, referees_id="\n".join( [str(referee.id) for referee in referees_to_ping]), streamers_id="\n".join( [str(streamer.id) for streamer in streamers_to_ping]), commentators_id="\n".join([ str(commentator.id) for commentator in commentators_to_ping ]), ) self.bot.session.add(staff_reschedule_message) elif staff_channel and tournament.notify_no_staff_reschedule: await self.send_reply( staff_channel, "reschedule", "no_staff_notification", match_id, match_info.team1.value, match_info.team2.value, previous_date_string, new_date_string, ) allowed_reschedules = (self.bot.session.query(AllowedReschedule).where( AllowedReschedule.tournament_id == tournament.id).all()) for allowed_reschedule in allowed_reschedules: if allowed_reschedule.match_id.upper() == match_id.upper(): self.bot.session.delete(allowed_reschedule)
async def reaction_on_staff_reschedule_message(self, message_id, emoji, guild, channel, user): """Removes the referee from the schedule spreadsheet""" staff_reschedule_message = ( self.bot.session.query(StaffRescheduleMessage).where( StaffRescheduleMessage.message_id == message_id).first()) if not staff_reschedule_message or staff_reschedule_message.in_use: return if user.id != staff_reschedule_message.staff_id: return if emoji.name != "❌": return try: tosurnament_user = self.get_verified_user(user.id) osu_name = tosurnament_user.osu_name except (tosurnament.UserNotLinked, tosurnament.UserNotVerified ): # ! Temporary for nik's tournament osu_name = user.display_name staff_reschedule_message.in_use = True self.bot.session.update(staff_reschedule_message) try: tournament = self.get_tournament(guild.id) bracket = self.bot.session.query(Bracket).where( Bracket.id == staff_reschedule_message.bracket_id).first() if not bracket: raise tosurnament.UnknownError("Bracket not found") schedules_spreadsheet = bracket.schedules_spreadsheet if not schedules_spreadsheet: raise tosurnament.NoSpreadsheet() match_id = staff_reschedule_message.match_id match_info = MatchInfo.from_id(schedules_spreadsheet, match_id) staff_cells = match_info.referees + match_info.streamers + match_info.commentators for staff_cell in staff_cells: if staff_cell.has_value(osu_name): if schedules_spreadsheet.use_range: staff_cell.value = "" else: staffs = staff_cell.value.split("/") if len(staffs) == 2 and staffs[0].strip() == osu_name: staff_cell.value = staffs[1].strip() elif len(staffs) == 2 and staffs[1].strip == osu_name: staff_cell.value = staffs[0].strip() elif len( staffs) == 1 and staffs[0].strip() == osu_name: staff_cell.value = "" try: schedules_spreadsheet.spreadsheet.update() except HttpError as e: raise tosurnament.SpreadsheetHttpError(e.code, e.operation, bracket.name, "schedules") to_channel = channel staff_channel = self.bot.get_channel(tournament.staff_channel_id) if staff_channel: to_channel = staff_channel await self.send_reply( to_channel, "reschedule", "removed_from_match", user.mention, match_id, ) self.bot.session.delete(staff_reschedule_message) except Exception as e: staff_reschedule_message.in_use = False self.bot.session.update(staff_reschedule_message) await self.reaction_on_staff_reschedule_message_handler(channel, e)
async def agree_to_reschedule(self, reschedule_message, guild, channel, user, tournament): """Updates the schedules spreadsheet with reschedule time.""" schedules_spreadsheet = tournament.current_bracket.schedules_spreadsheet if not schedules_spreadsheet: raise tosurnament.NoSpreadsheet(tournament.current_bracket.name, "schedules") match_id = reschedule_message.match_id match_info = MatchInfo.from_id(schedules_spreadsheet, match_id) previous_date = datetime.datetime.strptime( reschedule_message.previous_date, tosurnament.DATABASE_DATE_FORMAT) new_date = datetime.datetime.strptime(reschedule_message.new_date, tosurnament.DATABASE_DATE_FORMAT) date_format = "%d %B" if schedules_spreadsheet.date_format: date_format = schedules_spreadsheet.date_format if schedules_spreadsheet.range_date and schedules_spreadsheet.range_time: match_info.date.value = new_date.strftime(date_format) match_info.time.value = new_date.strftime("%H:%M") elif schedules_spreadsheet.range_date: match_info.date.value = new_date.strftime(date_format + " %H:%M") elif schedules_spreadsheet.range_time: match_info.time.value = new_date.strftime(date_format + " %H:%M") else: raise tosurnament.UnknownError("No date range") staff_name_to_ping = set() staff_cells = match_info.referees + match_info.streamers + match_info.commentators for staff_cell in staff_cells: if schedules_spreadsheet.use_range: staff_name_to_ping.add(staff_cell.value) else: staffs = staff_cell.value.split("/") for staff in staffs: staff_name_to_ping.add(staff.strip()) staff_to_ping = list( filter( None, [guild.get_member_named(name) for name in staff_name_to_ping])) try: schedules_spreadsheet.spreadsheet.update() except HttpError as e: raise tosurnament.SpreadsheetHttpError( e.code, e.operation, tournament.current_bracket.name, "schedules") 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", "accepted", ally_to_mention.mention, match_id, ) else: raise tosurnament.OpponentNotFound(user.mention) previous_date_string = previous_date.strftime( tosurnament.PRETTY_DATE_FORMAT) new_date_string = new_date.strftime(tosurnament.PRETTY_DATE_FORMAT) staff_channel = None if tournament.staff_channel_id: staff_channel = self.bot.get_channel(tournament.staff_channel_id) if staff_to_ping: if staff_channel: to_channel = staff_channel else: to_channel = channel for staff in staff_to_ping: sent_message = await self.send_reply( to_channel, "reschedule", "staff_notification", staff.mention, match_id, match_info.team1.value, match_info.team2.value, previous_date_string, new_date_string, ) staff_reschedule_message = StaffRescheduleMessage( tournament_id=reschedule_message.tournament_id, bracket_id=tournament.current_bracket.id, message_id=sent_message.id, match_id=match_id, new_date=reschedule_message.new_date, staff_id=staff.id, ) self.bot.session.add(staff_reschedule_message) elif staff_channel: await self.send_reply( staff_channel, "reschedule", "no_staff_notification", match_id, match_info.team1.value, match_info.team2.value, previous_date_string, new_date_string, ) allowed_reschedules = (self.bot.session.query(AllowedReschedule).where( AllowedReschedule.tournament_id == tournament.id).all()) for allowed_reschedule in allowed_reschedules: if allowed_reschedule.match_id.upper() == match_id.upper(): self.bot.session.delete(allowed_reschedule)
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()
async def reschedule_for_bracket( self, ctx, tournament, bracket, schedules_spreadsheet, players_spreadsheet, match_id, new_date, user, skip_deadline_validation, retry=False, ): try: match_info = MatchInfo.from_id(schedules_spreadsheet, match_id) except (tosurnament.SpreadsheetHttpError, InvalidWorksheet) as e: if retry: await self.on_cog_command_error(ctx, ctx.command.name, e) return False except MatchIdNotFound as e: if retry: self.bot.info_exception(e) return False match_id = match_info.match_id.value players_spreadsheet = bracket.players_spreadsheet if players_spreadsheet: await players_spreadsheet.get_spreadsheet() if not user.verified: # TODO find player_name from discord_id in players_spreadsheet pass ally_team_info, opponent_team_info = await self.get_teams_info( ctx, tournament, players_spreadsheet, match_info, user) if not ally_team_info: return False team_name = ally_team_info.team_name.value opponent_team_name = opponent_team_info.team_name.value opponent_user = tosurnament.UserAbstraction.get_from_osu_name( ctx.bot, opponent_team_info.players[0].value, opponent_team_info.discord[0].value) else: team_name = user.name if team_name == match_info.team1.value: opponent_team_name = match_info.team2.value elif team_name == match_info.team2.value: opponent_team_name = match_info.team1.value else: raise tosurnament.InvalidMatch() opponent_user = tosurnament.UserAbstraction.get_from_osu_name( ctx.bot, opponent_team_name) now = datetime.datetime.utcnow() new_date = self.validate_new_date(ctx, tournament, schedules_spreadsheet, match_info, now, new_date, skip_deadline_validation) previous_date = self.validate_reschedule_feasibility( ctx, tournament, schedules_spreadsheet, match_info, now, new_date, skip_deadline_validation) opponent_team_captain = opponent_user.get_member(ctx.guild) if not opponent_team_captain: raise tosurnament.OpponentNotFound(ctx.author.mention) opponent_to_ping = opponent_team_captain if players_spreadsheet and players_spreadsheet.range_team_name and tournament.reschedule_ping_team: role = tosurnament.get_role(ctx.guild.roles, None, opponent_team_name) if role: opponent_to_ping = role reschedule_message = RescheduleMessage(tournament_id=tournament.id, bracket_id=bracket.id, in_use=False) 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.match_id_hash = match_id reschedule_message.ally_user_id = ctx.author.id reschedule_message.opponent_user_id = opponent_team_captain.id if previous_date: previous_date_string = tosurnament.get_pretty_date( tournament, previous_date) reschedule_message.previous_date = previous_date.strftime( tosurnament.DATABASE_DATE_FORMAT) else: previous_date_string = "**No previous date**" reschedule_message.previous_date = "" new_date_string = tosurnament.get_pretty_date(tournament, new_date) 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(team_name), match_id, previous_date_string, new_date_string, ) reschedule_message.message_id = sent_message.id previous_reschedule_message = ( self.bot.session.query(RescheduleMessage).where( RescheduleMessage.tournament_id == tournament.id).where( RescheduleMessage.match_id_hash == match_id).first()) if previous_reschedule_message: self.bot.session.delete(previous_reschedule_message) self.bot.session.add(reschedule_message) await sent_message.add_reaction("👍") await sent_message.add_reaction("👎") return True