From 82ae9e39ba18cd2b01e15c73386f27ef298d8cc7 Mon Sep 17 00:00:00 2001
From: kwanok
Date: Mon, 18 Mar 2024 18:05:18 +0900
Subject: [PATCH] wip
---
web/league_entry.py | 22 +--
...nt_id_summoner_profile_icon_id_and_more.py | 38 ++++++
web/project/app/models.py | 18 ++-
web/project/app/riot_client.py | 7 +
web/project/app/serializers.py | 3 +-
web/project/app/urls.py | 15 ++-
web/project/app/views.py | 100 ++++++++++----
web/project/project/settings.py | 8 +-
web/project/templates/recommend/ai.html | 4 +-
web/project/templates/recommend/result.html | 2 +-
web/project/templates/users/profile.html | 125 +++++++++++++++---
web/project/users/admin.py | 4 +-
...summoner_info_appuser_summoner_and_more.py | 32 +++++
web/project/users/models.py | 15 +--
14 files changed, 303 insertions(+), 90 deletions(-)
create mode 100644 web/project/app/migrations/0007_summoner_account_id_summoner_profile_icon_id_and_more.py
create mode 100644 web/project/users/migrations/0003_remove_appuser_summoner_info_appuser_summoner_and_more.py
diff --git a/web/league_entry.py b/web/league_entry.py
index c37566d..2f8a061 100644
--- a/web/league_entry.py
+++ b/web/league_entry.py
@@ -15,15 +15,15 @@ def __init__(self):
self.api_key = os.environ.get("RIOT_API_KEY")
self.tiers = ["IRON", "BRONZE", "SILVER", "GOLD", "PLATINUM", "DIAMOND"]
self.divisions = ["I", "II", "III", "IV"]
-
+
self.db_user = os.environ.get("POSTGRES_USER")
self.db_password = os.environ.get("POSTGRES_PASSWORD")
self.db_host = "localhost"
self.db_port = os.environ.get("POSTGRES_PORT")
self.db_name = os.environ.get("POSTGRES_WEB_DB")
-
+
self.pool = None
-
+
async def create_db_pool(self):
self.pool = await asyncpg.create_pool(
user=self.db_user,
@@ -31,7 +31,7 @@ async def create_db_pool(self):
host=self.db_host,
port=self.db_port,
database=self.db_name,
- )
+ )
async def run(self):
await self.create_db_pool()
@@ -50,7 +50,9 @@ async def get_league_entries(self, tier: str, division: str):
league_entries = await self._fetch(url + f"&page={page}")
while league_entries:
- print(f"Fetching {tier} {division} page {page}... entries: {len(league_entries)}")
+ print(
+ f"Fetching {tier} {division} page {page}... entries: {len(league_entries)}"
+ )
summoners = [
(
league_entry["summonerId"],
@@ -58,10 +60,9 @@ async def get_league_entries(self, tier: str, division: str):
datetime.datetime.now(),
datetime.datetime.now(),
)
- for league_entry
- in league_entries
+ for league_entry in league_entries
]
-
+
async with self.pool.acquire() as connection:
async with connection.transaction():
await connection.executemany(
@@ -93,8 +94,7 @@ async def get_league_entries(self, tier: str, division: str):
datetime.datetime.now(),
datetime.datetime.now(),
)
- for league_entry
- in league_entries
+ for league_entry in league_entries
]
async with self.pool.acquire() as connection:
async with connection.transaction():
@@ -123,7 +123,7 @@ async def get_league_entries(self, tier: str, division: str):
page += 1
league_entries = await self._fetch(url + f"&page={page}")
-
+
return []
async def _fetch(self, url: str) -> list:
diff --git a/web/project/app/migrations/0007_summoner_account_id_summoner_profile_icon_id_and_more.py b/web/project/app/migrations/0007_summoner_account_id_summoner_profile_icon_id_and_more.py
new file mode 100644
index 0000000..292c239
--- /dev/null
+++ b/web/project/app/migrations/0007_summoner_account_id_summoner_profile_icon_id_and_more.py
@@ -0,0 +1,38 @@
+# Generated by Django 5.0.2 on 2024-03-15 06:51
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("app", "0006_summoner_app_summone_name_9a15eb_idx"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="summoner",
+ name="account_id",
+ field=models.CharField(max_length=100, null=True),
+ ),
+ migrations.AddField(
+ model_name="summoner",
+ name="profile_icon_id",
+ field=models.IntegerField(null=True),
+ ),
+ migrations.AddField(
+ model_name="summoner",
+ name="puuid",
+ field=models.CharField(max_length=100, null=True),
+ ),
+ migrations.AddField(
+ model_name="summoner",
+ name="revision_date",
+ field=models.BigIntegerField(null=True),
+ ),
+ migrations.AddField(
+ model_name="summoner",
+ name="summoner_level",
+ field=models.IntegerField(null=True),
+ ),
+ ]
diff --git a/web/project/app/models.py b/web/project/app/models.py
index 64591a2..a374022 100644
--- a/web/project/app/models.py
+++ b/web/project/app/models.py
@@ -1,6 +1,5 @@
# Create your models here.
-from django.contrib.postgres.search import SearchVector, SearchVectorField
from users.models import AppUser as User
from django.db import models
@@ -31,16 +30,19 @@ class Champion(models.Model):
class Summoner(models.Model):
id = models.CharField(max_length=100, blank=False, null=False, primary_key=True)
name = models.CharField(max_length=100, blank=False, null=False)
+ puuid = models.CharField(max_length=100, blank=False, null=True)
+ account_id = models.CharField(max_length=100, blank=False, null=True)
+ profile_icon_id = models.IntegerField(blank=False, null=True)
+ revision_date = models.BigIntegerField(blank=False, null=True)
+ summoner_level = models.IntegerField(blank=False, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
-
+
class Meta:
- indexes = [
- models.Index(fields=['name'])
- ]
+ indexes = [models.Index(fields=["name"])]
class LeagueEntry(models.Model):
@@ -61,8 +63,10 @@ class LeagueEntry(models.Model):
def __str__(self):
return f"{self.summoner.name} - {self.tier} {self.rank}"
-
+
class Meta:
constraints = [
- models.UniqueConstraint(fields=['summoner', 'queue_type'], name='unique_league_entry')
+ models.UniqueConstraint(
+ fields=["summoner", "queue_type"], name="unique_league_entry"
+ )
]
diff --git a/web/project/app/riot_client.py b/web/project/app/riot_client.py
index 9b63e0a..47ee2e9 100644
--- a/web/project/app/riot_client.py
+++ b/web/project/app/riot_client.py
@@ -30,6 +30,13 @@ def get_champion_masteries_by_puuid_top(self, puuid: str) -> requests.Response:
response = requests.get(url, headers={"X-Riot-Token": self.api_key})
return response
+ def get_summoner_by_encrypted_summoner_id(
+ self, encrypted_summoner_id: str
+ ) -> requests.Response:
+ url = f"{KR_API_HOST}/lol/summoner/v4/summoners/{encrypted_summoner_id}"
+ response = requests.get(url, headers={"X-Riot-Token": self.api_key})
+ return response
+
client = RiotClient()
diff --git a/web/project/app/serializers.py b/web/project/app/serializers.py
index a597750..ae825db 100644
--- a/web/project/app/serializers.py
+++ b/web/project/app/serializers.py
@@ -1,6 +1,7 @@
from app.models import Summoner, LeagueEntry
from rest_framework import serializers
+
class SummonerSerializer(serializers.ModelSerializer):
class Meta:
model = Summoner
@@ -10,4 +11,4 @@ class Meta:
class LeagueEntrySerializer(serializers.ModelSerializer):
class Meta:
model = LeagueEntry
- fields = "__all__"
\ No newline at end of file
+ fields = "__all__"
diff --git a/web/project/app/urls.py b/web/project/app/urls.py
index ee39366..3bff6e2 100644
--- a/web/project/app/urls.py
+++ b/web/project/app/urls.py
@@ -1,5 +1,6 @@
from django.urls import path, include
-from rest_framework import routers
+
+from project import settings
from .views import (
index,
get_account_by_summoner_name,
@@ -7,6 +8,7 @@
recommend_result,
riot_txt,
search_summoners_by_name,
+ save_summoner,
)
urlpatterns = [
@@ -15,6 +17,13 @@
path("summoner/", get_account_by_summoner_name, name="summoner"),
path("recommend-ai/", recommend_ai, name="recommend-ai"),
path("recommend-result/", recommend_result, name="recommend-result"),
- path("summoners/search/", search_summoners_by_name, name="search-summoners-by-name"),
- path("__debug__/", include("debug_toolbar.urls")),
+ path(
+ "summoners/search/", search_summoners_by_name, name="search-summoners-by-name"
+ ),
+ path("profile/summoner", save_summoner, name="save-summoner-info"),
]
+
+if settings.DEBUG:
+ import debug_toolbar
+
+ urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns
diff --git a/web/project/app/views.py b/web/project/app/views.py
index 5e79c89..01e7adf 100644
--- a/web/project/app/views.py
+++ b/web/project/app/views.py
@@ -1,18 +1,14 @@
-import os
-import uuid
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.core.handlers.wsgi import WSGIRequest
-import requests
from django.contrib.auth.decorators import login_required
-from users.models import SummonerInfo
+from app.models import Summoner
from rest_framework.decorators import api_view
from app.riot_client import get_client
-from app.riot_assets import get_riot_assets
-from rest_framework import viewsets
from app.serializers import SummonerSerializer, LeagueEntrySerializer
-from app.models import Summoner, LeagueEntry
+from app.models import LeagueEntry
+from users.models import AppUser
def riot_txt(request: WSGIRequest):
@@ -42,10 +38,10 @@ def authorize(request: WSGIRequest):
def get_account_by_summoner_name(request: WSGIRequest):
summoner_name = request.GET.get("summoner_name")
- if SummonerInfo.objects.filter(name=summoner_name).exists():
- summoner_info = SummonerInfo.objects.get(name=summoner_name)
+ if Summoner.objects.filter(name=summoner_name).exists():
+ summoner = Summoner.objects.get(name=summoner_name)
- return render(request, "summoner/index.html", {"summoner": summoner_info})
+ return render(request, "summoner/index.html", {"summoner": summoner})
client = get_client()
@@ -54,7 +50,7 @@ def get_account_by_summoner_name(request: WSGIRequest):
if response.status_code == 200:
data = response.json()
- summoner_info = SummonerInfo(
+ summoner = Summoner(
id=data["id"],
account_id=data["accountId"],
profile_icon_id=data["profileIconId"],
@@ -64,9 +60,9 @@ def get_account_by_summoner_name(request: WSGIRequest):
summoner_level=data["summonerLevel"],
)
- summoner_info.save()
+ summoner.save()
- return render(request, "summoner/index.html", {"summoner": summoner_info})
+ return render(request, "summoner/index.html", {"summoner": summoner})
return render(request, "summoner/index.html", {"error": response.json()})
@@ -90,30 +86,50 @@ def search_summoners_by_name(request: WSGIRequest):
count = request.GET.get("count")
if not name or not count:
return JsonResponse({"error": "name, count are required"}, status=400)
-
+
try:
count = int(count)
except ValueError:
return JsonResponse({"error": "count must be an integer"}, status=400)
-
+
if count > 10:
- return JsonResponse({"error": "count must be less than or equal to 10"}, status=400)
-
+ return JsonResponse(
+ {"error": "count must be less than or equal to 10"}, status=400
+ )
+
queryset = Summoner.objects.filter(name__startswith=name)[:count]
serializer = SummonerSerializer(queryset, many=True)
-
+
summoners = serializer.data
-
- summoner_ids = [
- summoner["id"]
- for summoner in serializer.data
- ]
-
+
+ summoner_ids = [summoner["id"] for summoner in serializer.data]
+
queryset = LeagueEntry.objects.filter(summoner_id__in=summoner_ids)
serializer = LeagueEntrySerializer(queryset, many=True)
-
+
league_entries = serializer.data
-
+
+ for summoner in summoners:
+ if summoner["puuid"] is None:
+ new_summoner = get_client().get_summoner_by_encrypted_summoner_id(
+ summoner["id"]
+ )
+
+ if new_summoner.status_code == 200:
+ summoner["puuid"] = new_summoner.json()["puuid"]
+ summoner["account_id"] = new_summoner.json()["accountId"]
+ summoner["profile_icon_id"] = new_summoner.json()["profileIconId"]
+ summoner["revision_date"] = new_summoner.json()["revisionDate"]
+ summoner["summoner_level"] = new_summoner.json()["summonerLevel"]
+
+ Summoner.objects.filter(id=summoner["id"]).update(
+ puuid=summoner["puuid"],
+ account_id=summoner["account_id"],
+ profile_icon_id=summoner["profile_icon_id"],
+ revision_date=summoner["revision_date"],
+ summoner_level=summoner["summoner_level"],
+ )
+
result = [
{
"summoner": summoner,
@@ -121,9 +137,35 @@ def search_summoners_by_name(request: WSGIRequest):
league_entry
for league_entry in league_entries
if league_entry["summoner"] == summoner["id"]
- ]
+ ],
}
for summoner in summoners
]
-
- return JsonResponse(result, safe=False)
\ No newline at end of file
+
+ return JsonResponse(result, safe=False)
+
+
+@api_view(["POST"])
+def save_summoner(request: WSGIRequest):
+ me = request.user
+
+ summoner_id = request.data["summoner_id"]
+
+ if not summoner_id:
+ return JsonResponse({"error": "id is required"}, status=400)
+
+ summoner = Summoner.objects.get(id=summoner_id)
+
+ AppUser.objects.filter(id=me.id).update(summoner=summoner)
+
+ return JsonResponse(
+ {
+ "name": summoner.name,
+ "puuid": summoner.puuid,
+ "level": summoner.summoner_level,
+ "account_id": summoner.account_id,
+ "profile_icon_id": summoner.profile_icon_id,
+ "revision_date": summoner.revision_date,
+ },
+ safe=False,
+ )
diff --git a/web/project/project/settings.py b/web/project/project/settings.py
index 465fc52..e9dc697 100644
--- a/web/project/project/settings.py
+++ b/web/project/project/settings.py
@@ -28,7 +28,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
if ENV == "production":
- DEBUG = True
+ DEBUG = False
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_SECONDS = 31536000 # 1 year
SESSION_COOKIE_SECURE = True
@@ -177,10 +177,10 @@
AUTH_USER_MODEL = "users.AppUser"
REST_FRAMEWORK = {
- 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
- 'PAGE_SIZE': 10
+ "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
+ "PAGE_SIZE": 10,
}
INTERNAL_IPS = [
"127.0.0.1",
-]
\ No newline at end of file
+]
diff --git a/web/project/templates/recommend/ai.html b/web/project/templates/recommend/ai.html
index 1faa87a..9c9e9c4 100644
--- a/web/project/templates/recommend/ai.html
+++ b/web/project/templates/recommend/ai.html
@@ -10,13 +10,13 @@ 안녕하세요, 방문자님
로그인을
하시면 AI 추천을 받아보실 수 있습니다.
- {% elif not user.summoner_info %}
+ {% elif not user.summoner %}
안녕하세요, {{ user.username }}님
라이엇 계정 연동을 통해 AI 추천을 받아보실 수 있습니다.
{% else %}
- 안녕하세요, {{ user.summoner_info.name }}님
+ 안녕하세요, {{ user.summoner.name }}님
diff --git a/web/project/templates/recommend/result.html b/web/project/templates/recommend/result.html
index 54e36a3..ce6b358 100644
--- a/web/project/templates/recommend/result.html
+++ b/web/project/templates/recommend/result.html
@@ -8,7 +8,7 @@
추천 결과
- {{ user.summoner_info.name }}님의 추천 결과입니다.
+ {{ user.summoner.name }}님의 추천 결과입니다.
diff --git a/web/project/templates/users/profile.html b/web/project/templates/users/profile.html
index fcd7556..f5a74ac 100644
--- a/web/project/templates/users/profile.html
+++ b/web/project/templates/users/profile.html
@@ -26,30 +26,28 @@ 👾 마이페이지
-
+
- {% if user.summoner_info %}
+ {% if user.summoner %}
@@ -61,7 +59,7 @@
👾 마이페이지
autocomplete="summoner_level"
class="block flex-1 border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
disabled="disabled"
- value="{{ user.summoner_info.summoner_level }}">
+ value="{{ user.summoner.summoner_level }}">
@@ -69,11 +67,11 @@ 👾 마이페이지
- {% if user.summoner_info %}
+ {% if user.summoner %}
{% else %}
{% endblock content %}
+{% block js %}
+
+{% endblock js %}
\ No newline at end of file
diff --git a/web/project/users/admin.py b/web/project/users/admin.py
index 6a48d48..8aa232d 100644
--- a/web/project/users/admin.py
+++ b/web/project/users/admin.py
@@ -6,8 +6,8 @@
class CustomUserAdmin(UserAdmin):
model = AppUser
# 추가된 필드를 관리자 페이지에서 보이도록 설정
- fieldsets = UserAdmin.fieldsets + ((None, {"fields": ("summoner_info",)}),)
- add_fieldsets = UserAdmin.add_fieldsets + ((None, {"fields": ("summoner_info",)}),)
+ fieldsets = UserAdmin.fieldsets + ((None, {"fields": ("summoner",)}),)
+ add_fieldsets = UserAdmin.add_fieldsets + ((None, {"fields": ("summoner",)}),)
admin.site.register(AppUser, CustomUserAdmin)
diff --git a/web/project/users/migrations/0003_remove_appuser_summoner_info_appuser_summoner_and_more.py b/web/project/users/migrations/0003_remove_appuser_summoner_info_appuser_summoner_and_more.py
new file mode 100644
index 0000000..43cc517
--- /dev/null
+++ b/web/project/users/migrations/0003_remove_appuser_summoner_info_appuser_summoner_and_more.py
@@ -0,0 +1,32 @@
+# Generated by Django 5.0.2 on 2024-03-18 06:20
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("app", "0007_summoner_account_id_summoner_profile_icon_id_and_more"),
+ ("users", "0002_summonerinfo_remove_appuser_riot_id_and_more"),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name="appuser",
+ name="summoner_info",
+ ),
+ migrations.AddField(
+ model_name="appuser",
+ name="summoner",
+ field=models.OneToOneField(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ to="app.summoner",
+ ),
+ ),
+ migrations.DeleteModel(
+ name="SummonerInfo",
+ ),
+ ]
diff --git a/web/project/users/models.py b/web/project/users/models.py
index 8a9671f..a603334 100644
--- a/web/project/users/models.py
+++ b/web/project/users/models.py
@@ -3,16 +3,7 @@
class AppUser(AbstractUser):
- summoner_info = models.OneToOneField(
- "SummonerInfo", on_delete=models.CASCADE, blank=True, null=True
- )
-
-class SummonerInfo(models.Model):
- id = models.CharField(max_length=100, blank=False, null=False, primary_key=True)
- account_id = models.CharField(max_length=100, blank=False, null=False)
- profile_icon_id = models.IntegerField(blank=False, null=False)
- revision_date = models.BigIntegerField(blank=False, null=False)
- name = models.CharField(max_length=100, blank=False, null=False)
- puuid = models.CharField(max_length=100, blank=False, null=False)
- summoner_level = models.IntegerField(blank=False, null=False)
+ summoner = models.OneToOneField(
+ "app.Summoner", on_delete=models.CASCADE, blank=True, null=True
+ )