[boardgames] Tighten up boardgame lookups
This commit is contained in:
24
PROJECT.org
24
PROJECT.org
@ -92,7 +92,7 @@ fetching and simple saving.
|
|||||||
:LOGBOOK:
|
:LOGBOOK:
|
||||||
CLOCK: [2025-07-09 Wed 09:55]--[2025-07-09 Wed 10:15] => 0:20
|
CLOCK: [2025-07-09 Wed 09:55]--[2025-07-09 Wed 10:15] => 0:20
|
||||||
:END:
|
:END:
|
||||||
* Backlog [1/26]
|
* Backlog [4/27]
|
||||||
** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :vrobbler:personal:bug:music:scrobbles:
|
** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :vrobbler:personal:bug:music:scrobbles:
|
||||||
** TODO [#C] Move to using more robust mopidy-webhooks pacakge form pypi :utility:improvement:
|
** TODO [#C] Move to using more robust mopidy-webhooks pacakge form pypi :utility:improvement:
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
@ -422,11 +422,6 @@ https://app.todoist.com/app/task/add-a-csv-endpoint-for-users-book-reads-that-li
|
|||||||
|
|
||||||
As an example https://comicbookroundup.com/comic-books/reviews/humanoids-publishing/the-history-of-science-fiction
|
As an example https://comicbookroundup.com/comic-books/reviews/humanoids-publishing/the-history-of-science-fiction
|
||||||
** TODO [#B] Add PuzzleLogData class with with_people and completed :vrobbler:feature:puzzles:logdata:personal:project:
|
** TODO [#B] Add PuzzleLogData class with with_people and completed :vrobbler:feature:puzzles:logdata:personal:project:
|
||||||
** TODO [#A] Add classmethod for metadata fetching to tracks :vrobbler:feature:music:personal:project:
|
|
||||||
:PROPERTIES:
|
|
||||||
:ID: bc4b45e5-4c65-13c5-ab7b-1937d3fbf5c2
|
|
||||||
:END:
|
|
||||||
|
|
||||||
** TODO [#A] Tasks from org-mode should properly update notes and leave them out of the body :vrobbler:bug:tasks:
|
** TODO [#A] Tasks from org-mode should properly update notes and leave them out of the body :vrobbler:bug:tasks:
|
||||||
** TODO [#A] Fix koreader scrobble imports to use DST properly :vrobbler:personal:bug:books:imports:
|
** TODO [#A] Fix koreader scrobble imports to use DST properly :vrobbler:personal:bug:books:imports:
|
||||||
|
|
||||||
@ -451,7 +446,22 @@ https://life.lab.unbl.ink/scrobble/e39779c8-62a5-46a6-bdef-fb7662810dc6/start/
|
|||||||
|
|
||||||
This may have already been resolved ... need to just confirm it.
|
This may have already been resolved ... need to just confirm it.
|
||||||
** TODO [#A] Find page numbers for comic books from ComicVine :vrobbler:feature:books:personal:project:
|
** TODO [#A] Find page numbers for comic books from ComicVine :vrobbler:feature:books:personal:project:
|
||||||
** STRT [#A] Fix views for TV series where next episode is now None :vrobbler:bug:personal:videos:
|
** DONE [#A] Use bgg-api for BoardGameGeek lookups :vrobbler:feature:boardgames:personal:project:
|
||||||
|
:PROPERTIES:
|
||||||
|
:ID: 738abb5a-c796-b16b-fe10-6e5639a0e10d
|
||||||
|
:END:
|
||||||
|
** DONE [#A] Add classmethod for metadata fetching to tracks :vrobbler:feature:music:personal:project:
|
||||||
|
:PROPERTIES:
|
||||||
|
:ID: bc4b45e5-4c65-13c5-ab7b-1937d3fbf5c2
|
||||||
|
:END:
|
||||||
|
|
||||||
|
- Note taken on [2025-10-29 Wed 21:44]
|
||||||
|
|
||||||
|
Beyond a classmethod (which I think we have now), we need to update the flow of how we look up tracks.
|
||||||
|
|
||||||
|
It's a hot mess right now where Various Artists walks over the actual artist, and we often hit MB when we don't have to.
|
||||||
|
|
||||||
|
** DONE [#A] Fix views for TV series where next episode is now None :vrobbler:bug:personal:videos:
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
:ID: d7014ac4-cda6-0802-2cdf-8f66c6389fea
|
:ID: d7014ac4-cda6-0802-2cdf-8f66c6389fea
|
||||||
:END:
|
:END:
|
||||||
|
|||||||
94
poetry.lock
generated
94
poetry.lock
generated
@ -361,6 +361,22 @@ python-dateutil = ">=2.8.2,<3.0.0"
|
|||||||
requests = ">=2.28.2,<3.0.0"
|
requests = ">=2.28.2,<3.0.0"
|
||||||
typing-extensions = ">=4.7.1,<5.0.0"
|
typing-extensions = ">=4.7.1,<5.0.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bgg-api"
|
||||||
|
version = "1.1.13"
|
||||||
|
description = "A Python API for boardgamegeek.com"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "bgg_api-1.1.13-py3-none-any.whl", hash = "sha256:6babe32ddb0ccbba7292b789770bd64ef523cab0d2cfd0a2c326cebce3e842e7"},
|
||||||
|
{file = "bgg_api-1.1.13.tar.gz", hash = "sha256:1e921b1d2818157418abb90d4ae7a50d8b071f1ade4ab47add1c8fdfa333e6dc"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
requests = ">=2.31.0,<3.0.0"
|
||||||
|
requests-cache = ">=1.1.1,<2.0.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "billiard"
|
name = "billiard"
|
||||||
version = "4.2.1"
|
version = "4.2.1"
|
||||||
@ -519,6 +535,33 @@ dev = ["CacheControl[filecache,redis]", "build", "cherrypy", "codespell[tomli]",
|
|||||||
filecache = ["filelock (>=3.8.0)"]
|
filecache = ["filelock (>=3.8.0)"]
|
||||||
redis = ["redis (>=2.10.5)"]
|
redis = ["redis (>=2.10.5)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cattrs"
|
||||||
|
version = "25.2.0"
|
||||||
|
description = "Composable complex class support for attrs and dataclasses."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.9"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "cattrs-25.2.0-py3-none-any.whl", hash = "sha256:539d7eedee7d2f0706e4e109182ad096d608ba84633c32c75ef3458f1d11e8f1"},
|
||||||
|
{file = "cattrs-25.2.0.tar.gz", hash = "sha256:f46c918e955db0177be6aa559068390f71988e877c603ae2e56c71827165cc06"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
attrs = ">=24.3.0"
|
||||||
|
exceptiongroup = {version = ">=1.1.1", markers = "python_version < \"3.11\""}
|
||||||
|
typing-extensions = ">=4.12.2"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
bson = ["pymongo (>=4.4.0)"]
|
||||||
|
cbor2 = ["cbor2 (>=5.4.6)"]
|
||||||
|
msgpack = ["msgpack (>=1.0.5)"]
|
||||||
|
msgspec = ["msgspec (>=0.19.0) ; implementation_name == \"cpython\""]
|
||||||
|
orjson = ["orjson (>=3.10.7) ; implementation_name == \"cpython\""]
|
||||||
|
pyyaml = ["pyyaml (>=6.0)"]
|
||||||
|
tomlkit = ["tomlkit (>=0.11.8)"]
|
||||||
|
ujson = ["ujson (>=5.10.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "celery"
|
name = "celery"
|
||||||
version = "5.4.0"
|
version = "5.4.0"
|
||||||
@ -4308,6 +4351,37 @@ urllib3 = ">=1.21.1,<3"
|
|||||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "requests-cache"
|
||||||
|
version = "1.2.1"
|
||||||
|
description = "A persistent cache for python requests"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "requests_cache-1.2.1-py3-none-any.whl", hash = "sha256:1285151cddf5331067baa82598afe2d47c7495a1334bfe7a7d329b43e9fd3603"},
|
||||||
|
{file = "requests_cache-1.2.1.tar.gz", hash = "sha256:68abc986fdc5b8d0911318fbb5f7c80eebcd4d01bfacc6685ecf8876052511d1"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
attrs = ">=21.2"
|
||||||
|
cattrs = ">=22.2"
|
||||||
|
platformdirs = ">=2.5"
|
||||||
|
requests = ">=2.22"
|
||||||
|
url-normalize = ">=1.4"
|
||||||
|
urllib3 = ">=1.25.5"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=6.0.1)", "redis (>=3)", "ujson (>=5.4)"]
|
||||||
|
bson = ["bson (>=0.5)"]
|
||||||
|
docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.9)"]
|
||||||
|
dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"]
|
||||||
|
json = ["ujson (>=5.4)"]
|
||||||
|
mongodb = ["pymongo (>=3)"]
|
||||||
|
redis = ["redis (>=3)"]
|
||||||
|
security = ["itsdangerous (>=2.0)"]
|
||||||
|
yaml = ["pyyaml (>=6.0.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "requests-oauthlib"
|
name = "requests-oauthlib"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@ -5013,6 +5087,24 @@ tzdata = {version = "*", markers = "platform_system == \"Windows\""}
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
|
devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "url-normalize"
|
||||||
|
version = "2.2.1"
|
||||||
|
description = "URL normalization for Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
groups = ["main"]
|
||||||
|
files = [
|
||||||
|
{file = "url_normalize-2.2.1-py3-none-any.whl", hash = "sha256:3deb687587dc91f7b25c9ae5162ffc0f057ae85d22b1e15cf5698311247f567b"},
|
||||||
|
{file = "url_normalize-2.2.1.tar.gz", hash = "sha256:74a540a3b6eba1d95bdc610c24f2c0141639f3ba903501e61a52a8730247ff37"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
idna = ">=3.3"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["mypy", "pre-commit", "pytest", "pytest-cov", "pytest-socket", "ruff"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "urllib3"
|
name = "urllib3"
|
||||||
version = "1.26.20"
|
version = "1.26.20"
|
||||||
@ -5539,4 +5631,4 @@ cffi = ["cffi (>=1.11)"]
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.1"
|
lock-version = "2.1"
|
||||||
python-versions = ">=3.9,<3.12"
|
python-versions = ">=3.9,<3.12"
|
||||||
content-hash = "2e297ef6f8c524840a381ad793946c87b601d81afd569e882fe58120a5f84626"
|
content-hash = "f89cff0d1019afe54e4df89a8debf50b79776c474e60d48fcae1e7c70daa3761"
|
||||||
|
|||||||
@ -58,6 +58,7 @@ tmdbv3api = "^1.9.0"
|
|||||||
themoviedb = "^1.0.2"
|
themoviedb = "^1.0.2"
|
||||||
feedparser = "^6.0.12"
|
feedparser = "^6.0.12"
|
||||||
titlecase = "^2.4.1"
|
titlecase = "^2.4.1"
|
||||||
|
bgg-api = "^1.1.13"
|
||||||
|
|
||||||
[tool.poetry.group.test]
|
[tool.poetry.group.test]
|
||||||
optional = true
|
optional = true
|
||||||
|
|||||||
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.19 on 2025-11-03 04:34
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('boardgames', '0011_remove_boardgame_run_time_seconds_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='boardgame',
|
||||||
|
name='bgg_rank',
|
||||||
|
field=models.IntegerField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.19 on 2025-11-03 04:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('boardgames', '0012_boardgame_bgg_rank'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='boardgame',
|
||||||
|
name='publishers',
|
||||||
|
field=models.ManyToManyField(related_name='board_games', to='boardgames.boardgamepublisher'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -2,12 +2,12 @@ from functools import cached_property
|
|||||||
import logging
|
import logging
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Optional
|
from typing import Optional, Any
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
import requests
|
import requests
|
||||||
from boardgames.bgg import lookup_boardgame_from_bgg
|
from boardgames.sources.bgg import lookup_boardgame_from_bgg
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from django.db import models
|
from django.db import models
|
||||||
@ -191,6 +191,10 @@ class BoardGame(ScrobblableMixin):
|
|||||||
publisher = models.ForeignKey(
|
publisher = models.ForeignKey(
|
||||||
BoardGamePublisher, **BNULL, on_delete=models.DO_NOTHING
|
BoardGamePublisher, **BNULL, on_delete=models.DO_NOTHING
|
||||||
)
|
)
|
||||||
|
publishers = models.ManyToManyField(
|
||||||
|
BoardGamePublisher,
|
||||||
|
related_name="board_games",
|
||||||
|
)
|
||||||
designers = models.ManyToManyField(
|
designers = models.ManyToManyField(
|
||||||
BoardGameDesigner,
|
BoardGameDesigner,
|
||||||
related_name="board_games",
|
related_name="board_games",
|
||||||
@ -224,6 +228,7 @@ class BoardGame(ScrobblableMixin):
|
|||||||
options={"quality": 75},
|
options={"quality": 75},
|
||||||
)
|
)
|
||||||
rating = models.FloatField(**BNULL)
|
rating = models.FloatField(**BNULL)
|
||||||
|
bgg_rank = models.IntegerField(**BNULL)
|
||||||
max_players = models.PositiveSmallIntegerField(**BNULL)
|
max_players = models.PositiveSmallIntegerField(**BNULL)
|
||||||
min_players = models.PositiveSmallIntegerField(**BNULL)
|
min_players = models.PositiveSmallIntegerField(**BNULL)
|
||||||
published_date = models.DateField(**BNULL)
|
published_date = models.DateField(**BNULL)
|
||||||
@ -301,29 +306,58 @@ class BoardGame(ScrobblableMixin):
|
|||||||
|
|
||||||
# Go get cover image if the URL is present
|
# Go get cover image if the URL is present
|
||||||
if cover_url and not self.cover:
|
if cover_url and not self.cover:
|
||||||
headers = {"User-Agent": "Vrobbler 0.11.12"}
|
self.save_image_from_url(cover_url)
|
||||||
r = requests.get(cover_url, headers=headers)
|
|
||||||
logger.debug(r.status_code)
|
def save_image_from_url(self, url):
|
||||||
if r.status_code == 200:
|
headers = {"User-Agent": "Vrobbler 0.11.12"}
|
||||||
fname = f"{self.title}_cover_{self.uuid}.jpg"
|
r = requests.get(url, headers=headers)
|
||||||
self.cover.save(fname, ContentFile(r.content), save=True)
|
if r.status_code == 200:
|
||||||
logger.debug("Loaded cover image from BGGeek")
|
fname = f"{self.title}_cover_{self.uuid}.jpg"
|
||||||
|
self.cover.save(fname, ContentFile(r.content), save=True)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def find_or_create(
|
def find_or_create(
|
||||||
cls, lookup_id: str, data: Optional[dict] = {}
|
cls, lookup_id: str, data: dict[str, Any] = {}
|
||||||
) -> Optional["BoardGame"]:
|
) -> "BoardGame":
|
||||||
"""Given a Lookup ID (either BGG or BGA ID), return a board game object"""
|
"""Given a Lookup ID (either BGG or BGA ID), return a board game object"""
|
||||||
boardgame = cls.objects.filter(bggeek_id=lookup_id).first()
|
game = cls.objects.filter(bggeek_id=lookup_id).first()
|
||||||
|
|
||||||
if not data or not boardgame:
|
if game:
|
||||||
data = lookup_boardgame_from_bgg(lookup_id)
|
logger.info("Board game exists in database.", extra={"lookup_id": lookup_id, "data": data})
|
||||||
|
return game
|
||||||
|
|
||||||
if data and not boardgame:
|
bgg_data = lookup_boardgame_from_bgg(data.get("name"))
|
||||||
boardgame, created = cls.objects.get_or_create(
|
|
||||||
title=data["title"], bggeek_id=lookup_id
|
|
||||||
)
|
|
||||||
if created:
|
|
||||||
boardgame.fix_metadata(data=data)
|
|
||||||
|
|
||||||
return boardgame
|
mechanics = bgg_data.pop("mechanics", [])
|
||||||
|
designers = bgg_data.pop("designers", [])
|
||||||
|
categories = bgg_data.pop("categories", [])
|
||||||
|
publishers = bgg_data.pop("publishers", [])
|
||||||
|
cover_url = bgg_data.pop("cover_url")
|
||||||
|
|
||||||
|
game = cls.objects.create(
|
||||||
|
**bgg_data
|
||||||
|
)
|
||||||
|
|
||||||
|
game.save_image_from_url(cover_url)
|
||||||
|
game.cooperative = data.get("cooperative", False)
|
||||||
|
game.highest_wins = data.get("highestWins", True)
|
||||||
|
game.no_points = data.get("noPoints", False)
|
||||||
|
game.uses_teams = data.get("useTeams", False)
|
||||||
|
game.bgstats_id = data.get("uuid", None)
|
||||||
|
game.save()
|
||||||
|
|
||||||
|
if designers:
|
||||||
|
for designer_name in designers:
|
||||||
|
designer, created = BoardGameDesigner.objects.get_or_create(
|
||||||
|
name=designer_name
|
||||||
|
)
|
||||||
|
game.designers.add(designer.id)
|
||||||
|
|
||||||
|
if publishers:
|
||||||
|
for name in publishers:
|
||||||
|
publisher, _ = BoardGamePublisher.objects.get_or_create(
|
||||||
|
name=name
|
||||||
|
)
|
||||||
|
game.publishers.add(publisher)
|
||||||
|
|
||||||
|
return game
|
||||||
|
|||||||
29
vrobbler/apps/boardgames/sources/bgg.py
Normal file
29
vrobbler/apps/boardgames/sources/bgg.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from typing import Any
|
||||||
|
from boardgamegeek import BGGClient
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
def lookup_boardgame_from_bgg(title: str) -> dict[str, Any]:
|
||||||
|
game_dict = {"title": title}
|
||||||
|
|
||||||
|
bgg = BGGClient(access_token=settings.BGG_ACCESS_TOKEN)
|
||||||
|
|
||||||
|
game = bgg.game(title)
|
||||||
|
|
||||||
|
if game:
|
||||||
|
game_dict["description"] = game.description
|
||||||
|
game_dict["published_year"] = game.yearpublished
|
||||||
|
game_dict["cover_url"] = game.image
|
||||||
|
game_dict["min_players"] = game.minplayers
|
||||||
|
game_dict["max_players"] = game.maxplayers
|
||||||
|
game_dict["recommended_age"] = game.minage
|
||||||
|
game_dict["rating"] = game.rating_average
|
||||||
|
game_dict["bgg_rank"] = game.bgg_rank
|
||||||
|
game_dict["base_run_time_seconds"] = int(game.playingtime) * 60 if game.playingtime else None
|
||||||
|
|
||||||
|
game_dict["mechanics"] = game.mechanics
|
||||||
|
game_dict["categories"] = game.categories
|
||||||
|
game_dict["designers"] = game.designers
|
||||||
|
game_dict["publishers"] = game.publishers
|
||||||
|
|
||||||
|
return game_dict
|
||||||
@ -355,29 +355,6 @@ def manual_scrobble_board_game(
|
|||||||
return Scrobble.create_or_update(boardgame, user_id, scrobble_dict)
|
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)
|
|
||||||
game.bgstats_id = game_dict.get("uuid", None)
|
|
||||||
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(", "):
|
|
||||||
designer, created = BoardGameDesigner.objects.get_or_create(
|
|
||||||
name=designer_name
|
|
||||||
)
|
|
||||||
game.designers.add(designer.id)
|
|
||||||
return game
|
|
||||||
|
|
||||||
|
|
||||||
def email_scrobble_board_game(
|
def email_scrobble_board_game(
|
||||||
bgstat_data: dict[str, Any], user_id: int
|
bgstat_data: dict[str, Any], user_id: int
|
||||||
) -> list[Scrobble]:
|
) -> list[Scrobble]:
|
||||||
@ -407,11 +384,11 @@ def email_scrobble_board_game(
|
|||||||
log_data = {}
|
log_data = {}
|
||||||
for game in game_list:
|
for game in game_list:
|
||||||
logger.info(f"Finding and enriching {game.get('name')}")
|
logger.info(f"Finding and enriching {game.get('name')}")
|
||||||
enriched_game = find_and_enrich_board_game_data(game)
|
game_obj = BoardGame.find_or_create(game.get("bggId"), data=game)
|
||||||
if game.get("isBaseGame"):
|
if game.get("isBaseGame"):
|
||||||
base_games[game.get("id")] = enriched_game
|
base_games[game.get("id")] = game_obj
|
||||||
if game.get("isExpansion"):
|
if game.get("isExpansion"):
|
||||||
expansions[game.get("id")] = enriched_game
|
expansions[game.get("id")] = game_obj
|
||||||
|
|
||||||
locations = {}
|
locations = {}
|
||||||
for location_dict in bgstat_data.get("locations", []):
|
for location_dict in bgstat_data.get("locations", []):
|
||||||
|
|||||||
Reference in New Issue
Block a user