import datetime import requests from allauth.socialaccount.providers.oauth2.views import ( OAuth2Adapter, OAuth2CallbackView, OAuth2LoginView, ) from django.http import HttpResponse from django.shortcuts import redirect, render, reverse from django.views.generic import ListView from django.views.generic.edit import FormView from .forms import OpponentForm, PreferencesForm from .models import Opponent, Preferences from .provider import TeamsnapProvider from .utils import get_teamsnap_client 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 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) else: return super().form_invalid(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.teamsnap_preferences.managed_team_id, ) client = get_teamsnap_client(request) no_past = bool(request.GET.get("no_past", 0)) games_only = bool(request.GET.get("games_only", 0)) from pyteamsnap.objects import Event 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.teamsnap_preferences.managed_team_id ) from pyteamsnap.objects import ( AvailabilitySummary, Event, EventLineup, EventLineupEntry, Member, ) client = get_teamsnap_client(request) 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 multi_lineup_choose(request, team_id): from django.forms import formset_factory from pyteamsnap.objects import Event from .forms import EventChooseForm client = get_teamsnap_client(request) if request.method == "POST": ts_events = Event.search(client, team_id=team_id) EventChooseFormset = formset_factory(EventChooseForm) formset = EventChooseFormset(request.POST) choices = [(e.data["id"], e.data["formatted_title"]) for e in ts_events] for form in formset: form.fields["event_id"].choices = choices if formset.is_valid(): event_ids = [f.cleaned_data["event_id"] for f in formset] else: event_ids = request.GET.get("event_ids").split(",") EventChooseFormset = formset_factory(EventChooseForm) formset = EventChooseFormset(request.POST) return redirect( "teamsnap_edit_lineup", team_id=team_id, event_ids=",".join(event_ids), ) elif not request.GET.get("num"): return HttpResponse(500) else: num = int(request.GET.get("num")) TEAM_ID = team_id ts_events = Event.search(client, team_id=TEAM_ID) ts_events = {e.data["id"]: e for e in ts_events} EventChooseFormset = formset_factory(EventChooseForm, extra=num) formset = EventChooseFormset() choices = [(id, e.data["formatted_title"]) for id, e in ts_events.items()] for form in formset: form.fields["event_id"].choices = choices pass return render( request, "lineup/multiple_choose.html", context={"formset": formset, "team_id": team_id}, ) class OpponentFormView(FormView): pk_url_kwarg = "opponent_id" template_name = "opponent.html" form_class = OpponentForm def get_success_url(self): team_id = self.kwargs.get("team_id") return reverse("teamsnap_opponents", kwargs={"team_id": team_id}) def form_valid(self, form): # This method is called when valid form data has been POSTed. # It should return an HttpResponse. import pyteamsnap ts_client = get_teamsnap_client(self.request) user = pyteamsnap.api.Me(ts_client) team_id = int(self.kwargs.get("team_id")) opponent_id = int(self.kwargs.get("opponent_id")) opponent = pyteamsnap.api.Opponent.get(ts_client, opponent_id) if ( team_id in user.data["managed_team_ids"] and opponent.data["team_id"] == team_id ): form.save() return super().form_valid(form) else: return super().form_invalid(form) def get_form(self): """ Returns the initial data to use for forms on this view. """ try: opponent, _ = Opponent.objects.get_or_create( id=self.kwargs.get("opponent_id") ) form = OpponentForm(instance=opponent, **self.get_form_kwargs()) except Opponent.DoesNotExist: form = super().get_form(self.form_class) # form.widgets['id'] = forms.HiddenInput() return form def get_context_data(self, **kwargs): import pyteamsnap ts_client = get_teamsnap_client(self.request) context = super().get_context_data(**kwargs) opponent = pyteamsnap.api.Opponent.get( ts_client, self.kwargs.get("opponent_id") ) context["opponent"] = opponent return context class Opponents(ListView): model = Opponent template_name = "opponents.html" pass def get_queryset(self): import pyteamsnap ts_client = get_teamsnap_client(self.request) team_id = self.kwargs.get("team_id") ts_opponents = pyteamsnap.api.Opponent.search(ts_client, team_id=team_id) ts_opponents.sort(key=lambda t: t.data.get("name")) opponents = [] for opponent in ts_opponents: o, _ = Opponent.objects.get_or_create(id=opponent.data["id"]) opponents.append((opponent, o)) return opponents def get_context_data(self, **kwargs): team_id = self.kwargs.get("team_id") context = super().get_context_data(**kwargs) context["team_id"] = team_id return context