# Copyright (C) 2024 by Animath # SPDX-License-Identifier: GPL-3.0-or-later from django.contrib.auth.models import User from django.db import models from django.db.models import Q, QuerySet from django.utils.text import format_lazy from django.utils.translation import gettext_lazy as _ from participation.models import Tournament from registration.models import ParticipantRegistration, Registration, VolunteerRegistration from tfjm.permissions import PermissionType class Channel(models.Model): name = models.CharField( max_length=255, verbose_name=_("name"), ) read_access = models.CharField( max_length=16, verbose_name=_("read permission"), choices=PermissionType, ) write_access = models.CharField( max_length=16, verbose_name=_("write permission"), choices=PermissionType, ) tournament = models.ForeignKey( 'participation.Tournament', on_delete=models.CASCADE, blank=True, null=True, default=None, verbose_name=_("tournament"), related_name='chat_channels', help_text=_("For a permission that concerns a tournament, indicates what is the concerned tournament."), ) pool = models.ForeignKey( 'participation.Pool', on_delete=models.CASCADE, blank=True, null=True, default=None, verbose_name=_("pool"), related_name='chat_channels', help_text=_("For a permission that concerns a pool, indicates what is the concerned pool."), ) team = models.ForeignKey( 'participation.Team', on_delete=models.CASCADE, blank=True, null=True, default=None, verbose_name=_("team"), related_name='chat_channels', help_text=_("For a permission that concerns a team, indicates what is the concerned team."), ) private = models.BooleanField( verbose_name=_("private"), default=False, help_text=_("If checked, only users who have been explicitly added to the channel will be able to access it."), ) invited = models.ManyToManyField( 'auth.User', verbose_name=_("invited users"), related_name='+', blank=True, help_text=_("Extra users who have been invited to the channel, " "in addition to the permitted group of the channel."), ) def __str__(self): return str(format_lazy(_("Channel {name}"), name=self.name)) @staticmethod async def get_accessible_channels(user: User, permission_type: str = 'read') -> QuerySet["Channel"]: permission_type = 'write_access' if 'write' in permission_type.lower() else 'read_access' qs = Channel.objects.none() if user.is_anonymous: return Channel.objects.filter(**{permission_type: PermissionType.ANONYMOUS}) qs |= Channel.objects.filter(**{permission_type: PermissionType.AUTHENTICATED}) registration = await Registration.objects.aget(user_id=user.id) if registration.is_admin: return Channel.objects.all() if registration.is_volunteer: registration = await VolunteerRegistration.objects \ .prefetch_related('jury_in__tournament', 'organized_tournaments').aget(user_id=user.id) qs |= Channel.objects.filter(**{permission_type: PermissionType.VOLUNTEER}) qs |= Channel.objects.filter(Q(tournament__in=registration.interesting_tournaments), **{permission_type: PermissionType.TOURNAMENT_MEMBER}) qs |= Channel.objects.filter(Q(tournament__in=registration.organized_tournaments.all()), **{permission_type: PermissionType.TOURNAMENT_ORGANIZER}) qs |= Channel.objects.filter(Q(tournament__pools__in=registration.pools_presided.all()) | Q(tournament__in=registration.organized_tournaments.all()), **{permission_type: PermissionType.TOURNAMENT_JURY_PRESIDENT}) qs |= Channel.objects.filter(Q(pool__in=registration.jury_in.all()) | Q(pool__tournament__in=registration.organized_tournaments.all()) | Q(pool__tournament__pools__in=registration.pools_presided.all()), **{permission_type: PermissionType.JURY_MEMBER}) qs |= Channel.objects.filter(Q(pool__in=registration.jury_in.all()) | Q(pool__tournament__in=registration.organized_tournaments.all()) | Q(pool__tournament__pools__in=registration.pools_presided.all()), **{permission_type: PermissionType.POOL_MEMBER}) else: registration = await ParticipantRegistration.objects \ .prefetch_related('team__participation__pools', 'team__participation__tournament').aget(user_id=user.id) team = registration.team tournaments = [] if team.participation.valid: tournaments.append(team.participation.tournament) if team.participation.final: tournaments.append(await Tournament.objects.aget(final=True)) qs |= Channel.objects.filter(Q(tournament__in=tournaments), **{permission_type: PermissionType.TOURNAMENT_MEMBER}) qs |= Channel.objects.filter(Q(pool__in=team.participation.pools.all()), **{permission_type: PermissionType.POOL_MEMBER}) qs |= Channel.objects.filter(Q(team=team), **{permission_type: PermissionType.TEAM_MEMBER}) qs |= Channel.objects.filter(invited=user) print(user) print(qs.query) return qs class Meta: verbose_name = _("channel") verbose_name_plural = _("channels") ordering = ('name',) class Message(models.Model): channel = models.ForeignKey( Channel, on_delete=models.CASCADE, verbose_name=_("channel"), related_name='messages', ) author = models.ForeignKey( 'auth.User', verbose_name=_("author"), on_delete=models.SET_NULL, null=True, related_name='chat_messages', ) created_at = models.DateTimeField( verbose_name=_("created at"), auto_now_add=True, ) updated_at = models.DateTimeField( verbose_name=_("updated at"), auto_now=True, ) content = models.TextField( verbose_name=_("content"), ) class Meta: verbose_name = _("message") verbose_name_plural = _("messages") ordering = ('created_at',)