import random import string from django.db.models.signals import post_save, pre_delete, post_delete from django.dispatch import receiver from django.conf import settings from django.utils import timezone from .models import Club, Tournament, FailedApiCall, CustomUser, Log, TeamRegistration, PlayerRegistration, UnregisteredTeam, UnregisteredPlayer, PlayerDataSource import requests from tournaments.services.email_service import TournamentEmailService # Others from shared.discord import send_discord_log_message, send_discord_failed_calls_message 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 send_discord_message(webhook_url, content): # data = { # "content": content # } # requests.post(webhook_url, json=data) # # if response.status_code != 204: # # raise ValueError( # # f'Error sending message to Discord webhook: {response.status_code}, {response.text}' # # ) @receiver(pre_delete, sender=TeamRegistration) def unregister_team(sender, instance, **kwargs): team_registration = instance tournament = instance.tournament if not tournament or tournament.is_deleted is True: return # Create unregistered player records and track captain/other player captain = None other_player = None for player in team_registration.player_registrations.all(): if player.captain is True: captain = player else: other_player = player # Send unregistration confirmation if captain and captain.registered_online and captain.email: TournamentEmailService.send_unregistration_confirmation( captain, tournament, other_player ) first_waiting_list_team = tournament.first_waiting_list_team() print("first_waiting_list_team", first_waiting_list_team) # Handle waiting list notifications if first_waiting_list_team: waiting_captain = None waiting_other_player = None for player in first_waiting_list_team.player_registrations.all(): if player.captain is True: waiting_captain = player else: waiting_other_player = player if waiting_captain and waiting_captain.registered_online and waiting_captain.email: TournamentEmailService.send_out_of_waiting_list_confirmation( waiting_captain, tournament, waiting_other_player ) @receiver(post_save, sender=Tournament) def notify_players_of_tournament_cancellation(sender, instance, **kwargs): tournament = instance if tournament.is_deleted is False: return # Get all team registrations team_registrations = tournament.team_registrations.all() for team_registration in team_registrations: captain = None other_player = None # Get players who registered online and have email for player in team_registration.player_registrations.all(): print(player, player.registered_online) if player.captain: captain = player else: other_player = player # Send email to captain if captain and captain.registered_online and captain.email: TournamentEmailService.send_tournament_cancellation_notification( captain, tournament, other_player ) # Send email to other player if they exist and registered online if other_player and other_player.registered_online and other_player.email: TournamentEmailService.send_tournament_cancellation_notification( other_player, tournament, captain )