diff --git a/apps/participation/models.py b/apps/participation/models.py index 03bbd58..b62b1a9 100644 --- a/apps/participation/models.py +++ b/apps/participation/models.py @@ -1,3 +1,4 @@ +import asyncio import os import re @@ -56,6 +57,7 @@ class Team(models.Model): "hotline", # TODO Use a custom sympa template f"Liste de diffusion pour contacter l'équipe {self.name} des Correspondances", "education", + raise_error=False, ) def delete_mailing_list(self): @@ -68,6 +70,7 @@ class Team(models.Model): Matrix.create_room( visibility=RoomVisibility.private, + name=f"#équipe-{self.trigram.lower()}", alias=f"team-{self.trigram.lower()}", topic=f"Discussion de l'équipe {self.name}", preset=RoomPreset.private_chat, diff --git a/apps/participation/views.py b/apps/participation/views.py index fa6d6bf..b9345b9 100644 --- a/apps/participation/views.py +++ b/apps/participation/views.py @@ -1,11 +1,12 @@ +import asyncio from io import BytesIO -import os from zipfile import ZipFile from django.shortcuts import redirect -from django.views.generic.base import View, TemplateView +from django.views.generic.base import TemplateView from corres2math.lists import get_sympa_client +from corres2math.matrix import Matrix from corres2math.views import AdminMixin from django.contrib.auth.mixins import LoginRequiredMixin from django.core.exceptions import PermissionDenied @@ -51,6 +52,9 @@ class CreateTeamView(LoginRequiredMixin, CreateView): registration.save() get_sympa_client().subscribe(user.email, f"equipe-{form.instance.trigram.lower()}", False, f"{user.first_name} {user.last_name}") + + Matrix.invite(f"#team-{form.instance.trigram.lower()}:correspondances-maths.fr", + f"@{user.registration.matrix_username}:correspondances-maths.fr") return ret def get_success_url(self): @@ -82,6 +86,9 @@ class JoinTeamView(LoginRequiredMixin, FormView): registration.save() get_sympa_client().subscribe(user.email, f"equipe-{form.instance.trigram.lower()}", False, f"{user.first_name} {user.last_name}") + + Matrix.invite(f"#team-{form.instance.trigram.lower()}:correspondances-maths.fr", + f"@{user.registration.matrix_username}:correspondances-maths.fr") return ret def get_success_url(self): diff --git a/apps/registration/auth.py b/apps/registration/auth.py index dd993e1..d2febf4 100644 --- a/apps/registration/auth.py +++ b/apps/registration/auth.py @@ -9,6 +9,6 @@ class CustomAuthUser(DjangoAuthUser): def attributs(self): d = super().attributs() if self.user: - d["matrix_username"] = f"corres2math_{self.user.pk}" + d["matrix_username"] = self.user.registration.matrix_username d["display_name"] = str(self.user.registration) return d diff --git a/apps/registration/models.py b/apps/registration/models.py index 71c890d..de33c65 100644 --- a/apps/registration/models.py +++ b/apps/registration/models.py @@ -64,6 +64,10 @@ class Registration(PolymorphicModel): def is_admin(self): return isinstance(self, AdminRegistration) or self.user.is_superuser + @property + def matrix_username(self): + return f"corres2math_{self.user.pk}" + def get_absolute_url(self): return reverse_lazy("registration:user_detail", args=(self.user_id,)) diff --git a/corres2math/matrix.py b/corres2math/matrix.py index 94c7b67..ea6274d 100644 --- a/corres2math/matrix.py +++ b/corres2math/matrix.py @@ -1,24 +1,22 @@ import asyncio from typing import Any, Dict, Optional, Union +from asgiref.sync import async_to_sync from nio import AsyncClient, RoomCreateError, RoomCreateResponse, RoomInviteError, RoomInviteResponse, RoomPreset, \ - RoomVisibility + RoomVisibility, RoomResolveAliasResponse class Matrix: @classmethod - def _get_client(cls) -> AsyncClient: - if hasattr(cls, "_client"): - return cls._client - - async def login(): - cls._client = AsyncClient("https://correspondances-maths.fr", "@corres2mathbot:correspondances-maths.fr") - await cls._client.login("toto1234") - return cls._client - return asyncio.get_event_loop().run_until_complete(login()) + async def _get_client(cls) -> AsyncClient: + # TODO Store + client = AsyncClient("https://correspondances-maths.fr", "@corres2mathbot:correspondances-maths.fr") + await client.login("toto1234") + return client @classmethod - def create_room( + @async_to_sync + async def create_room( cls, visibility: RoomVisibility = RoomVisibility.private, alias: Optional[str] = None, @@ -34,10 +32,21 @@ class Matrix: ) -> Union[RoomCreateResponse, RoomCreateError]: resp: Union[RoomCreateResponse, RoomCreateError] - return asyncio.get_event_loop().run_until_complete(cls._get_client().room_create( + client = await cls._get_client() + return await client.room_create( visibility, alias, name, topic, room_version, federate, is_direct, preset, invite, initial_state, - power_level_override)) + power_level_override) @classmethod - def invite(cls, room_id: str, user_id: str) -> Union[RoomInviteResponse, RoomInviteError]: - return asyncio.get_event_loop().run_until_complete(cls._get_client().room_invite(room_id, user_id)) + async def resolve_room_alias(cls, room_alias: str) -> str: + client = await cls._get_client() + resp: RoomResolveAliasResponse = await client.room_resolve_alias(room_alias) + return resp.room_id + + @classmethod + @async_to_sync + async def invite(cls, room_id: str, user_id: str) -> Union[RoomInviteResponse, RoomInviteError]: + client = await cls._get_client() + if room_id.startswith("#"): + room_id = await cls.resolve_room_alias(room_id) + return await client.room_invite(room_id, user_id)