diff --git a/.env.sample b/.env.sample index 158f7350..cc401799 100644 --- a/.env.sample +++ b/.env.sample @@ -38,4 +38,9 @@ PROTECTED_API_KEY = SYSTEM_ADMIN_ID = -LAUNCHPAD_ADMIN_EMAIL = \ No newline at end of file +LAUNCHPAD_ADMIN_EMAIL = + +DISCORD_CLIENT_ID=xxx +DISCORD_CLIENT_SECRET=xxx +DISCORD_GUILD_ID=xxx +DISCORD_BOT_TOKEN=xxx \ No newline at end of file diff --git a/api/register/register_views.py b/api/register/register_views.py index 2f0f28c4..df08f9c0 100644 --- a/api/register/register_views.py +++ b/api/register/register_views.py @@ -15,6 +15,49 @@ from utils.permission import CustomizePermission, JWTUtils from decouple import config import requests +from mu_celery.task import onboard_user + +DISCORD_CLIENT_ID = config("DISCORD_CLIENT_ID") +DISCORD_CLIENT_SECRET = config("DISCORD_CLIENT_SECRET") +FR_DOMAIN_NAME = config("FR_DOMAIN_NAME") + + +class ConnectDiscordAPI(APIView): + def get(self, request): + if not JWTUtils.is_jwt_authenticated(request): + return CustomResponse( + general_message="Unauthorized access" + ).get_failure_response() + user_id = JWTUtils.fetch_user_id(request) + token = request.GET.get("code") + if not token: + return CustomResponse( + general_message="Invalid or no token given" + ).get_failure_response() + token_url = "https://discord.com/api/oauth2/token" + redirect_uri = f"{FR_DOMAIN_NAME}/dashboard/connect-discord/" + data = { + "client_id": DISCORD_CLIENT_ID, + "client_secret": DISCORD_CLIENT_SECRET, + "grant_type": "authorization_code", + "code": token, + "redirect_uri": redirect_uri, + } + headers = {"Content-Type": "application/x-www-form-urlencoded"} + token_response = requests.post( + token_url, + data=data, + headers=headers, + ) + access_token = token_response.json().get("access_token") + if token_response.status_code != 200: + return CustomResponse( + general_message="Failed to get access token" + ).get_failure_response() + onboard_user.delay(access_token, user_id) + return CustomResponse( + general_message="You will be added to the discord server soon" + ).get_success_response() class UserInterestAPI(APIView): diff --git a/api/register/serializers.py b/api/register/serializers.py index 4330fb75..9067e639 100644 --- a/api/register/serializers.py +++ b/api/register/serializers.py @@ -451,7 +451,7 @@ def update(self, instance, validated_data): def validate_choosen_interests(self, interests): if not all( - interest in ("maker", "software", "creative", "manager", "other") + interest in ("maker", "software", "creative", "management", "others") for interest in interests ): raise serializers.ValidationError("Invalid interests selected.") @@ -465,7 +465,7 @@ def validate_choosen_endgoals(self, end_goals): "higher_education", "gig_work", "entrepreneurship", - "other", + "others", ) for goal in end_goals ): diff --git a/api/register/urls.py b/api/register/urls.py index 4b9a2900..daf1d4ad 100644 --- a/api/register/urls.py +++ b/api/register/urls.py @@ -22,6 +22,6 @@ path("user-country/", register_views.UserCountryAPI.as_view()), path("user-state/", register_views.UserStateAPI.as_view()), path("user-zone/", register_views.UserZoneAPI.as_view()), - path("interests /", register_views.UserInterestAPI.as_view()), - # path("connect-discord/", register_views.ConnectDiscordAPI.as_view()), + path("interests/", register_views.UserInterestAPI.as_view()), + path("connect-discord/", register_views.ConnectDiscordAPI.as_view()), ] diff --git a/mu_celery/task.py b/mu_celery/task.py index d55c75b7..f70d2c91 100644 --- a/mu_celery/task.py +++ b/mu_celery/task.py @@ -1,7 +1,50 @@ from celery import shared_task from utils.utils import send_template_mail +import requests +from decouple import config +from db.user import User + +DISCORD_GUILD_ID = config("DISCORD_GUILD_ID") +DISCORD_BOT_TOKEN = config("DISCORD_BOT_TOKEN") @shared_task def send_email(context: dict, subject: str, address: list[str], attachment: str = None): return send_template_mail(context, subject, address, attachment) + + +@shared_task +def onboard_user(access_token: str, user_id: int): + user = User.objects.get(id=user_id) + user_response = requests.get( + "https://discord.com/api/users/@me", + headers={"Authorization": f"Bearer {access_token}"}, + ) + if user_response.status_code != 200: + return {"status": "error", "message": "Failed to get user data"} + user_data = user_response.json() + discord_user_id = user_data.get("id") + guild_url = ( + f"https://discord.com/api/guilds/{DISCORD_GUILD_ID}/members/{discord_user_id}" + ) + member_data = {"access_token": access_token} + bot_headers = { + "Authorization": f"Bot {DISCORD_BOT_TOKEN}", + "Content-Type": "application/json", + } + already_linked_account = User.objects.filter(discord_id=discord_user_id).first() + if already_linked_account: + already_linked_account.exist_in_guild = False + already_linked_account.discord_id = None + already_linked_account.save() + user.discord_id = discord_user_id + user.exist_in_guild = True + user.save() + join_response = requests.put(guild_url, json=member_data, headers=bot_headers) + if ( + join_response.status_code != 201 + and join_response.status_code != 200 + and join_response.status_code != 204 + ): + return {"status": "error", "message": "Failed to join guild"} + return {"status": "success", "message": "User onboarded successfully"}