mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-06-21 07:18:25 +02:00
Move apps in main directory
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
2
participation/management/commands/__init__.py
Normal file
2
participation/management/commands/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
# Copyright (C) 2020 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
87
participation/management/commands/check_hello_asso.py
Normal file
87
participation/management/commands/check_hello_asso.py
Normal file
@ -0,0 +1,87 @@
|
||||
# Copyright (C) 2020 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import os
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.management import BaseCommand
|
||||
from django.db.models import Q
|
||||
import requests
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def handle(self, *args, **options): # noqa: C901
|
||||
# Get access token
|
||||
response = requests.post('https://api.helloasso.com/oauth2/token', headers={
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}, data={
|
||||
'client_id': os.getenv('HELLOASSO_CLIENT_ID', ''),
|
||||
'client_secret': os.getenv('HELLOASSO_CLIENT_SECRET', ''),
|
||||
'grant_type': 'client_credentials',
|
||||
}).json()
|
||||
|
||||
token = response['access_token']
|
||||
|
||||
organization = "animath"
|
||||
form_slug = "tfjm-2023-tournois-regionaux"
|
||||
from_date = "2000-01-01"
|
||||
url = f"https://api.helloasso.com/v5/organizations/{organization}/forms/Event/{form_slug}/payments" \
|
||||
f"?from={from_date}&pageIndex=1&pageSize=100&retrieveOfflineDonations=false"
|
||||
headers = {
|
||||
"Accept": "application/json",
|
||||
"Authorization": f"Bearer {token}",
|
||||
}
|
||||
http_response = requests.get(url, headers=headers)
|
||||
response = http_response.json()
|
||||
|
||||
if http_response.status_code != 200:
|
||||
message = response["message"]
|
||||
self.stderr.write(f"Error while querying Hello Asso: {message}")
|
||||
return
|
||||
|
||||
for payment in response["data"]:
|
||||
if payment["state"] != "Authorized":
|
||||
continue
|
||||
|
||||
payer = payment["payer"]
|
||||
email = payer["email"]
|
||||
last_name = payer["lastName"]
|
||||
first_name = payer["firstName"]
|
||||
base_filter = Q(
|
||||
registration__participantregistration__isnull=False,
|
||||
registration__participantregistration__team__isnull=False,
|
||||
registration__participantregistration__team__participation__valid=True,
|
||||
)
|
||||
qs = User.objects.filter(
|
||||
base_filter,
|
||||
email=email,
|
||||
)
|
||||
if not qs.exists():
|
||||
qs = User.objects.filter(
|
||||
base_filter,
|
||||
last_name__icontains=last_name,
|
||||
)
|
||||
if qs.count() >= 2:
|
||||
qs = qs.filter(first_name__icontains=first_name)
|
||||
if not qs.exists():
|
||||
self.stderr.write(f"Warning: a payment was found by {first_name} {last_name} ({email}), "
|
||||
"but this user is unknown.")
|
||||
continue
|
||||
if qs.count() > 1:
|
||||
self.stderr.write(f"Warning: a payment was found by {first_name} {last_name} ({email}), "
|
||||
f"but there are {qs.count()} matching users.")
|
||||
continue
|
||||
user = qs.get()
|
||||
if not user.registration.participates:
|
||||
self.stderr.write(f"Warning: a payment was found by the email address {email}, "
|
||||
"but this user is not a participant.")
|
||||
continue
|
||||
payment_obj = user.registration.payment
|
||||
payment_obj.valid = True
|
||||
payment_obj.type = "helloasso"
|
||||
payment_obj.additional_information = f"Identifiant de transation : {payment['id']}\n" \
|
||||
f"Date : {payment['date']}\n" \
|
||||
f"Reçu : {payment['paymentReceiptUrl']}\n" \
|
||||
f"Montant : {payment['amount'] / 100:.2f} €"
|
||||
payment_obj.save()
|
||||
self.stdout.write(f"{payment_obj} is validated")
|
86
participation/management/commands/export_results.py
Normal file
86
participation/management/commands/export_results.py
Normal file
@ -0,0 +1,86 @@
|
||||
# Copyright (C) 2021 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django.core.management import BaseCommand
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.translation import activate
|
||||
|
||||
from .models import Tournament
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def handle(self, *args, **kwargs):
|
||||
activate('fr')
|
||||
|
||||
tournaments = Tournament.objects.order_by('-date_start', 'name')
|
||||
for tournament in tournaments:
|
||||
self.handle_tournament(tournament)
|
||||
self.w("")
|
||||
self.w("")
|
||||
|
||||
def w(self, msg):
|
||||
self.stdout.write(msg)
|
||||
|
||||
def handle_tournament(self, tournament):
|
||||
name = tournament.name
|
||||
date_start = date_format(tournament.date_start, "DATE_FORMAT")
|
||||
date_end = date_format(tournament.date_end, "DATE_FORMAT")
|
||||
|
||||
notes = dict()
|
||||
for participation in tournament.participations.filter(valid=True).all():
|
||||
note = sum(pool.average(participation)
|
||||
for pool in tournament.pools.filter(participations=participation).all())
|
||||
notes[participation] = note
|
||||
notes = sorted(notes.items(), key=lambda x: x[1], reverse=True)
|
||||
|
||||
self.w("<!-- wp:heading {\"level\":3} -->")
|
||||
self.w(f"<h3><strong>{name}</strong></h3>")
|
||||
self.w("<!-- /wp:heading -->")
|
||||
self.w("")
|
||||
self.w("<!-- wp:paragraph -->")
|
||||
if tournament.final:
|
||||
self.w(f"<p>La finale a eu lieu le weekend du {date_start} au {date_end} et a été remporté par l'équipe "
|
||||
f"<em>{notes[0][0].team.name}</em> suivie de l'équipe <em>{notes[1][0].team.name}</em>. "
|
||||
f"Les deux premières équipes sont sélectionnées pour représenter la France lors de l'ITYM.</p>")
|
||||
else:
|
||||
self.w(f"<p>Le tournoi de {name} a eu lieu le weekend du {date_start} au {date_end} et a été remporté par "
|
||||
f"l'équipe <em>{notes[0][0].team.name}</em>.</p>")
|
||||
self.w("<!-- /wp:paragraph -->")
|
||||
self.w("")
|
||||
self.w("")
|
||||
self.w("<!-- wp:table -->")
|
||||
self.w("<figure class=\"wp-block-table\">")
|
||||
self.w("<table>")
|
||||
self.w("<thead>")
|
||||
self.w("<tr>")
|
||||
self.w("\t<th>Équipe</th>")
|
||||
self.w("\t<th>Score Tour 1</th>")
|
||||
self.w("\t<th>Score Tour 2</th>")
|
||||
self.w("\t<th>Total</th>")
|
||||
self.w("\t<th class=\"has-text-align-center\">Prix</th>")
|
||||
self.w("</tr>")
|
||||
self.w("</thead>")
|
||||
self.w("<tbody>")
|
||||
for i, (participation, note) in enumerate(notes):
|
||||
self.w("<tr>")
|
||||
if i < (2 if len(notes) >= 7 else 1):
|
||||
self.w(f"\t<th>{participation.team.name} ({participation.team.trigram})</td>")
|
||||
else:
|
||||
self.w(f"\t<td>{participation.team.name} ({participation.team.trigram})</td>")
|
||||
for pool in tournament.pools.filter(participations=participation).all():
|
||||
pool_note = pool.average(participation)
|
||||
self.w(f"\t<td>{pool_note:.01f}</td>")
|
||||
self.w(f"\t<td>{note:.01f}</td>")
|
||||
if i == 0:
|
||||
self.w("\t<td class=\"has-text-align-center\">1<sup>er</sup> prix</td>")
|
||||
elif i < (5 if tournament.final else 3):
|
||||
self.w(f"\t<td class=\"has-text-align-center\">{i + 1}<sup>ème</sup> prix</td>")
|
||||
elif i < 2 * len(notes) / 3:
|
||||
self.w("\t<td class=\"has-text-align-center\">Mention très honorable</td>")
|
||||
else:
|
||||
self.w("\t<td class=\"has-text-align-center\">Mention honorable</td>")
|
||||
self.w("</tr>")
|
||||
self.w("</tbody>")
|
||||
self.w("</table>")
|
||||
self.w("</figure>")
|
||||
self.w("<!-- /wp:table -->")
|
82
participation/management/commands/export_solutions.py
Normal file
82
participation/management/commands/export_solutions.py
Normal file
@ -0,0 +1,82 @@
|
||||
# Copyright (C) 2021 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from django.core.management import BaseCommand
|
||||
from django.utils.translation import activate
|
||||
|
||||
from .models import Solution, Tournament
|
||||
|
||||
|
||||
PROBLEMS = [
|
||||
"Pliage de polygones",
|
||||
"Mélodie des hirondelles",
|
||||
"Professeur confiné",
|
||||
"Nain sans mémoire",
|
||||
"Bricolage microscopique",
|
||||
"Villes jumelées",
|
||||
"Promenade de chiens",
|
||||
"Persée et la Gorgone",
|
||||
]
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def handle(self, *args, **kwargs):
|
||||
activate('fr')
|
||||
|
||||
base_dir = Path(__file__).parent.parent.parent.parent.parent
|
||||
base_dir /= "output"
|
||||
if not base_dir.is_dir():
|
||||
base_dir.mkdir()
|
||||
base_dir /= "Par équipe"
|
||||
if not base_dir.is_dir():
|
||||
base_dir.mkdir()
|
||||
|
||||
tournaments = Tournament.objects.all()
|
||||
for tournament in tournaments:
|
||||
self.handle_tournament(tournament, base_dir)
|
||||
|
||||
base_dir = base_dir.parent / "Par problème"
|
||||
if not base_dir.is_dir():
|
||||
base_dir.mkdir()
|
||||
|
||||
for problem_id, problem_name in enumerate(PROBLEMS):
|
||||
dir_name = f"Problème n°{problem_id + 1} : {problem_name}"
|
||||
problem_dir = base_dir / dir_name
|
||||
if not problem_dir.is_dir():
|
||||
problem_dir.mkdir()
|
||||
self.handle_problem(problem_id + 1, problem_dir)
|
||||
|
||||
def handle_tournament(self, tournament, base_dir):
|
||||
name = tournament.name
|
||||
tournament_dir = base_dir / name
|
||||
if not tournament_dir.is_dir():
|
||||
tournament_dir.mkdir()
|
||||
|
||||
for participation in tournament.participations.filter(valid=True).all():
|
||||
self.handle_participation(participation, tournament_dir)
|
||||
|
||||
def handle_participation(self, participation, tournament_dir):
|
||||
name = participation.team.name
|
||||
trigram = participation.team.trigram
|
||||
team_dir = tournament_dir / f"{name} ({trigram})"
|
||||
if not team_dir.is_dir():
|
||||
team_dir.mkdir()
|
||||
|
||||
for solution in participation.solutions.all():
|
||||
filename = f"{solution}.pdf"
|
||||
with solution.file as file_input:
|
||||
with open(team_dir / filename, 'wb') as file_output:
|
||||
file_output.write(file_input.read())
|
||||
|
||||
def handle_problem(self, problem_id, directory):
|
||||
solutions = Solution.objects.filter(problem=problem_id).all()
|
||||
|
||||
for solution in solutions:
|
||||
team = solution.participation.team
|
||||
tournament_name = team.participation.tournament.name
|
||||
output_file = directory / f'{solution}.pdf'
|
||||
if output_file.is_file():
|
||||
output_file.unlink()
|
||||
output_file.symlink_to(f'../../Par équipe/{tournament_name}/{team.name} ({team.trigram})/{solution}.pdf')
|
477
participation/management/commands/fix_matrix_channels.py
Normal file
477
participation/management/commands/fix_matrix_channels.py
Normal file
@ -0,0 +1,477 @@
|
||||
# Copyright (C) 2020 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from django.core.management import BaseCommand
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.translation import activate
|
||||
from participation.models import Team, Tournament
|
||||
from registration.models import Registration, VolunteerRegistration
|
||||
from tfjm.matrix import Matrix, RoomPreset, RoomVisibility
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def handle(self, *args, **options): # noqa: C901
|
||||
activate("fr")
|
||||
|
||||
async def main():
|
||||
await Matrix.set_display_name("Bot du TFJM²")
|
||||
|
||||
if not os.getenv("SYNAPSE_PASSWORD"):
|
||||
avatar_uri = "plop"
|
||||
else: # pragma: no cover
|
||||
if not os.path.isfile(".matrix_avatar"):
|
||||
avatar_uri = await Matrix.get_avatar()
|
||||
if isinstance(avatar_uri, str):
|
||||
with open(".matrix_avatar", "w") as f:
|
||||
f.write(avatar_uri)
|
||||
else:
|
||||
stat_file = os.stat("tfjm/static/logo.png")
|
||||
with open("tfjm/static/logo.png", "rb") as f:
|
||||
resp = (await Matrix.upload(f, filename="../../../tfjm/static/logo.png", content_type="image/png",
|
||||
filesize=stat_file.st_size))[0][0]
|
||||
avatar_uri = resp.content_uri
|
||||
with open(".matrix_avatar", "w") as f:
|
||||
f.write(avatar_uri)
|
||||
await Matrix.set_avatar(avatar_uri)
|
||||
|
||||
with open(".matrix_avatar", "r") as f:
|
||||
avatar_uri = f.read().rstrip(" \t\r\n")
|
||||
|
||||
# Create basic channels
|
||||
if not await Matrix.resolve_room_alias("#aide-jurys-orgas:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias="aide-jurys-orgas",
|
||||
name="Aide jurys & orgas",
|
||||
topic="Pour discuter de propblèmes d'organisation",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias("#annonces:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias="annonces",
|
||||
name="Annonces",
|
||||
topic="Informations importantes du TFJM²",
|
||||
federate=False,
|
||||
preset=RoomPreset.public_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias("#bienvenue:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias="bienvenue",
|
||||
name="Bienvenue",
|
||||
topic="Bienvenue au TFJM² 2023 !",
|
||||
federate=False,
|
||||
preset=RoomPreset.public_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias("#bot:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias="bot",
|
||||
name="Bot",
|
||||
topic="Vive les r0b0ts",
|
||||
federate=False,
|
||||
preset=RoomPreset.public_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias("#cno:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias="cno",
|
||||
name="CNO",
|
||||
topic="Channel des dieux",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias("#dev-bot:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias="dev-bot",
|
||||
name="Bot - développement",
|
||||
topic="Vive le bot",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias("#faq:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias="faq",
|
||||
name="FAQ",
|
||||
topic="Posez toutes vos questions ici !",
|
||||
federate=False,
|
||||
preset=RoomPreset.public_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias("#flood:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias="flood",
|
||||
name="Flood",
|
||||
topic="Discutez de tout et de rien !",
|
||||
federate=False,
|
||||
preset=RoomPreset.public_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias("#je-cherche-une-equipe:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias="je-cherche-une-equipe",
|
||||
name="Je cherche une équipe",
|
||||
topic="Le Tinder du TFJM²",
|
||||
federate=False,
|
||||
preset=RoomPreset.public_chat,
|
||||
)
|
||||
|
||||
# Setup avatars
|
||||
await Matrix.set_room_avatar("#aide-jurys-orgas:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar("#annonces:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar("#bienvenue:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar("#bot:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar("#cno:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar("#dev-bot:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar("#faq:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar("#flood:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar("#je-cherche-une-equipe:tfjm.org", avatar_uri)
|
||||
|
||||
# Read-only channels
|
||||
await Matrix.set_room_power_level_event("#annonces:tfjm.org", "events_default", 50)
|
||||
await Matrix.set_room_power_level_event("#bienvenue:tfjm.org", "events_default", 50)
|
||||
|
||||
# Invite everyone to public channels
|
||||
for r in Registration.objects.all():
|
||||
await Matrix.invite("#annonces:tfjm.org", f"@{r.matrix_username}:tfjm.org")
|
||||
await Matrix.invite("#bienvenue:tfjm.org", f"@{r.matrix_username}:tfjm.org")
|
||||
await Matrix.invite("#bot:tfjm.org", f"@{r.matrix_username}:tfjm.org")
|
||||
await Matrix.invite("#faq:tfjm.org", f"@{r.matrix_username}:tfjm.org")
|
||||
await Matrix.invite("#flood:tfjm.org", f"@{r.matrix_username}:tfjm.org")
|
||||
await Matrix.invite("#je-cherche-une-equipe:tfjm.org",
|
||||
f"@{r.matrix_username}:tfjm.org")
|
||||
self.stdout.write(f"Invite {r} in most common channels...")
|
||||
|
||||
# Volunteers have access to the help channel
|
||||
for volunteer in VolunteerRegistration.objects.all():
|
||||
await Matrix.invite("#aide-jurys-orgas:tfjm.org", f"@{volunteer.matrix_username}:tfjm.org")
|
||||
self.stdout.write(f"Invite {volunteer} in #aide-jury-orgas...")
|
||||
|
||||
# Admins are admins
|
||||
for admin in VolunteerRegistration.objects.filter(admin=True).all():
|
||||
self.stdout.write(f"Invite {admin} in #cno and #dev-bot...")
|
||||
await Matrix.invite("#cno:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
|
||||
await Matrix.invite("#dev-bot:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
|
||||
|
||||
self.stdout.write(f"Give admin permissions for {admin}...")
|
||||
await Matrix.set_room_power_level("#aide-jurys-orgas:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level("#annonces:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level("#bienvenue:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level("#bot:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level("#cno:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level("#dev-bot:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level("#faq:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level("#flood:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level("#je-cherche-une-equipe:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
|
||||
# Create tournament-specific channels
|
||||
for tournament in Tournament.objects.all():
|
||||
self.stdout.write(f"Managing tournament of {tournament.name}.")
|
||||
|
||||
name = tournament.name
|
||||
slug = name.lower().replace(" ", "-")
|
||||
|
||||
if not await Matrix.resolve_room_alias(f"#annonces-{slug}:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"annonces-{slug}",
|
||||
name=f"{name} - Annonces",
|
||||
topic=f"Annonces du tournoi de {name}",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias(f"#general-{slug}:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"general-{slug}",
|
||||
name=f"{name} - Général",
|
||||
topic=f"Accueil du tournoi de {name}",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias(f"#flood-{slug}:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"flood-{slug}",
|
||||
name=f"{name} - Flood",
|
||||
topic=f"Discussion libre du tournoi de {name}",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias(f"#jury-{slug}:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"jury-{slug}",
|
||||
name=f"{name} - Jury",
|
||||
topic=f"Discussion entre les orgas et jurys du tournoi de {name}",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias(f"#orga-{slug}:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"orga-{slug}",
|
||||
name=f"{name} - Organisateurs",
|
||||
topic=f"Discussion entre les orgas du tournoi de {name}",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
if not await Matrix.resolve_room_alias(f"#tirage-au-sort-{slug}:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"tirage-au-sort-{slug}",
|
||||
name=f"{name} - Tirage au sort",
|
||||
topic=f"Tirage au sort du tournoi de {name}",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
# Setup avatars
|
||||
await Matrix.set_room_avatar(f"#annonces-{slug}:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar(f"#flood-{slug}:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar(f"#general-{slug}:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar(f"#jury-{slug}:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar(f"#orga-{slug}:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar(f"#tirage-au-sort-{slug}:tfjm.org", avatar_uri)
|
||||
|
||||
# Invite admins and give permissions
|
||||
for admin in VolunteerRegistration.objects.filter(admin=True).all():
|
||||
self.stdout.write(f"Invite {admin} in all channels of the tournament {name}...")
|
||||
await Matrix.invite(f"#annonces-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#flood-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#general-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#jury-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#orga-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#tirage-au-sort-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
|
||||
|
||||
self.stdout.write(f"Give permissions to {admin} in all channels of the tournament {name}...")
|
||||
await Matrix.set_room_power_level(f"#annonces-{slug}:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level(f"#flood-{slug}:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level(f"#general-{slug}:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level(f"#jury-{slug}:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level(f"#orga-{slug}:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level(f"#tirage-au-sort-{slug}:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
|
||||
# Invite organizers and give permissions
|
||||
for orga in tournament.organizers.all():
|
||||
self.stdout.write(f"Invite organizer {orga} in all channels of the tournament {name}...")
|
||||
await Matrix.invite(f"#annonces-{slug}:tfjm.org", f"@{orga.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#flood-{slug}:tfjm.org", f"@{orga.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#general-{slug}:tfjm.org", f"@{orga.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#jury-{slug}:tfjm.org", f"@{orga.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#orga-{slug}:tfjm.org", f"@{orga.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#tirage-au-sort-{slug}:tfjm.org", f"@{orga.matrix_username}:tfjm.org")
|
||||
|
||||
if not orga.is_admin:
|
||||
await Matrix.set_room_power_level(f"#annonces-{slug}:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org", 50)
|
||||
await Matrix.set_room_power_level(f"#flood-{slug}:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org", 50)
|
||||
await Matrix.set_room_power_level(f"#general-{slug}:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org", 50)
|
||||
await Matrix.set_room_power_level(f"#jury-{slug}:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org", 50)
|
||||
await Matrix.set_room_power_level(f"#orga-{slug}:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org", 50)
|
||||
await Matrix.set_room_power_level(f"#tirage-au-sort-{slug}:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org", 50)
|
||||
|
||||
# Invite participants
|
||||
for participation in tournament.participations.filter(valid=True).all():
|
||||
for participant in participation.team.participants.all():
|
||||
self.stdout.write(f"Invite {participant} in public channels of the tournament {name}...")
|
||||
await Matrix.invite(f"#annonces-{slug}:tfjm.org",
|
||||
f"@{participant.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#flood-{slug}:tfjm.org",
|
||||
f"@{participant.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#general-{slug}:tfjm.org",
|
||||
f"@{participant.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#tirage-au-sort-{slug}:tfjm.org",
|
||||
f"@{participant.matrix_username}:tfjm.org")
|
||||
|
||||
# Create pool-specific channels
|
||||
for pool in tournament.pools.all():
|
||||
self.stdout.write(f"Managing {pool}...")
|
||||
five = pool.participations.count() >= 5
|
||||
for i in range(2 if five else 1):
|
||||
# Fix for five teams-pools
|
||||
suffix = f"-{chr(ord('A') + i)}" if five else ""
|
||||
if not await Matrix.resolve_room_alias(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"poule-{slug}-{pool.id}{suffix}",
|
||||
name=f"{name} - Jour {pool.round} - Poule " +
|
||||
', '.join(participation.team.trigram
|
||||
for participation in pool.participations.all()) + suffix,
|
||||
topic=f"Discussion avec les équipes - {pool}{suffix}",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
if not await Matrix.resolve_room_alias(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"poule-{slug}-{pool.id}{suffix}-jurys",
|
||||
name=f"{name} - Jour {pool.round}{suffix} - Jurys poule " +
|
||||
', '.join(participation.team.trigram
|
||||
for participation in pool.participations.all()) + suffix,
|
||||
topic=f"Discussion avec les jurys - {pool}{suffix}",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
|
||||
await Matrix.set_room_avatar(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org", avatar_uri)
|
||||
await Matrix.set_room_avatar(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org", avatar_uri)
|
||||
|
||||
bbb_url = pool.bbb_url.strip()
|
||||
if five and ';' in bbb_url:
|
||||
bbb_url = bbb_url.split(";")[i].strip()
|
||||
url_params = urlencode(dict(url=bbb_url,
|
||||
isAudioConf='false', displayName='$matrix_display_name',
|
||||
avatarUrl='$matrix_avatar_url', userId='$matrix_user_id')) \
|
||||
.replace("%24", "$")
|
||||
await Matrix.add_integration(
|
||||
f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
|
||||
f"https://scalar.vector.im/api/widgets/bigbluebutton.html?{url_params}",
|
||||
f"bbb-{slug}-{pool.id}{suffix}", "bigbluebutton", "BigBlueButton", str(pool))
|
||||
await Matrix.add_integration(
|
||||
f"#poule-{slug}-{pool.id}:tfjm.org",
|
||||
f"https://board.tfjm.org/boards/{slug}-{pool.id}", f"board-{slug}-{pool.id}",
|
||||
"customwidget", "Tableau", str(pool))
|
||||
|
||||
# Invite admins and give permissions
|
||||
for admin in VolunteerRegistration.objects.filter(admin=True).all():
|
||||
await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org")
|
||||
|
||||
await Matrix.set_room_power_level(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
await Matrix.set_room_power_level(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org",
|
||||
f"@{admin.matrix_username}:tfjm.org", 95)
|
||||
|
||||
# Invite organizers and give permissions
|
||||
for orga in tournament.organizers.all():
|
||||
await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org")
|
||||
|
||||
if not orga.is_admin:
|
||||
await Matrix.set_room_power_level(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org", 50)
|
||||
await Matrix.set_room_power_level(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org",
|
||||
f"@{orga.matrix_username}:tfjm.org", 50)
|
||||
|
||||
# Invite the jury, give good permissions
|
||||
for jury in pool.juries.all():
|
||||
await Matrix.invite(f"#annonces-{slug}:tfjm.org", f"@{jury.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#general-{slug}:tfjm.org", f"@{jury.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#flood-{slug}:tfjm.org", f"@{jury.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#jury-{slug}:tfjm.org", f"@{jury.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#orga-{slug}:tfjm.org", f"@{jury.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
|
||||
f"@{jury.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org",
|
||||
f"@{jury.matrix_username}:tfjm.org")
|
||||
await Matrix.invite(f"#tirage-au-sort-{slug}:tfjm.org",
|
||||
f"@{jury.matrix_username}:tfjm.org")
|
||||
|
||||
if not jury.is_admin:
|
||||
await Matrix.set_room_power_level(f"#jury-{slug}:tfjm.org",
|
||||
f"@{jury.matrix_username}:tfjm.org", 50)
|
||||
await Matrix.set_room_power_level(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
|
||||
f"@{jury.matrix_username}:tfjm.org", 50)
|
||||
await Matrix.set_room_power_level(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org",
|
||||
f"@{jury.matrix_username}:tfjm.org", 50)
|
||||
|
||||
# Invite participants to the right pool
|
||||
for participation in pool.participations.all():
|
||||
for participant in participation.team.participants.all():
|
||||
await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
|
||||
f"@{participant.matrix_username}:tfjm.org")
|
||||
|
||||
# Create private channels for teams
|
||||
for team in Team.objects.all():
|
||||
self.stdout.write(f"Create private channel for {team}...")
|
||||
if not await Matrix.resolve_room_alias(f"#equipe-{team.trigram.lower()}:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"equipe-{team.trigram.lower()}",
|
||||
name=f"Équipe {team.trigram}",
|
||||
topic=f"Discussion interne de l'équipe {team.name}",
|
||||
federate=False,
|
||||
preset=RoomPreset.private_chat,
|
||||
)
|
||||
for participant in team.participants.all():
|
||||
await Matrix.invite(f"#equipe-{team.trigram.lower}:tfjm.org",
|
||||
f"@{participant.matrix_username}:tfjm.org")
|
||||
await Matrix.set_room_power_level(f"#equipe-{team.trigram.lower()}:tfjm.org",
|
||||
f"@{participant.matrix_username}:tfjm.org", 50)
|
||||
|
||||
"""
|
||||
# Manage channels to discuss about problems
|
||||
for i in range(9):
|
||||
self.stdout.write(f"Create channel for problem {i}...")
|
||||
if not await Matrix.resolve_room_alias(f"#mec-{i}:tfjm.org"):
|
||||
await Matrix.create_room(
|
||||
visibility=RoomVisibility.public,
|
||||
alias=f"mec-{i}",
|
||||
name=f"Mise en commun - {'Général' if i == 0 else f'Problème {i}'}",
|
||||
topic=f"Discussion autour des problèmes",
|
||||
federate=False,
|
||||
preset=RoomPreset.public_chat,
|
||||
invite=[f"@{registration.matrix_username}:tfjm.org"
|
||||
for registration in Registration.objects.all()],
|
||||
power_level_override={
|
||||
f"@{registration.matrix_username}:tfjm.org": (95 if registration.is_admin else 50)
|
||||
for registration in VolunteerRegistration.objects.all()
|
||||
},
|
||||
)
|
||||
await Matrix.set_room_avatar(f"#mec-{i}:tfjm.org", avatar_uri)
|
||||
|
||||
for registration in Registration.objects.all():
|
||||
await Matrix.invite(f"#mec-{i}:tfjm.org", registration.matrix_username)
|
||||
|
||||
for registration in VolunteerRegistration.objects.all():
|
||||
await Matrix.set_room_power_level(f"#mec-{i}:tfjm.org",
|
||||
f"@{registration.matrix_username}:tfjm.org",
|
||||
95 if registration.is_admin else 50)
|
||||
"""
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(main())
|
75
participation/management/commands/fix_sympa_lists.py
Normal file
75
participation/management/commands/fix_sympa_lists.py
Normal file
@ -0,0 +1,75 @@
|
||||
# Copyright (C) 2020 by Animath
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django.core.management import BaseCommand
|
||||
from django.db.models import Q
|
||||
from participation.models import Team, Tournament
|
||||
from registration.models import ParticipantRegistration, VolunteerRegistration
|
||||
from tfjm.lists import get_sympa_client
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
def handle(self, *args, **options):
|
||||
"""
|
||||
Create Sympa mailing lists and register teams.
|
||||
"""
|
||||
sympa = get_sympa_client()
|
||||
|
||||
sympa.create_list("equipes", "Equipes du TFJM2", "hotline",
|
||||
"Liste de diffusion pour contacter toutes les equipes validees du TFJM2.",
|
||||
"education", raise_error=False)
|
||||
sympa.create_list("equipes-non-valides", "Equipes non valides du TFJM2", "hotline",
|
||||
"Liste de diffusion pour contacter toutes les equipes non validees du TFJM2.",
|
||||
"education", raise_error=False)
|
||||
|
||||
sympa.create_list("admins", "Administrateurs du TFJM2", "hotline",
|
||||
"Liste de diffusion pour contacter tous les administrateurs du TFJM2.",
|
||||
"education", raise_error=False)
|
||||
sympa.create_list("organisateurs", "Organisateurs du TFJM2", "hotline",
|
||||
"Liste de diffusion pour contacter tous les organisateurs du TFJM2.",
|
||||
"education", raise_error=False)
|
||||
sympa.create_list("jurys", "Jurys du TFJM2", "hotline",
|
||||
"Liste de diffusion pour contacter tous les jurys du TFJM2.",
|
||||
"education", raise_error=False)
|
||||
|
||||
for tournament in Tournament.objects.all():
|
||||
slug = tournament.name.lower().replace(" ", "-")
|
||||
sympa.create_list(f"equipes-{slug}", f"Equipes du tournoi {tournament.name}", "hotline",
|
||||
f"Liste de diffusion pour contacter toutes les equipes du tournoi {tournament.name}"
|
||||
" du TFJM2.", "education", raise_error=False)
|
||||
sympa.create_list(f"organisateurs-{slug}", f"Organisateurs du tournoi {tournament.name}", "hotline",
|
||||
"Liste de diffusion pour contacter tous les organisateurs du tournoi "
|
||||
f"{tournament.name} du TFJM2.", "education", raise_error=False)
|
||||
sympa.create_list(f"jurys-{slug}", f"Jurys du tournoi {tournament.name}", "hotline",
|
||||
f"Liste de diffusion pour contacter tous les jurys du tournoi {tournament.name}"
|
||||
f" du TFJM2.", "education", raise_error=False)
|
||||
|
||||
sympa.subscribe(tournament.teams_email, "equipes", True)
|
||||
sympa.subscribe(tournament.organizers_email, "organisateurs", True)
|
||||
sympa.subscribe(tournament.jurys_email, "jurys", True)
|
||||
|
||||
for team in Team.objects.filter(participation__valid=True).all():
|
||||
team.create_mailing_list()
|
||||
sympa.unsubscribe(team.email, "equipes-non-valides", True)
|
||||
sympa.subscribe(team.email, f"equipes-{team.participation.tournament.name.lower().replace(' ', '-')}",
|
||||
True, f"Equipe {team.name}")
|
||||
|
||||
for team in Team.objects.filter(Q(participation__valid=False) | Q(participation__valid__isnull=True)).all():
|
||||
team.create_mailing_list()
|
||||
sympa.subscribe(team.email, "equipes-non-valides", True, f"Equipe {team.name}")
|
||||
|
||||
for participant in ParticipantRegistration.objects.filter(team__isnull=False).all():
|
||||
sympa.subscribe(participant.user.email, f"equipe-{participant.team.trigram.lower()}",
|
||||
True, f"{participant}")
|
||||
|
||||
for volunteer in VolunteerRegistration.objects.all():
|
||||
for organized_tournament in volunteer.organized_tournaments.all():
|
||||
slug = organized_tournament.name.lower().replace(" ", "-")
|
||||
sympa.subscribe(volunteer.user.email, f"organisateurs-{slug}", True)
|
||||
|
||||
for jury_in in volunteer.jury_in.all():
|
||||
slug = jury_in.tournament.name.lower().replace(" ", "-")
|
||||
sympa.subscribe(volunteer.user.email, f"jurys-{slug}", True)
|
||||
|
||||
for admin in VolunteerRegistration.objects.filter(admin=True).all():
|
||||
sympa.subscribe(admin.user.email, "admins", True)
|
Reference in New Issue
Block a user