gamechanger updates (added events, teams). not used yet.

update requirements
This commit is contained in:
2022-06-20 09:35:59 -05:00
parent c0c857a765
commit e027d3d6ae
12 changed files with 229 additions and 34 deletions

View File

@@ -1,8 +1,9 @@
from django.contrib import admin
from .models import Account, Player, Preferences
from .models import Account, Player, Preferences, Team
# Register your models here.
admin.site.register(Account)
admin.site.register(Preferences)
admin.site.register(Player)
admin.site.register(Team)

View File

@@ -5,14 +5,14 @@ from .models import Account, Player, Preferences
class PreferencesForm(ModelForm):
season_id = ""
class Meta:
model = Preferences
fields = ["user", "season_id", "team_id"]
fields = ["user", "managed_team"]
widgets = {
"user": forms.HiddenInput(),
"managed_team_id": forms.TextInput(),
}
labels = {"managed_team_id": "Selected Team"}
class AccountForm(ModelForm):

View File

@@ -0,0 +1,37 @@
# Generated by Django 3.2.13 on 2022-06-15 18:30
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('gamechanger', '0005_alter_preferences_options'),
]
operations = [
migrations.CreateModel(
name='Team',
fields=[
('id', models.CharField(max_length=30, primary_key=True, serialize=False)),
('season_id', models.CharField(max_length=30)),
('name_slug', models.CharField(max_length=30)),
('season_slug', models.CharField(max_length=30)),
],
),
migrations.RemoveField(
model_name='preferences',
name='season_id',
),
migrations.RemoveField(
model_name='preferences',
name='team_id',
),
migrations.AddField(
model_name='preferences',
name='managed_team',
field=models.OneToOneField(default=1, on_delete=django.db.models.deletion.CASCADE, to='gamechanger.team'),
preserve_default=False,
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 3.2.13 on 2022-06-15 19:41
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('gamechanger', '0006_auto_20220615_1330'),
]
operations = [
migrations.RemoveField(
model_name='team',
name='season_id',
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 3.2.13 on 2022-06-15 21:18
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('gamechanger', '0007_remove_team_season_id'),
]
operations = [
migrations.RenameField(
model_name='team',
old_name='name_slug',
new_name='slug',
),
]

View File

@@ -14,12 +14,17 @@ class Account(models.Model):
password = CharField(max_length=255)
class Team(models.Model):
id = models.CharField(primary_key=True, max_length=30)
slug = CharField(max_length=30)
season_slug = CharField(max_length=30)
class Preferences(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, related_name="gamechanger_preferences"
)
season_id = CharField(max_length=255)
team_id = CharField(max_length=255)
managed_team = models.OneToOneField(Team, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "preferences"

View File

@@ -7,7 +7,7 @@ import pytz
import requests
from bs4 import BeautifulSoup
url = "https://gc.com/t/{season_id}/{team_id}/{page}"
url = "https://gc.com/t/{season_id}/{team_slug}-{team_id}/{page}"
def get_authenticated_session(request):
@@ -35,12 +35,16 @@ def get_authenticated_session(request):
def submit_lineup(request, lineup):
authenticated_session = get_authenticated_session(request)
season_id = request.user.gamechanger_preferences.season_id
team_id = request.user.gamechanger_preferences.team_id
season_id = request.user.gamechanger_preferences.managed_team.season_slug
team_slug = request.user.gamechanger_preferences.managed_team.slug
team_id = request.user.gamechanger_preferences.managed_team.id
authenticated_session.headers.update(
{
"referer": url.format(
season_id=season_id, team_id=team_id, page="lineup_edit"
season_id=season_id,
team_slug=team_slug,
team_id=team_id,
page="lineup_edit",
),
"x-csrftoken": authenticated_session.cookies.get("csrftoken"),
"Content-Type": "application/x-www-form-urlencoded;",
@@ -48,12 +52,10 @@ def submit_lineup(request, lineup):
)
r = authenticated_session.post(
cookies=authenticated_session.cookies,
url="https://gc.com/do-save-lineup/{team_id}".format(
team_id=team_id.split("-").pop()
),
url=f"https://gc.com/do-save-lineup/{team_id}",
json={"lineup": lineup},
)
if r.status_code == 200:
if r.status_code == 20 and r.content == b"OK":
return r
else:
raise requests.exceptions.RequestException(
@@ -61,8 +63,10 @@ def submit_lineup(request, lineup):
)
def scrape_page(season_id, team_id, page):
r = requests.get(url.format(season_id=season_id, team_id=team_id, page=page))
def scrape_page(season_id, team_id, team_slug, page):
r = requests.get(
url.format(season_id=season_id, team_id=team_id, team_slug=team_slug, page=page)
)
initialize_page_json = re.search(
r'page.initialize\(\$.parseJSON\("(.*?)"\)', r.content.decode("unicode_escape")
)
@@ -160,14 +164,34 @@ def stream():
def stats(request):
authenticated_session = get_authenticated_session(request)
season_id = request.user.gamechanger_preferences.season_id
team_id = request.user.gamechanger_preferences.team_id
season_id = request.user.gamechanger_preferences.managed_team.season_slug
team_id = request.user.gamechanger_preferences.managed_team.id
team_slug = request.user.gamechanger_preferences.managed_team.slug
page = "stats/batting/Qualified/standard/csv"
authenticated_session.headers.update(
{
"referer": url.format(
season_id=season_id, team_id=team_id, team_slug=team_slug, page="stats"
),
"x-csrftoken": authenticated_session.cookies.get("csrftoken"),
}
)
r = authenticated_session.get(
url.format(season_id=season_id, team_id=team_id, page=page)
cookies=authenticated_session.cookies,
url=url.format(
season_id=season_id, team_id=team_id, team_slug=team_slug, page=page
),
)
roster = scrape_page(season_id, team_id, "roster")
if (
r.status_code != 200
or "Please sign in or join to continue." in r.content.decode("utf-8")
):
raise Exception("Stats fetch failed.")
roster = scrape_page(
season_id=season_id, team_id=team_id, team_slug=team_slug, page="roster"
)
id_lookup = {
(p.get("fname"), p.get("lname")): p.get("player_id") for p in roster["roster"]
}

View File

@@ -1,3 +1,4 @@
from django import forms
from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseServerError
from django.shortcuts import render
from django.views.generic.edit import FormView
@@ -5,7 +6,7 @@ from django.views.generic.edit import FormView
from teamsnap.views import get_teamsnap_client
from .forms import AccountForm, PlayerFormSet, PreferencesForm
from .models import Account, Player, Preferences
from .models import Account, Player, Preferences, Team
from .utils import gamechanger
@@ -30,10 +31,15 @@ class PreferencesFormView(FormView):
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):
if form.cleaned_data["user"].username == str(
self.request.user.gamechanger_account.user
):
form.save()
return super().form_valid(form)
def form_invalid(self, form):
pass
def get_initial(self):
"""
Returns the initial data to use for forms on this view.
@@ -51,11 +57,32 @@ class PreferencesFormView(FormView):
"""
try:
contact = Preferences.objects.get(user=self.request.user)
form = PreferencesForm(instance=contact, **self.get_form_kwargs())
preferences = Preferences.objects.get(user=self.request.user)
form = PreferencesForm(instance=preferences, **self.get_form_kwargs())
except Preferences.DoesNotExist:
form = super().get_form(self.form_class)
gc_session = gamechanger.get_authenticated_session(self.request)
teams = gamechanger.get_teams(gc_session)
team_instances = []
choices = []
for team in teams:
instance, _ = Team.objects.get_or_create(
id=team["id"],
slug="-".join(team["team_slug"].split("-")[:-1]),
season_slug=team["season_slug"],
)
team_instances.append(instance)
choices.append((team["id"], f"{team['name']} ({team['season']})"))
form.fields["managed_team"].widget = forms.Select(
choices=choices, attrs={"class": "form-control"}
)
# form.fields["managed_team"].choices = [choice[0] for choice in choices]
# form.fields["managed_team"].widget.choices = choices
return form
@@ -97,8 +124,8 @@ class AccountFormView(FormView):
def roster(request):
season_id = request.user.gamechanger_preferences.season_id
team_id = request.user.gamechanger_preferences.team_id
season_id = request.user.gamechanger_preferences.managed_team.season_slug
team_id = request.user.gamechanger_preferences.id
page = "roster"
d = gamechanger.scrape_page(season_id, team_id, page)
roster = d["roster"]
@@ -110,8 +137,9 @@ def roster_import(request):
from pyteamsnap.api import Member
client = get_teamsnap_client(request)
season_id = request.user.gamechanger_preferences.season_id
team_id = request.user.gamechanger_preferences.team_id
season_id = request.user.gamechanger_preferences.managed_team.season_slug
team_slug = request.user.gamechanger_preferences.managed_team.slug
team_id = request.user.gamechanger_preferences.managed_team.id
teamsnap_team_id = request.user.teamsnap_preferences.managed_team_id
teamsnap_members = {
f"{member.data['first_name']} {member.data['last_name']}": member
@@ -120,7 +148,7 @@ def roster_import(request):
page = "roster"
d = gamechanger.scrape_page(season_id, team_id, page)
d = gamechanger.scrape_page(season_id, team_id, team_slug, page)
roster = d["roster"]
initial = [
{
@@ -128,12 +156,18 @@ def roster_import(request):
"fname": player["fname"],
"lname": player["lname"],
"teamsnap_name": "{first_name} {last_name}".format(
**teamsnap_members[f"{player['fname']} {player['lname']}"].data
**getattr(
teamsnap_members.get(f"{player['fname']} {player['lname']}"),
"data",
{"first_name": "", "last_name": ""},
)
),
"id": player.get("player_id"),
"teamsnap_member_id": teamsnap_members[
f"{player['fname']} {player['lname']}"
].data["id"],
"teamsnap_member_id": getattr(
teamsnap_members.get(f"{player['fname']} {player['lname']}"),
"data",
{"id": None},
)["id"],
}
for player in roster
]

View File

@@ -3,6 +3,10 @@ version: '3'
volumes:
benchcoach_local_postgres_data: {}
benchcoach_local_postgres_data_backups: {}
certs: {}
vhost: {}
html: {}
acme: {}
services:
django:
@@ -60,9 +64,23 @@ services:
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /root/teamsnap-benchcoach/certs:/etc/nginx/certs
- certs:/etc/nginx/certs
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
env_file:
- ./.envs/.linode/.nginx-proxy
restart: always
depends_on:
- django
nginx-proxy-acme:
image: nginxproxy/acme-companion
container_name: nginx-proxy-acme
volumes_from:
- nginx-proxy
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- certs:/etc/nginx/certs:rw
- acme:/etc/acme.sh
env_file:
- ./.envs/.linode/.nginx-proxy-acme

View File

@@ -16,3 +16,5 @@ django-allauth==0.50.0 # https://github.com/pennersr/django-allauth
django-crispy-forms==1.14.0 # https://github.com/django-crispy-forms/django-crispy-forms
crispy-bootstrap5==0.6 # https://github.com/django-crispy-forms/crispy-bootstrap5
django-redis==5.2.0 # https://github.com/jazzband/django-redis
beautifulsoup4==4.11.1

37
requirements/linode.txt Normal file
View File

@@ -0,0 +1,37 @@
-r base.txt
Werkzeug[watchdog]==2.0.3 # https://github.com/pallets/werkzeug
ipdb==0.13.9 # https://github.com/gotcha/ipdb
psycopg2==2.9.3 # https://github.com/psycopg/psycopg2
# Testing
# ------------------------------------------------------------------------------
mypy==0.950 # https://github.com/python/mypy
django-stubs==1.9.0 # https://github.com/typeddjango/django-stubs
pytest==7.1.2 # https://github.com/pytest-dev/pytest
pytest-sugar==0.9.4 # https://github.com/Frozenball/pytest-sugar
# Documentation
# ------------------------------------------------------------------------------
sphinx==4.5.0 # https://github.com/sphinx-doc/sphinx
sphinx-autobuild==2021.3.14 # https://github.com/GaretJax/sphinx-autobuild
# Code quality
# ------------------------------------------------------------------------------
flake8==4.0.1 # https://github.com/PyCQA/flake8
flake8-isort==4.1.1 # https://github.com/gforcada/flake8-isort
coverage==6.4 # https://github.com/nedbat/coveragepy
black==22.3.0 # https://github.com/psf/black
pylint-django==2.5.3 # https://github.com/PyCQA/pylint-django
pre-commit==2.19.0 # https://github.com/pre-commit/pre-commit
# Django
# ------------------------------------------------------------------------------
factory-boy==3.2.1 # https://github.com/FactoryBoy/factory_boy
django-debug-toolbar==3.4.0 # https://github.com/jazzband/django-debug-toolbar
django-extensions==3.1.5 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==2.0.3 # https://github.com/nedbat/django_coverage_plugin
pytest-django==4.5.2 # https://github.com/pytest-dev/pytest-django
bs4

View File

@@ -33,3 +33,5 @@ django-debug-toolbar==3.4.0 # https://github.com/jazzband/django-debug-toolbar
django-extensions==3.1.5 # https://github.com/django-extensions/django-extensions
django-coverage-plugin==2.0.3 # https://github.com/nedbat/django_coverage_plugin
pytest-django==4.5.2 # https://github.com/pytest-dev/pytest-django
bs4