Compare commits

..

9 Commits
36 ... 37

14 changed files with 134 additions and 66 deletions

View File

@ -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/23] * Backlog [0/19]
** 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:
@ -421,7 +421,12 @@ 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] Tasks from org-mode should properly update notes and leave them out of the body :vrobbler:bug:tasks: ** TODO [#A] Fix raw text webpage title not truncating to 254 chars :vrobbler:personal:bug:webpages:
- Note taken on [2025-09-30 Tue 09:33]
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] 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:
- Note taken on [2025-09-25 Thu 10:37] \\ - Note taken on [2025-09-25 Thu 10:37] \\
@ -436,15 +441,24 @@ https://app.todoist.com/app/task/add-a-csv-endpoint-for-users-book-reads-that-li
an hour for part of the year. Also, we'd need to adjust any old scrobbles that an hour for part of the year. Also, we'd need to adjust any old scrobbles that
took place with DST off to roll them back by an hour. took place with DST off to roll them back by an hour.
** TODO [#A] Allow scrobbling from the Food list page's start links :vrobbler:bug:food:scrobbling:personal:project: * Version 37.0 [4/4]
** DONE [#A] Tasks from org-mode should properly update notes and leave them out of the body :vrobbler:bug:tasks:
:PROPERTIES:
:ID: c8410001-dbb7-1536-bd89-9784189e058f
:END:
** DONE [#A] Allow scrobbling from the Food list page's start links :vrobbler:bug:food:scrobbling:personal:project:
:PROPERTIES:
:ID: 00f99f60-ac00-6cde-311d-c31f41a01353
:END:
https://life.lab.unbl.ink/scrobble/e39779c8-62a5-46a6-bdef-fb7662810dc6/start/ https://life.lab.unbl.ink/scrobble/e39779c8-62a5-46a6-bdef-fb7662810dc6/start/
** TODO [#A] Puzzles (and all longplays) should have a "Completed?" column on their detail page :vrobbler:bug:puzzles:personal:project: ** DONE [#B] Food scrobbles should inherit calories from obj if missing :vrobbler:feature:food:personal:project:
** TODO [#A] Fix raw text webpage title not truncating to 254 chars :vrobbler:personal:bug:webpages: :PROPERTIES:
:ID: 3322ff69-4252-db65-36b3-fae56c1b9327
- Note taken on [2025-09-30 Tue 09:33] :END:
** DONE [#A] Puzzles (and all longplays) should have a "Completed?" column on their detail page :vrobbler:bug:puzzles:personal:project:
This may have already been resolved ... need to just confirm it. :PROPERTIES:
** TODO [#A] Find page numbers for comic books from ComicVine :vrobbler:feature:books:personal:project: :ID: e3e49a9a-67d2-8ad8-1114-6f05effee9b7
:END:
* Version 36.0 [1/1] * Version 36.0 [1/1]
** DONE [#A] Refactor how videos are scrobbled :vrobbler:vidoes:feature:personal:project: ** DONE [#A] Refactor how videos are scrobbled :vrobbler:vidoes:feature:personal:project:
:PROPERTIES: :PROPERTIES:

81
poetry.lock generated
View File

@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. # This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
[[package]] [[package]]
name = "aiohappyeyeballs" name = "aiohappyeyeballs"
@ -249,19 +249,19 @@ tests = ["mypy (>=1.14.0)", "pytest", "pytest-asyncio"]
[[package]] [[package]]
name = "asttokens" name = "asttokens"
version = "3.0.0" version = "3.0.1"
description = "Annotate AST trees with source code positions" description = "Annotate AST trees with source code positions"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, {file = "asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a"},
{file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, {file = "asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7"},
] ]
[package.extras] [package.extras]
astroid = ["astroid (>=2,<4)"] astroid = ["astroid (>=2,<5)"]
test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"] test = ["astroid (>=2,<5)", "pytest (<9.0)", "pytest-cov", "pytest-xdist"]
[[package]] [[package]]
name = "async-timeout" name = "async-timeout"
@ -322,14 +322,14 @@ testing = ["jaraco.test", "pytest (!=8.0.*)", "pytest (>=6,!=8.1.*)", "pytest-ch
[[package]] [[package]]
name = "bandit" name = "bandit"
version = "1.8.6" version = "1.9.1"
description = "Security oriented static analyser for python code." description = "Security oriented static analyser for python code."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.10"
groups = ["test"] groups = ["test"]
files = [ files = [
{file = "bandit-1.8.6-py3-none-any.whl", hash = "sha256:3348e934d736fcdb68b6aa4030487097e23a501adf3e7827b63658df464dddd0"}, {file = "bandit-1.9.1-py3-none-any.whl", hash = "sha256:0a1f34c04f067ee28985b7854edaa659c9299bd71e1b7e18236e46cccc79720b"},
{file = "bandit-1.8.6.tar.gz", hash = "sha256:dbfe9c25fc6961c2078593de55fd19f2559f9e45b99f1272341f5b95dea4e56b"}, {file = "bandit-1.9.1.tar.gz", hash = "sha256:6dbafd1a51e276e065404f06980d624bad142344daeac3b085121fcfd117b7cf"},
] ]
[package.dependencies] [package.dependencies]
@ -405,14 +405,14 @@ requests-cache = ">=1.1.1,<2.0.0"
[[package]] [[package]]
name = "billiard" name = "billiard"
version = "4.2.2" version = "4.2.3"
description = "Python multiprocessing fork with improvements and bugfixes" description = "Python multiprocessing fork with improvements and bugfixes"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "billiard-4.2.2-py3-none-any.whl", hash = "sha256:4bc05dcf0d1cc6addef470723aac2a6232f3c7ed7475b0b580473a9145829457"}, {file = "billiard-4.2.3-py3-none-any.whl", hash = "sha256:989e9b688e3abf153f307b68a1328dfacfb954e30a4f920005654e276c69236b"},
{file = "billiard-4.2.2.tar.gz", hash = "sha256:e815017a062b714958463e07ba15981d802dc53d41c5b69d28c5a7c238f8ecf3"}, {file = "billiard-4.2.3.tar.gz", hash = "sha256:96486f0885afc38219d02d5f0ccd5bec8226a414b834ab244008cbb0025b8dcb"},
] ]
[[package]] [[package]]
@ -470,18 +470,18 @@ css = ["tinycss2 (>=1.1.0,<1.5)"]
[[package]] [[package]]
name = "boto3" name = "boto3"
version = "1.40.73" version = "1.40.75"
description = "The AWS SDK for Python" description = "The AWS SDK for Python"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "boto3-1.40.73-py3-none-any.whl", hash = "sha256:85172e11e3b8d5a09504bc532b6589730ac68845410403ca3793d037b8a5d445"}, {file = "boto3-1.40.75-py3-none-any.whl", hash = "sha256:c246fb35d9978b285c5b827a20b81c9e77d52f99c9d175fbd91f14396432953f"},
{file = "boto3-1.40.73.tar.gz", hash = "sha256:3716703cb8b126607533853d7e2a85f0bb23b0b9d4805c69170abead33d725ef"}, {file = "boto3-1.40.75.tar.gz", hash = "sha256:a5219a2f397f8616462d7908e696c281f120aa2d8458280ff24f7ddeb2108faf"},
] ]
[package.dependencies] [package.dependencies]
botocore = ">=1.40.73,<1.41.0" botocore = ">=1.40.75,<1.41.0"
jmespath = ">=0.7.1,<2.0.0" jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.14.0,<0.15.0" s3transfer = ">=0.14.0,<0.15.0"
@ -490,14 +490,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]] [[package]]
name = "botocore" name = "botocore"
version = "1.40.73" version = "1.40.75"
description = "Low-level, data-driven core of boto 3." description = "Low-level, data-driven core of boto 3."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "botocore-1.40.73-py3-none-any.whl", hash = "sha256:87524c5fe552ecceaea72f51163b37ab35eb82aaa6a64eb80489ade7340c1d23"}, {file = "botocore-1.40.75-py3-none-any.whl", hash = "sha256:e822004688ca8035c518108e27d5b450d3ab0e0b3a73bcb8b87b80a8e5bd1910"},
{file = "botocore-1.40.73.tar.gz", hash = "sha256:0650ceada268824282da9af8615f3e4cf2453be8bf85b820f9207eff958d56d0"}, {file = "botocore-1.40.75.tar.gz", hash = "sha256:bf8b067209fee5a9738800d41852e113b8ebdb01bd7f1e8b4541d55ecdbdb8f3"},
] ]
[package.dependencies] [package.dependencies]
@ -506,7 +506,7 @@ python-dateutil = ">=2.1,<3.0.0"
urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""} urllib3 = {version = ">=1.25.4,<2.2.0 || >2.2.0,<3", markers = "python_version >= \"3.10\""}
[package.extras] [package.extras]
crt = ["awscrt (==0.27.6)"] crt = ["awscrt (==0.28.4)"]
[[package]] [[package]]
name = "build" name = "build"
@ -531,14 +531,14 @@ virtualenv = ["virtualenv (>=20.11) ; python_version < \"3.10\"", "virtualenv (>
[[package]] [[package]]
name = "cachecontrol" name = "cachecontrol"
version = "0.14.3" version = "0.14.4"
description = "httplib2 caching for requests" description = "httplib2 caching for requests"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.10"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "cachecontrol-0.14.3-py3-none-any.whl", hash = "sha256:b35e44a3113f17d2a31c1e6b27b9de6d4405f84ae51baa8c1d3cc5b633010cae"}, {file = "cachecontrol-0.14.4-py3-none-any.whl", hash = "sha256:b7ac014ff72ee199b5f8af1de29d60239954f223e948196fa3d84adaffc71d2b"},
{file = "cachecontrol-0.14.3.tar.gz", hash = "sha256:73e7efec4b06b20d9267b441c1f733664f989fb8688391b670ca812d70795d11"}, {file = "cachecontrol-0.14.4.tar.gz", hash = "sha256:e6220afafa4c22a47dd0badb319f84475d79108100d04e26e8542ef7d3ab05a1"},
] ]
[package.dependencies] [package.dependencies]
@ -547,7 +547,7 @@ msgpack = ">=0.5.2,<2.0.0"
requests = ">=2.16.0" requests = ">=2.16.0"
[package.extras] [package.extras]
dev = ["CacheControl[filecache,redis]", "build", "cherrypy", "codespell[tomli]", "furo", "mypy", "pytest", "pytest-cov", "ruff", "sphinx", "sphinx-copybutton", "tox", "types-redis", "types-requests"] dev = ["cachecontrol[filecache,redis]", "cheroot (>=11.1.2)", "cherrypy", "codespell", "furo", "mypy", "pytest", "pytest-cov", "ruff", "sphinx", "sphinx-copybutton", "types-redis", "types-requests"]
filecache = ["filelock (>=3.8.0)"] filecache = ["filelock (>=3.8.0)"]
redis = ["redis (>=2.10.5)"] redis = ["redis (>=2.10.5)"]
@ -906,14 +906,14 @@ rapidfuzz = ">=3.0.0,<4.0.0"
[[package]] [[package]]
name = "click" name = "click"
version = "8.3.0" version = "8.3.1"
description = "Composable command line interface toolkit" description = "Composable command line interface toolkit"
optional = false optional = false
python-versions = ">=3.10" python-versions = ">=3.10"
groups = ["main", "test"] groups = ["main", "test"]
files = [ files = [
{file = "click-8.3.0-py3-none-any.whl", hash = "sha256:9b9f285302c6e3064f4330c05f05b81945b2a39544279343e6e7c5f27a9baddc"}, {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"},
{file = "click-8.3.0.tar.gz", hash = "sha256:e7b8232224eba16f4ebe410c25ced9f7875cb5f3263ffc93cc3e8da705e229c4"}, {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"},
] ]
[package.dependencies] [package.dependencies]
@ -2326,14 +2326,14 @@ typing-extensions = ">=4.5.0"
[[package]] [[package]]
name = "keyring" name = "keyring"
version = "25.6.0" version = "25.7.0"
description = "Store and access your passwords safely." description = "Store and access your passwords safely."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "keyring-25.6.0-py3-none-any.whl", hash = "sha256:552a3f7af126ece7ed5c89753650eec89c7eaae8617d0aa4d9ad2b75111266bd"}, {file = "keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f"},
{file = "keyring-25.6.0.tar.gz", hash = "sha256:0b39998aa941431eb3d9b0d4b2460bc773b9df6fed7621c2dfb291a7e0187a66"}, {file = "keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b"},
] ]
[package.dependencies] [package.dependencies]
@ -2350,9 +2350,9 @@ check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"
completion = ["shtab (>=1.1.0)"] completion = ["shtab (>=1.1.0)"]
cover = ["pytest-cov"] cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
enabler = ["pytest-enabler (>=2.2)"] enabler = ["pytest-enabler (>=3.4)"]
test = ["pyfakefs", "pytest (>=6,!=8.1.*)"] test = ["pyfakefs", "pytest (>=6,!=8.1.*)"]
type = ["pygobject-stubs", "pytest-mypy", "shtab", "types-pywin32"] type = ["pygobject-stubs", "pytest-mypy (>=1.0.1)", "shtab", "types-pywin32"]
[[package]] [[package]]
name = "kombu" name = "kombu"
@ -4197,6 +4197,13 @@ optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["test"] groups = ["test"]
files = [ files = [
{file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"},
{file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"},
{file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3"},
{file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6"},
{file = "PyYAML-6.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369"},
{file = "PyYAML-6.0.3-cp38-cp38-win32.whl", hash = "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295"},
{file = "PyYAML-6.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b"},
{file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"}, {file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"},
{file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"}, {file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"},
{file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8"}, {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8"},
@ -5050,14 +5057,14 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,
[[package]] [[package]]
name = "trove-classifiers" name = "trove-classifiers"
version = "2025.9.11.17" version = "2025.11.14.15"
description = "Canonical source for classifiers on PyPI (pypi.org)." description = "Canonical source for classifiers on PyPI (pypi.org)."
optional = false optional = false
python-versions = "*" python-versions = "*"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "trove_classifiers-2025.9.11.17-py3-none-any.whl", hash = "sha256:5d392f2d244deb1866556457d6f3516792124a23d1c3a463a2e8668a5d1c15dd"}, {file = "trove_classifiers-2025.11.14.15-py3-none-any.whl", hash = "sha256:d1dac259c1e908939862e3331177931c6df0a37af2c1a8debcc603d9115fcdd9"},
{file = "trove_classifiers-2025.9.11.17.tar.gz", hash = "sha256:931ca9841a5e9c9408bc2ae67b50d28acf85bef56219b56860876dd1f2d024dd"}, {file = "trove_classifiers-2025.11.14.15.tar.gz", hash = "sha256:6b60f49d40bbd895bc61d8dc414fc2f2286d70eb72ed23548db8cf94f62804ca"},
] ]
[[package]] [[package]]

View File

@ -1,6 +1,10 @@
from videos.sources.imdb import lookup_video_from_imdb from videos.sources.imdb import lookup_video_from_imdb
def test_lookup_imdb_without_tt():
def test_lookup_imdb():
metadata = lookup_video_from_imdb("8946378") metadata = lookup_video_from_imdb("8946378")
print(metadata.__dict__)
assert not metadata.imdb_id
def test_lookup_imdb_with_tt():
metadata = lookup_video_from_imdb("tt8946378")
assert metadata.title == "Knives Out" assert metadata.title == "Knives Out"

View File

@ -153,8 +153,8 @@ class Book(LongPlayScrobblableMixin):
comicvine_id = models.CharField(max_length=255, **BNULL) comicvine_id = models.CharField(max_length=255, **BNULL)
readcomics_url = models.CharField(max_length=255, **BNULL) readcomics_url = models.CharField(max_length=255, **BNULL)
next_readcomics_url = models.CharField(max_length=255, **BNULL) next_readcomics_url = models.CharField(max_length=255, **BNULL)
issue_number = models.IntegerField(max_length=5, **BNULL) issue_number = models.IntegerField(**BNULL)
volume_number = models.IntegerField(max_length=5, **BNULL) volume_number = models.IntegerField(**BNULL)
# OpenLibrary # OpenLibrary
openlibrary_id = models.CharField(max_length=255, **BNULL) openlibrary_id = models.CharField(max_length=255, **BNULL)
cover = models.ImageField(upload_to="books/covers/", **BNULL) cover = models.ImageField(upload_to="books/covers/", **BNULL)

View File

@ -18,7 +18,6 @@ BNULL = {"blank": True, "null": True}
class FoodLogData(BaseLogData, WithPeopleLogData): class FoodLogData(BaseLogData, WithPeopleLogData):
calories: Optional[int] = None calories: Optional[int] = None
meal: Optional[str] = None meal: Optional[str] = None
rating: Optional[str] = None
class FoodCategory(TimeStampedModel): class FoodCategory(TimeStampedModel):

View File

@ -11,17 +11,15 @@ from django_extensions.db.models import TimeStampedModel
from imagekit.models import ImageSpecField from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFit from imagekit.processors import ResizeToFit
from puzzles.sources import ipdb from puzzles.sources import ipdb
from scrobbles.dataclasses import JSONDataclass from scrobbles.dataclasses import BaseLogData, WithPeopleLogData, LongPlayLogData
from scrobbles.mixins import ScrobblableConstants, ScrobblableMixin from scrobbles.mixins import ScrobblableConstants, ScrobblableMixin
BNULL = {"blank": True, "null": True} BNULL = {"blank": True, "null": True}
@dataclass @dataclass
class PuzzleLogData(JSONDataclass): class PuzzleLogData(BaseLogData, WithPeopleLogData, LongPlayLogData):
with_people: Optional[int] = None
rating: Optional[str] = None rating: Optional[str] = None
notes: Optional[str] = None
class PuzzleManufacturer(TimeStampedModel): class PuzzleManufacturer(TimeStampedModel):

View File

@ -13,7 +13,10 @@ User = get_user_model()
class ScrobbleLogDataEncoder(json.JSONEncoder): class ScrobbleLogDataEncoder(json.JSONEncoder):
def default(self, o): def default(self, o):
return o.__dict__ try:
return o.__dict__
except AttributeError:
return {}
class ScrobbleLogDataDecoder(json.JSONDecoder): class ScrobbleLogDataDecoder(json.JSONDecoder):

View File

@ -77,11 +77,8 @@ def form_from_dataclass(dataclass):
override_fields = {} override_fields = {}
for klass in dataclass.mro(): for klass in dataclass.mro():
if hasattr(klass, "override_fields"): if hasattr(klass, "override_fields"):
print(klass, ": ", klass.override_fields())
override_fields.update(klass.override_fields()) override_fields.update(klass.override_fields())
print("overrides: ", override_fields)
for f in fields(dataclass): for f in fields(dataclass):
print(f)
if f.name in override_fields: if f.name in override_fields:
form_fields[f.name] = override_fields[f.name] form_fields[f.name] = override_fields[f.name]
continue continue

View File

@ -22,7 +22,7 @@ from django.db import models
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from django_extensions.db.models import TimeStampedModel from django_extensions.db.models import TimeStampedModel
from foods.models import Food from foods.models import Food, FoodLogData
from imagekit.models import ImageSpecField from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFit from imagekit.processors import ResizeToFit
from lifeevents.models import LifeEvent from lifeevents.models import LifeEvent
@ -1210,6 +1210,9 @@ class Scrobble(TimeStampedModel):
"source": source, "source": source,
}, },
) )
if mtype == cls.MediaType.FOOD and not scrobble_data.get("log", {}).get("calories", None):
if media.calories:
scrobble_data["log"] = FoodLogData(calories=media.calories)
scrobble = cls.create(scrobble_data) scrobble = cls.create(scrobble_data)
return scrobble return scrobble

View File

@ -949,10 +949,10 @@ class ScrobbleDetailView(DetailView):
log = self.object.log or {} log = self.object.log or {}
initial_notes = log.get("notes", []) initial_notes = log.get("notes", [])
if isinstance(initial_notes, list) and isinstance(initial_notes[0], dict): if isinstance(initial_notes, list) and len(initial_notes) > 0 and isinstance(initial_notes[0], dict):
notes_str = note_list_to_str(notes) notes_str = note_list_to_str(notes)
else: else:
notes_str = "\n".join(initial_notes) notes_str = "\n".join(initial_notes) if initial_notes else ""
notes_str_fixed = notes_str.encode("utf-8").decode( notes_str_fixed = notes_str.encode("utf-8").decode(
"unicode_escape" "unicode_escape"

View File

@ -0,0 +1,43 @@
{% load urlreplace %}
{% load naturalduration %}
<table class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">Latest</th>
<th scope="col">Title</th>
<th scope="col">Scrobbles</th>
<th scope="col">Complete</th>
<th scope="col">Start</th>
</tr>
</thead>
<tbody>
{% for obj in object_list %}
{% if obj.title %}
<tr>
<td><a href="{{obj.scrobble_set.last.get_absolute_url}}">{{obj.scrobble_set.last.local_timestamp}}
<td><a href="{{obj.get_absolute_url}}">{{obj}}</a></td>
{% if request.user.is_authenticated %}
<td>{{obj.scrobble_count}}</td>
<td>{% if obj.scrobble_set.last.logdata.long_play_complete == True %}Yes{% endif %}</td>
<td><a type="button" class="btn btn-sm btn-primary" href="{{obj.start_url}}">Scrobble</a></td>
{% endif %}
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
<p class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
<a href="?{% urlreplace page=page_obj.previous_page_number %}">prev</a>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</span>
{% if page_obj.has_next %}
<a href="?{% urlreplace page=page_obj.next_page_number %}">next</a>
{% endif %}
</span>
</p>

View File

@ -16,7 +16,7 @@
<div class="col-md"> <div class="col-md">
<div class="table-responsive"> <div class="table-responsive">
{% include "_scrobblable_list.html" %} {% include "_longplay_scrobblable_list.html" %}
</div> </div>
</div> </div>
</div> </div>

View File

@ -16,7 +16,7 @@
<div class="col-md"> <div class="col-md">
<div class="table-responsive"> <div class="table-responsive">
{% include "_scrobblable_list.html" %} {% include "_longplay_scrobblable_list.html" %}
</div> </div>
</div> </div>
</div> </div>

View File

@ -16,7 +16,7 @@
<div class="col-md"> <div class="col-md">
<div class="table-responsive"> <div class="table-responsive">
{% include "_scrobblable_list.html" %} {% include "_longplay_scrobblable_list.html" %}
</div> </div>
</div> </div>
</div> </div>