-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve First-time Login Flow + Add Profiles Manually (#3)
* Refactor /login and /authorize/check endpoints to return all user info * Add /profile endpoint for parsing and saving profiles The /profile endpoint recieves a URL from the frontend that is parsed with regex to extract the fragment containing profile info. That fragment is then inserted into an API URL, where the full profile info in JSON format is fetched. All the relevant profile info is then consolidated in a dictionary and saved to the users BattlenetAccount model. If data for the profile already exists the dictionaries are updated or merged.
- Loading branch information
Showing
12 changed files
with
432 additions
and
212 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
env_settings/ | ||
apps/api/keys/ | ||
apps/user_profile/secret.py | ||
apps/user_profile/secret/ | ||
apps/process_replays/utils/replay_parser_production.py | ||
media/ | ||
node_modules/ | ||
.vscode/ | ||
*.pyc | ||
.idea/ | ||
Zephyrus-f579da64eb8e.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from rest_framework.authentication import BaseAuthentication | ||
from rest_framework.exceptions import AuthenticationFailed | ||
|
||
|
||
class IsOptionsAuthentication(BaseAuthentication): | ||
""" | ||
Allows preflight requests to complete | ||
Used for CORS requests in development | ||
""" | ||
def authenticate(self, request): | ||
if request.method == 'OPTIONS': | ||
return None | ||
else: | ||
raise AuthenticationFailed |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from rest_framework.permissions import BasePermission | ||
|
||
|
||
class IsOptionsPermission(BasePermission): | ||
""" | ||
Allows preflight requests to complete | ||
Used for CORS requests in development | ||
""" | ||
def has_permission(self, request, view): | ||
if request.method == 'OPTIONS': | ||
return True | ||
else: | ||
return False | ||
|
||
|
||
class IsPostPermission(BasePermission): | ||
""" | ||
Allows preflight requests to complete | ||
Used for CORS requests in development | ||
""" | ||
def has_permission(self, request, view): | ||
if request.method == 'POST': | ||
return True | ||
else: | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import copy | ||
import datetime | ||
from math import floor | ||
from django.http import HttpResponseNotFound | ||
from zephyrus.settings import FRONTEND_URL | ||
from allauth.account.models import EmailAddress | ||
from apps.user_profile.models import Replay, BattlenetAccount | ||
from ..models import ReplaySerializer | ||
|
||
|
||
def filter_user_replays(request, race=None): | ||
user = request.user | ||
user_id = EmailAddress.objects.get(email=user.email) | ||
|
||
# check that user has a battlenet account linked | ||
if BattlenetAccount.objects.filter(user_account_id=user_id).exists(): | ||
battlenet_account = BattlenetAccount.objects.get( | ||
user_account_id=user_id | ||
) | ||
# if not return 404 response | ||
else: | ||
response = HttpResponseNotFound() | ||
response['Access-Control-Allow-Origin'] = FRONTEND_URL | ||
response['Access-Control-Allow-Headers'] = 'authorization' | ||
return response | ||
|
||
replay_queryset = Replay.objects.filter( | ||
battlenet_account_id=battlenet_account | ||
) | ||
|
||
serialized_replays = [] | ||
replay_queryset = list(replay_queryset) | ||
replay_queryset.sort(key=lambda x: x.played_at, reverse=True) | ||
|
||
# if there was a race param in the endpoint URL, | ||
# filter out irrelevant replays | ||
if race: | ||
races = ['protoss', 'terran', 'zerg'] | ||
if race not in races: | ||
return None | ||
|
||
# use .filter() method? | ||
race_replay_queryset = [] | ||
for replay in replay_queryset: | ||
player_id = str(replay.user_match_id) | ||
if race == replay.players[player_id]['race'].lower(): | ||
race_replay_queryset.append(replay) | ||
replay_queryset = race_replay_queryset | ||
|
||
# limit returned replays to 100 for performance reasons | ||
limited_queryset = replay_queryset[:100] | ||
|
||
# calculate how long ago since each match was played | ||
# replace with native HTML? | ||
for replay in limited_queryset: | ||
date = replay.played_at | ||
days = datetime.timedelta( | ||
seconds=datetime.datetime.timestamp(datetime.datetime.now()) - datetime.datetime.timestamp(date) | ||
).days | ||
|
||
if days != -1: | ||
weeks = int(round(days / 7, 0)) | ||
months = int(floor(weeks / 4)) | ||
else: | ||
weeks = 0 | ||
months = 0 | ||
|
||
if months > 0: | ||
if weeks - (months * 4) == 0: | ||
date_diff = f'{months}m' | ||
else: | ||
date_diff = f'{months}m' # *{weeks - (months * 4)}/4*' | ||
elif weeks > 0: | ||
date_diff = f'{weeks}w' | ||
else: | ||
if days == -1: | ||
date_diff = 'Today' | ||
elif days == 1: | ||
date_diff = 'Yesterday' | ||
else: | ||
date_diff = f'{days}d' | ||
|
||
serializer = ReplaySerializer(replay) | ||
serializer = copy.deepcopy(serializer.data) | ||
serializer['played_at'] = date_diff | ||
|
||
new_serializer = {} | ||
for stat, info in serializer.items(): | ||
if stat == 'match_data': | ||
new_serializer['match_data'] = {} | ||
|
||
# replace nested dict structure with flat one | ||
# only resource stats are nested | ||
for name, values in info.items(): | ||
if type(values) is dict and 'minerals' in values: | ||
for resource, value in values.items(): | ||
new_serializer[stat][f'{name}_{resource}'] = value | ||
else: | ||
new_serializer[stat][name] = values | ||
else: | ||
new_serializer[stat] = info | ||
serializer = new_serializer | ||
serialized_replays.append(serializer) | ||
return serialized_replays |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from apps.user_profile.models import Replay | ||
|
||
|
||
def find_main_race(user): | ||
account_replays = Replay.objects.filter(user_account_id=user.email).exclude(battlenet_account_id__isnull=True) | ||
race_count = {'protoss': 0, 'terran': 0, 'zerg': 0} | ||
|
||
for replay in account_replays: | ||
user_race = replay.players[str(replay.user_match_id)]['race'] | ||
race_count[user_race.lower()] += 1 | ||
counts = list(race_count.values()) | ||
races = list(race_count.keys()) | ||
max_count_index = counts.index(max(counts)) | ||
return races[max_count_index] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from rest_framework.authtoken.models import Token | ||
from allauth.account.models import EmailAddress | ||
from apps.user_profile.models import BattlenetAccount | ||
from .find_main_race import find_main_race | ||
|
||
|
||
def get_user_info(user): | ||
user_account = EmailAddress.objects.get(email=user.email) | ||
user_battlenet = BattlenetAccount.objects.filter(user_account_id=user.email) | ||
if user_battlenet: | ||
battlenet_accounts = [] | ||
for account in user_battlenet: | ||
current_account = { | ||
'battletag': account.battletag, | ||
'profiles': account.region_profiles, | ||
} | ||
battlenet_accounts.append(current_account) | ||
else: | ||
battlenet_accounts = None | ||
token = Token.objects.get(user=user) | ||
main_race = find_main_race(user) | ||
|
||
return { | ||
'user': { | ||
'email': user.email, | ||
'verified': user_account.verified, | ||
'battlenet_accounts': battlenet_accounts, | ||
'token': token.key, | ||
'main_race': main_race, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import re | ||
import requests | ||
|
||
|
||
def parse_profile(url): | ||
url_data = re.search('(?!/profile/)\d/\d/\d*', url) | ||
|
||
if not url_data: | ||
return None | ||
|
||
region_id = int(url_data.group().split('/')[0]) | ||
|
||
data_url = f'https://starcraft2.com/en-us/api/sc2/profile/{url_data.group()}?locale=en_US' | ||
profile_data = requests.get(data_url).json() | ||
|
||
realm_id = int(profile_data['summary']['realm']) | ||
profile_id = int(profile_data['summary']['id']) | ||
profile_name = profile_data['summary']['displayName'] | ||
|
||
regions = {1: 'NA', 2: 'EU', 3: 'KR'} | ||
|
||
return { | ||
str(region_id): { | ||
'realm_id': realm_id, | ||
'profile_id': [profile_id], | ||
'region_name': regions[region_id], | ||
'profile_name': profile_name, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# import beatifulsoup scraping lib | ||
|
||
|
||
def scrape_profile_url(url): | ||
# check url, if invalid return None | ||
# if valid, scrape data and return | ||
|
||
isUrlValid = True | ||
|
||
if not isUrlValid: | ||
return None | ||
|
||
# scrape profile | ||
|
||
profile_info = { | ||
'profile_name': '', | ||
'profile_id': None, | ||
'region_id': 1, | ||
'realm_id': 1, | ||
} | ||
|
||
return profile_info |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.