[boardgames] Adding email scrobbler for BG Stats
This commit is contained in:
@ -1,12 +1,12 @@
|
||||
import logging
|
||||
import re
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Optional
|
||||
|
||||
import pendulum
|
||||
import pytz
|
||||
from beers.models import Beer
|
||||
from boardgames.models import BoardGame
|
||||
from boardgames.models import BoardGame, BoardGameDesigner, BoardGameLocation
|
||||
from books.models import Book
|
||||
from bricksets.models import BrickSet
|
||||
from dateutil.parser import parse
|
||||
@ -15,6 +15,7 @@ from locations.constants import LOCATION_PROVIDERS
|
||||
from locations.models import GeoLocation
|
||||
from music.constants import JELLYFIN_POST_KEYS, MOPIDY_POST_KEYS
|
||||
from music.models import Track
|
||||
from people.models import Person
|
||||
from podcasts.models import PodcastEpisode
|
||||
from podcasts.utils import parse_mopidy_uri
|
||||
from puzzles.models import Puzzle
|
||||
@ -28,10 +29,10 @@ from scrobbles.utils import convert_to_seconds, extract_domain
|
||||
from sports.models import SportEvent
|
||||
from sports.thesportsdb import lookup_event_from_thesportsdb
|
||||
from tasks.models import Task
|
||||
from tasks.utils import get_title_from_labels
|
||||
from videogames.howlongtobeat import lookup_game_from_hltb
|
||||
from videogames.models import VideoGame
|
||||
from videos.models import Video
|
||||
from tasks.utils import get_title_from_labels
|
||||
from webpages.models import WebPage
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -311,26 +312,117 @@ def manual_scrobble_board_game(
|
||||
return Scrobble.create_or_update(boardgame, user_id, scrobble_dict)
|
||||
|
||||
|
||||
def find_and_enrich_board_game_data(game_dict: dict) -> BoardGame | None:
|
||||
"""TODO Move this to a utility somewhere"""
|
||||
game = BoardGame.find_or_create(game_dict.get("bggId"))
|
||||
|
||||
if game:
|
||||
game.cooperative = game_dict.get("cooperative", False)
|
||||
game.highest_wins = game_dict.get("highestWins", True)
|
||||
game.no_points = game_dict.get("noPoints", False)
|
||||
game.uses_teams = game_dict.get("useTeams", False)
|
||||
if not game.rating:
|
||||
game.rating = game_dict.get("rating") / 10
|
||||
game.save()
|
||||
|
||||
if game_dict.get("designers"):
|
||||
for designer_name in game_dict.get("designers", "").split(", "):
|
||||
BoardGameDesigner.objects.get_or_create(name=designer_name)
|
||||
return game
|
||||
|
||||
|
||||
def email_scrobble_board_game(
|
||||
bgstat_data: dict[str, Any], user_id: int
|
||||
) -> Scrobble | None:
|
||||
game_dict: dict[str, Any] = bgstat_data.get("games", [])[0]
|
||||
if not game_dict.get("bggId", False):
|
||||
player_dict = {}
|
||||
for player in bgstat_data.get("players", []):
|
||||
if player.get("isAnonymous"):
|
||||
person, _created = Person.objects.get_or_create(name="Anonymous")
|
||||
else:
|
||||
person, _created = Person.objects.get_or_create(
|
||||
bgstats_id=player.get("uuid")
|
||||
)
|
||||
if not person.name:
|
||||
person.name = player.get("name", "")
|
||||
person.save()
|
||||
player_dict[player.get("id")] = person
|
||||
|
||||
game_list: list = bgstat_data.get("games", [])
|
||||
if not game_list:
|
||||
logger.info(
|
||||
"Data from BG Stats JSON had not BGG ID, not scrobbling",
|
||||
"No game data from BG Stats, not scrobbling",
|
||||
extra={"bgstat_data": bgstat_data},
|
||||
)
|
||||
return
|
||||
|
||||
boardgame = BoardGame.find_or_create(game_dict.get("bggId"))
|
||||
# TODO Enrich data from our bgstats data?
|
||||
#
|
||||
# TODO Build up board game meta data from the rest of the data
|
||||
scrobble_dict = {}
|
||||
players_list: list[dict[str, Any]] = bgstat_data.get("players", [])
|
||||
location: dict[str, Any] = bgstat_data.get("locations", [])[0]
|
||||
base_game = None
|
||||
expansions = []
|
||||
log_data = {}
|
||||
for game in game_list:
|
||||
logger.info(f"Finding and enriching {game.get('name')}")
|
||||
enriched_game = find_and_enrich_board_game_data(game)
|
||||
if game.get("isBaseGame"):
|
||||
base_game = enriched_game
|
||||
elif game.get("isExpansion"):
|
||||
expansions.append(enriched_game)
|
||||
|
||||
return Scrobble.create_or_update(boardgame, user_id, scrobble_dict)
|
||||
for expansion in expansions:
|
||||
expansion.expansion_for_boardgame = base_game
|
||||
expansion.save()
|
||||
log_data["expansion_ids"] = [e.id for e in expansions]
|
||||
|
||||
location_dict: dict[str, Any] = bgstat_data.get("locations", [])[0]
|
||||
location, _created = BoardGameLocation.objects.get_or_create(
|
||||
bgstats_id=location_dict.get("uuid")
|
||||
)
|
||||
if not location.name:
|
||||
location.name = location_dict.get("name")
|
||||
geoloc = GeoLocation.objects.filter(
|
||||
title__icontains=location.name
|
||||
).first()
|
||||
if geoloc:
|
||||
location.geo_location = geoloc
|
||||
location.save()
|
||||
log_data["location_id"] = location.id
|
||||
|
||||
play_dict = bgstat_data.get("plays", [])[0]
|
||||
if play_dict.get("rounds", False):
|
||||
log_data["rounds"] = play_dict.get("rounds")
|
||||
if play_dict.get("board", False):
|
||||
log_data["board"] = play_dict.get("board")
|
||||
|
||||
log_data["players"] = []
|
||||
for score_dict in play_dict.get("playerScores", []):
|
||||
log_data["players"].append(
|
||||
{
|
||||
"person_id": player_dict[score_dict.get("playerRefId")].id,
|
||||
"new": score_dict.get("newPlayer"),
|
||||
"win": score_dict.get("winner"),
|
||||
"score": score_dict.get("score"),
|
||||
"rank": score_dict.get("rank"),
|
||||
"seat_order": score_dict.get("seatOrder"),
|
||||
"role": score_dict.get("role"),
|
||||
}
|
||||
)
|
||||
|
||||
start = parse(play_dict.get("playDate"))
|
||||
duration_seconds = play_dict.get("durationMin") * 60
|
||||
stop = start + timedelta(seconds=duration_seconds)
|
||||
scrobble_dict = {
|
||||
"user_id": user_id,
|
||||
"timestamp": start,
|
||||
"playback_position_seconds": duration_seconds,
|
||||
"source": "BG Stats",
|
||||
"log": log_data,
|
||||
}
|
||||
|
||||
scrobble = Scrobble.create_or_update(base_game, user_id, scrobble_dict)
|
||||
scrobble.stop_timestamp = stop
|
||||
scrobble.in_progress = False
|
||||
scrobble.played_to_completion = True
|
||||
scrobble.save()
|
||||
|
||||
return scrobble
|
||||
|
||||
|
||||
def manual_scrobble_from_url(
|
||||
|
||||
Reference in New Issue
Block a user