Files
benchcoach-django/teamsnap/views.py

415 lines
14 KiB
Python

import datetime
import requests
from allauth.socialaccount.providers.oauth2.views import (
OAuth2Adapter,
OAuth2CallbackView,
OAuth2LoginView,
)
from django.shortcuts import redirect, render
from django.views.generic.edit import FormView
from .forms import PreferencesForm
from .models import Preferences
from .provider import TeamsnapProvider
class TeamsnapAdapter(OAuth2Adapter):
provider_id = TeamsnapProvider.id
# Fetched programmatically, must be reachable from container
access_token_url = "{}/oauth/token/".format("https://auth.teamsnap.com")
profile_url = "{}/me/".format("https://api.teamsnap.com/v3/")
# Accessed by the user browser, must be reachable by the host
authorize_url = "{}/oauth/authorize/".format("https://auth.teamsnap.com/")
# NOTE: trailing slashes in URLs are important, don't miss it
def complete_login(self, request, app, token, **kwargs):
headers = {"Authorization": f"Bearer {token.token}"}
resp = requests.get(self.profile_url, headers=headers)
j = resp.json()
if j.get("collection", {}).get("items"):
extra_data = {
i["name"]: i["value"] for i in j["collection"]["items"][0]["data"]
}
return self.get_provider().sociallogin_from_response(request, extra_data)
def populate_user(self, request, sociallogin, data):
user = super().populate_user(request, sociallogin, data)
user.username = user.email
return user
# def get_callback_url(self, request, app):
# callback_url = reverse(self.provider_id + "_callback")
# protocol = self.redirect_uri_protocol
# return build_absolute_uri(request, callback_url, protocol)
# return "urn:ietf:wg:oauth:2.0:oob"
oauth2_login = OAuth2LoginView.adapter_view(TeamsnapAdapter)
oauth2_callback = OAuth2CallbackView.adapter_view(TeamsnapAdapter)
class PreferencesFormView(FormView):
template_name = "preferences.html"
form_class = PreferencesForm
success_url = "/"
def form_valid(self, form):
# This method is called when valid form data has been POSTed.
# It should return an HttpResponse.
if form.data["user"] == str(self.request.user.id):
form.save()
return super().form_valid(form)
def get_initial(self):
"""
Returns the initial data to use for forms on this view.
"""
initial = super().get_initial()
initial["user"] = self.request.user
# initial['managed_team_id']
return initial
def get_form(self):
"""
Returns the initial data to use for forms on this view.
"""
import pyteamsnap
ts_account = self.request.user.socialaccount_set.first()
ts_token = ts_account.socialtoken_set.first()
# ts_token =
ts = pyteamsnap.TeamSnap(token=ts_token)
me = pyteamsnap.api.Me(ts)
teams = [
(id, pyteamsnap.api.Team.get(ts, id=id))
for id in me.data["managed_team_ids"]
]
try:
contact = Preferences.objects.get(user=self.request.user)
form = PreferencesForm(instance=contact, **self.get_form_kwargs())
except Preferences.DoesNotExist:
form = super().get_form(self.form_class)
choices = [
(id, f"{team.data['name']} ({team.data['season_name']})")
for id, team in teams
]
form.fields["managed_team_id"].widget.choices = choices
return form
def schedule_view(request, team_id=None):
if not team_id:
return redirect(
"teamsnap_schedule", team_id=request.user.preferences.managed_team_id
)
request.user.socialaccount_set.filter(provider="teamsnap").first()
current_teamsnap_user = request.user.socialaccount_set.filter(
provider="teamsnap"
).first()
ts_token = (
current_teamsnap_user.socialtoken_set.order_by("-expires_at").first().token
)
no_past = bool(request.GET.get("no_past", 0))
games_only = bool(request.GET.get("games_only", 0))
from pyteamsnap.api import Event, TeamSnap
client = TeamSnap(token=ts_token)
ts_events = Event.search(client, team_id=team_id)
if no_past:
ts_events = [
e
for e in ts_events
if e.data["start_date"] > datetime.datetime.now(datetime.timezone.utc)
]
if games_only:
ts_events = [e for e in ts_events if e.data["is_game"]]
ts_events = {e.data["id"]: e for e in ts_events}
pass
return render(
request,
"schedule.html",
context={"events": ts_events.values(), "team_id": team_id},
)
def view_event(request, event_id, team_id=None):
if not team_id:
return redirect(
"teamsnap_event", team_id=request.user.preferences.managed_team_id
)
request.user.socialaccount_set.filter(provider="teamsnap").first()
current_teamsnap_user = request.user.socialaccount_set.filter(
provider="teamsnap"
).first()
ts_token = (
current_teamsnap_user.socialtoken_set.order_by("-expires_at").first().token
)
from pyteamsnap.api import (
AvailabilitySummary,
Event,
EventLineup,
EventLineupEntry,
Member,
TeamSnap,
)
client = TeamSnap(token=ts_token)
ts_bulkload = client.bulk_load(
team_id=team_id,
types=[Event, EventLineup, EventLineupEntry, AvailabilitySummary, Member],
event__id=event_id,
)
ts_event = [i for i in ts_bulkload if isinstance(i, Event)][0]
ts_availability_summary = [
i
for i in ts_bulkload
if isinstance(i, AvailabilitySummary) and i.data["event_id"] == event_id
][0]
ts_lineup_entries = [
i
for i in ts_bulkload
if isinstance(i, EventLineupEntry) and i.data["event_id"] == event_id
]
return render(
request,
"event/view_event.html",
context={
"availability_summary": ts_availability_summary,
"event": ts_event,
"availablities": [],
"lineup_entries": ts_lineup_entries,
},
)
def edit_lineup(request, event_ids, team_id):
import re
from teamsnap.forms import LineupEntryFormset
request.user.socialaccount_set.filter(provider="teamsnap").first()
current_teamsnap_user = request.user.socialaccount_set.filter(
provider="teamsnap"
).first()
ts_token = (
current_teamsnap_user.socialtoken_set.order_by("-expires_at").first().token
)
from pyteamsnap.api import (
Availability,
AvailabilitySummary,
Event,
EventLineup,
EventLineupEntry,
Member,
TeamSnap,
)
client = TeamSnap(token=ts_token)
event_ids = str(event_ids).split(",")
ts_bulkload = client.bulk_load(
team_id=team_id,
types=[Event, EventLineup, EventLineupEntry, AvailabilitySummary, Member],
event__id=",".join(event_ids),
)
event_ids = [int(i) for i in event_ids]
contexts = []
for event_id in event_ids:
ts_event = [
i for i in ts_bulkload if isinstance(i, Event) and i.data["id"] == event_id
][0]
ts_availabilities = Availability.search(client, event_id=ts_event.data["id"])
ts_lineup_entries = EventLineupEntry.search(client, event_id=event_id)
ts_members = [i for i in ts_bulkload if isinstance(i, Member)]
ts_member_lookup = {m.data["id"]: m for m in ts_members}
ts_availability_lookup = {m.data["member_id"]: m for m in ts_availabilities}
ts_lineup_entries_lookup = {m.data["member_id"]: m for m in ts_lineup_entries}
members = []
for lineup_entry in ts_lineup_entries:
members.append(
{
"member": getattr(ts_member_lookup[lineup_entry.data['member_id']],'data'),
"availability": getattr(
ts_availability_lookup.get(lineup_entry.data['member_id'], {}), "data", {}
),
"lineup_entry": getattr(
lineup_entry, "data", {}
),
}
)
in_lineup_already = [m['member'] for m in members]
for member in ts_members:
if not member.data in in_lineup_already:
members.append(
{
"member": getattr(member, "data"),
"availability": getattr(
ts_availability_lookup.get(member.data["id"], {}), "data", {}
),
"lineup_entry": getattr(
ts_lineup_entries_lookup.get(member.data["id"], {}), "data", {}
),
}
)
members = sorted(
members,
key=lambda d: (
{None: 3, 0: 2, 2: 1, 1: 0}.get( # No Response # No # Maybe # Yes
d["availability"].get("status_code")
),
d["member"].get("last_name"),
),
)
initial = []
for member in members:
if not member["member"]["is_non_player"]:
if re.search(
r"([A-Z0-9]+)(?:\s+\[(.*)\])?",
member["lineup_entry"].get("label", ""),
):
position, position_note = re.search(
r"([A-Z0-9]+)(?:\s+\[(.*)\])?",
member["lineup_entry"].get("label", ""),
).groups()
else:
position, position_note = ("", "")
position_only = position_note == "PO"
initial.append(
{
"event_lineup_entry_id": member["lineup_entry"].get("id"),
"event_lineup_id": member["lineup_entry"].get(
"event_lineup_id"
),
"event_id": event_id,
"position_only": position_only,
"member_id": member["member"]["id"],
"sequence": member["lineup_entry"].get("sequence"),
"label": position,
}
)
formset = LineupEntryFormset(initial=initial)
for form in formset:
form.member = ts_member_lookup.get(form["member_id"].initial)
form.availability = ts_availability_lookup.get(form["member_id"].initial)
formset_startinglineup = [
form
for form in formset
if form.initial.get("event_lineup_entry_id")
and not form.initial.get("position_only")
]
formset_startinglineup = sorted(
formset_startinglineup, key=lambda d: d.initial.get("sequence", 100)
)
formset_startingpositiononly = [
form
for form in formset
if form.initial.get("event_lineup_entry_id")
and form not in formset_startinglineup
]
formset_startingpositiononly = sorted(
formset_startingpositiononly, key=lambda d: d.initial.get("sequence", 100)
)
formset_bench = [
form
for form in formset
if form not in formset_startinglineup
and form not in formset_startingpositiononly
and form.availability.data["status_code"] in [2, 1]
]
formset_out = [
form
for form in formset
if form not in formset_startinglineup
and form not in formset_bench
and form not in formset_startingpositiononly
and not form.member.data["is_non_player"]
]
contexts.append(
{
"event": ts_event,
"formset": formset,
"formset_bench": formset_bench,
"formset_startinglineup": formset_startinglineup,
"formset_startingpositionalonly": formset_startingpositiononly,
"formset_out": formset_out,
}
)
return render(
request, "lineup/multiple_edit.html", context={"contexts": contexts}
)
def dashboard(request, team_id=None):
if not team_id:
return redirect(
"teamsnap_dashboard", team_id=request.user.preferences.managed_team_id
)
request.user.socialaccount_set.filter(provider="teamsnap").first()
current_teamsnap_user = request.user.socialaccount_set.filter(
provider="teamsnap"
).first()
ts_token = (
current_teamsnap_user.socialtoken_set.order_by("-expires_at").first().token
)
from pyteamsnap.api import AvailabilitySummary, Event, TeamSnap
client = TeamSnap(token=ts_token)
ts_events = Event.search(client, team_id=team_id)
ts_availability_summaries_d = {
a.data["id"]: a for a in AvailabilitySummary.search(client, team_id=team_id)
}
ts_events_future = [
e
for e in ts_events
if e.data["start_date"] > datetime.datetime.now(datetime.timezone.utc)
]
ts_events_past = [
e
for e in reversed(ts_events)
if e.data["start_date"] < datetime.datetime.now(datetime.timezone.utc)
]
return render(
request,
"dashboard.html",
{
"ts_events_future": ts_events_future,
"ts_events_past": ts_events_past,
"events_availabilities": [
(e, ts_availability_summaries_d[e.data["id"]]) for e in ts_events_future
],
},
)