140 lines
3.7 KiB
Python
140 lines
3.7 KiB
Python
# -*- encoding: utf-8 -*-
|
|
|
|
import json
|
|
import logging
|
|
import requests
|
|
|
|
from django.conf import settings
|
|
from django.http import JsonResponse
|
|
from django.views.generic import View, TemplateView
|
|
from django.shortcuts import render, redirect
|
|
from django.contrib.auth import authenticate, login
|
|
|
|
from .models import UserServerLink
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class DiscordLoginAction(View):
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
return redirect(settings.DISCORD_OAUTH2_URL)
|
|
|
|
|
|
class DiscordLoginRedirect(View):
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
"""
|
|
Endpoint function directed to once authorized from Discord.
|
|
This method will "login" the user.
|
|
"""
|
|
|
|
code = request.GET.get("code")
|
|
access_token = self.exchange_code_for_token(code)
|
|
raw_user_data = self.get_raw_user_data(access_token)
|
|
raw_user_data["access_token"] = access_token
|
|
|
|
log.debug(raw_user_data)
|
|
|
|
discord_user = authenticate(request, discord_user_data=raw_user_data)
|
|
login(request, discord_user)
|
|
|
|
return redirect("home:index")
|
|
|
|
def exchange_code_for_token(self, code: str) -> dict:
|
|
"""
|
|
Exchanges the given code for an access token.
|
|
A call is made to the Discord API.
|
|
"""
|
|
|
|
request_data = settings.DISCORD_CODE_EXCHANGE_REQUEST
|
|
request_data["data"]["code"] = code
|
|
|
|
log.debug("request data: %s", request_data)
|
|
|
|
# Fetch the access token
|
|
response = requests.post(
|
|
url=f"{settings.DISCORD_API_URL}/oauth2/token",
|
|
data=request_data["data"],
|
|
headers=request_data["headers"]
|
|
)
|
|
|
|
log.debug(response)
|
|
|
|
return response.json()["access_token"]
|
|
|
|
def get_raw_user_data(self, access_token: str):
|
|
"""
|
|
Fetches the raw user data using the given access token.
|
|
A call is made to the Discord API.
|
|
"""
|
|
|
|
response = requests.get(
|
|
url=f"{settings.DISCORD_API_URL}/users/@me",
|
|
headers={"Authorization": f"Bearer {access_token}"}
|
|
)
|
|
|
|
log.debug(response)
|
|
|
|
return response.json()
|
|
|
|
|
|
class Login(TemplateView):
|
|
|
|
template_name = "accounts/login.html"
|
|
|
|
|
|
class GuildsView(View):
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
response = requests.get(
|
|
url=f"{settings.DISCORD_API_URL}/users/@me/guilds",
|
|
headers={"Authorization": f"Bearer {request.user.access_token}"}
|
|
)
|
|
|
|
content = response.json()
|
|
self.create_server_links(request.user, content)
|
|
|
|
return JsonResponse(content, safe=False)
|
|
|
|
def create_server_links(self, user, content: list[dict]):
|
|
"""
|
|
Creates objects representing the user's discord servers, storing
|
|
server info and the user's permissions within.
|
|
|
|
Parameters
|
|
----------
|
|
content : list[dict]
|
|
Raw data for the servers.
|
|
"""
|
|
|
|
servers = [
|
|
UserServerLink(
|
|
server_id=server["id"],
|
|
user=user,
|
|
name=server["name"],
|
|
permissions=server["permissions"]
|
|
)
|
|
for server in content
|
|
]
|
|
|
|
UserServerLink.objects.filter(user=user).delete()
|
|
UserServerLink.objects.bulk_create(servers)
|
|
|
|
|
|
class GuildChannelsView(View):
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
|
guild_id = request.GET.get("guild")
|
|
|
|
log.debug("fetching channels from %s using token: %s", guild_id, settings.BOT_TOKEN)
|
|
|
|
response = requests.get(
|
|
url=f"{settings.DISCORD_API_URL}/guilds/{guild_id}/channels",
|
|
headers={"Authorization": f"Bot {settings.BOT_TOKEN}"}
|
|
)
|
|
|
|
return JsonResponse(response.json(), safe=False)
|