Merge branch 'dev-gamechanger' into dev

# Conflicts:
#	gamechanger/utils/gamechanger.py
#	gamechanger/views.py
This commit is contained in:
2022-06-23 07:56:03 -05:00
5 changed files with 46 additions and 248 deletions

2
.idea/benchcoach.iml generated
View File

@@ -21,6 +21,8 @@
</content> </content>
<orderEntry type="jdk" jdkName="Python 3.9 (benchcoach) (2)" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Python 3.9 (benchcoach) (2)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="pyteamsnap" />
<orderEntry type="module" module-name="gamescrapyr" />
</component> </component>
<component name="PackageRequirementsSettings"> <component name="PackageRequirementsSettings">
<option name="requirementsPath" value="$MODULE_DIR$/requirements/local.txt" /> <option name="requirementsPath" value="$MODULE_DIR$/requirements/local.txt" />

2
.idea/modules.xml generated
View File

@@ -3,6 +3,8 @@
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/.idea/benchcoach.iml" filepath="$PROJECT_DIR$/.idea/benchcoach.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/benchcoach.iml" filepath="$PROJECT_DIR$/.idea/benchcoach.iml" />
<module fileurl="file://$PROJECT_DIR$/../gamescrapyr/.idea/gamescrapyr.iml" filepath="$PROJECT_DIR$/../gamescrapyr/.idea/gamescrapyr.iml" />
<module fileurl="file://$PROJECT_DIR$/../pyteamsnap/.idea/pyteamsnap.iml" filepath="$PROJECT_DIR$/../pyteamsnap/.idea/pyteamsnap.iml" />
</modules> </modules>
</component> </component>
</project> </project>

3
.idea/vcs.xml generated
View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" /> <mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/../gamescrapyr" vcs="Git" />
</component> </component>
</project> </project>

View File

@@ -1,243 +1,33 @@
import csv import logging
import datetime
import json
import re
import pytz from gamescrapyr.gamescrapyr import GameChangerClient
import requests
from bs4 import BeautifulSoup # This retrieves a Python logging instance (or creates it)
logger = logging.getLogger(__name__)
url = "https://gc.com/t/{season_id}/{team_slug}-{team_id}/{page}" url = "https://gc.com/t/{season_id}/{team_slug}-{team_id}/{page}"
def get_authenticated_session(request): def get_gamechanger_client(request):
gc_username = request.user.gamechanger_account.user managed_team = request.user.gamechanger_preferences.managed_team
gc_password = request.user.gamechanger_account.password
s = requests.Session()
s.headers.update({"referer": "https://gc.com/do-login"})
s.get("https://gc.com/login")
r2 = s.post(
"https://gc.com/do-login",
cookies=s.cookies,
data={
"csrfmiddlewaretoken": s.cookies.get("csrftoken"),
"email": gc_username,
"password": gc_password,
},
)
if r2.status_code == 200:
return s
else:
raise requests.exceptions.RequestException(
f"Returned {r2.status_code} for {r2.reason}"
)
def submit_lineup(request, lineup):
authenticated_session = get_authenticated_session(request)
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_slug=team_slug,
team_id=team_id,
page="lineup_edit",
),
"x-csrftoken": authenticated_session.cookies.get("csrftoken"),
"Content-Type": "application/x-www-form-urlencoded;",
}
)
r = authenticated_session.post(
cookies=authenticated_session.cookies,
url=f"https://gc.com/do-save-lineup/{team_id}",
json={"lineup": lineup},
)
if r.status_code == 20 and r.content == b"OK":
return r
else:
raise requests.exceptions.RequestException(
f"Returned {r.status_code} for {r.reason}"
)
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")
)
m = initialize_page_json.group(1)
return json.loads(m)
def get_teams(session):
url = "https://gc.com/account/teams"
session.headers.update(
{
"referer": url.format("https://gc.com/account/profile"),
"x-csrftoken": session.cookies.get("csrftoken"),
}
)
page = session.get(cookies=session.cookies, url=url)
soup = BeautifulSoup(page.content, "html.parser")
team_elements = [i for i in soup.find_all("li") if i.attrs.get("data-team-id")]
teams = []
for i, team_element in enumerate(team_elements):
league_type, number_of_games = [
c.text.strip() for c in team_element.findChildren("li")
][1:3]
season_slug, team_slug = (
team_element.find("a").attrs.get("href", "///").split("/")[2:]
)
teams.append(
{
"name": team_element.find("a").text,
"id": team_element.attrs.get("data-team-id"),
"season": team_element.findPrevious("header").text,
"league_type": league_type,
"number_of_games": number_of_games,
"season_slug": season_slug,
"team_slug": team_slug,
}
)
return teams
pass
def get_events(request):
authenticated_session = get_authenticated_session(request)
season_id = request.user.gamechanger_preferences.season_id
team_id = request.user.gamechanger_preferences.team_id
page = "stats/batting/Qualified/standard/csv"
authenticated_session.get(
url.format(season_id=season_id, team_id=team_id, page=page)
)
authenticated_session.headers.update(
{
"x-csrftoken": authenticated_session.cookies.get("csrftoken"),
}
)
page = authenticated_session.get(
cookies=authenticated_session.cookies,
url=url.format(season_id=season_id, team_id=team_id, page="schedule/games"),
)
soup = BeautifulSoup(page.content, "html.parser")
game_elements = [r for r in soup.find_all("tr") if "game" in r.attrs.get("class")]
games = []
for i, game_element in enumerate(game_elements):
game_slug = game_element.find("a").attrs.get("href").split("/")[1]
title = game_element.find("a").text
jslocaldate, jslocaltime_start, jslocaltime_arrival = (
t.attrs.get("datetime") for t in game_element.findAll("time")
)
games.append(
{
"id": game_element.attrs.get("data-id"),
"title": title,
"game_slug": game_slug,
"start": pytz.timezone("utc").localize(
datetime.datetime.fromisoformat(jslocaltime_start)
),
}
)
return games
def stream():
# game_page = authenticated_session.get(
# cookies=authenticated_session.cookies,
# url=f"https://gc.com/{game_slug}",
# )
# game_soup = BeautifulSoup(game_page.content, "html.parser")
# data_push_url_rel = game_soup.find("body").attrs.get("data-push-url")[2:]
# data_push_url = f"https://{data_push_url_rel}?sabertooth_aware=true"
# stream_page = authenticated_session.get(
# cookies=authenticated_session.cookies, url=data_push_url
# )
# game_stream = json.loads(stream_page.content)
pass
def stats(request):
authenticated_session = get_authenticated_session(request)
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(
cookies=authenticated_session.cookies,
url=url.format(
season_id=season_id, team_id=team_id, team_slug=team_slug, page=page
),
)
if ( if (
r.status_code != 200 not request.session.get("gamechanger_client")
or "Please sign in or join to continue." in r.content.decode("utf-8") or not request.session["gamechanger_client"].is_authorized()
): ):
raise Exception("Stats fetch failed.") logger.info("GameChanger client not found or not authorized, creating...")
gc_username = request.user.gamechanger_account.user
roster = scrape_page( gc_password = request.user.gamechanger_account.password
season_id=season_id, team_id=team_id, team_slug=team_slug, page="roster" client = GameChangerClient(
) email=gc_username,
id_lookup = { password=gc_password,
(p.get("fname"), p.get("lname")): p.get("player_id") for p in roster["roster"] team_id=managed_team.id,
} team_slug=managed_team.slug,
season_slug=managed_team.season_slug,
decoded_content = r.content.decode("utf-8")
cr = csv.reader(decoded_content.splitlines(), delimiter=",")
my_list = list(cr)
player_keys = [
(i, key)
for i, key in enumerate(my_list[1][: my_list[0].index("Offensive Stats")])
]
offensive_keys = [
(i, key)
for i, key in enumerate(
my_list[1][
my_list[0]
.index("Offensive Stats") : my_list[0]
.index("Defensive Stats")
- 1
],
start=my_list[0].index("Offensive Stats"),
) )
] request.session["gamechanger_client"] = client
defensive_keys = [ else:
(i, key) logger.info("GameChanger client found and authorized, loading...")
for i, key in enumerate( client = request.session["gamechanger_client"]
my_list[1][my_list[0].index("Defensive Stats") :],
start=my_list[0].index("Defensive Stats"),
)
]
stats = {} return client
for row in my_list[2:]:
player_keys
number, lname, fname = row[:3]
if number == "Team":
break
gamechanger_id = id_lookup[(fname, lname)]
stats[gamechanger_id] = {
"offensive": {k: row[i] for i, k in offensive_keys},
"defensive": {k: row[i] for i, k in defensive_keys},
}
return stats
# d = scrape_page(season_id, team_id, page)
pass

View File

@@ -8,6 +8,7 @@ from teamsnap.views import get_teamsnap_client
from .forms import AccountForm, PlayerFormSet, PreferencesForm from .forms import AccountForm, PlayerFormSet, PreferencesForm
from .models import Account, Player, Preferences, Team from .models import Account, Player, Preferences, Team
from .utils import gamechanger from .utils import gamechanger
from .utils.gamechanger import get_gamechanger_client
def teams(request): def teams(request):
@@ -124,32 +125,31 @@ class AccountFormView(FormView):
def roster(request): def roster(request):
season_id = request.user.gamechanger_preferences.managed_team.season_slug gamechanger = get_gamechanger_client(request)
team_id = request.user.gamechanger_preferences.id roster = gamechanger.get_roster()
page = "roster"
d = gamechanger.scrape_page(season_id, team_id, page)
roster = d["roster"]
return render(request, "gamechanger/roster.html", context={"roster": roster}) return render(request, "gamechanger/roster.html", context={"roster": roster})
def roster_import(request): def roster_import(request):
if request.method == "GET": if request.method == "GET":
from pyteamsnap.api import Member from pyteamsnap.objects import Member
client = get_teamsnap_client(request) gc_client = get_gamechanger_client(request)
season_id = request.user.gamechanger_preferences.managed_team.season_slug season_slug = request.user.gamechanger_preferences.managed_team.season_slug
team_slug = request.user.gamechanger_preferences.managed_team.slug team_slug = request.user.gamechanger_preferences.managed_team.slug
team_id = request.user.gamechanger_preferences.managed_team.id team_id = request.user.gamechanger_preferences.managed_team.id
ts_client = get_teamsnap_client(request)
teamsnap_team_id = request.user.teamsnap_preferences.managed_team_id teamsnap_team_id = request.user.teamsnap_preferences.managed_team_id
teamsnap_members = { teamsnap_members = {
f"{member.data['first_name']} {member.data['last_name']}": member f"{member.data['first_name']} {member.data['last_name']}": member
for member in Member.search(client, team_id=teamsnap_team_id) for member in Member.search(ts_client, team_id=teamsnap_team_id)
} }
page = "roster" roster = gc_client.get_roster(
team_id=team_id, team_slug=team_slug, season_slug=season_slug
d = gamechanger.scrape_page(season_id, team_id, team_slug, page) )
roster = d["roster"]
initial = [ initial = [
{ {
"gamechanger_name": f"{player['fname']} {player['lname']}", "gamechanger_name": f"{player['fname']} {player['lname']}",
@@ -215,6 +215,9 @@ def lineup_submit(request):
if request.GET: if request.GET:
return HttpResponseNotAllowed() return HttpResponseNotAllowed()
if request.POST: if request.POST:
from gamechanger.utils.gamechanger import get_gamechanger_client
gc_client = get_gamechanger_client(request)
formset = LineupEntryFormset(request.POST) formset = LineupEntryFormset(request.POST)
if formset.is_valid(): if formset.is_valid():
lineup_data = [ lineup_data = [
@@ -251,7 +254,7 @@ def lineup_submit(request):
) )
elif lineup_entry["label"] != "DR": elif lineup_entry["label"] != "DR":
lineup.append(d) lineup.append(d)
r = gamechanger.submit_lineup(request, lineup) r = gc_client.submit_lineup(lineup)
if r.content == b"OK": if r.content == b"OK":
return HttpResponse(status=200) return HttpResponse(status=200)
else: else: