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.
 
 
 
 
padelclub_backend/tournaments/signals.py

169 lines
7.0 KiB

import random
import string
from django.db.models.signals import pre_save, post_save, pre_delete, post_delete
from django.dispatch import receiver
from django.conf import settings
from tournaments.models.tournament import Tournament
from tournaments.models.unregistered_player import UnregisteredPlayer
from django.utils import timezone
from .models import Club, FailedApiCall, CustomUser, Log, TeamRegistration, PlayerRegistration, UnregisteredTeam, UnregisteredPlayer, TeamSortingType
import requests
from tournaments.services.email_service import TournamentEmailService, TeamEmailType
from tournaments.models import PlayerDataSource
from shared.discord import send_discord_log_message, send_discord_failed_calls_message
from datetime import datetime
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, created, **kwargs):
if created and 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
message = f'{site_name} > New {instance.__class__.__name__} created: {instance.discord_string()}'
if isinstance(instance, FailedApiCall):
send_discord_failed_calls_message(message)
else:
send_discord_log_message(message)
def notify_team(team, tournament, message_type):
if tournament.enable_online_registration is False:
return
print(team, message_type)
TournamentEmailService.notify_team(team, tournament, message_type)
@receiver(pre_delete, sender=TeamRegistration)
def unregister_team(sender, instance, **kwargs):
if instance.tournament.is_deleted:
return
if instance.tournament.enable_online_registration is False:
return
notify_team(instance, instance.tournament, TeamEmailType.UNREGISTERED)
first_waiting_list_team = instance.tournament.first_waiting_list_team()
if first_waiting_list_team and first_waiting_list_team.id != instance.id:
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.teamregistration_set.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 = []
if previous_state.team_count > instance.team_count:
teams_to_remove_count = previous_state.team_count - instance.team_count
previous_state_teams = previous_state.teams(True)
sorted_teams = sorted(
[team for team in previous_state_teams if team.stage != "Attente" and not (team.wildcard_bracket or team.wildcard_groupstage)],
key=lambda t: (
t.registration_date is None, t.registration_date or datetime.min, t.initial_weight, t.team_registration.id
) if previous_state.team_sorting == TeamSortingType.INSCRIPTION_DATE else
(t.initial_weight, t.team_registration.id)
)
teams_out_to_warn = sorted_teams[-teams_to_remove_count:]
elif previous_state.team_count < instance.team_count:
teams_in_to_warn = [
team for team in previous_state.teams(True)[(instance.team_count - previous_state.team_count):]
if team.stage == "Attente"
]
for team in teams_in_to_warn:
notify_team(team.team_registration, instance, TeamEmailType.IN_TOURNAMENT_STRUCTURE)
for team in teams_out_to_warn:
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:
return
if instance.tournament.enable_online_registration is False:
return
try:
previous_instance = TeamRegistration.objects.get(id=instance.id)
except TeamRegistration.DoesNotExist:
previous_instance = None
if previous_instance is None:
return
previous_teams = previous_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:
if previous_retrieved_teams[0].stage == "Attente":
was_out = True
if len(current_retrieved_teams) > 0:
if 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:
notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_WAITING_LIST)
if not previous_instance.out_of_tournament() and instance.out_of_tournament():
notify_team(instance, instance.tournament, TeamEmailType.WALKOUT)
if was_out and not is_out:
is_in, first_out_of_list = instance.tournament.first_out_of_list(instance)
if is_in:
notify_team(instance, instance.tournament, TeamEmailType.OUT_OF_WALKOUT_IS_IN)
if first_out_of_list:
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()
if first_waiting_list_team:
notify_team(first_waiting_list_team, instance.tournament, TeamEmailType.OUT_OF_WAITING_LIST)