[release] Bump to version 69.0
- Make book matching use Google Books ID or author name - Fix dead source icon links on book and brick set pages - Books created via koreader do not get enriched - There should a global chart aggregator that builds charts across all users - Make it possible for anonymous users to view media objects
This commit is contained in:
153
CHANGELOG.org
153
CHANGELOG.org
@ -1,5 +1,158 @@
|
||||
#+title: CHANGELOG
|
||||
|
||||
* Version 69.0 [5/5]
|
||||
** DONE [#B] Make book matching use Google Books ID or author name :bug:books:matching:
|
||||
*** Description
|
||||
|
||||
This may be a no-op situation as we've moved away from Google Books. But maybe we haven't.
|
||||
|
||||
Turns out we hadn't. Google Books is still a primary metadata source alongside
|
||||
OpenLibrary and ComicVine. =Book.find_or_create()= only matched by
|
||||
=original_title=, which is fragile. It now also matches by Google Books ID or
|
||||
author name (like Track does with =musicbrainz_id=).
|
||||
|
||||
*** Implementation
|
||||
|
||||
- ~vrobbler/apps/books/sources/google.py~: =lookup_book_from_google()= now
|
||||
accepts an optional =author= (used as an =inauthor:= query term) and returns
|
||||
the top-level Google Books volume =id= as =google_books_id=.
|
||||
- ~vrobbler/apps/books/models.py~: added a =google_books_id= CharField to
|
||||
=Book=. =find_or_create()= now:
|
||||
- short-circuits on an exact =original_title= match (no lookups);
|
||||
- after enrichment, reuses an existing book by =google_books_id=, falling
|
||||
back to a =title= + author match — mirroring how Track keys off
|
||||
=musicbrainz_id=.
|
||||
- =fix_metadata()= gained a Google Books fallback so asynchronously enriched
|
||||
(e.g. KoReader-imported) books also capture =google_books_id=.
|
||||
- ~vrobbler/apps/books/management/commands/cleanup_book_metadata.py~: passes
|
||||
the author to the Google lookup and persists =google_books_id= on backfill.
|
||||
- Migration ~0040_book_google_books_id~ adds the field.
|
||||
|
||||
** DONE [#C] Fix dead source icon links on book and brick set pages :books:templates:
|
||||
:PROPERTIES:
|
||||
:ID: 35ce01a2-0dca-4bd3-83ea-ca826c734c36
|
||||
:END:
|
||||
|
||||
*** Description
|
||||
|
||||
The book detail page rendered OpenLibrary and Amazon source icons via
|
||||
=object.openlibrary_link= and =object.amazon_link=, but neither property
|
||||
existed on =Book= (the model has no Amazon ASIN field at all), so both icons
|
||||
were dead links around broken images. The brick set detail page was a copy of
|
||||
the book template and had the same broken icons for a type with no
|
||||
OpenLibrary/Amazon presence.
|
||||
|
||||
*** Implementation
|
||||
|
||||
- ~vrobbler/apps/books/models.py~: added =Book.openlibrary_link= (builds
|
||||
=https://openlibrary.org/works/{olid}= or =/books/{olid}= for edition IDs)
|
||||
and =Book.bookshop_link= (uses the ISBN, in =/a/{affiliate_id}/{isbn}=
|
||||
affiliate form when =BOOKSHOP_AFFILIATE_ID= is set, otherwise a
|
||||
=/books?keywords={isbn}= search link).
|
||||
- ~vrobbler/settings.py~: added =BOOKSHOP_AFFILIATE_ID= read from
|
||||
=VROBBLER_BOOKSHOP_AFFILIATE_ID=.
|
||||
- ~vrobbler/templates/books/book_detail.html~: source icons now render
|
||||
conditionally (only when a link exists, like the music pages), link to
|
||||
OpenLibrary and Bookshop, and the dead Amazon icon is gone.
|
||||
- ~vrobbler/templates/bricksets/brickset_detail.html~: removed the dead
|
||||
OpenLibrary/Amazon source icon row entirely.
|
||||
- Added official OpenLibrary and Bookshop logos at
|
||||
~vrobbler/apps/scrobbles/static/images/~
|
||||
(=openlibrary-logo.png=, =bookshop-logo.png=).
|
||||
- Tests in ~tests/books_tests/test_book_source_links.py= cover both link
|
||||
properties (work vs edition OLIDs, ISBN-10/13, with/without affiliate ID).
|
||||
- ~vrobbler/apps/books/management/commands/cleanup_book_metadata.py~: added a
|
||||
=--missing-source_id= filter flag for books lacking any of
|
||||
=openlibrary_id= / =google_books_id= / =comicvine_id=.
|
||||
- ~vrobbler/apps/books/models.py~: added =Book.is_comic= so ComicVine is only
|
||||
queried for books that already carry comic source data
|
||||
(=comicvine_id=, =volume_comicvine_id=, =readcomics_url=, issue/volume
|
||||
fields) or whose title contains "Issue "/"Volume ". The blanket ComicVine
|
||||
fallback in =find_or_create()=, =fix_metadata()=, and
|
||||
~cleanup_book_metadata.py~ now respects this, so unrelated prose books no
|
||||
longer get matched to comics.
|
||||
|
||||
** DONE [#B] Books created via koreader do not get enriched :books:metadata:bug:
|
||||
:PROPERTIES:
|
||||
:ID: ddfed612-1f4e-b0bb-5310-19adf9cf9336
|
||||
:END:
|
||||
|
||||
*** Description
|
||||
|
||||
When a new books arrives inside of a KoReader import, the metadata is not enriched.
|
||||
|
||||
*** Implementation
|
||||
|
||||
- Added =scrobbles.tasks.enrich_book_metadata()=, a background Celery task that
|
||||
calls =Book.fix_metadata()= and tags the book =book-enriched= on success or
|
||||
=enrichment-failed= on failure.
|
||||
- =create_book_from_row()= in ~vrobbler/apps/books/koreader.py~ now dispatches
|
||||
that task asynchronously after creating a new book, instead of the commented
|
||||
out synchronous =fix_metadata()= call.
|
||||
- Fixed =Book.fix_metadata()= to not reference the removed =locg_slug= field,
|
||||
and to handle =authors=/=genres= keys returned by the current OpenLibrary
|
||||
source (previously it would crash).
|
||||
- Routed =enrich_book_metadata= to the =background= worker queue.
|
||||
|
||||
** DONE [#B] There should a global chart aggregator that builds charts across all users :charts:feature:
|
||||
:PROPERTIES:
|
||||
:ID: ccc257d5-7d35-42b0-9af2-2941b67880fd
|
||||
:END:
|
||||
|
||||
*** Description
|
||||
|
||||
Currently we build charts for individual users ... noting content that has been
|
||||
tops for a given year, month, week or day. We should also build such global
|
||||
charts across all users, but limit it to just the top three items (gold, silver,
|
||||
bronze). There should also be a toggle in profile settings that allows a user to
|
||||
include their scrobbles in global aggregation. If that check box is not selected
|
||||
(and it should off by default) that user is not included in the global charts.
|
||||
|
||||
*** Implementation
|
||||
|
||||
- Global chart records are stored as =ChartRecord= rows with a NULL =user=
|
||||
(the column is already nullable), so they reuse the existing model,
|
||||
upserting, indexing and chart rendering infrastructure.
|
||||
- Added =UserProfile.include_in_global_charts= (default off) plus a settings
|
||||
form checkbox; users who do not opt in are excluded from aggregation.
|
||||
Toggling the setting triggers =scrobbles.tasks.rebuild_global_charts_for_user()=
|
||||
which rebuilds every global chart period the user has scrobbles in, so the
|
||||
change is reflected immediately instead of waiting for the next scheduled
|
||||
chart build.
|
||||
- Refactored ~vrobbler/apps/charts/utils.py~: extracted the media type config
|
||||
into a module-level =MEDIA_CONFIG= and pulled the aggregation and upsert
|
||||
logic into shared =_aggregate_media()= and =_upsert_chart_records()=
|
||||
helpers used by both =build_charts()= and the new =build_global_charts()=.
|
||||
- Added =build_global_charts()= plus =build_global_daily/weekly/monthly/yearly_charts()=
|
||||
wrappers. Global charts aggregate scrobbles from opted-in users only and
|
||||
keep just the top three items (gold, silver, bronze) per media type/period.
|
||||
- Wired global chart building into the scheduled Celery tasks
|
||||
(~vrobbler/apps/scrobbles/tasks.py~): =create_yesterdays_charts()=,
|
||||
=rebuild_weekly_charts()=, =rebuild_monthly_charts()= and
|
||||
=rebuild_yearly_charts()= now also build the matching global charts.
|
||||
- Added =GlobalChartView= at =/charts/global/= (~charts.GlobalChartView~) with a
|
||||
new ~charts/global_chart_index.html~ template showing the medal top three
|
||||
per media type, with the same year/month/week navigation as user charts.
|
||||
- Anonymous users now see the global top-three charts on media detail pages:
|
||||
~scrobbles.views.ChartContextMixin~ queries =user__isnull=True= records
|
||||
when the request user is anonymous.
|
||||
- Tests in ~vrobbler/apps/charts/tests/test_views.py~ and new global chart
|
||||
tests in ~vrobbler/apps/charts/tests/test_utils.py~.
|
||||
|
||||
** DONE [#B] Make it possible for anonymous users to view media objects :media:templates:
|
||||
:PROPERTIES:
|
||||
:ID: f12fd0b4-b728-4fbc-adf7-d51695d8c155
|
||||
:END:
|
||||
|
||||
*** Description
|
||||
|
||||
Currently if you click on a Book link when logged out (like via a shared URL: https://life.lab.unbl.ink/shared/KkViBro/ ) you get a 500 error due to the anonymous user not having some properties of an authenticated user. Anonymous users should be able view media on the site, just without an scrobble data being present.
|
||||
|
||||
*** Error
|
||||
#+begin_src json
|
||||
{"levelname": "ERROR", "name": "django.request", "funcName": "log_response", "lineno": 241, "asctime": "2026-09-01 08:49:52,844", "message": "Internal Server Error: /books/0879dd15-fe34-4ed4-b6b0-f68c924aed23/", "exc_info": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/fields/__init__.py\", line 2053, in get_prep_value\n return int(value)\n ^^^^^^^^^^\nTypeError: int() argument must be a string, a bytes-like object or a real number, not 'SimpleLazyObject'\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py\", line 55, in inner\n response = get_response(request)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py\", line 197, in _get_response\n response = wrapped_callback(request, *callback_args, **callback_kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/views/generic/base.py\", line 104, in view\n return self.dispatch(request, *args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/views/generic/base.py\", line 143, in dispatch\n return handler(request, *args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/views/generic/detail.py\", line 109, in get\n context = self.get_context_data(object=self.object)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/views.py\", line 219, in get_context_data\n qs = media.scrobble_set.filter(user=self.request.user)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/manager.py\", line 87, in manager_method\n return getattr(self.get_queryset(), name)(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/query.py\", line 1436, in filter\n return self._filter_or_exclude(False, args, kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/query.py\", line 1454, in _filter_or_exclude\n clone._filter_or_exclude_inplace(negate, args, kwargs)\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/query.py\", line 1461, in _filter_or_exclude_inplace\n self._query.add_q(Q(*args, **kwargs))\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/sql/query.py\", line 1546, in add_q\n clause, _ = self._add_q(q_object, self.used_aliases)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/sql/query.py\", line 1577, in _add_q\n child_clause, needed_inner = self.build_filter(\n ^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/sql/query.py\", line 1492, in build_filter\n condition = self.build_lookup(lookups, col, value)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/sql/query.py\", line 1319, in build_lookup\n lookup = lookup_class(lhs, rhs)\n ^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/lookups.py\", line 27, in __init__\n self.rhs = self.get_prep_lookup()\n ^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/fields/related_lookups.py\", line 166, in get_prep_lookup\n self.rhs = target_field.get_prep_value(self.rhs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/fields/__init__.py\", line 2055, in get_prep_value\n raise e.__class__(\nTypeError: Field 'id' expected a number but got <SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x8ffebe31690>>.", "status_code": 500, "request": "<WSGIRequest: GET '/books/0879dd15-fe34-4ed4-b6b0-f68c924aed23/'>"}
|
||||
#+end_src
|
||||
|
||||
* Version 68.6 [1/1]
|
||||
** DONE [#A] Music track scrobbles now frequently find the wrong track :music:metadata:scrobbles:
|
||||
:PROPERTIES:
|
||||
|
||||
153
PROJECT.org
153
PROJECT.org
@ -18,7 +18,7 @@ tasks, Todoist tasks, web pages I've read and trails I've hiked has turned out
|
||||
to be sometimes cathartic and sometimes functional as I try to remember when I
|
||||
did a thing.
|
||||
|
||||
* Backlog [1/35] :vrobbler:project:personal:
|
||||
* Backlog [0/31] :vrobbler:project:personal:
|
||||
** TODO [#C] Configure IMAP folder/start in user profile :imap:settings:
|
||||
*** Description
|
||||
|
||||
@ -589,154 +589,3 @@ The Edit log form should have from top to bottom:
|
||||
|
||||
Currently the images on the book source page go nowhere. We should add links to Amazon and Goodreads, and maybe Bookshop.org if we can find a way to generate that link easily.
|
||||
|
||||
** DONE [#B] Make book matching use Google Books ID or author name :bug:books:matching:
|
||||
*** Description
|
||||
|
||||
This may be a no-op situation as we've moved away from Google Books. But maybe we haven't.
|
||||
|
||||
Turns out we hadn't. Google Books is still a primary metadata source alongside
|
||||
OpenLibrary and ComicVine. =Book.find_or_create()= only matched by
|
||||
=original_title=, which is fragile. It now also matches by Google Books ID or
|
||||
author name (like Track does with =musicbrainz_id=).
|
||||
|
||||
*** Implementation
|
||||
|
||||
- ~vrobbler/apps/books/sources/google.py~: =lookup_book_from_google()= now
|
||||
accepts an optional =author= (used as an =inauthor:= query term) and returns
|
||||
the top-level Google Books volume =id= as =google_books_id=.
|
||||
- ~vrobbler/apps/books/models.py~: added a =google_books_id= CharField to
|
||||
=Book=. =find_or_create()= now:
|
||||
- short-circuits on an exact =original_title= match (no lookups);
|
||||
- after enrichment, reuses an existing book by =google_books_id=, falling
|
||||
back to a =title= + author match — mirroring how Track keys off
|
||||
=musicbrainz_id=.
|
||||
- =fix_metadata()= gained a Google Books fallback so asynchronously enriched
|
||||
(e.g. KoReader-imported) books also capture =google_books_id=.
|
||||
- ~vrobbler/apps/books/management/commands/cleanup_book_metadata.py~: passes
|
||||
the author to the Google lookup and persists =google_books_id= on backfill.
|
||||
- Migration ~0040_book_google_books_id~ adds the field.
|
||||
|
||||
** DONE [#C] Fix dead source icon links on book and brick set pages :books:templates:
|
||||
:PROPERTIES:
|
||||
:ID: 35ce01a2-0dca-4bd3-83ea-ca826c734c36
|
||||
:END:
|
||||
|
||||
*** Description
|
||||
|
||||
The book detail page rendered OpenLibrary and Amazon source icons via
|
||||
=object.openlibrary_link= and =object.amazon_link=, but neither property
|
||||
existed on =Book= (the model has no Amazon ASIN field at all), so both icons
|
||||
were dead links around broken images. The brick set detail page was a copy of
|
||||
the book template and had the same broken icons for a type with no
|
||||
OpenLibrary/Amazon presence.
|
||||
|
||||
*** Implementation
|
||||
|
||||
- ~vrobbler/apps/books/models.py~: added =Book.openlibrary_link= (builds
|
||||
=https://openlibrary.org/works/{olid}= or =/books/{olid}= for edition IDs)
|
||||
and =Book.bookshop_link= (uses the ISBN, in =/a/{affiliate_id}/{isbn}=
|
||||
affiliate form when =BOOKSHOP_AFFILIATE_ID= is set, otherwise a
|
||||
=/books?keywords={isbn}= search link).
|
||||
- ~vrobbler/settings.py~: added =BOOKSHOP_AFFILIATE_ID= read from
|
||||
=VROBBLER_BOOKSHOP_AFFILIATE_ID=.
|
||||
- ~vrobbler/templates/books/book_detail.html~: source icons now render
|
||||
conditionally (only when a link exists, like the music pages), link to
|
||||
OpenLibrary and Bookshop, and the dead Amazon icon is gone.
|
||||
- ~vrobbler/templates/bricksets/brickset_detail.html~: removed the dead
|
||||
OpenLibrary/Amazon source icon row entirely.
|
||||
- Added official OpenLibrary and Bookshop logos at
|
||||
~vrobbler/apps/scrobbles/static/images/~
|
||||
(=openlibrary-logo.png=, =bookshop-logo.png=).
|
||||
- Tests in ~tests/books_tests/test_book_source_links.py= cover both link
|
||||
properties (work vs edition OLIDs, ISBN-10/13, with/without affiliate ID).
|
||||
- ~vrobbler/apps/books/management/commands/cleanup_book_metadata.py~: added a
|
||||
=--missing-source_id= filter flag for books lacking any of
|
||||
=openlibrary_id= / =google_books_id= / =comicvine_id=.
|
||||
- ~vrobbler/apps/books/models.py~: added =Book.is_comic= so ComicVine is only
|
||||
queried for books that already carry comic source data
|
||||
(=comicvine_id=, =volume_comicvine_id=, =readcomics_url=, issue/volume
|
||||
fields) or whose title contains "Issue "/"Volume ". The blanket ComicVine
|
||||
fallback in =find_or_create()=, =fix_metadata()=, and
|
||||
~cleanup_book_metadata.py~ now respects this, so unrelated prose books no
|
||||
longer get matched to comics.
|
||||
|
||||
** DONE [#B] Books created via koreader do not get enriched :books:metadata:bug:
|
||||
:PROPERTIES:
|
||||
:ID: ddfed612-1f4e-b0bb-5310-19adf9cf9336
|
||||
:END:
|
||||
|
||||
*** Description
|
||||
|
||||
When a new books arrives inside of a KoReader import, the metadata is not enriched.
|
||||
|
||||
*** Implementation
|
||||
|
||||
- Added =scrobbles.tasks.enrich_book_metadata()=, a background Celery task that
|
||||
calls =Book.fix_metadata()= and tags the book =book-enriched= on success or
|
||||
=enrichment-failed= on failure.
|
||||
- =create_book_from_row()= in ~vrobbler/apps/books/koreader.py~ now dispatches
|
||||
that task asynchronously after creating a new book, instead of the commented
|
||||
out synchronous =fix_metadata()= call.
|
||||
- Fixed =Book.fix_metadata()= to not reference the removed =locg_slug= field,
|
||||
and to handle =authors=/=genres= keys returned by the current OpenLibrary
|
||||
source (previously it would crash).
|
||||
- Routed =enrich_book_metadata= to the =background= worker queue.
|
||||
|
||||
** DONE [#B] There should a global chart aggregator that builds charts across all users :charts:feature:
|
||||
:PROPERTIES:
|
||||
:ID: ccc257d5-7d35-42b0-9af2-2941b67880fd
|
||||
:END:
|
||||
|
||||
*** Description
|
||||
|
||||
Currently we build charts for individual users ... noting content that has been
|
||||
tops for a given year, month, week or day. We should also build such global
|
||||
charts across all users, but limit it to just the top three items (gold, silver,
|
||||
bronze). There should also be a toggle in profile settings that allows a user to
|
||||
include their scrobbles in global aggregation. If that check box is not selected
|
||||
(and it should off by default) that user is not included in the global charts.
|
||||
|
||||
*** Implementation
|
||||
|
||||
- Global chart records are stored as =ChartRecord= rows with a NULL =user=
|
||||
(the column is already nullable), so they reuse the existing model,
|
||||
upserting, indexing and chart rendering infrastructure.
|
||||
- Added =UserProfile.include_in_global_charts= (default off) plus a settings
|
||||
form checkbox; users who do not opt in are excluded from aggregation.
|
||||
Toggling the setting triggers =scrobbles.tasks.rebuild_global_charts_for_user()=
|
||||
which rebuilds every global chart period the user has scrobbles in, so the
|
||||
change is reflected immediately instead of waiting for the next scheduled
|
||||
chart build.
|
||||
- Refactored ~vrobbler/apps/charts/utils.py~: extracted the media type config
|
||||
into a module-level =MEDIA_CONFIG= and pulled the aggregation and upsert
|
||||
logic into shared =_aggregate_media()= and =_upsert_chart_records()=
|
||||
helpers used by both =build_charts()= and the new =build_global_charts()=.
|
||||
- Added =build_global_charts()= plus =build_global_daily/weekly/monthly/yearly_charts()=
|
||||
wrappers. Global charts aggregate scrobbles from opted-in users only and
|
||||
keep just the top three items (gold, silver, bronze) per media type/period.
|
||||
- Wired global chart building into the scheduled Celery tasks
|
||||
(~vrobbler/apps/scrobbles/tasks.py~): =create_yesterdays_charts()=,
|
||||
=rebuild_weekly_charts()=, =rebuild_monthly_charts()= and
|
||||
=rebuild_yearly_charts()= now also build the matching global charts.
|
||||
- Added =GlobalChartView= at =/charts/global/= (~charts.GlobalChartView~) with a
|
||||
new ~charts/global_chart_index.html~ template showing the medal top three
|
||||
per media type, with the same year/month/week navigation as user charts.
|
||||
- Anonymous users now see the global top-three charts on media detail pages:
|
||||
~scrobbles.views.ChartContextMixin~ queries =user__isnull=True= records
|
||||
when the request user is anonymous.
|
||||
- Tests in ~vrobbler/apps/charts/tests/test_views.py~ and new global chart
|
||||
tests in ~vrobbler/apps/charts/tests/test_utils.py~.
|
||||
|
||||
** DONE [#B] Make it possible for anonymous users to view media objects :media:templates:
|
||||
:PROPERTIES:
|
||||
:ID: f12fd0b4-b728-4fbc-adf7-d51695d8c155
|
||||
:END:
|
||||
|
||||
*** Description
|
||||
|
||||
Currently if you click on a Book link when logged out (like via a shared URL: https://life.lab.unbl.ink/shared/KkViBro/ ) you get a 500 error due to the anonymous user not having some properties of an authenticated user. Anonymous users should be able view media on the site, just without an scrobble data being present.
|
||||
|
||||
*** Error
|
||||
#+begin_src json
|
||||
{"levelname": "ERROR", "name": "django.request", "funcName": "log_response", "lineno": 241, "asctime": "2026-09-01 08:49:52,844", "message": "Internal Server Error: /books/0879dd15-fe34-4ed4-b6b0-f68c924aed23/", "exc_info": "Traceback (most recent call last):\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/fields/__init__.py\", line 2053, in get_prep_value\n return int(value)\n ^^^^^^^^^^\nTypeError: int() argument must be a string, a bytes-like object or a real number, not 'SimpleLazyObject'\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File \"/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py\", line 55, in inner\n response = get_response(request)\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py\", line 197, in _get_response\n response = wrapped_callback(request, *callback_args, **callback_kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/views/generic/base.py\", line 104, in view\n return self.dispatch(request, *args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/views/generic/base.py\", line 143, in dispatch\n return handler(request, *args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/views/generic/detail.py\", line 109, in get\n context = self.get_context_data(object=self.object)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/views.py\", line 219, in get_context_data\n qs = media.scrobble_set.filter(user=self.request.user)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/manager.py\", line 87, in manager_method\n return getattr(self.get_queryset(), name)(*args, **kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/query.py\", line 1436, in filter\n return self._filter_or_exclude(False, args, kwargs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/query.py\", line 1454, in _filter_or_exclude\n clone._filter_or_exclude_inplace(negate, args, kwargs)\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/query.py\", line 1461, in _filter_or_exclude_inplace\n self._query.add_q(Q(*args, **kwargs))\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/sql/query.py\", line 1546, in add_q\n clause, _ = self._add_q(q_object, self.used_aliases)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/sql/query.py\", line 1577, in _add_q\n child_clause, needed_inner = self.build_filter(\n ^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/sql/query.py\", line 1492, in build_filter\n condition = self.build_lookup(lookups, col, value)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/sql/query.py\", line 1319, in build_lookup\n lookup = lookup_class(lhs, rhs)\n ^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/lookups.py\", line 27, in __init__\n self.rhs = self.get_prep_lookup()\n ^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/fields/related_lookups.py\", line 166, in get_prep_lookup\n self.rhs = target_field.get_prep_value(self.rhs)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/django/db/models/fields/__init__.py\", line 2055, in get_prep_value\n raise e.__class__(\nTypeError: Field 'id' expected a number but got <SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x8ffebe31690>>.", "status_code": 500, "request": "<WSGIRequest: GET '/books/0879dd15-fe34-4ed4-b6b0-f68c924aed23/'>"}
|
||||
#+end_src
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "vrobbler"
|
||||
version = "68.6"
|
||||
version = "69.0"
|
||||
description = ""
|
||||
authors = ["Colin Powell <colin@unbl.ink>"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user