# 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 AdminRegistration, 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="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 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 Matrix.resolve_room_alias("#bienvenue:tfjm.org"): await Matrix.create_room( visibility=RoomVisibility.public, alias="bienvenue", name="Bienvenue", topic="Bienvenue au TFJM² 2021 !", federate=False, preset=RoomPreset.public_chat, ) if not 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 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 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 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 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 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 AdminRegistration.objects.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 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 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 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 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 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 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 AdminRegistration.objects.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 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 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 if five: 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 AdminRegistration.objects.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 VolunteerRegistration.objects.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 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) asyncio.get_event_loop().run_until_complete(main())