You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
9.8 KiB
219 lines
9.8 KiB
import random
|
|
import string
|
|
from django.db.models.signals import pre_save, post_save, pre_delete
|
|
from django.dispatch import receiver
|
|
from django.conf import settings
|
|
from .models import Club, Tournament, FailedApiCall, Log, TeamRegistration
|
|
from tournaments.services.email_service import TournamentEmailService
|
|
from tournaments.services.email_service import TeamEmailType
|
|
from shared.discord import send_discord_log_message, send_discord_failed_calls_message
|
|
from .utils.extensions import is_not_sqlite_backend
|
|
|
|
def generate_unique_code():
|
|
characters = string.ascii_lowercase + string.digits
|
|
while True:
|
|
code = ''.join(random.sample(characters, 3))
|
|
if not Club.objects.filter(broadcast_code=code).exists():
|
|
return code
|
|
|
|
@receiver(post_save, sender=Club)
|
|
def assign_unique_code(sender, instance, **kwargs):
|
|
if not instance.broadcast_code:
|
|
instance.broadcast_code = generate_unique_code()
|
|
instance.save()
|
|
|
|
@receiver(post_save, sender=FailedApiCall)
|
|
def notify_discord_on_create(sender, instance, created, **kwargs):
|
|
notify_object_creation_on_discord(created, instance)
|
|
|
|
@receiver(post_save, sender=Log)
|
|
def notify_log_creation_on_discord(sender, instance, created, **kwargs):
|
|
notify_object_creation_on_discord(created, instance)
|
|
|
|
# WARNING: using this method requires the instance to have a discord_string method
|
|
def notify_object_creation_on_discord(created, instance):
|
|
if created:
|
|
default_db_engine = settings.DATABASES['default']['ENGINE']
|
|
if default_db_engine != 'django.db.backends.sqlite3':
|
|
site_name = settings.SITE_NAME
|
|
if hasattr(instance, 'discord_string'):
|
|
message = f'{site_name} > {instance.__class__.__name__} created: {instance.discord_string()}'
|
|
else:
|
|
message = "no message. Please configure 'discord_string' on your instance"
|
|
|
|
if isinstance(instance, FailedApiCall):
|
|
send_discord_failed_calls_message(message)
|
|
else:
|
|
send_discord_log_message(message)
|
|
|
|
|
|
def notify_team(team, tournament, message_type):
|
|
print(team, message_type)
|
|
# if tournament.enable_online_registration is False:
|
|
# print("returning because tournament.enable_online_registration false")
|
|
# return
|
|
if team.has_registered_online() is False:
|
|
print("returning because team.has_registered_online false")
|
|
return
|
|
if tournament.has_ended():
|
|
print("returning because tournament.has_ended")
|
|
return
|
|
if tournament.has_started():
|
|
print("returning because tournament.has_started")
|
|
return
|
|
|
|
if is_not_sqlite_backend():
|
|
print("is_not_sqlite_backend")
|
|
TournamentEmailService.notify_team(team, tournament, message_type)
|
|
|
|
@receiver(pre_delete, sender=TeamRegistration)
|
|
def unregister_team(sender, instance, **kwargs):
|
|
if not instance.tournament:
|
|
return
|
|
if instance.tournament.is_deleted:
|
|
return
|
|
if instance.tournament.enable_online_registration is False:
|
|
return
|
|
|
|
notify_team(instance, instance.tournament, TeamEmailType.UNREGISTERED)
|
|
teams = instance.tournament.teams(True)
|
|
|
|
# Check if the team being deleted is in the waiting list
|
|
team_being_deleted = next((team for team in teams if team.team_registration.id == instance.id), None)
|
|
is_team_in_waiting_list = team_being_deleted and team_being_deleted.team_registration.out_of_tournament() == True
|
|
|
|
# Only notify the first waiting list team if the deleted team is NOT in the waiting list
|
|
if not is_team_in_waiting_list:
|
|
first_waiting_list_team = instance.tournament.first_waiting_list_team(teams)
|
|
if first_waiting_list_team and first_waiting_list_team.id != instance.id:
|
|
if instance.tournament.automatic_waiting_list():
|
|
waiting_list_teams = instance.tournament.waiting_list_teams(teams)
|
|
ttc = None
|
|
if waiting_list_teams is not None:
|
|
ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams))
|
|
first_waiting_list_team.set_time_to_confirm(ttc)
|
|
notify_team(first_waiting_list_team, instance.tournament, TeamEmailType.OUT_OF_WAITING_LIST)
|
|
|
|
@receiver(post_save, sender=Tournament)
|
|
def notify_players_of_tournament_cancellation(sender, instance, **kwargs):
|
|
if not instance.is_deleted:
|
|
return
|
|
|
|
if instance.enable_online_registration is False:
|
|
return
|
|
|
|
for team_registration in instance.team_registrations.all():
|
|
notify_team(team_registration, instance, TeamEmailType.TOURNAMENT_CANCELED)
|
|
|
|
@receiver(pre_save, sender=Tournament)
|
|
def check_waiting_list(sender, instance, **kwargs):
|
|
if instance.id is None:
|
|
return
|
|
|
|
if instance.enable_online_registration is False:
|
|
return
|
|
|
|
try:
|
|
previous_state = Tournament.objects.get(id=instance.id)
|
|
except Tournament.DoesNotExist:
|
|
previous_state = None
|
|
|
|
if previous_state is None:
|
|
return
|
|
|
|
teams_out_to_warn = []
|
|
teams_in_to_warn = []
|
|
previous_state_teams = previous_state.teams(True)
|
|
if previous_state.team_count > instance.team_count:
|
|
teams_that_will_be_out = instance.teams(True)[instance.team_count:]
|
|
teams_out_to_warn = [
|
|
team for team in teams_that_will_be_out
|
|
if team.stage != "Attente"
|
|
]
|
|
elif previous_state.team_count < instance.team_count:
|
|
teams_that_will_be_in = previous_state_teams[previous_state.team_count:instance.team_count]
|
|
teams_in_to_warn = [
|
|
team for team in teams_that_will_be_in
|
|
if team.stage == "Attente"
|
|
]
|
|
|
|
waiting_list_teams = previous_state.waiting_list_teams(previous_state_teams)
|
|
automatic_waiting_list = instance.automatic_waiting_list()
|
|
ttc = None
|
|
for team in teams_in_to_warn:
|
|
if automatic_waiting_list:
|
|
if waiting_list_teams is not None:
|
|
ttc = previous_state.calculate_time_to_confirm(len(waiting_list_teams))
|
|
team.team_registration.set_time_to_confirm(ttc)
|
|
notify_team(team.team_registration, instance, TeamEmailType.IN_TOURNAMENT_STRUCTURE)
|
|
|
|
for team in teams_out_to_warn:
|
|
team.team_registration.cancel_time_to_confirm()
|
|
notify_team(team.team_registration, instance, TeamEmailType.OUT_OF_TOURNAMENT_STRUCTURE)
|
|
|
|
@receiver(pre_save, sender=TeamRegistration)
|
|
def warn_team_walkout_status_change(sender, instance, **kwargs):
|
|
if instance.id is None or instance.tournament is None or instance.tournament.enable_online_registration is False:
|
|
return
|
|
|
|
print("warn_team_walkout_status_change", instance)
|
|
previous_instance = None
|
|
try:
|
|
previous_instance = TeamRegistration.objects.get(id=instance.id)
|
|
except TeamRegistration.DoesNotExist:
|
|
print("TeamRegistration.DoesNotExist")
|
|
return
|
|
|
|
ttc = None
|
|
previous_teams = instance.tournament.teams(True)
|
|
current_teams = instance.tournament.teams(True, instance)
|
|
previous_retrieved_teams = [team for team in previous_teams if team.team_registration.id == previous_instance.id]
|
|
current_retrieved_teams = [team for team in current_teams if team.team_registration.id == instance.id]
|
|
was_out = previous_instance.out_of_tournament()
|
|
is_out = instance.out_of_tournament()
|
|
if len(previous_retrieved_teams) > 0 and previous_retrieved_teams[0].stage == "Attente":
|
|
was_out = True
|
|
|
|
if len(current_retrieved_teams) > 0 and current_retrieved_teams[0].stage == "Attente":
|
|
is_out = True
|
|
|
|
print(was_out, previous_instance.out_of_tournament(), is_out, instance.out_of_tournament())
|
|
if not instance.out_of_tournament() and is_out and (previous_instance.out_of_tournament() or not was_out):
|
|
instance.cancel_time_to_confirm()
|
|
notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_WAITING_LIST)
|
|
elif was_out and not is_out:
|
|
if instance.tournament.automatic_waiting_list():
|
|
waiting_list_teams = instance.tournament.waiting_list_teams(current_teams)
|
|
if waiting_list_teams is not None:
|
|
ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams))
|
|
instance.set_time_to_confirm(ttc)
|
|
notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_IS_IN)
|
|
elif not previous_instance.out_of_tournament() and instance.out_of_tournament():
|
|
instance.cancel_time_to_confirm()
|
|
print("User did cancel registration", instance.user_did_cancel_registration())
|
|
if instance.user_did_cancel_registration():
|
|
notify_team(instance, instance.tournament, TeamEmailType.UNREGISTERED)
|
|
else:
|
|
notify_team(instance, instance.tournament, TeamEmailType.WALKOUT)
|
|
|
|
if was_out and not is_out:
|
|
first_out_of_list = instance.tournament.first_waiting_list_team(current_teams)
|
|
if first_out_of_list:
|
|
first_out_of_list.cancel_time_to_confirm()
|
|
notify_team(first_out_of_list, instance.tournament, TeamEmailType.UNEXPECTED_OUT_OF_TOURNAMENT)
|
|
elif not was_out and is_out:
|
|
first_waiting_list_team = instance.tournament.first_waiting_list_team(previous_teams)
|
|
if first_waiting_list_team:
|
|
if instance.tournament.automatic_waiting_list():
|
|
waiting_list_teams = instance.tournament.waiting_list_teams(current_teams)
|
|
if waiting_list_teams is not None:
|
|
ttc = instance.tournament.calculate_time_to_confirm(len(waiting_list_teams))
|
|
first_waiting_list_team.set_time_to_confirm(ttc)
|
|
|
|
notify_team(first_waiting_list_team, instance.tournament, TeamEmailType.OUT_OF_WAITING_LIST)
|
|
|
|
@receiver(post_save, sender=TeamRegistration)
|
|
def team_confirm_if_placed(sender, instance, **kwargs):
|
|
if instance.id is None or instance.tournament is None:
|
|
return
|
|
instance.confirm_if_placed()
|
|
|