- Fix bug in fetching expansions for board games - Board games should have genres extracted from family data
3156 lines
120 KiB
Org Mode
3156 lines
120 KiB
Org Mode
#+title: Vrobbler Project
|
||
|
||
We should convert this PROJECT file to put tickets in a subdirectory, tickets, with each ticket having it's own shortid_title.org
|
||
* Overview
|
||
|
||
Vrobbler began humbly enough as a way to use Jellyfin's webhook to keep track of
|
||
the shows and movies I was watching. More specifically, I broke my ankle a few
|
||
days after Christmas in 2022 and spent the next four months very slowly
|
||
recovering after surgical repair. So once I had the webhook working, and
|
||
scrobbling videos, it was only a matter of time till I expaned it to mopidy to
|
||
replicate LastFM. Then I added board games, books via KoReader, sports events,
|
||
podcasts ... it just keeps going. Vrobbler is now a sort of Frankenstein's
|
||
monster of scrobbling an entire life.
|
||
|
||
I am still unconvinced I can keep this going, but being able to scrobble org
|
||
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.
|
||
|
||
|
||
* Features
|
||
** Beer
|
||
*** Triggers
|
||
**** Bookmarklet
|
||
**** Manual
|
||
*** Metadata sources
|
||
**** Untappd
|
||
** Book
|
||
*** Triggers
|
||
**** Webdav via KoReader
|
||
**** Manual
|
||
*** Metadata sources
|
||
**** Google Books
|
||
This is the preferred method at this time. Also, the Book model implements a
|
||
`find_or_create` classmethod which is an example of an interface we can use for
|
||
other data models to get metadata in a way that provides easy testing, bulk
|
||
fetching and simple saving.
|
||
**** OpenLibrary
|
||
**** ComicVine
|
||
** Board Game
|
||
*** Triggers
|
||
**** IMAP import
|
||
**** Bookmarklet
|
||
**** Manual
|
||
** Location
|
||
*** Triggers
|
||
**** GPSLogger (Android)
|
||
*** Metadata sources
|
||
**** User input
|
||
** Music
|
||
*** Triggers
|
||
**** Last.FM
|
||
**** Rockbox files
|
||
**** Mopidy
|
||
**** Jellyfin
|
||
*** Metadata sources
|
||
**** Musicbrainz
|
||
** Podcast
|
||
*** Triggers
|
||
**** Mopidy
|
||
*** Metadata sources
|
||
**** Google Podcasts
|
||
**** PodcastIndex
|
||
** Sport
|
||
*** Triggers
|
||
**** Bookmarklet
|
||
**** Manual
|
||
*** Metadata sources
|
||
**** Thes Sports DB
|
||
** Task
|
||
*** Triggers
|
||
**** Todoist
|
||
**** Org-mode
|
||
*** Metadata sources
|
||
**** User profile
|
||
** Trails
|
||
** Video
|
||
*** Triggers
|
||
**** Jellyfin
|
||
**** Bookmarklet
|
||
**** Manual
|
||
*** Metadata sources
|
||
**** IMDB
|
||
**** Youtube
|
||
** Web Page
|
||
*** Triggers
|
||
**** Bookmarklet
|
||
*** Metadata sources
|
||
**** Scraper
|
||
|
||
* Backlog [0/24] :vrobbler:project:personal:
|
||
** TODO [#C] After transition to linux add curl_cffi as webpage scrapper again :webpages:metadata:
|
||
** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :bug:music:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: 702462cf-d54b-48c6-8a7c-78b8de751deb
|
||
:END:
|
||
** TODO [#C] Move to using more robust mopidy-webhooks pacakge form pypi :utility:improvement:
|
||
:PROPERTIES:
|
||
:ID: ab31fdc3-359c-1b1d-6b9d-546b476021ba
|
||
:END:
|
||
*** Example payloads from mopidy-webhooks
|
||
**** Podcast playback ended
|
||
#+begin_src json
|
||
{
|
||
"type": "event",
|
||
"event": "track_playback_ended",
|
||
"data": {
|
||
"tl_track": {
|
||
"__model__": "TlTrack",
|
||
"tlid": 13,
|
||
"track": {
|
||
"__model__": "Track",
|
||
"uri": "file:///var/lib/mopidy/media/podcasts/The%20Prince/2022-09-28-Wolf-warriors.mp3",
|
||
"name": "Wolf warriors",
|
||
"artists": [
|
||
{
|
||
"__model__": "Artist",
|
||
"name": "The Economist"
|
||
}
|
||
],
|
||
"album": {
|
||
"__model__": "Album",
|
||
"name": "The Prince",
|
||
"date": "2022"
|
||
},
|
||
"genre": "Blues",
|
||
"date": "2022",
|
||
"length": 2437778,
|
||
"bitrate": 127988
|
||
}
|
||
},
|
||
"time_position": 3290
|
||
}
|
||
}
|
||
#+end_src
|
||
**** Podcast playback state changes
|
||
#+begin_src json
|
||
{
|
||
"type": "event",
|
||
"event": "playback_state_changed",
|
||
"data": {
|
||
"old_state": "paused",
|
||
"new_state": "playing"
|
||
}
|
||
}
|
||
#+end_src
|
||
|
||
#+begin_src json
|
||
{
|
||
"type": "event",
|
||
"event": "playback_state_changed",
|
||
"data": {
|
||
"old_state": "stopped",
|
||
"new_state": "playing"
|
||
}
|
||
}
|
||
#+end_src
|
||
**** Podcast playback started
|
||
#+begin_src json
|
||
{
|
||
"type": "event",
|
||
"event": "track_playback_started",
|
||
"data": {
|
||
"tl_track": {
|
||
"__model__": "TlTrack",
|
||
"tlid": 13,
|
||
"track": {
|
||
"__model__": "Track",
|
||
"uri": "file:///var/lib/mopidy/media/podcasts/The%20Prince/2022-09-28-Wolf-warriors.mp3",
|
||
"name": "Wolf warriors",
|
||
"artists": [
|
||
{
|
||
"__model__": "Artist",
|
||
"name": "The Economist"
|
||
}
|
||
],
|
||
"album": {
|
||
"__model__": "Album",
|
||
"name": "The Prince",
|
||
"date": "2022"
|
||
},
|
||
"genre": "Blues",
|
||
"date": "2022",
|
||
"length": 2437778,
|
||
"bitrate": 127988
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#+end_src
|
||
**** Podcast playback paused
|
||
#+begin_src json
|
||
{
|
||
"type": "status",
|
||
"data": {
|
||
"state": "paused",
|
||
"current_track": {
|
||
"__model__": "Track",
|
||
"uri": "file:///var/lib/mopidy/media/podcasts/The%20Prince/2022-09-28-Wolf-warriors.mp3",
|
||
"name": "Wolf warriors",
|
||
"artists": [
|
||
{
|
||
"__model__": "Artist",
|
||
"name": "The Economist"
|
||
}
|
||
],
|
||
"album": {
|
||
"__model__": "Album",
|
||
"name": "The Prince",
|
||
"date": "2022"
|
||
},
|
||
"genre": "Blues",
|
||
"date": "2022",
|
||
"length": 2437778,
|
||
"bitrate": 127988
|
||
},
|
||
"time_position": 2350
|
||
}
|
||
}
|
||
|
||
#+end_src
|
||
**** Track playback started
|
||
#+begin_src json
|
||
{
|
||
"type": "event",
|
||
"event": "track_playback_started",
|
||
"data": {
|
||
"tl_track": {
|
||
"__model__": "TlTrack",
|
||
"tlid": 14,
|
||
"track": {
|
||
"__model__": "Track",
|
||
"uri": "local:track:Various%20Artists%20-%202008%20-%20Twilight%20OST/01-muse-supermassive_black_hole.mp3",
|
||
"name": "Supermassive Black Hole",
|
||
"artists": [
|
||
{
|
||
"__model__": "Artist",
|
||
"uri": "local:artist:md5:250dd6551b66a58a6b4897aa697f200c",
|
||
"name": "Muse",
|
||
"musicbrainz_id": "9c9f1380-2516-4fc9-a3e6-f9f61941d090"
|
||
}
|
||
],
|
||
"album": {
|
||
"__model__": "Album",
|
||
"uri": "local:album:md5:455343d54cdd89cb5a3b5ad537ea99d0",
|
||
"name": "Twilight: Original Motion Picture Soundtrack",
|
||
"artists": [
|
||
{
|
||
"__model__": "Artist",
|
||
"uri": "local:artist:md5:54e4db2d5624f80b0cc290346e696756",
|
||
"name": "Various Artists",
|
||
"musicbrainz_id": "89ad4ac3-39f7-470e-963a-56509c546377"
|
||
}
|
||
],
|
||
"num_tracks": 12,
|
||
"num_discs": 1,
|
||
"date": "2008-11-04",
|
||
"musicbrainz_id": "b4889eaf-d9f4-434c-a68d-69227b12b6a4"
|
||
},
|
||
"composers": [
|
||
{
|
||
"__model__": "Artist",
|
||
"uri": "local:artist:md5:4d49cbca0b347e0a89047bb019d2779d",
|
||
"name": "Matt Bellamy"
|
||
}
|
||
],
|
||
"genre": "Rock",
|
||
"track_no": 1,
|
||
"disc_no": 1,
|
||
"date": "2008-11-04",
|
||
"length": 211121,
|
||
"musicbrainz_id": "ff1e3e1a-f6e8-4692-b426-355880383bb6",
|
||
"last_modified": 1672712949510
|
||
}
|
||
}
|
||
}
|
||
}
|
||
#+end_src
|
||
**** Track playback in progress
|
||
#+begin_src json
|
||
{
|
||
"type": "status",
|
||
"data": {
|
||
"state": "playing",
|
||
"current_track": {
|
||
"__model__": "Track",
|
||
"uri": "local:track:Various%20Artists%20-%202008%20-%20Twilight%20OST/01-muse-supermassive_black_hole.mp3",
|
||
"name": "Supermassive Black Hole",
|
||
"artists": [
|
||
{
|
||
"__model__": "Artist",
|
||
"uri": "local:artist:md5:250dd6551b66a58a6b4897aa697f200c",
|
||
"name": "Muse",
|
||
"musicbrainz_id": "9c9f1380-2516-4fc9-a3e6-f9f61941d090"
|
||
}
|
||
],
|
||
"album": {
|
||
"__model__": "Album",
|
||
"uri": "local:album:md5:455343d54cdd89cb5a3b5ad537ea99d0",
|
||
"name": "Twilight: Original Motion Picture Soundtrack",
|
||
"artists": [
|
||
{
|
||
"__model__": "Artist",
|
||
"uri": "local:artist:md5:54e4db2d5624f80b0cc290346e696756",
|
||
"name": "Various Artists",
|
||
"musicbrainz_id": "89ad4ac3-39f7-470e-963a-56509c546377"
|
||
}
|
||
],
|
||
"num_tracks": 12,
|
||
"num_discs": 1,
|
||
"date": "2008-11-04",
|
||
"musicbrainz_id": "b4889eaf-d9f4-434c-a68d-69227b12b6a4"
|
||
},
|
||
"composers": [
|
||
{
|
||
"__model__": "Artist",
|
||
"uri": "local:artist:md5:4d49cbca0b347e0a89047bb019d2779d",
|
||
"name": "Matt Bellamy"
|
||
}
|
||
],
|
||
"genre": "Rock",
|
||
"track_no": 1,
|
||
"disc_no": 1,
|
||
"date": "2008-11-04",
|
||
"length": 211121,
|
||
"musicbrainz_id": "ff1e3e1a-f6e8-4692-b426-355880383bb6",
|
||
"last_modified": 1672712949510
|
||
},
|
||
"time_position": 17031
|
||
}
|
||
}
|
||
#+end_src
|
||
**** Track event playback paused
|
||
#+begin_src json
|
||
{
|
||
"type": "event",
|
||
"event": "track_playback_paused",
|
||
"data": {
|
||
"tl_track": {
|
||
"__model__": "TlTrack",
|
||
"tlid": 14,
|
||
"track": {
|
||
"__model__": "Track",
|
||
"uri": "local:track:Various%20Artists%20-%202008%20-%20Twilight%20OST/01-muse-supermassive_black_hole.mp3",
|
||
"name": "Supermassive Black Hole",
|
||
"artists": [
|
||
{
|
||
"__model__": "Artist",
|
||
"uri": "local:artist:md5:250dd6551b66a58a6b4897aa697f200c",
|
||
"name": "Muse",
|
||
"musicbrainz_id": "9c9f1380-2516-4fc9-a3e6-f9f61941d090"
|
||
}
|
||
],
|
||
"album": {
|
||
"__model__": "Album",
|
||
"uri": "local:album:md5:455343d54cdd89cb5a3b5ad537ea99d0",
|
||
"name": "Twilight: Original Motion Picture Soundtrack",
|
||
"artists": [
|
||
{
|
||
"__model__": "Artist",
|
||
"uri": "local:artist:md5:54e4db2d5624f80b0cc290346e696756",
|
||
"name": "Various Artists",
|
||
"musicbrainz_id": "89ad4ac3-39f7-470e-963a-56509c546377"
|
||
}
|
||
],
|
||
"num_tracks": 12,
|
||
"num_discs": 1,
|
||
"date": "2008-11-04",
|
||
"musicbrainz_id": "b4889eaf-d9f4-434c-a68d-69227b12b6a4"
|
||
},
|
||
"composers": [
|
||
{
|
||
"__model__": "Artist",
|
||
"uri": "local:artist:md5:4d49cbca0b347e0a89047bb019d2779d",
|
||
"name": "Matt Bellamy"
|
||
}
|
||
],
|
||
"genre": "Rock",
|
||
"track_no": 1,
|
||
"disc_no": 1,
|
||
"date": "2008-11-04",
|
||
"length": 211121,
|
||
"musicbrainz_id": "ff1e3e1a-f6e8-4692-b426-355880383bb6",
|
||
"last_modified": 1672712949510
|
||
}
|
||
},
|
||
"time_position": 67578
|
||
}
|
||
}
|
||
#+end_src
|
||
** TODO [#C] Allow auto trail tracking via email with Garmin LiveTrack URLs :trails:feature:
|
||
:PROPERTIES:
|
||
:ID: 133bcf71-078f-4efa-a029-1eae4b4d146d
|
||
:END:
|
||
** TODO [#C] Fix exporting so it works reliably :exporting:feature:
|
||
|
||
*** Description
|
||
|
||
The existing export function is very naieve. It runs in the web process, takes
|
||
too long and just dumps tracks. We should make it more robust by creating one
|
||
CSV file per scrobble media type and writing them into a zip file that gets
|
||
placed in the media directory:
|
||
|
||
`/media/exports/user_<user_id>/<timestamp>-export.zip`
|
||
|
||
And this should all be done in a celery task that is just kicked off by the
|
||
"Export" button on the frontend
|
||
|
||
** TODO [#B] Add AllTrails as a source for Trail data :trails:feature:
|
||
:PROPERTIES:
|
||
:ID: 39313362-cdfe-46e7-bbd4-9139a65c0b3c
|
||
:END:
|
||
|
||
*** Description
|
||
Pretty clear, I would love to make trails more useful. Historically I wasn't
|
||
hiking a lot, which made the source for this a bit silly. But it's clear that
|
||
AllTrails is the best source, though having TrailForks is nice to.
|
||
|
||
** TODO [#B] Add `garmin_activity_id` to the TrailLogData class :trails:feature:
|
||
:PROPERTIES:
|
||
:ID: 5a4fb0f8-0555-40ec-b06f-93c26bd686f4
|
||
:END:
|
||
*** Description
|
||
|
||
Would be nice to have some loose connection to the actual event in my Garmin
|
||
profile.
|
||
|
||
** TODO [#B] Fix how we show notes and descriptions from scrobbles to users :metadata:notes:tasks:
|
||
:PROPERTIES:
|
||
:ID: adf4c513-a417-4ec9-8831-f01ffcf63276
|
||
:END:
|
||
*** Description
|
||
|
||
Currently the display of notes leaves something to be desired. The biggest issue
|
||
is that they don't look good on mobile and are probably trying to be too cute.
|
||
Rather than post-it note style, we should just put notes in a list under the
|
||
description, above the Edit Log toggle, with timestamps for when they were
|
||
added.
|
||
|
||
They should also probably support markdown formatting and that should be
|
||
displayed in the template.
|
||
|
||
** TODO [#B] Add CSV endpoint for book scrobbles that LibraryThing can ingest :books:feature:export:
|
||
https://app.todoist.com/app/task/add-a-csv-endpoint-for-users-book-reads-that-library-thing-can-ingest-6X7QPMRp265xMXqg#comment-6X7QrXq6gJjMP4hg
|
||
** TODO [#B] Make IMAP and WebDAV configurable :webdav:feature:imap:importers:
|
||
:PROPERTIES:
|
||
:ID: b1426d92-2feb-4d15-9738-d5b7b0594f96
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently we have webdav able to import post types of file-based incoming data,
|
||
usually in the form of CSVs but also gpx files, bgstats json files, and
|
||
audioscrobbler TSV files.
|
||
|
||
What if the user could specify via their profile (settings) which imports they
|
||
wanted to use IMAP for and which ones they wanted to use WebDAV for.
|
||
|
||
Then we'd have two celery tasks that would be kicked off periodically via
|
||
celerybeat, one for IMAP imports every 12 minutes and one for WebDAV every 3
|
||
minutes. Both would be responsible for checking if a user has an configured
|
||
imports of their type, check if an import needs to run, and dispatch the
|
||
needed import celery task. This is how the WebDAV celery task currently works.
|
||
|
||
This would also be an opporunity to clean up the code around WebDAV imports
|
||
and make them more re-usable for other import services.
|
||
|
||
** TODO [#A] Add an exception list of artists as a constant that are exempted from splitting :music:artists:metadata:
|
||
:PROPERTIES:
|
||
:ID: fd86a11a-73ec-470d-b5e3-2d90ba9137c8
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Certain artists like "Simon & Garfunkel" are actually one artist. While we don't want to mess with splitting up
|
||
tracks into featured artists, we should have a "LITERAL_ARTIST_TITLES" constant that can have exceptions like
|
||
this put into it and then we stop trying to pull the artist apart when we run into it.
|
||
|
||
** TODO [#A] Before enriching anything, trust the POST data :feature:scrobbles:metadata:
|
||
:PROPERTIES:
|
||
:ID: db6b05f8-09f4-49f5-9838-fbacc9fe9cd0
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Both Jellyfin and Mopidy provide a decent amount of metadata when they POST to our webhooks.
|
||
|
||
In most cases, we should be able to trust this data to created music tracks or videos rather
|
||
than going to third-party services to enrich. Thus, for tracks and videos we should search in
|
||
the local database for imdb_id or musicbrainz_id for the specific content and, if found, not
|
||
enrich further.
|
||
|
||
If not found, tracks and videos from mopidy and jellyfin should be created as completely as
|
||
possible using only the POST data from the webhooks, tagged the scrobble with "webhook-metadata-only"
|
||
and start the scrobble. A separate celery task should be kicked off to enrich the track or video
|
||
async with the POST data stored in the log["raw_data"] and used by the celery enrichment task
|
||
to go try to enrich the media instance. Should this enrichment fail, tag the scrobble as "enrichment-failed"
|
||
log a warning and move on.
|
||
|
||
** TODO [#B] Allow browing a user's favorited media :favorites:feature:
|
||
:PROPERTIES:
|
||
:ID: 5c2cf004-d01f-4576-9bbb-974235e7408a
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
We should have a global view `/favorites/` that shows the logged in users's
|
||
favorited media objects.
|
||
|
||
** TODO [#B] Find page numbers for comic books from ComicVine :feature:books:
|
||
:PROPERTIES:
|
||
:ID: 79f867c3-1288-4143-b6bf-2a452983ee9f
|
||
:END:
|
||
** TODO [#C] Implement loguru into project :feature:loguru:logging:
|
||
:PROPERTIES:
|
||
:ID: efcd0c0a-db81-4518-9c23-5505d59e8ef5
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Would be great to formalize how we log so we can search for errors and such more
|
||
easily. And our exposure to PII is really low at this point in the project,
|
||
so we can probably use backtrace=True and diagnose=True to help us root cause
|
||
bugs faster.
|
||
|
||
** TODO [#B] Scrape ComicBookRoundUp ratings for comic book metadata :books:feature:comicbook:
|
||
:PROPERTIES:
|
||
:ID: b3cc57ca-3d2c-468d-ab7c-c47f1120309b
|
||
:END:
|
||
|
||
*** Description
|
||
As an example https://comicbookroundup.com/comic-books/reviews/humanoids-publishing/the-history-of-science-fiction
|
||
|
||
** TODO [#C] Make podcast date format configurable in settings :podcasts:configuration:
|
||
:PROPERTIES:
|
||
:ID: b01a94f8-328f-41ed-a62e-8b99c755b82d
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
=PODCAST_DATE_FORMAT= is hardcoded to ="YYYY-MM-DD"=. Should be in Django settings or environment variables for deploy-specific configuration.
|
||
|
||
File: ~vrobbler/apps/podcasts/utils.py~ (line 13)
|
||
|
||
** TODO [#C] Extract zombie scrobble query into custom manager :refactoring:manager:
|
||
:PROPERTIES:
|
||
:ID: 79c874e1-ca6f-4bce-9259-e3eebdca8a41
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
The zombie scrobble cleanup query lives in a utility function. Should be a
|
||
custom model manager method (e.g. =Scrobble.objects.zombies()=).
|
||
|
||
File: ~vrobbler/apps/scrobbles/utils.py~ (line 204)
|
||
|
||
** TODO [#C] Allow profile to set start of week :profiles:configuration:
|
||
:PROPERTIES:
|
||
:ID: 0449279a-9550-430e-be0c-816df7273080
|
||
:END:
|
||
|
||
*** Description
|
||
=start_of_week()= and =end_of_week()= use Monday as default. Should be a user
|
||
profile setting for different cultural week start conventions.
|
||
|
||
File: ~vrobbler/apps/profiles/utils.py~ (lines 39, 44)
|
||
|
||
** TODO [#C] Add constants for data dictionary keys (multiple files) :refactoring:constants:
|
||
:PROPERTIES:
|
||
:ID: d4415f9b-620a-4be7-925d-fa71c02ba1d1
|
||
:END:
|
||
|
||
*** Description
|
||
Multiple files use magic string literals for dict keys. Should be extracted to
|
||
named constants for maintainability.
|
||
|
||
- Files:
|
||
- ~vrobbler/apps/locations/models.py~ (line 63) -- ="lat"=, ="lon"= etc.
|
||
- ~vrobbler/apps/webpages/models.py~ (line 290) -- ="url"=
|
||
- ~vrobbler/apps/scrobbles/importers/tsv.py~ (line 55) -- ="S"= completion status
|
||
|
||
|
||
** TODO [#A] Deduplicate BGG plays before posting :boardgames:bgg:duplication:
|
||
:PROPERTIES:
|
||
:ID: e9b842bf-0049-42e7-a060-f3ebd0067d2f
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
No check for existing BGG plays before posting, which can create duplicates.
|
||
Should look up past plays by =bggeek_id= first.
|
||
|
||
File: ~vrobbler/apps/boardgames/bgg.py~ (line 117)
|
||
|
||
** TODO [#C] Clean up naming of =bgsplay= parsing :importers:refactoring:
|
||
:PROPERTIES:
|
||
:ID: c751dbbc-464a-4e63-9fe3-e034303f7b54
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
We should rename `email_scrobble_board_game` to reflect the fact that it's just
|
||
a helper method to create board game scrobbles given a json blob. It's
|
||
independent of the email flow it was originally creatdd for
|
||
|
||
** TODO [#B] Is there way to create unique slugs for media instances :media_types:
|
||
** TODO [#A] Update how board game scrobbles work :boardgames:
|
||
|
||
*** Description
|
||
|
||
When we scrobble a board game from a BGG URL, instead of going to the media
|
||
detail page, we should go to the scrobble detail page, with the Edit Log form
|
||
expanded by default.
|
||
|
||
The Edit log form should have from top to bottom:
|
||
|
||
- Board/Variant (one or many BoardGameVariant in a multi-select widget)
|
||
- People (which should be similar to the Bird widget on BirdLocation and allow setting per user score, win true/false, rank, new true/false, seat_ordrer)
|
||
- Expansion ids (which should a multi-select widget of expansions for this game)
|
||
- Location (which should be a drop down of BoardGameLocations for this user)
|
||
|
||
* Version 59.4 [2/2]
|
||
** DONE Fix bug in fetching expansions for board games :boardgames:
|
||
:PROPERTIES:
|
||
:ID: 17995312-e76e-4a50-b591-0eab78cb59ab
|
||
:END:
|
||
|
||
#+begin_src python
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/boardgames/management/commands/fetch_expansions.py", line 60, in handle
|
||
fetch_and_link_expansions(game, expansions)
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/boardgames/utils.py", line 51, in fetch_and_link_expansions
|
||
expansion = BoardGame.find_or_create(str(exp_id))
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/boardgames/models.py", line 409, in find_or_create
|
||
bgg_data = lookup_boardgame_from_bgg(lookup_id=lookup_id)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/boardgames/sources/bgg.py", line 15, in lookup_boardgame_from_bgg
|
||
game = bgg.game(game_id=lookup_id)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/boardgamegeek/api.py", line 1045, in game
|
||
raise BGGApiError(msg)
|
||
boardgamegeek.exceptions.BGGApiError: invalid data for game id: 242117
|
||
#+end_src
|
||
|
||
** DONE Board games should have genres extracted from family data :boardgames:metadata:
|
||
:PROPERTIES:
|
||
:ID: 7214b270-dccc-4b98-ac58-ff4f76c8cda9
|
||
:END:
|
||
|
||
|
||
* Version 59.3 [2/2]
|
||
** DONE Exclude some board games from auto-expansion imports :boardgames:
|
||
:PROPERTIES:
|
||
:ID: 51ffdf20-e732-4774-b781-c3501d26d46f
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Some board games, especially trading card games, have silly amounts of expansions.
|
||
We should have a setting SKIP_AUTO_EXPANSION_DOWNLOAD that is a list of BGG ids of
|
||
games where expansions should not be download automatically. This exclusion should also auto-include
|
||
any games with "Collectible Card Games" in it's family.
|
||
|
||
** DONE Should be able to add new variants to board games via the log data form :boardgames:
|
||
:PROPERTIES:
|
||
:ID: 5ed0dd25-3026-3da8-dc5c-f2a75751af9a
|
||
:END:
|
||
|
||
* Version 59.2 [1/1]
|
||
** DONE Fix test failure in discgolf app :discgolf:tests:
|
||
:PROPERTIES:
|
||
:ID: 813ae357-0568-5a4c-1a35-172e95d02740
|
||
:END:
|
||
|
||
* Version 59.1 [1/1]
|
||
** DONE Fix bug when expansions have no image :boardgames:bug:
|
||
:PROPERTIES:
|
||
:ID: 9fee96c9-c6a0-32d9-b6f8-212c60fc3540
|
||
:END:
|
||
|
||
* Version 59.0 [3/3]
|
||
** DONE [#A] Add BoardGameVariant model :boardgames:
|
||
:PROPERTIES:
|
||
:ID: 0ffb20d5-252f-b13d-473d-5529014602ff
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Variants represent unique boards being used per scrobble or scenarios when
|
||
playing a game. Scrobbles of a board game may have one or more
|
||
boardgame_variant_ids assocaited with their log data, and a variant is created
|
||
for one specific board game.
|
||
|
||
|
||
** DONE [#A] Lookup all Expansions for a game when creating it :boardgames:
|
||
:PROPERTIES:
|
||
:ID: 8a84b06d-555c-4701-9058-ff364c89c198
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
We don't want to blow up the BGG API, but if possible with not too
|
||
many calls, when we scrobble a board game, in order to allow
|
||
populating the "Expansions" multi select, we should fetch any
|
||
expansions for the board game when creating it for the first time.
|
||
|
||
We should also create a managemnt script to update existing board games.
|
||
|
||
** DONE [#A] Board game expansion lookup should be async on URL scrobbles :boardgames:
|
||
:PROPERTIES:
|
||
:ID: 968d8dde-f906-cdf0-af4e-b87ce28ddbbb
|
||
:END:
|
||
|
||
* Version 58.8 [1/1]
|
||
** DONE [#B] Clean up trend templates :trends:templates:
|
||
:PROPERTIES:
|
||
:ID: 83237e2c-857b-47c9-c86c-32a5e3f1359d
|
||
:END:
|
||
|
||
* Version 58.7 [2/2]
|
||
** DONE [#B] Split up chart page between tables and maloja :charts:templates:
|
||
:PROPERTIES:
|
||
:ID: 103ab084-2016-cfa4-c677-3c5fdc54cce0
|
||
:END:
|
||
** DONE [#A] Fix CI so we don't double run deploys and builds :ci:
|
||
:PROPERTIES:
|
||
:ID: 1a93e7cb-b883-aae5-2bd5-fcdd6e16f8ab
|
||
:END:
|
||
|
||
* Version 58.6 [1/1]
|
||
** DONE [#B] Cleanup commands should check for broken images :metadata:cleanup:
|
||
:PROPERTIES:
|
||
:ID: bacce321-73c7-ae1f-bfa7-c3ee517b5441
|
||
:END:
|
||
|
||
* Version 58.5 [1/1]
|
||
** DONE [#A] The maloja style charts are messed up :templates:charts:
|
||
:PROPERTIES:
|
||
:ID: 987397a2-7e74-4eb1-87cc-4c8bbe1c7b23
|
||
:END:
|
||
|
||
* Version 58.4 [2/2]
|
||
** DONE [#B] Allow people all trends or individual trends :trends:profiles:
|
||
:PROPERTIES:
|
||
:ID: 1d081152-abd1-73c2-a625-903565a10c6c
|
||
:END:
|
||
** DONE [#A] Fix a bug in board game scorelog data :boardgames:logdata:
|
||
:PROPERTIES:
|
||
:ID: 014bab30-13bf-fae7-e678-4666a8d38ae4
|
||
:END:
|
||
|
||
* Version 58.3 [1/1]
|
||
** DONE [#A] Remove curl-cffi as it doesn't work on FreeBSD :webpages:deps:
|
||
:PROPERTIES:
|
||
:ID: 6bc1b0dd-e449-3d32-a176-46451e793e5d
|
||
:END:
|
||
|
||
* Version 58.2 [2/2]
|
||
** DONE [#B] Add more robust webpage scraping :webpages:metadata:
|
||
:PROPERTIES:
|
||
:ID: 84d9bfa5-75c0-0718-764e-379f7456602a
|
||
:END:
|
||
** DONE [#B] Time of Day Categories trend :trends:
|
||
:PROPERTIES:
|
||
:ID: 6598074f-2290-46db-967b-29f45d30be29
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Added a "Time of Day Categories" trend that groups scrobbles for Books, Trails,
|
||
Birding Locations, and Board Games into Early Bird (5-10:59am), Day Jay (11am-6:59pm),
|
||
and Night Owl (7pm-4:59am) buckets. Shows both overall and per-media-type breakdowns.
|
||
|
||
|
||
* Version 58.1 [1/1]
|
||
** DONE [#B] Add auto genre tagging for papers :books:papers:metadata:
|
||
:PROPERTIES:
|
||
:ID: e6b5c3a5-7fc6-b530-96c2-b5962a716db6
|
||
:END:
|
||
|
||
* Version 58.0 [1/1]
|
||
** DONE [#B] Add scrobbling of Papers via webpages with doi.org links in them :feature:papers:
|
||
:PROPERTIES:
|
||
:ID: d30bb8aa-eefd-002c-38d5-3f2fcef345f2
|
||
:END:
|
||
|
||
* Version 57.1 [1/1]
|
||
** DONE [#A] Write poetry lock file :bug:deps:
|
||
:PROPERTIES:
|
||
:ID: 0f5a6f4b-a486-ba7e-bbce-f7581274398c
|
||
:END:
|
||
|
||
* Version 57.0 [5/5]
|
||
** DONE [#A] Scrobble button on some media list pages dont work :bug:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: a3a5c707-2e3d-a6b1-0f7f-4c6f7433aa1f
|
||
:END:
|
||
** DONE [#B] Use HTMx to update the Now Playing widget :feature:templates:
|
||
:PROPERTIES:
|
||
:ID: 5f5631fc-9ee1-d5a5-d0f8-94fea6fbbfa4
|
||
:END:
|
||
** DONE [#B] Add a live page that updates the scrobble list via JS polling :feature:templates:
|
||
:PROPERTIES:
|
||
:ID: 58790d76-dc6e-8aa5-2dc0-e64fe786fbf1
|
||
:END:
|
||
** DONE [#A] Turns out we cant cache the now playing widget :bug:templates:
|
||
:PROPERTIES:
|
||
:ID: 9ce669ea-c000-cdfe-a634-ad5cdaeae81c
|
||
:END:
|
||
** DONE [#C] What would it look like to add an MCP server to expose scrobbles and media items? :mcpserver:feature:
|
||
:PROPERTIES:
|
||
:ID: c5fca159-c7e0-5795-7c05-bbc48f539650
|
||
:END:
|
||
|
||
* Version 56.4 [3/3]
|
||
** DONE [#B] Add ability to do reverse address lookup on lat-long pairs :geolocations:feature:
|
||
:PROPERTIES:
|
||
:ID: 86c071ff-7638-41ba-6b65-1382df1cb5aa
|
||
:END:
|
||
** DONE [#B] Add address fields to GeoLocation :addresses:geolocation:
|
||
:PROPERTIES:
|
||
:ID: a55ae508-07ab-ccdd-e453-846bd3fca6fb
|
||
:END:
|
||
** DONE [#B] Add better detail template for Disc Golf Courses :discgolf:templates:
|
||
:PROPERTIES:
|
||
:ID: 12cee67c-f723-0fa3-848a-cbc6e4d65fc3
|
||
:END:
|
||
|
||
* Version 56.3 [1/1]
|
||
** DONE [#A] Fix bug in importer script from discgolf being added :bug:
|
||
:PROPERTIES:
|
||
:ID: c3733f96-18f1-eef8-f5d9-edaf97e35623
|
||
:END:
|
||
|
||
* Version 56.2 [1/1]
|
||
** DONE [#A] Fix bug in creating people when importing course plays :discgolf:bug:
|
||
:PROPERTIES:
|
||
:ID: 255e9886-098b-39ae-1077-25e43223660e
|
||
:END:
|
||
|
||
* Version 56.1 [1/1]
|
||
** DONE [#A] Add tests to discgolf app :discgolf:tests:
|
||
:PROPERTIES:
|
||
:ID: 28e8344e-c3cf-19af-ce1c-cb821d4fcb5f
|
||
:END:
|
||
|
||
* Version 56.0 [1/1]
|
||
** DONE [#B] Add DiscGolf as a scrobbleable media :discgolf:
|
||
:PROPERTIES:
|
||
:ID: 8cdde5d3-0ae5-7d5a-99d2-200c86afae03
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
I have a csv file fro the uDisc disc golf scoring app that looks like:
|
||
|
||
Singles round. Note second row is the par for the course
|
||
#+begin_src csv
|
||
PlayerName,CourseName,LayoutName,StartDate,EndDate,Total,+/-,RoundRating,Hole1,Hole2,Hole3,Hole4,Hole5,Hole6,Hole7,Hole8,Hole9
|
||
Par,DR Front 9,Custom Layout,2026-06-19 1535-0400,2026-06-19 1725-0400,27,,,3,3,3,3,3,3,3,3,3
|
||
Colin Powell,DR Front 9,Custom Layout,2026-06-19 1535-0400,2026-06-19 1725-0400,30,3,,2,3,4,4,3,4,3,3,4
|
||
Asa Sewell,DR Front 9,Custom Layout,2026-06-19 1535-0400,2026-06-19 1725-0400,44,17,,5,4,4,8,5,5,4,4,5
|
||
Emma Sweet,DR Front 9,Custom Layout,2026-06-19 1535-0400,2026-06-19 1725-0400,41,14,,5,4,5,6,3,4,3,5,6
|
||
Jane Sewell,DR Front 9,Custom Layout,2026-06-19 1535-0400,2026-06-19 1725-0400,44,17,,4,5,5,5,5,5,4,6,5
|
||
Nabby Sewell,DR Front 9,Custom Layout,2026-06-19 1535-0400,2026-06-19 1725-0400,59,32,,6,6,7,7,6,7,6,6,8
|
||
Silas Sewell,DR Front 9,Custom Layout,2026-06-19 1535-0400,2026-06-19 1725-0400,41,14,,5,5,4,5,3,5,4,4,6`
|
||
#+end_src
|
||
|
||
Teams of two or more persons. Note second row is the par for the course
|
||
#+begin_src csv
|
||
PlayerName,CourseName,LayoutName,StartDate,EndDate,Total,+/-,RoundRating,Hole1,Hole2,Hole3,Hole4,Hole5,Hole6,Hole7,Hole8,Hole9
|
||
Par,Peninsula Links,Main,2026-06-19 2322-0400,2026-06-19 2323-0400,27,,,3,3,3,3,3,3,3,3,3
|
||
Colin Powell + Asa Sewell,Peninsula Links,Main,2026-06-19 2322-0400,2026-06-19 2323-0400,29,2,,3,4,2,3,2,3,5,3,4
|
||
Emma Sweet + Jane Sewell,Peninsula Links,Main,2026-06-19 2322-0400,2026-06-19 2323-0400,28,1,,4,3,4,2,3,4,3,3,2
|
||
#+end_src
|
||
|
||
We should add a new app called discgolf that has the following data models:
|
||
|
||
- DiscGolfRound - scrobblable media + course_id, round_type (Singles, Teams)
|
||
- DiscGolfCourse - name, layoutname, number_of_holes
|
||
|
||
And the logdata for a DiscGolfOuting scrobble should have:
|
||
+ {person: {hole_number: score}, total: int}
|
||
+ {team: {name: "", people: [person, person], hole_number: score}, total: int}
|
||
+ weather
|
||
+ fun_factor (miserable, not great, so-so, good, excellent, party time)
|
||
|
||
|
||
* Version 55.6 [1/1]
|
||
** DONE [#A] Figure out why historical Lastfm imports don't work :importers:lastfm:music:
|
||
:PROPERTIES:
|
||
:ID: 71b18c1b-de96-6d93-20fa-de2ec0df1288
|
||
:END:
|
||
|
||
* Version 55.5 [1/1]
|
||
** DONE [#B] Fix bug in lastfm import for new users :importers:lastfm:music:
|
||
:PROPERTIES:
|
||
:ID: d034966d-0c7f-e512-4cf8-7329c9026b6f
|
||
:END:
|
||
|
||
* Version 55.4 [1/1]
|
||
** DONE [#A] Tighten up the speed of startup and first request :perf:
|
||
:PROPERTIES:
|
||
:ID: 9ee8834c-6be2-d04b-df6d-56375504083f
|
||
:END:
|
||
|
||
|
||
* Version 55.3 [3/3]
|
||
** DONE [#C] =alt_names= feature for artists (commented out / dead code) :music:dead-code:
|
||
:PROPERTIES:
|
||
:ID: e22060a2-5f7a-4f33-9056-309ecd27159c
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
File: ~vrobbler/apps/music/models.py~ (line 236)
|
||
|
||
An entire block of code for tracking alternate artist names is commented
|
||
out. The TODO questions whether it even works. Review: either implement
|
||
properly or remove the dead code.
|
||
|
||
** DONE [#A] Put chart rebuilds in a lower priority task queue :charts:tasks:
|
||
:PROPERTIES:
|
||
:ID: 43c90de0-fc1c-1139-dac7-9b7c82006b2e
|
||
:END:
|
||
** DONE [#A] Check for existing book scrobble and update page count :books:scrobbling:
|
||
:PROPERTIES:
|
||
:ID: 1a0609bc-6b16-4da4-96c1-59588229e4b4
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
File: ~vrobbler/apps/scrobbles/scrobblers.py~ (line 330)
|
||
|
||
When scrobbling a book (comic), the code doesn't check for prior scrobbles to
|
||
update reading progress. Needed for proper page-count tracking.
|
||
|
||
|
||
* Version 55.2 [2/2]
|
||
** DONE [#A] Fix bug in scrobble id in calendar view :templates:
|
||
:PROPERTIES:
|
||
:ID: 8cb34852-b18f-e794-cd9b-fb1ecad70a0d
|
||
:END:
|
||
** DONE [#A] Video game cleanup script should clear out broken images :metadata:videogames:
|
||
:PROPERTIES:
|
||
:ID: ca1f1ea9-0f79-082c-5ff7-867671faff4b
|
||
:END:
|
||
|
||
* Version 55.1 [1/1]
|
||
** DONE [#A] Clean up metadata scrapping for video games :metadata:videogames:
|
||
:PROPERTIES:
|
||
:ID: fbc421b5-21a3-4aed-9062-c59192ead065
|
||
:END:
|
||
|
||
* Version 55.0 [3/3]
|
||
** DONE [#B] Use pk ID for scrobble detail view, not uuid :scrobbles:
|
||
:PROPERTIES:
|
||
:ID: 9cc3b285-e478-041e-394b-3d550aefbe1d
|
||
:END:
|
||
** DONE [#B] Display videogame screenshots on scrobble detail if they exist :videogames:templates:
|
||
:PROPERTIES:
|
||
:ID: 0406d082-20f6-0d12-76e2-f281c4801468
|
||
:END:
|
||
** DONE [#B] Add autotagging to webpages based on domain, title :webpages:metadata:
|
||
:PROPERTIES:
|
||
:ID: f658435b-f7a0-42e6-b9f6-226678a77a55
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
For easier filtering, like we do with tasks, we should auto tag WebPage instances
|
||
based on the domain name split part by periods (so news.ycombinator.com tags: news, ycombinator, com)
|
||
|
||
And also based on the nouns in the title.
|
||
|
||
|
||
* Version 54.5 [1/1]
|
||
** DONE Fix bug in generating mood trends :trends:
|
||
:PROPERTIES:
|
||
:ID: 8e75abfa-8e70-d85b-00a4-a4813bbce879
|
||
:END:
|
||
|
||
* Version 54.4 [2/2]
|
||
** DONE [#A] Remove all-time trends :trends:
|
||
:PROPERTIES:
|
||
:ID: 53b231d1-7677-8cd3-1d88-dae110aba1e6
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
All time trends take forever to calculate and don't provide too much data
|
||
|
||
** DONE [#B] Add a trend around moods :moods:trends:
|
||
:PROPERTIES:
|
||
:ID: fba3f4ae-8f97-ee0b-e762-31630884518a
|
||
:END:
|
||
|
||
* Version 54.3 [1/1]
|
||
** DONE [#B] Fix bug in series metadata cleanup script :videos:metadta:
|
||
:PROPERTIES:
|
||
:ID: 85448702-907c-5d63-f5af-7795661d7c46
|
||
:END:
|
||
|
||
* Version 54.2 [4/4]
|
||
** DONE [#B] Add script to clean up TV series metadata :videos:metadata:
|
||
:PROPERTIES:
|
||
:ID: a468b328-59d9-f84b-9ddb-087216783453
|
||
:END:
|
||
** DONE [#A] Update youtube video detail pages with links to channel :videos:templates:
|
||
:PROPERTIES:
|
||
:ID: 8b87cb42-09e5-a3f5-136f-182f967fa81f
|
||
:END:
|
||
** DONE [#A] Concurrent reading trend does not consolidate on single book :trends:reading:
|
||
:PROPERTIES:
|
||
:ID: fe220f55-7e0d-2a17-2477-a5aa7c4a1f2c
|
||
:END:
|
||
** DONE [#B] Trends dont seem to look very far back :trends:
|
||
:PROPERTIES:
|
||
:ID: ffcfba3f-5a93-9ee0-9680-666e6eccd684
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Specificially, looking at reading-pace when run on prod, it claims that I've
|
||
only had one reading session without music. Which may be true, but perhaps we
|
||
need to indicate what the time frame we're looking at is (month, week, year)
|
||
and provide a way to jump back and forward through time, same as charts.
|
||
|
||
|
||
* Version 54.1 [1/1]
|
||
** DONE [#A] Concurrent listening trend is inefficient and should be disabled :trends:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: 4aa3b719-6b22-cae9-85f0-fac67b4fc753
|
||
:END:
|
||
|
||
* Version 54.0 [3/3]
|
||
** DONE [#B] Add peak hour, weekly rhythm and activity dist trends :trends:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: 5fa52fac-d5f0-4369-bcaa-589c886b07d3
|
||
:END:
|
||
|
||
** DONE [#A] Implement YouTube channel info scraping :videos:youtube:stub:
|
||
:PROPERTIES:
|
||
:ID: 1d3beafd-62cb-4735-a465-edb37bf885db
|
||
:END:
|
||
|
||
*** Description
|
||
File: ~vrobbler/apps/videos/models.py~ (line 140)
|
||
|
||
=Video.fix_metadata()= is a stub that logs "Not implemented yet" and returns.
|
||
Needs actual implementation to scrape channel metadata from YouTube.
|
||
|
||
** DONE [#A] Fix Amazon book scraper :amazon:scraper:broken:
|
||
:PROPERTIES:
|
||
:ID: c38aba25-0171-49ab-a9f3-acf2003da429
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
File: ~vrobbler/apps/books/amazon.py~ (line 56)
|
||
|
||
The =scrape_data_from_amazon()= function is likely broken due to Amazon blocking
|
||
scrapers and changing HTML structure. Needs rewrite or replacement with a proper
|
||
API.
|
||
|
||
|
||
* Version 53.1 [1/1]
|
||
** DONE [#A] Error with loading logdict :scrobbles:bug:logdata:
|
||
:PROPERTIES:
|
||
:ID: 92d4fa16-4b90-47e0-95ae-472bdca582ce
|
||
:END:
|
||
|
||
|
||
* Version 53.0 [5/5]
|
||
** DONE [#B] Add a /trends/ page that shows trends based on scrobble data :feature:trends:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: 03e9fe30-2bc6-4062-bb24-e95b98daf05b
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
This project is a bit invovled. But we should add a top level URL `trends` that shows
|
||
various trends as defined either in a static settings file, or dynamically via a database table.
|
||
|
||
Trends could be things like doing multiple things at the same time, like while driving, what
|
||
did we listen to this week, or while running, what were listening to this week?
|
||
|
||
Or more complicated trends like, how time per page changes based on the book I was reading, or if I was doing something else (music or sport event) while reading.
|
||
|
||
** DONE [#B] Notify users when Last.fm import completes :importers:notifications:
|
||
:PROPERTIES:
|
||
:ID: 92846b36-54c5-4b78-9c57-bdc401045fbe
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
After a bulk import from Last.fm, users receive no confirmation. Should add a notification (in-app, email, or similar).
|
||
|
||
File: ~vrobbler/apps/scrobbles/importers/lastfm.py~ (line 96)
|
||
|
||
** DONE [#C] Cleaner =GeoLocationLogData= deserialization :models:refactoring:
|
||
:PROPERTIES:
|
||
:ID: 85465dbf-69b3-48cb-9df0-cd076c4470ab
|
||
:END:
|
||
|
||
*** Description
|
||
Currently special-cases =GeoLocationLogData= by reaching into a nested ="movement_detection"= key. Should be handled at the LogData dataclass level.
|
||
|
||
File: ~vrobbler/apps/scrobbles/models.py~ (line 977)
|
||
|
||
** DONE [#B] Webpage scrobbles should diff existing webpages content :webpages:metadata:
|
||
:PROPERTIES:
|
||
:ID: 25576197-258f-48d6-bfe9-e4172a0a1898
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Webpages change content between scrobbles. The current model stores the webpage content once, the
|
||
first time it's scrobbled. When a page has been seen before, we should move the existing content
|
||
to a new model HistoricalWebPage with the following fields:
|
||
|
||
webpage_id -> FK to WebPage
|
||
date -> date from existing WebPage content
|
||
domain -> same as existing WebPage content
|
||
extract -> copy of existing WebPage content
|
||
|
||
Once the HistoricalWebPage instance is successfully created, the new extract data
|
||
should be saved into the WebPage instance.
|
||
|
||
|
||
** DONE [#B] Make ArchiveBox push asynchronous :archivebox:async:
|
||
:PROPERTIES:
|
||
:ID: 17c116a7-5952-db37-e56c-2987c2fc456b
|
||
:END:
|
||
*** Description
|
||
|
||
=push_to_archivebox()= runs synchronously during the request. Should be moved to a
|
||
Celery task or similar background worker.
|
||
|
||
File: ~vrobbler/apps/webpages/models.py~ (line 133)
|
||
|
||
|
||
* Version 52.2 [1/1]
|
||
** DONE [#A] Fix bug in recomputing long play seconds taking forever :bug:longplay:commands:
|
||
:PROPERTIES:
|
||
:ID: 0a813cf9-17fb-dbd7-b5a7-7410d9bd4d8c
|
||
:END:
|
||
|
||
* Version 52.1 [1/1]
|
||
** DONE [#C] Show time per scrobble in long play lists and total time playing :templates:longplay:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: b3d16230-8ec5-46db-b166-59e98d0ee06c
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Long play time should be show in the table of scrobbles on a media detail page.
|
||
The total time spent in a long play that's either no completed yet or completed
|
||
should be displayed as well. If completed, the date finished should be shown as
|
||
well.
|
||
|
||
|
||
* Version 52.0 [5/5]
|
||
** DONE [#B] Allow marking media as long play complete from detail page :templates:scrobbles:longplay:
|
||
:PROPERTIES:
|
||
:ID: 2c314768-be97-9b10-d13c-9cfd0f38a64e
|
||
:END:
|
||
** DONE [#A] Fix how long play scrobbles are tracked :scrobbles:longplay:serial:
|
||
:PROPERTIES:
|
||
:ID: 908b0493-cabf-40c1-825f-cd59a8ad0f7a
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently we have this idea of "long_play" scrobbles but there's a lot missing
|
||
to tie it together.
|
||
|
||
What we'd prefer is that when a new scrobble is added for a media_type that
|
||
`is_long_play` the most recent scrobble finished is added as the
|
||
`last_serial_scrobble` to the log data. But all the other long play stuff exsits
|
||
as data model fields. We should add `long_play_last_scrobble` as a FK to this
|
||
scrobble when creating a new longplay scrobble.
|
||
|
||
Additionally, `long_play_seconds` we should have a recompute management command
|
||
to walk backward from `long_play_last_scrobble` until a `long_play_complete`
|
||
scrobble is found (exclusive) and save the time.
|
||
|
||
We should also ony use `long_play_complete` field on the scrobble ... some
|
||
logdatas have a similar field, but we should make sure that we always use the
|
||
model field to determine if a long play is finished.
|
||
|
||
This should include a command to clean up long play data to consolidate around
|
||
the `long_play_complete` field.
|
||
|
||
|
||
** DONE [#B] Paginate or limite scrobbles on media admin pages :admin:scrobbles:media:
|
||
:PROPERTIES:
|
||
:ID: f02e487b-d7ed-4834-838a-303560f2ad3b
|
||
:END:
|
||
|
||
** DONE [#B] Clean up books admin :admin:books:bug:
|
||
:PROPERTIES:
|
||
:ID: 7539bee6-0a52-26f6-ebc6-5554ac49a716
|
||
:END:
|
||
** DONE [#B] Clean up favorites admin :admin:favorites:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: f2be0c69-1bf8-b5a3-5269-9c8ea873361d
|
||
:END:
|
||
|
||
|
||
*** Description
|
||
|
||
Some FK lookups in admin should be raw_id_fields.
|
||
|
||
|
||
|
||
* Version 51.4 [1/1]
|
||
** DONE [#A] Clean up metadata comicbook enrichment :bug:comics:books:metadata:
|
||
:PROPERTIES:
|
||
:ID: cd875450-7117-78ca-8be4-9c8b73037dba
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Still getting wonky results with some comicbooks. Would be nice to be able to
|
||
tag a Book as a comicbook, and also gather volume information. I also noticed
|
||
that some books that are found in OL never get their comicvine_id populated. We
|
||
should make sure we always have comicvine_ids if available.
|
||
|
||
|
||
* Version 51.3 [1/1]
|
||
** DONE [#A] Improve speed of index and chart pages :bug:scrobbles:perf:
|
||
:PROPERTIES:
|
||
:ID: 031a23f8-7c02-4926-9884-6654ceca16c2
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Over the last few releases, the home page and charts pages have gotten really
|
||
slow.
|
||
|
||
We should look into what's causing the slowness and maybe do more agressive
|
||
query optimization or caching.
|
||
|
||
|
||
* Version 51.2 [2/2]
|
||
** DONE [#A] Fix bug where last page of book gets separate scrobble :bug:books:importers:koreader:
|
||
:PROPERTIES:
|
||
:ID: e13e0b4c-461e-e5a9-c685-b972f4e262e5
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
The new KoReader code is working great to import books with the correct timezone
|
||
and what-not. But it has a weird artifact of creating one extra scrobble for the
|
||
last page read. Need to button that up.
|
||
|
||
** DONE [#B] Fix metadata scraping for books :books:metadata:
|
||
:PROPERTIES:
|
||
:ID: ea416a69-a8a8-4d05-b7d4-0a3470820e34
|
||
:END:
|
||
|
||
|
||
* Version 51.1 [1/1]
|
||
** DONE [#A] Fix scrobbling comic books :books:scrobbles:bug:
|
||
:PROPERTIES:
|
||
:ID: 8dfbff19-3fa4-f3b8-21c7-7a416498000c
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
At some point logdata and log got confused, and now when you try
|
||
to scrobble a comic book, it just throws errors. We should look
|
||
into where the confusion happened and fix it.
|
||
|
||
|
||
* Version 51.0 [3/3]
|
||
** DONE [#B] Fix koreader scrobble imports to use DST properly :bug:books:imports:
|
||
:PROPERTIES:
|
||
:ID: 79758cba-a440-48b6-a637-efb88827acf2
|
||
:END:
|
||
|
||
- Note taken on [2025-09-25 Thu 10:37] \\
|
||
|
||
This may already be fixed ... need to check.
|
||
|
||
- Note taken on [2025-02-25 12:34] \\
|
||
|
||
The page data has the canonical date something was read in it, but it seems
|
||
to be an hour off. I traced this back to being off during DST, so we just need
|
||
the importer to be aware of whether a user is using DST or not and roll back
|
||
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.
|
||
|
||
|
||
*** Description
|
||
|
||
This is a long-standing problem when daylight saving time takes effect. Time is
|
||
manually set on a KoReader device (or at least, always saved in local time). So
|
||
whatever time KoReader reports, we need to know, given the date and the user
|
||
profile's historic timezone, how many hours to adjust the KoReader time to get
|
||
to GMT to save it in the database.
|
||
|
||
** DONE [#A] Fix book scrobbles where page_data is a list :bug:books:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: 35b323fa-ccc0-4009-b227-8a0f12bbd469
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Comic scrobbling is currently kind of janky. Most of the problems boil down to them
|
||
storing saved page data in a list of dicts rather than a dict keyed off of the page number that
|
||
was read.
|
||
|
||
We need to adjust comic scrobbling to use a dict of pages keyed off the page number, and also
|
||
write a migration script that runs as a data migration to update any book scrobbles that may
|
||
have page_data as a list.
|
||
|
||
*** Example data
|
||
#+begin_src python
|
||
{"notes": null, "page_end": 27, "page_data": [{"notes": null, "end_ts": 1771815895, "duration": 14, "start_ts": 1771815881, "description": null, "page_number": "1"}, {"notes": null, "end_ts": 1771815908, "duration": 13, "start_ts": 1771815895, "description": null, "page_number": "1"}, {"notes": null, "end_ts": 1771815913, "duration": 5, "start_ts": 1771815908, "description": null, "page_number": "2"}, {"notes": null, "end_ts": 1771815933, "duration": 20, "start_ts": 1771815913, "description": null, "page_number": "3"}, {"notes": null, "end_ts": 1771815945, "duration": 12, "start_ts": 1771815933, "description": null, "page_number": "4"}, {"notes": null, "end_ts": 1771815983, "duration": 38, "start_ts": 1771815945, "description": null, "page_number": "5"}, {"notes": null, "end_ts": 1771816007, "duration": 24, "start_ts": 1771815983, "description": null, "page_number": "6"}, {"notes": null, "end_ts": 1771816011, "duration": 4, "start_ts": 1771816007, "description": null, "page_number": "7"}, {"notes": null, "end_ts": 1771816013, "duration": 2, "start_ts": 1771816011, "description": null, "page_number": "8"}, {"notes": null, "end_ts": 1771816052, "duration": 39, "start_ts": 1771816013, "description": null, "page_number": "7"}, {"notes": null, "end_ts": 1771816127, "duration": 75, "start_ts": 1771816052, "description": null, "page_number": "8"}, {"notes": null, "end_ts": 1771816134, "duration": 7, "start_ts": 1771816127, "description": null, "page_number": "9"}, {"notes": null, "end_ts": 1771816196, "duration": 62, "start_ts": 1771816134, "description": null, "page_number": "10"}, {"notes": null, "end_ts": 1771816262, "duration": 66, "start_ts": 1771816196, "description": null, "page_number": "11"}, {"notes": null, "end_ts": 1771816293, "duration": 31, "start_ts": 1771816262, "description": null, "page_number": "12"}, {"notes": null, "end_ts": 1771816322, "duration": 29, "start_ts": 1771816293, "description": null, "page_number": "13"}, {"notes": null, "end_ts": 1771816330, "duration": 8, "start_ts": 1771816322, "description": null, "page_number": "14"}, {"notes": null, "end_ts": 1771816368, "duration": 38, "start_ts": 1771816330, "description": null, "page_number": "15"}, {"notes": null, "end_ts": 1771816388, "duration": 20, "start_ts": 1771816368, "description": null, "page_number": "16"}, {"notes": null, "end_ts": 1771816482, "duration": 94, "start_ts": 1771816388, "description": null, "page_number": "17"}, {"notes": null, "end_ts": 1771816550, "duration": 68, "start_ts": 1771816482, "description": null, "page_number": "18"}, {"notes": null, "end_ts": 1771816567, "duration": 17, "start_ts": 1771816550, "description": null, "page_number": "19"}, {"notes": null, "end_ts": 1771816586, "duration": 19, "start_ts": 1771816567, "description": null, "page_number": "20"}, {"notes": null, "end_ts": 1771816597, "duration": 11, "start_ts": 1771816586, "description": null, "page_number": "21"}, {"notes": null, "end_ts": 1771816616, "duration": 19, "start_ts": 1771816597, "description": null, "page_number": "22"}, {"notes": null, "end_ts": 1771816640, "duration": 24, "start_ts": 1771816616, "description": null, "page_number": "23"}, {"notes": null, "end_ts": 1771816690, "duration": 50, "start_ts": 1771816640, "description": null, "page_number": "24"}, {"notes": null, "end_ts": 1771816702, "duration": 12, "start_ts": 1771816690, "description": null, "page_number": "25"}, {"notes": null, "end_ts": 1771816823, "duration": 121, "start_ts": 1771816702, "description": null, "page_number": "26"}, {"notes": null, "end_ts": null, "duration": null, "start_ts": 1771816823, "description": null, "page_number": "27"}], "page_start": 1, "pages_read": 27, "resume_url": null, "description": null, "koreader_hash": null, "long_play_complete": false}
|
||
|
||
#+end_src
|
||
** DONE [#A] Lichess imports do not set default visbility :boardgames:bug:importers:lichess:
|
||
:PROPERTIES:
|
||
:ID: a78f7c72-a20a-8db2-cde0-d92a731d4fba
|
||
:END:
|
||
|
||
* Version 50.2 [2/2]
|
||
** DONE [#B] Koreader imports only import single-page scrobbles the next day :bug:books:importers:
|
||
:PROPERTIES:
|
||
:ID: b50141fd-cda6-4a3a-afd3-cd8499e7523e
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
When you read a single page in a book in Koreader and try to import it, the scrobble is only
|
||
created the day after, not on the day of the reading.
|
||
|
||
** DONE [#A] Fix bugs in celery tasks causing imports to fail :bug:celery:tasks:
|
||
:PROPERTIES:
|
||
:ID: d1171cb0-6413-44b8-a68a-019a4d2fb285
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Seems like all celery tasks are failing for different reasons except the chart
|
||
updates.
|
||
|
||
*** Errors
|
||
**** scrobbles.tasks.send_notification_for_in_progress
|
||
#+begin_src bash
|
||
KeyError: 'track'
|
||
|
||
During handling of the above exception, another exception occurred:
|
||
|
||
Traceback (most recent call last):
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
|
||
return self.cursor.execute(sql, params)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
psycopg2.errors.UndefinedColumn: column music_track.artist_id does not exist
|
||
LINE 1: ..."."title", "music_track"."base_run_time_seconds", "music_tra...
|
||
^
|
||
HINT: Perhaps you meant to reference the column "music_track.artist_fk_id".
|
||
#+end_src
|
||
|
||
**** scrobbles.tasks.import_from_webdav_all_users
|
||
#+begin_src bash
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/importers/webdav.py", line 166, in scan_webdav_for_koreader
|
||
if last_import and last_import.webdav_etag and remote_etag:
|
||
^^^^^^^^^^^^^^^^^^^^^^^
|
||
AttributeError: 'KoReaderImport' object has no attribute 'webdav_etag'
|
||
#+end_src
|
||
|
||
**** scrobbles.tasks.process_bgstats_import
|
||
#+begin_src bash
|
||
|
||
Traceback (most recent call last):
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
|
||
return self.cursor.execute(sql, params)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
psycopg2.errors.NotNullViolation: null value in column "visibility" of relation "scrobbles_scrobble" violates not-null constraint
|
||
DETAIL: Failing row contains (374463, 2026-06-11 13:27:06.528319+00, 2026-06-11 13:27:06.52834+00, 2026-06-11 13:17:34+00, 180, f, f, BG Stats, 1, null, t, {"players": [{"new": false, "win": false, "rank": 0, "role": "",..., null, null, null, 8e73ceec-b731-4623-9637-712bbf9f76ce, null, null, null, null, , null, BoardGame, 324, null, null, America/New_York, null, null, , null, null, , null, null, null, null, null, null, null, null, null, null, null).
|
||
#+end_src
|
||
|
||
* Version 50.1 [1/1]
|
||
** DONE [#B] Fix bug in charts where only #1 is displayed :charts:templates:
|
||
:PROPERTIES:
|
||
:ID: 7136dffb-e6b7-184b-48ac-bb09bae0b0f0
|
||
:END:
|
||
|
||
* Version 50.0 [2/2]
|
||
** DONE [#A] Allow updating all a user's scrobble visibility at once :scrobbles:sharing:feature:
|
||
:PROPERTIES:
|
||
:ID: 9ed2ec65-bf69-4300-965c-6a7d3ef7ea03
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
We now have the ability to share or unshare scrobbles and create private links.
|
||
We should add a toggle in the user's settings that will bulk make all their
|
||
scrobbles public or private, so that a user can either share everything, or lock
|
||
their account down.
|
||
|
||
This should not affect scrobbles that are in the "Shared" visibility state.
|
||
|
||
And users should be able to also control whether all scrobbles of a specific
|
||
type are shared or not. Maybe this could be a JSONField in profile that contains
|
||
a media_type key with a visibility type for a value, and if it's not present,
|
||
sharing defaults to private?
|
||
|
||
Additionally, users's should have links in their settings to see what scrobbles
|
||
are either public, shared or private. Probably this could be done with a
|
||
?visbility=<> filter on the /scrobbles/ page.
|
||
|
||
*** Changes
|
||
|
||
- Added `media_type_visibility` JSONField to UserProfile (migration 0038)
|
||
- Created `BulkVisibilityView` at `/settings/visibility/` with:
|
||
- Radio toggle to make all non-shared scrobbles Public or Private
|
||
- Per-media-type dropdown for each of the 20 media types (inherit/public/shared/private)
|
||
- Created `BulkVisibilityForm` with dynamic media_type fields
|
||
- Created `profiles/visibility_settings.html` template with visibility stats + filter links
|
||
- Added link from main settings page to visibility settings
|
||
- Added `?visibility=` filter support to `ScrobbleListView` (public/shared/private)
|
||
- Added filter indicator to `scrobble_all_list.html`
|
||
- Updated `Scrobble.create()` to check `user.profile.media_type_visibility` for media-type-specific defaults before falling back to PRIVATE
|
||
|
||
|
||
|
||
** DONE [#A] Replace columsn of Top Artists, Tracks and Series with Maloja widget :templates:charts:
|
||
:PROPERTIES:
|
||
:ID: 3946afb1-932c-46fe-a188-f4c9add1a491
|
||
:END:
|
||
|
||
|
||
*** Description
|
||
|
||
The tables are fine, but Maloja widgets are better. We should drop the top track table, add top albums
|
||
and replace top artists and top tv series with the Maloja style widgets.
|
||
|
||
|
||
* Version 49.1 [1/1]
|
||
** DONE [#A] Fix bug with missing default visbility for scrobbles :bug:scrobbles:sharing:
|
||
:PROPERTIES:
|
||
:ID: 20843992-6453-9a9a-cde6-2c2b6677db23
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
We can't scrobble anything now because visbility is not null, but has no default
|
||
value.
|
||
|
||
*** Notes
|
||
- Note taken on [2026-06-09 Tue 13:14]
|
||
The full stack trace:
|
||
#+begin_src sh
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/models.py", line 1430, in create_or_update
|
||
elif "log" in scrobble_data.keys() and scrobble.log:
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/models.py", line 1583, in create
|
||
)
|
||
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
|
||
return getattr(self.get_queryset(), name)(*args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 658, in create
|
||
obj.save(force_insert=True, using=self.db)
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/models.py", line 870, in save
|
||
if self.media_obj:
|
||
^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django_extensions/db/models.py", line 22, in save
|
||
super().save(**kwargs)
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 814, in save
|
||
self.save_base(
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 877, in save_base
|
||
updated = self._save_table(
|
||
^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 1020, in _save_table
|
||
results = self._do_insert(
|
||
^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 1061, in _do_insert
|
||
return manager._insert(
|
||
^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
|
||
return getattr(self.get_queryset(), name)(*args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 1805, in _insert
|
||
return query.get_compiler(using=using).execute_sql(returning_fields)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1822, in execute_sql
|
||
cursor.execute(sql, params)
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 67, in execute
|
||
return self._execute_with_wrappers(
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
|
||
return executor(sql, params, many, context)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 84, in _execute
|
||
with self.db.wrap_database_errors:
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/utils.py", line 91, in __exit__
|
||
raise dj_exc_value.with_traceback(traceback) from exc_value
|
||
File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
|
||
return self.cursor.execute(sql, params)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
django.db.utils.IntegrityError: null value in column "visibility" of relation "scrobbles_scrobble" violates not-null constraint
|
||
DETAIL: Failing row contains (373813, 2026-06-09 17:13:38.11355+00, 2026-06-09 17:13:38.113566+00, 2026-06-09 17:13:36+00, 0, f, f, Todoist, 1, null, t, {"title": "Animal chores", "labels": ["chore", "farm"], "todoist..., null, null, null, 68680dbf-f9a9-476c-b1c7-adbd231bbab6, null, null, null, null, , null, Task, null, null, null, America/New_York, null, null, , null, null, , 72, null, null, null, null, null, null, null, null, null, null).
|
||
#+end_src
|
||
|
||
* Version 49.0 [1/1]
|
||
** DONE [#A] Fix broken tests with new sharing and add tests :scrobbles:sharing:tests:
|
||
:PROPERTIES:
|
||
:ID: 10ecd169-eaee-8554-d4ee-f1d34bfad99f
|
||
:END:
|
||
|
||
* Version 48.3 [1/1]
|
||
** DONE [#A] Fix bug in missing sqids dep :dependencies:project:
|
||
:PROPERTIES:
|
||
:ID: 0b619837-729a-cd74-7a97-6fa2a148b27d
|
||
:END:
|
||
|
||
* Version 48.2 [1/1]
|
||
** DONE [#A] Lock down scrobbles and use sqids to share them :feature:sharing:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: a6e869f7-8012-7e83-8f68-d0a0ed4c3c6a
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently all scrobbles are public. Anyone with the uuid can view any other
|
||
scrobbles. We should use SQIDs to allow shareable links to scrobbles and then
|
||
make all scrobbles hidden by default.
|
||
|
||
|
||
* Version 48.1 [2/2]
|
||
** DONE [#A] Generate a report of tracks with mistmatched metadata :music:tracks:metadata:
|
||
:PROPERTIES:
|
||
:ID: 684b8cd2-a3c1-4995-ba9e-7abdb02c37f2
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
We should have a management command that outputs a CSV file of track IDs where
|
||
the log["raw_data"]["Artist"] (for Jellyfin) or log["raw_data"]["artist"]
|
||
(mopidy) value does not match the Track.artists names.
|
||
|
||
And we should see the same thing for albums (log["raw_data"]["Album"] or
|
||
log["raw_data]["album"]).
|
||
|
||
It should output the fields "track_id", "track_artist_name", "track_album_name",
|
||
"raw_artist", "raw_album", "source"
|
||
|
||
Where source is either Jellyfin or Mopidy based on the keys.
|
||
|
||
Put the file /tmp/metadata-report.csv by default and overwrite exsiting reports.
|
||
|
||
The command should also accept a file-path to overide this default.
|
||
|
||
|
||
** DONE [#A] Date parsing failing in eBird imports :birds:ebird:importers:
|
||
:PROPERTIES:
|
||
:ID: 72e0254f-39d8-4843-9857-623e0362d77e
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
On line 45 in the apps/birds/importer.py file, the import is thorowing this
|
||
error:
|
||
|
||
#+begin_src python
|
||
ValueError: time data 'Jun 7, 2026, 5:15 PM' does not match format '%B %d, %Y %I:%M %p'
|
||
#+end_src
|
||
|
||
Historically other files starting on May 24 worked, so I suspect this is a
|
||
problem of the date formatter expecting Long month names and zero-padded days
|
||
and the only sample we had was a three-letter month (May) and days with two
|
||
digites(24 through the 31)
|
||
|
||
We should also add a "error_log" to the importers so that errors tha occur are
|
||
surfaced, even when 0 successful files were processed. And we should make sure
|
||
all importers do this as well.
|
||
|
||
|
||
|
||
* Version 48.0 [2/2]
|
||
** DONE [#B] Show team or player images on sport detail and scrobble detail :sports:templates:
|
||
:PROPERTIES:
|
||
:ID: 68c17383-ee6e-4b5f-b3f5-1b637a0a3ea8
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
On the sport event detail page, we should show the images of the teams or
|
||
players invovled.
|
||
|
||
Also, those images for the sport event should be shown on the scrobble detail
|
||
page for sport event scrobble details.
|
||
|
||
** DONE [#B] Add fix_metadta method to Video instances :videos:metadata:
|
||
:PROPERTIES:
|
||
:ID: 9df5404d-1b60-4eee-b7cf-1f7e6dfade65
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Turns out we don't have a fix_metadata method for videos. We should add that using
|
||
the basic logic from find_or_create on the Video model.
|
||
|
||
|
||
* Version 47.2 [1/1]
|
||
** DONE [#B] Add OMDB source as backup when TMDB returns nothing :videos:metadata:imdb:
|
||
:PROPERTIES:
|
||
:ID: 20195445-7fdd-49be-9767-103b12da0bfb
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
TMDb works great for most cases. There are some edge cases, though where it does
|
||
not import videos, when TV shows are split up differently in TMDb than in IMDB.
|
||
One example I stumbled on is the 2020 reboot of Animaniacs. TMDb splits the
|
||
epiodes up in three parts, while they were always broadcast three-in-one, and
|
||
that's how IMDB lists them. Thus, the IMDB ID means nothing, and the videos end
|
||
up unenriched.
|
||
|
||
|
||
* Version 47.1 [1/1]
|
||
** DONE [#A] Untangle the sports migrations errors :sports:bug:migrations:
|
||
:PROPERTIES:
|
||
:ID: 4d50ca2e-f45b-dde8-e3c9-cd84f353b349
|
||
:END:
|
||
|
||
|
||
* Version 47.0 [1/1]
|
||
** DONE [#B] Change sports scrobbling a bit :feature:sports:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: cd27d683-c847-4251-b3d1-8243f45c01ca
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently, the way we scrobble sports means that basically the same event will
|
||
never be scrobbled again. I will likely never watch the 2025 Monaco Grand Prix
|
||
again, but I will watch the Monaco Grand Prix again. But I also wont watch one
|
||
specific game between Arsenal and Man City twice, but I may watch those two
|
||
teams play multiple times.
|
||
|
||
What if instead of scrobbling a specific sports event on a specific date, we
|
||
make the unique Scrobblable item the players or teams in the event?
|
||
|
||
That would not work for races where the unique item would have to be the name of
|
||
the event.
|
||
|
||
Maybe that means SportEvent is too generic, and we'd need the event type to be
|
||
scrobble items.
|
||
|
||
A race, the Indy 500 or Coke 600, or Boston Marathon would be scrobblable, while
|
||
for games, the teams would be unique, so a game between Arsenal and Man City
|
||
would be unique (with extra logdata context for who's home and who's away, and
|
||
the location, could even have the weather per scrobble).
|
||
|
||
And finally, for Tennis, the title would be the round of the event, Roland
|
||
Garros Women's Semifinal, US Open Men's Final, Miami Invitational Round of 32,
|
||
with two players, or two teams and a start datetime, which is similar to what we
|
||
have now. The round becomes not a foreign key, but just a string, and we'd need
|
||
a FK to an organizer field which would replace league, and would be like "ATP
|
||
Tour" or "PGA Tour". Season would also need to be a string, and would be
|
||
something like: 2026 or 2024-2025.
|
||
|
||
Examples:
|
||
- Super Bowl
|
||
- Sochaux v Concarneau
|
||
- French Open Final
|
||
- Carlos Alcaraz v Jannik Sinner
|
||
|
||
We'd also want a script to reorganize existing sports events and move scrobbles
|
||
to the right place as best as we're able, and to flag sportsevents and scrobbles
|
||
that could not automatically be migrated with a unique tag like
|
||
"migration-failed"
|
||
|
||
Ultimately I think what we need is to greatly simplify the SportEvent to be just a placeholder
|
||
for a sport event type for a given league, then each scrobble holds the details of teams, players
|
||
start, thesportsdb_id, round and season.
|
||
|
||
Thus, I've already simplified that model, but what we need is a migration script that will move
|
||
existing complex SportEvent instances into very basic ones, and updating any scrobbles for those
|
||
events with a new SportEventLogData structure with all the specific details in it. We also need to
|
||
move the obj.round.season.league into the FK for the given event.
|
||
|
||
|
||
|
||
* Version 46.0 [1/1]
|
||
** DONE [#C] Add sentiment parsing for Scrobbles with notes :scrobbles:sentiment:
|
||
:PROPERTIES:
|
||
:ID: 37781d6a-f3b0-48b2-bf98-33c2c791cf85
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Not sure how useful this would be, but I wonder if we can add a `sentiment` JSONField
|
||
on each scrobble that can store the output of VADER over the notes in a scrobble with notes.
|
||
|
||
I'm not sure that the value prop here is worth the storage and processing time.
|
||
|
||
But if we do add it, it should be a process that scans for scrobbles with both notes and no
|
||
sentiment field value (unless --overwrite is used) and just run periodically.
|
||
|
||
|
||
* Version 45.1 [1/1]
|
||
** DONE [#B] Mopidy favorites or monthly playlist adds should look at all scrobbles :bug:mopidy:favorites:tracks:
|
||
:PROPERTIES:
|
||
:ID: 0be7d11e-e268-2fd5-836a-e5b4d210e0fa
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
When favoriting a track and trying to add it to the Moidy favorite playlist, it
|
||
sometimes happens that one scrobble did not come from Mopidy, but an earlier or
|
||
later one did.
|
||
|
||
Can we scan all the scrobbles of the track for a given user to see if any have
|
||
`mopidy_uri` in the log and if so, use that to send along to Mopidy?
|
||
|
||
|
||
* Version 45.0 [1/1]
|
||
** DONE [#B] Add ability to add mopidy tracks to Monthly playlists :feature:favorites:tracks:
|
||
:PROPERTIES:
|
||
:ID: c872ff0a-e71f-415f-b5a6-e62ea9634d14
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Now that we can favorite a mopidy track and have it added to a Favorites playlist, it would
|
||
be great if we could also populate a monthly_mopidy_playlist_pattern in a user profile and,
|
||
if configured, you could press "Add to monthly playlist" button on a given track that has
|
||
a mopidy_uri in it's log, and it would be added to the playlist.
|
||
|
||
The patterns would be based on traditional Django date formatting patterns: https://gregbrown.co/code/date-format
|
||
|
||
So "Y m F" would yield "2026 05 May" if the link is clicked in May of 2026.
|
||
|
||
|
||
* Version 44.0 [1/1]
|
||
** DONE [#B] Add favorite feature for scrobbles :feature:favorites:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: 2780ae5f-fe23-49a5-8b33-d19e7f3e8ec6
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Would be great to have a FavoriteMedia data model that would accept any media_type ID and a user_id
|
||
marking that media as a favorite for that user.
|
||
|
||
Additionally, for tracks, we should add the ability to set a "favorites_mopidy_playlist" in a user profile
|
||
and if populated, and a track media type is favorited, and the track has a mopidy_uri value in a scrobble log,
|
||
send a POST to the mopidy server RPC endpoint for the favorite playlist and add the track.
|
||
|
||
|
||
|
||
* Version 43.0 [5/5]
|
||
** DONE [#B] Can we show a graph of all past Weigh-in tasks :scale:tasks:graphs:javascript:
|
||
:PROPERTIES:
|
||
:ID: ae499d87-03bf-4e48-9b2c-1a421a46af11
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
I wonder if, as a special type of task, Weigh-in's could show a graph of the
|
||
metrics that are stored against all the past weigh-ins?
|
||
|
||
The graph would contain all Weigh-in scrobbles for that user, no matter which
|
||
date is being viewed, and the highlighted value on the graph would be the date
|
||
being viewed.
|
||
|
||
Probably could use something like chart.js although maybe that's too heavy?
|
||
|
||
And can we have each metric overlayed on the same graph?
|
||
|
||
** DONE [#B] When viewing scrobbles by tag, sum the total time :scrobbles:tags:
|
||
:PROPERTIES:
|
||
:ID: d51f23df-c2c5-4e1a-b000-67c89032af02
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
On scrobbles filtered by tags, we should see a sum of the time spent doing those tasks, in a human
|
||
readable format like "X days, X hours, X minutes and X seconds"
|
||
|
||
** DONE [#A] Orgmode tasks are not updated if in progress :tasks:orgmode:bug:
|
||
:PROPERTIES:
|
||
:ID: 7dcebb2c-7c4c-4ac5-bee6-c2e36c3811f9
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently if you POST to the orgmode webhook with a task that's already in progress, the request just stops there.
|
||
|
||
We should add logic where if the task is in-progress, instead of doing nothing,
|
||
it checks the webhook payload against the in-progress tasks and updates the
|
||
description of the scrobble.log with the incoming task description if it's
|
||
different. And the same for comments. If a comment (by timestamp key) is
|
||
different in the webhook than what's in the scrobble.log, update the comment in
|
||
the scrobble.log
|
||
|
||
** DONE [#A] Ignore tag 'inprogress' for Tasks :bug:tasks:tags:
|
||
:PROPERTIES:
|
||
:ID: cd37c1ec-e2fc-b93c-daf8-6b329712c3f1
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
When scrobbling tasks from Todoist, the tag `inprogress` is always in the
|
||
payload, because that's how we parse tasks starting from the Todoist webhooks.
|
||
|
||
But we don't really need anything tagged as `inprogress` Can we ignore this tag
|
||
when applying tags to Task scrobbles coming from Todoist?`
|
||
|
||
|
||
|
||
** DONE [#A] Deploys are now throwing an unknown version error :bug:tooling:releases:
|
||
:PROPERTIES:
|
||
:ID: 3870f9d3-b5ed-4b87-9e8c-9bf905bfb766
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Almost everything is working, but for some reason `__version__` does not seem to
|
||
exist.
|
||
|
||
#+begin_src sh
|
||
out: Installing collected packages: vrobbler
|
||
out: Successfully installed vrobbler-42.0
|
||
err: WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
|
||
err: Traceback (most recent call last):
|
||
err: File "<string>", line 1, in <module>
|
||
err: AttributeError: module 'vrobbler' has no attribute '__version__'
|
||
2026/06/04 17:18:15 Process exited with status 1
|
||
failed to remove container: Error response from daemon: removal of container c8ac64bee9b6bf5978d2c16f299e5ac271d8bbf7192b7a4023c3712bc2444f8b is already in progress
|
||
❌ Failure - Main Install wheel and restart services
|
||
exit with `FAILURE`: 1
|
||
#+end_src
|
||
|
||
|
||
* Version 42.0 [1/1]
|
||
** DONE [#B] Add ability to add track to current Mopidy queue :feature:mopidy:tracks:
|
||
:PROPERTIES:
|
||
:ID: 79d5b580-4ea6-461b-4c6c-2c950d8b3e4c
|
||
:END:
|
||
|
||
|
||
* Version 41.0 [5/5]
|
||
** DONE [#B] For any scrobble detail page with notes display them better :templates:notes:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: c0dcf9da-227f-4a22-bcd9-9d46053607d9
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently notes are displayed as little post-it notes. This is cute, but not terribly useful.
|
||
|
||
We should update note rendering to be a simple newest to oldest display in a
|
||
single column with the timestamp has a small header, and the content rendered as
|
||
markdown with a small bar or horizontal divider marking them from the next note.
|
||
|
||
** DONE [#A] Imports should send notifications :feature:notifications:imports:
|
||
:PROPERTIES:
|
||
:ID: 6f78f8d5-ecaa-4d8a-a666-ae4e27653191
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently importing board games sends out a ntfy message when a scrobble is
|
||
created.
|
||
|
||
We should do the same thing for other import types; namely: gpx, ebird, and scale.
|
||
|
||
** DONE [#A] Board game imports send duplicate ntfy message :bug:notifications:boardgames:
|
||
:PROPERTIES:
|
||
:ID: 8f067432-0399-4b79-9e93-727edcccedbd
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
When a board game scrobble is created via a bgstats import, ntfy messages are
|
||
sent.
|
||
|
||
But right now they are duplicated (two are sent at the same time). Can we review
|
||
the code to see why this is happening and fix it?
|
||
|
||
** DONE [#A] Too many geolocation notifications go out :bug:notifications:geolocations:
|
||
:PROPERTIES:
|
||
:ID: 6357ad7a-fe4e-49dd-a063-55d87e459c17
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently ntfy gets overwhelemed when there's more than a hundred or so messages left in a queue on a client.
|
||
|
||
It would be nice if we could not spam ntfy, and this is especially true with Geolocations, where we really
|
||
don't need to alert folks unless they have a named Geolocation (has a title). Can we adjust the ntfy
|
||
sending for Geolocations to only send if the scrobbled location has a title?
|
||
|
||
|
||
** DONE [#C] Fix bug where Weigh-in imports do not set title :bug:tasks:scale:
|
||
:PROPERTIES:
|
||
:ID: 622e354a-8e66-4ecd-9e1c-a53f0a2ec362
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently when we import a scale CSV row and create data, the title is left
|
||
blank which makes it look funny in a list view. Let's save the weight as the
|
||
title of the Weigh-in task.
|
||
|
||
|
||
* Version 40.2 [1/1]
|
||
** DONE [#A] Try fixing deploy bugs again :tooling:releases:bug:
|
||
:PROPERTIES:
|
||
:ID: 15894943-be1d-200f-8400-a136770ad9d2
|
||
:END:
|
||
|
||
|
||
* Version 40.1 [2/2]
|
||
** DONE [#A] Releases are still broken :bug:releases:tooling:
|
||
:PROPERTIES:
|
||
:ID: bca37a18-afa2-4ddd-a11b-ef0555f38bc9
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Deploys are still broken, even with them being pulled apart and run separately.
|
||
|
||
We need to address the way the commit ends up stashed in the codebase.
|
||
|
||
** DONE [#C] Fix bug on chart pages where trail titles missing :bug:trails:charts:
|
||
:PROPERTIES:
|
||
:ID: 21075430-8a93-4e59-9a02-479315960ae6
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
When trails are rendered on the chart views, there are no titles, which means we don't see
|
||
anything except the ranking number.
|
||
|
||
|
||
* Version 40.0 [2/2]
|
||
** DONE [#A] Fix error in org-mode task sync :emacs:orgmode:tasks:bug:
|
||
:PROPERTIES:
|
||
:ID: 03256d2a-48aa-4be7-aeb3-fa1cfddc86bf
|
||
:END:
|
||
|
||
*** Description
|
||
#+begin_src python
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/tasks/webhooks.py", line 236, in post
|
||
emacs_scrobble_update_task(
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/scrobblers.py", line 844, in emacs_scrobble_update_task
|
||
for note in emacs_notes:
|
||
TypeError: 'NoneType' object is not iterable
|
||
#+end_src
|
||
** DONE [#B] Adjust how similar artists are shown :feature:templates:artists:music:
|
||
:PROPERTIES:
|
||
:ID: 2a081620-a0a2-4851-a7cf-4043f9c2ee31
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Currently we show the top 10 similar artists on the Artist detail page linked to
|
||
the artist detail page on Vrobbler.
|
||
|
||
First off, this is very slow. We should look into speeding up the rendering of
|
||
the similar artists widget.
|
||
|
||
Second, the artist name in the similar artist list should be a link to the
|
||
Vrobbler artist detail page, but there should also be a [musicbrainz] link next
|
||
to it, that links out to the musicbrainz page whether we have the artist in the
|
||
Vrobbler database or not.
|
||
|
||
|
||
|
||
* Version 39.3 [2/2]
|
||
** DONE [#A] Issue found when doing a release :bug:tooling:release:cicd:
|
||
:PROPERTIES:
|
||
:ID: a8fc3ec9-74ec-4190-8ac2-62cd8a33e828
|
||
:END:
|
||
|
||
*** Description
|
||
#+begin_src sh
|
||
err: ERROR: Cannot install vrobbler 0.16.1 (from /var/lib/vrobbler/dist/vrobbler-0.16.1-py3-none-any.whl) and vrobbler 38.0 (from /var/lib/vrobbler/dist/vrobbler-38.0-py3-none-any.whl) because these package versions have conflicting dependencies.
|
||
out: The conflict is caused by:
|
||
out: The user requested vrobbler 0.16.1 (from /var/lib/vrobbler/dist/vrobbler-0.16.1-py3-none-any.whl)
|
||
out: The user requested vrobbler 38.0 (from /var/lib/vrobbler/dist/vrobbler-38.0-py3-none-any.whl)
|
||
out: To fix this you could try to:
|
||
out: 1. loosen the range of package versions you've specified
|
||
out: 2. remove package versions to allow pip attempt to solve the dependency conflict
|
||
err: ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts
|
||
2026/06/01 14:15:00 Process exited with status 1
|
||
failed to remove container: Error response from daemon: removal of container 3fe0eaf032c5518aca4ab71734b52bda7c54ed406136b82136ab7155bf5ff3c1 is already in progress
|
||
#+end_src
|
||
|
||
** DONE [#A] Fix deploy actions running twice :bug:tooling:cicd:
|
||
:PROPERTIES:
|
||
:ID: aa56f2a6-2b61-4ddf-9e27-9eadcddf8412
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Turns out we're now running the build-deploy action twice, once on branch push
|
||
and once on tag push.
|
||
|
||
We should do builds on each push and build and deploys only when a new tag is
|
||
detected.
|
||
|
||
|
||
* Version 39.2 [2/2]
|
||
** DONE [#B] Releases do not pin commit to the repo for display :bug:tooling:releases:
|
||
:PROPERTIES:
|
||
:ID: 2a9f2ff5-2642-47ab-ba1d-e41825411713
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Somewhere in implementing the justfile release flow, we lost the capture of the
|
||
latest commit in the relesae flow so the footer now always says: vXX.x (unknown)
|
||
|
||
It should have the first bit of the commit in the parens at the end.
|
||
|
||
** DONE [#B] Fix the way timestamps are stored for notes on tasks :bug:scrobbles:tasks:
|
||
:PROPERTIES:
|
||
:ID: 32973bb3-079b-8cdf-6495-82f8ae907299
|
||
:END:
|
||
|
||
*** Description
|
||
:PROPERTIES:
|
||
:ID: d833a3df-6eb2-36bb-1863-e438e5d36151
|
||
:END:
|
||
|
||
Turns out Todoist uses a human-readable timestamp format for comments. We should
|
||
adapt that for use from org-mode as well.
|
||
|
||
Format should be: "%Y-%m-%dT%H:%M:%S.%fZ"
|
||
|
||
|
||
* Version 39.1 [1/1]
|
||
** DONE [#A] Fix bug in tests for notes saving :bug:scrobbles:forms:
|
||
:PROPERTIES:
|
||
:ID: 68a011b2-bb6f-3ba8-2312-5947c41db9ac
|
||
:END:
|
||
|
||
|
||
* Version 39.0 [3/3]
|
||
** DONE [#B] Clean up org-mode tasks metadata :bug:tasks:metadata:
|
||
:PROPERTIES:
|
||
:ID: 0c762d09-fc69-4e75-be40-7eaaf04f178e
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Org-mode tasks have a `Description` subheader, which should populate the
|
||
"Description" of a task.
|
||
|
||
The title should come from the actual TODO content, with tags coming from the
|
||
tags in colons after the task. This behaviour should already work.
|
||
|
||
Next, any comments should go under a `Comments` subheader. Under these should be a list tag like:
|
||
|
||
"Note taken on [2026-05-31 Sun 20:03]"
|
||
|
||
Which declares it's a note with a timestamp like "YYYY-MM-DD d HH:MM".
|
||
|
||
When scrobbling a task from org-mode, the description should always be copied to
|
||
the scrobble's log["description"].
|
||
|
||
Any comments that exist on the task when the scrobble is first created, should
|
||
be ignored.
|
||
|
||
Any comments on a task that is updated (a re-POST'd while the task is in
|
||
progress, should add a comment in the log["notes"], a dictionary, keyed off the
|
||
timestamp the note string. If a note for that datetime already exists, the
|
||
content should be replaced with the new comment.
|
||
|
||
Additionally, when a task is re-POST'd while the task is in progress, the
|
||
description should also be compared, and if different, the newest description
|
||
should be used.
|
||
|
||
Note, the biggest change for this flow is making sure comments that already
|
||
exist are not added to any new tasks and that both comments and descriptions are
|
||
added or updated if the new values are different than what is already in the
|
||
currently in-progress task.
|
||
|
||
If the task is completed, don't touch it.
|
||
|
||
*** Comments
|
||
- Note taken on [2026-05-31 Sun 20:03]
|
||
|
||
** DONE [#A] Actually push branches up and add a just command to do it :release:justfile:tooling:
|
||
:PROPERTIES:
|
||
:ID: 50aa5daa-a802-6aa9-38a3-218b7a9d4b34
|
||
:END:
|
||
** DONE [#A] Try to fix deploy failing with bad release plan :release:tooling:pyproject:
|
||
:PROPERTIES:
|
||
:ID: 63dc633c-4382-e6a5-e663-b01871ce86ce
|
||
:END:
|
||
|
||
|
||
* Version 38.0 [38/38]
|
||
** DONE [#A] Fix release flow to be easier to trigger :pyproject:release:tooling:
|
||
:PROPERTIES:
|
||
:ID: e321f8a3-26ea-b316-8493-294b50c0b516
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
We should have a command like `just relesae <major|minor>` that can cut new
|
||
releases on command by updating the PROJECT.org file with a release header for
|
||
all DONE tasks and creating the appropriate release commits and tags based on
|
||
either the new release version type.
|
||
|
||
It should also update the pyproject file.
|
||
|
||
** DONE [#A] Move imported retroarch lrtl files to processed/ directory on WebDAV :webdav:retroarch:importers:
|
||
:PROPERTIES:
|
||
:ID: 881b5af6-e96f-4e71-9e66-2d30824e5504
|
||
:END:
|
||
|
||
- File: ~vrobbler/apps/scrobbles/importers/webdav.py~ (line 439)
|
||
- Same pattern as the GPX importer: after importing a =.csv= file from
|
||
WebDAV, move it to =var/retroarch/processed/= with a timestamp appended.
|
||
|
||
** DONE [#A] Add listenbrainz support for similar tracks :feature:music:metadata:
|
||
:PROPERTIES:
|
||
:ID: a3abba14-7603-db51-58e1-1941a47fa35e
|
||
:END:
|
||
** DONE [#B] Consolidate albums in the same musicbrainz_releasegroup_id :music:albums:metadata:
|
||
:PROPERTIES:
|
||
:ID: 6b331bdb-1516-bb86-7cb3-8cb9e3de59ce
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
When we look up albums, we should check if one already exists with the same
|
||
musicbrainz_releasegroup_id and prefer that one, rather than creating a new
|
||
album.
|
||
|
||
Also, we should create a data migration to clean up albums with matching
|
||
musicbrainz_releasegroup_id fields by consolidating tracks around the first
|
||
album found.
|
||
|
||
Whether the track was enriched by musicbrainz or not, the track should get
|
||
tagged with `musicbrainz_enriched` or `musicbrainz_notfound`
|
||
|
||
** DONE [#A] Clean up metadata on music tracks :music:tracks:metadata:musicbrainz:
|
||
:PROPERTIES:
|
||
:ID: 3a007bd7-b901-43cb-892e-102d39fffc85
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
There's a over 3K tracks without a musicbrainz_id and almost 30K without a
|
||
base_run_time_seconds. We should have a clean up script that can run through the
|
||
ones missing musicbrainz_ids and see about getting metadata from musicbrainz and
|
||
for the 30K without base_run_time_seconds, check with their musicbrainz_ids to
|
||
see if we can look up the track length, and if not, tag the track with
|
||
"missing-metadata" tag.
|
||
|
||
Also, if the tracks without musicbrainz_ids actually are not in the MB database,
|
||
we should tag those with "not-in-musicbrainz"
|
||
|
||
And a big part of this work will probably involve checking for "Various Artists"
|
||
tracks where the track erroneously got set with a generic artist. In those
|
||
cases, we should try just looking up by track title.
|
||
|
||
** DONE [#B] Make artists_m2m field source of artist truth for albums :music:bug:albums:
|
||
:PROPERTIES:
|
||
:ID: 05a24455-0e71-45ef-ac6e-c1b7b843047d
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Albums have an FK for album_artist, but like artists, the M2M should be the
|
||
source of truth. We should migrate all uses of album_artist to an `artist`
|
||
property on the Album model and use a data migration to populate artists with
|
||
the album_artist value.
|
||
|
||
** DONE [#A] Fix various artist album problem with Superwolves (track with multiple artists) :vrobbler:project:music:bug:artists:
|
||
:PROPERTIES:
|
||
:ID: 590bc038-745f-710b-8272-4d8a3d2efa01
|
||
:END:
|
||
|
||
*** Description
|
||
We have an issue with tracks where there are two artists, like `Matt Sweeney &
|
||
Bonnie "Prince" Billy`
|
||
|
||
I think we need to allow creating a single artist with both names, so the Artist
|
||
is the full name. That said, the ampersand is usually used to split feature
|
||
artsits (I think) so I'm not sure how this would work reliably.
|
||
|
||
Also, it's possible musicbrainz does not have dual artist listings. So it's
|
||
possible the longer term solution is to allow multiple artists per track the way
|
||
we now allow tracks to be on multiple albums. We could deprecate the Artist FK
|
||
or at least make it optional, and then require a M2M between Track and Artist.
|
||
|
||
Then this one would be a Track by both `Matt Sweeney` and `Bonnie "Prince"
|
||
Billy`
|
||
|
||
** DONE [#A] Move imported eBird CSV files to processed/ directory on WebDAV :webdav:ebird:importers:
|
||
:PROPERTIES:
|
||
:ID: 445e1253-d353-4b55-b1d8-39d0a0dcdd34
|
||
:END:
|
||
|
||
- File: ~vrobbler/apps/scrobbles/importers/webdav.py~ (line 439)
|
||
- Same pattern as the GPX importer: after importing a =.csv= file from
|
||
WebDAV, move it to =var/ebird/processed/= with a timestamp appended.
|
||
|
||
** DONE [#A] Move imported Board Game CSV files to processed/ directory on WebDAV :webdav:boardgames:importers:
|
||
:PROPERTIES:
|
||
:ID: a3f8d30c-d2c3-4ee7-b062-f0f16bd9b0b4
|
||
:END:
|
||
|
||
- File: ~vrobbler/apps/scrobbles/importers/webdav.py~ (line 496)
|
||
- Same pattern as the GPX importer: after importing a =.csv= file from
|
||
WebDAV, move it to =var/bgstats/processed/= with a timestamp appended.
|
||
|
||
** DONE [#A] Move imported Scale CSV files to processed/ directory on WebDAV :webdav:scale:importers:
|
||
:PROPERTIES:
|
||
:ID: 1a0de363-d1ea-466e-9966-e24941a6180b
|
||
:END:
|
||
- File: ~vrobbler/apps/scrobbles/importers/webdav.py~ (line 496)
|
||
- Same pattern as the GPX importer: after importing a =.csv= file from
|
||
WebDAV, move it to =var/scale/processed/= with a timestamp appended.
|
||
|
||
** DONE [#A] Allow special parameter to re-import already processed GPX files :imports:gpx:
|
||
:PROPERTIES:
|
||
:ID: 166c0809-c11a-4d02-8071-7a69dcb36e64
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Now that we stash imported GPX files in the processed/ subdirectory on import,
|
||
it would be nice to have a flag like --include-processed on the webdav importer
|
||
that would import files both in the root of gpx/ and also in the processed
|
||
directory. This would aide testing imports in staging quickly without constantly
|
||
moving files back and forth.
|
||
|
||
** DONE [#A] Move imported GPX files to processed/ directory on WebDAV :webdav:gpx:importers:
|
||
:PROPERTIES:
|
||
:ID: db2b02fc-817c-4c39-bd51-13f9b77c7888
|
||
:END:
|
||
- File: ~vrobbler/apps/scrobbles/importers/webdav.py~ (line 198)
|
||
- After importing a GPX/FIT file from WebDAV, move it to a =processed/=
|
||
subdirectory with a timestamp appended. This eliminates the DB lookup for
|
||
already-imported filenames — any file present in the top-level directory
|
||
is new. Also makes manual re-imports easy (just move a file back).
|
||
|
||
** DONE [#A] Add CSS Grid calendar view for scrobbles :vrobbler:personal:project:templates:feature:
|
||
:PROPERTIES:
|
||
:ID: be915acf-d803-466a-8770-823819ebf2a9
|
||
:END:
|
||
|
||
*** Description
|
||
|
||
Calendar view at /scrobbles/calendar/ showing select media types (Tasks,
|
||
Birding, Food, Trails, VideoGames, Books) in a CSS Grid month layout.
|
||
|
||
- Emoji badges per scrobble on each day cell, hover reveals title
|
||
- Click emoji to navigate to scrobble detail
|
||
- Prev/Next month navigation
|
||
- Based on the CodePen CSS Grid calendar pattern:
|
||
https://codepen.io/oliviale/pen/QYqybo
|
||
|
||
** DONE [#C] Come up with a possible flow using WebDAV and super-productivity for tasks :personal:feature:project:vrobbler:tasks:
|
||
:PROPERTIES:
|
||
:ID: dd751edf-6192-2ed0-cd85-905f423f82b0
|
||
:END:
|
||
** DONE [#B] Fix PuzzleLogData has no attribute form :vrobbler:puzzles:personal:project:logdata:
|
||
:PROPERTIES:
|
||
:ID: cb8e697a-9fc2-c463-5d4d-fa15d3e833a0
|
||
:END:
|
||
** DONE [#B] Add PuzzleLogData class with with_people and completed :vrobbler:feature:puzzles:logdata:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 1b38c8a8-86d3-b73d-c584-dfb0497970dc
|
||
:END:
|
||
** DONE Add weather lookup to the mood check-in flow :vrobbler:project:moods:feature:checkin:
|
||
:PROPERTIES:
|
||
:ID: 175678e2-bfe1-0833-f2a9-f03b9323db78
|
||
:END:
|
||
<2026-05-20 Wed>
|
||
** DONE Add importing of openScale CSV files to Tasks :vrobbler:project:personal:tasks:openscale:
|
||
:PROPERTIES:
|
||
:ID: 344d1f5d-dda6-a1fb-da53-e00eebdd2262
|
||
:END:
|
||
** DONE Add ability to track Birding sessions via BirdingLocation scrobbles :vrobbler:project:birds:feature:
|
||
:PROPERTIES:
|
||
:ID: 8200ce29-a691-5cf6-c11a-c77e3d8b64c6
|
||
:END:
|
||
** DONE List only the last 20 scrobbles per category on the home page :vrobbler:project:scrobbles:templates:
|
||
:PROPERTIES:
|
||
:ID: b56402b9-5542-a10c-6c13-e12f56f2a2d1
|
||
:END:
|
||
** DONE Fix display of notes so they look like stickies :vrobbler:project:personal:notes:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: 0ace8814-e96e-fa54-28d1-c57dcb508f1e
|
||
:END:
|
||
** DONE Add searching to scrobbles :vrobbler:project:personal:search:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: b4690c76-d741-4320-20e8-c003251fe035
|
||
:END:
|
||
** DONE Fix uniqueness of imdb_id messing up youtube videos :vrobbler:project:bug:videos:
|
||
:PROPERTIES:
|
||
:ID: 610b8c4c-abf1-8630-a4fd-08d9939da9f5
|
||
:END:
|
||
|
||
Turns out you can't make imdb_id unique by itself or you never get to create
|
||
youtube videos. Rather, we should make imdb_id and youtube_id unique together so
|
||
imdb_id can be empty for every youtube_id and vice versa.
|
||
|
||
** DONE Fix genearting chart records :vrobbler:bug:personal:project:chartrecords:
|
||
:PROPERTIES:
|
||
:ID: e749d762-44ac-dd7e-017e-2423016737ff
|
||
:END:
|
||
|
||
** DONE [#A] Save raw scrobble request data to every scrobble log :vrobbler:personal:feature:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: b4686db4-1319-399c-9b84-f0b1036c6815
|
||
:END:
|
||
|
||
The idea here is that no matter where the data comes from, we should just save
|
||
it in the scrobble for posterity, so we can always in some form recover the
|
||
original intent of the scrobble.
|
||
|
||
It may also allow us to clean up junk scrobbles if the data was just horribly
|
||
wrong.
|
||
|
||
** DONE [#B] Clean up follow up notifications for if you're still scrobbling :vrobbler:personal:project:beers:boardgames:notifications:feature:
|
||
:PROPERTIES:
|
||
:ID: 7937545f-2a62-4188-ad49-34f85fad0c25
|
||
:END:
|
||
|
||
- Note taken on [2025-09-30 Tue 09:32]
|
||
|
||
I added this feature in a very rough way, but now we should add "Action"
|
||
headers so that we can either Finish or Cancel the associated scrobble:
|
||
|
||
https://docs.ntfy.sh/publish/#send-http-request
|
||
|
||
** DONE [#A] Fix lookup of music tracks from Musicbrainz :vrobbler:bug:tracks:music:
|
||
:PROPERTIES:
|
||
:ID: 2bc1cc0b-6c4e-bc3d-e7c3-47df364df206
|
||
:END:
|
||
|
||
Turns out we're not looking up music tracks properly, again.
|
||
|
||
** DONE Check opencode about a way to present stats like movies per month :vrobbler:scrobbles:stats:personal:project:
|
||
:PROPERTIES:
|
||
:ID: eed39a0b-3aa7-dc65-9e03-a58fa401c8c6
|
||
:END:
|
||
** DONE Fix bug in Jellyfin audio track playback :vrobbler:personal:project:bug:music:jellyfin:
|
||
:PROPERTIES:
|
||
:ID: 002bd234-4507-5313-fb59-2d3baa49b847
|
||
:END:
|
||
|
||
#+begin_src shell
|
||
ERROR django.request:241 log_response Internal Server Error: /webhook/jellyfin/
|
||
Traceback (most recent call last):
|
||
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
|
||
response = get_response(request)
|
||
^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
|
||
response = wrapped_callback(request, *callback_args, **callback_kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
|
||
return view_func(*args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
|
||
return view_func(*args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
|
||
return self.dispatch(request, *args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch
|
||
response = self.handle_exception(exc)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception
|
||
self.raise_uncaught_exception(exc)
|
||
File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
|
||
raise exc
|
||
File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch
|
||
response = handler(request, *args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/rest_framework/decorators.py", line 50, in handler
|
||
return func(*args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/views.py", line 494, in jellyfin_webhook
|
||
scrobble = jellyfin_scrobble_media(post_data, request.user.id)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/scrobblers.py", line 177, in jellyfin_scrobble_media
|
||
log["album_id"] = media_obj.album_id
|
||
~~~^^^^^^^^^^^^
|
||
TypeError: 'tuple' object does not support item assignment
|
||
#+end_src
|
||
** DONE [#B] Auto calc duration if no playback time seconds present :vrobbler:bug:scrobbles:personal:project:
|
||
:PROPERTIES:
|
||
:ID: e16228b2-b062-bd00-32e6-b2353e6406e9
|
||
:END:
|
||
** DONE Fix bug in video find_or_create :vrobbler:personal:project:bug:videos:
|
||
:PROPERTIES:
|
||
:ID: 10e611a5-fbcf-7473-25f0-c9bad7b79ffd
|
||
:END:
|
||
The error:
|
||
#+begin_src shell
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/views.py", line 493, in jellyfin_webhook
|
||
scrobble = jellyfin_scrobble_media(post_data, request.user.id)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/scrobbles/scrobblers.py", line 149, in jellyfin_scrobble_media
|
||
media_obj = Video.find_or_create(imdb_id)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/videos/models.py", line 390, in find_or_create
|
||
return cls.get_from_imdb_id(source_id, overwrite)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/videos/models.py", line 374, in get_from_imdb_id
|
||
video.tv_series = Series.find_or_create(
|
||
^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/videos/models.py", line 203, in find_or_create
|
||
vdict, _, cover, genres = lookup_video_from_imdb(
|
||
^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/videos/sources/imdb.py", line 17, in lookup_video_from_imdb
|
||
imdb_result = imdb.get_title(imdb_id)
|
||
^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/cinemagoerng/web.py", line 127, in get_title
|
||
data = _scrape(spec=spec, context=context, headers=headers)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/cinemagoerng/web.py", line 120, in _scrape
|
||
document = fetch(url, headers=request_headers)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/cinemagoerng/web.py", line 44, in fetch
|
||
with urlopen(request) as response:
|
||
^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/urllib/request.py", line 216, in urlopen
|
||
return opener.open(url, data, timeout)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/urllib/request.py", line 525, in open
|
||
response = meth(req, response)
|
||
^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/urllib/request.py", line 634, in http_response
|
||
response = self.parent.error(
|
||
^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/urllib/request.py", line 563, in error
|
||
return self._call_chain(*args)
|
||
^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/urllib/request.py", line 496, in _call_chain
|
||
result = func(*args)
|
||
^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/urllib/request.py", line 643, in http_error_default
|
||
raise HTTPError(req.full_url, code, msg, hdrs, fp)
|
||
urllib.error.HTTPError: HTTP Error 500: Internal Server Error
|
||
#+end_src
|
||
|
||
- Note taken on [2026-03-11 Wed 20:53]
|
||
|
||
It turns out that every time a TV show was scrobbled were were hitting IMDB.
|
||
Woof.
|
||
|
||
** DONE Update admin page to be easier to use :vrobbler:djadmin:project:personal:
|
||
:PROPERTIES:
|
||
:ID: 0779be1f-1ad7-ddc7-8861-d3c7c833cbe9
|
||
:END:
|
||
** DONE Fix migrations and update repo :vrobbler:scrobbles:admin:personal:project:
|
||
:PROPERTIES:
|
||
:ID: ccbc2ef0-68bf-9ef7-dcaf-febab5ebefe2
|
||
:END:
|
||
** DONE Add recipe parsing for food lookups :vrobbler:foods:project:feature:personal:
|
||
:PROPERTIES:
|
||
:ID: 86456c78-247b-fb63-7ae8-d6d17e7666b1
|
||
:END:
|
||
** DONE [#A] Videos are scrobbling duplicates again :vrobbler:bug:videos:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: a46884fe-7ef1-410a-316b-7ac6d7599331
|
||
:END:
|
||
<2026-03-06 Fri>
|
||
** DONE Fix board games not saving BGG id on lookup :vrobbler:bug:boardgames:
|
||
:PROPERTIES:
|
||
:ID: 506c2965-51d6-6cb9-fc4f-4f0468d2d62f
|
||
:END:
|
||
** DONE Fix board game lookup with name like Unmatched Game System :vrobbler:bug:boardgames:
|
||
:PROPERTIES:
|
||
:ID: 57956723-b34a-37ad-fde9-44947cc9bb65
|
||
:END:
|
||
** DONE [#A] Fix raw text webpage title not truncating to 254 chars :vrobbler:personal:bug:webpages:
|
||
:PROPERTIES:
|
||
:ID: 13fa0efd-2c3f-dd07-deb2-62882096feff
|
||
:END:
|
||
|
||
- Note taken on [2025-09-30 Tue 09:33]
|
||
|
||
This may have already been resolved ... need to just confirm it.
|
||
|
||
|
||
* 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/
|
||
** DONE [#B] Food scrobbles should inherit calories from obj if missing :vrobbler:feature:food:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 3322ff69-4252-db65-36b3-fae56c1b9327
|
||
:END:
|
||
** DONE [#A] Puzzles (and all longplays) should have a "Completed?" column on their detail page :vrobbler:bug:puzzles:personal:project:
|
||
:PROPERTIES:
|
||
:ID: e3e49a9a-67d2-8ad8-1114-6f05effee9b7
|
||
:END:
|
||
|
||
* Version 36.0 [1/1]
|
||
** DONE [#A] Refactor how videos are scrobbled :vrobbler:vidoes:feature:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 6034a11d-5376-994d-9a4b-e1640e258cfa
|
||
:END:
|
||
|
||
* Version 35.0 [3/3]
|
||
** DONE [#B] Add youtube link in place of IMDB on video detail page :vrobbler:feature:videos:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 84064bd6-2258-a4de-f048-b131db9465c9
|
||
:END:
|
||
** DONE [#B] Add missing API lookups to resolve broken scrobbles endpoint :vrobbler:feature:api:scrobbles:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 0f668a54-f587-3b17-353e-3a56969d3a82
|
||
:END:
|
||
** DONE [#A] IMDB lookups are not working :vrobbler:bug:videos:personal:project:
|
||
:PROPERTIES:
|
||
:ID: d1ba1ca1-509b-13a9-1307-b2dc94a2eafe
|
||
:END:
|
||
|
||
* Version 34.0 [4/4]
|
||
** 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:
|
||
:ID: d7014ac4-cda6-0802-2cdf-8f66c6389fea
|
||
:END:
|
||
|
||
#+begin_src python
|
||
ERROR django.request:241 log_response Internal Server Error: /series/c24100d1-da45-4abe-86bf-27cfce9b1f89/
|
||
Traceback (most recent call last):
|
||
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
|
||
response = get_response(request)
|
||
^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
|
||
response = wrapped_callback(request, *callback_args, **callback_kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
|
||
return self.dispatch(request, *args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/contrib/auth/mixins.py", line 73, in dispatch
|
||
return super().dispatch(request, *args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 143, in dispatch
|
||
return handler(request, *args, **kwargs)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/django/views/generic/detail.py", line 109, in get
|
||
context = self.get_context_data(object=self.object)
|
||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||
File "/usr/local/lib/python3.11/site-packages/vrobbler/apps/videos/views.py", line 33, in get_context_data
|
||
context_data["next_episode_id"] = "tt" + next_episode_id
|
||
~~~~~^~~~~~~~~~~~~~~~~
|
||
TypeError: can only concatenate str (not "NoneType") to str
|
||
#+end_src
|
||
|
||
** DONE [#A] Emacs tasks are duplicating rather than updating :vrobbler:bug:tasks:emacs:personal:project:
|
||
:PROPERTIES:
|
||
:ID: e93efc25-7ce9-8ef2-662e-0a19dd0b29c9
|
||
:END:
|
||
|
||
- Note taken on [2025-10-29 Wed 16:38]
|
||
|
||
Turns out I was misusing `orgmode` for the source of tasks when it shoulda been `Org-mode`
|
||
|
||
A good lesson in using constants for things.
|
||
|
||
|
||
* Version 33.0 [3/3]
|
||
** DONE [#A] Fix bug where scrobble is_stale only uses seconds not total_seconds :vrobbler:bug:scrobbles:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 7f6070ac-4f67-011d-ebd5-f3dc47da46ed
|
||
:END:
|
||
** DONE [#B] Fix duplicatged Read next issue for Comic books :vrobbler:bug:books:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 97943040-1f03-b0b7-b0aa-123a783e4f7b
|
||
:END:
|
||
** DONE [#A] Add API authentication to BGG calls :vrobbler:bug:boardgames:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 4955cc34-0882-50db-92f7-f36a95bf57a4
|
||
:END:
|
||
<2025-10-28 Tue>
|
||
|
||
* Version 32.0 [2/2]
|
||
** DONE [#B] Save path to reading source on book scrobbles and show it on the detail page :vrobbler:feature:books:personal:project:
|
||
:PROPERTIES:
|
||
:ID: f1ef3945-e6e4-66c1-b72e-3cede7a0f84a
|
||
:END:
|
||
** DONE [#B] Move comic resume URL to next page and check if it exists :vrobbler:feature:books:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 9fe09567-11a3-7083-53c7-07458a9591d0
|
||
:END:
|
||
|
||
* Version 31.0 [3/3]
|
||
** DONE [#A] Stop comic book webpage scrobbles from overwriting old scrobbles :vrobbler:personal:bug:books:scrobbling:
|
||
:PROPERTIES:
|
||
:ID: 4b2ec068-a281-a88b-c31d-6248d6eb0aa0
|
||
:END:
|
||
** DONE [#A] Add page calculation to manually scrobbled books :vrobbler:personal:feature:books:scrobbling:
|
||
:PROPERTIES:
|
||
:ID: b2e313b3-5c35-57e7-8933-627535baf34b
|
||
:END:
|
||
** DONE [#A] Fix bug in scrobbling comics where google fails :vrobbler:personal:bug:books:scrobbling:
|
||
:PROPERTIES:
|
||
:ID: 9a870c05-6d20-0803-d35d-c03fbe1d0ee1
|
||
:END:
|
||
|
||
* Version 30.0 [3/3]
|
||
** DONE [#A] Fix readcomicsonline browsing to update pages :vrobbler:books:feature:comicbook:personal:project:scrobbling:
|
||
:PROPERTIES:
|
||
:ID: 981b215a-6473-5fc7-d4cc-51b3eddec4c3
|
||
:END:
|
||
** DONE [#B] Redirect webpages back to the original page when starting or stopping :vrobbler:project:webpages:bug:
|
||
:PROPERTIES:
|
||
:ID: 6183d03a-452b-51d5-cceb-5bfeada947aa
|
||
:END:
|
||
|
||
** DONE [#B] Fix ComicVine as source for comic book metadata :vrobbler:books:feature:comicbook:personal:project:scrobbling:
|
||
:PROPERTIES:
|
||
:ID: d22cec3f-117f-f203-33a5-efbefa8a5cee
|
||
:END:
|
||
|
||
* Version 29.0 [1/1]
|
||
** DONE HOTFIX podcast lookups, final
|
||
|
||
* Version 28.0 [1/1]
|
||
** DONE HOTFIX podcast lookups
|
||
|
||
* Version 27.0 [3/3]
|
||
** DONE [#A] Fix bug where podcast scrobbling creates duplicate Podcast :project:vrobbler:scrobbling:podcasts:bug:personal:
|
||
:PROPERTIES:
|
||
:ID: 7377ef6c-5fa7-9e4e-9080-f9810a76118c
|
||
:END:
|
||
|
||
Rather than pick up an existing Podcast using the podcast title in the mopidy
|
||
file name, Vrobbler creates a new podcast with no enriched data. Not a big deal
|
||
for my use as the volume of podcasts I listen to makes manual fixes easy. But
|
||
it's annoying.
|
||
|
||
** DONE [#A] Allow reading comic books from readcomicsoline.ru :vrobbler:books:feature:comicbook:personal:project:scrobbling:
|
||
:PROPERTIES:
|
||
:ID: 7c7e9ecc-b675-68c3-764f-ef771ce5d88f
|
||
:END:
|
||
|
||
- Note taken on [2025-09-25 Thu 10:52]
|
||
|
||
Things to consider are whether we scrobble the issue on one page, send it to
|
||
archivebox? (yes), and how best to enrich the data
|
||
|
||
** DONE [#A] Add RSS feed lookups to podcasts :vrobbler:personal:feature:podcasts:
|
||
:PROPERTIES:
|
||
:ID: d60645b0-7578-97c1-0278-05bd9de4269c
|
||
:END:
|
||
|
||
- Note taken on [2025-10-14 Tue 10:08]
|
||
|
||
Turns out the Podcast plugin for mopidy does a pretty good job of showing the
|
||
latest file without having to scroll the bottom using only Muse to not parse
|
||
the podcast title name. BUT, now we're getting urls like this:
|
||
|
||
https://nsf.libsyn.com/rss#77e01251-cb20-4609-b577-d48e985d2e7b
|
||
|
||
This is great, because there's more context there, but it has to read out of
|
||
the RSS feed. We should add a check in the podcast util to sniff out the file
|
||
referenced in the # in that url and populate the info from there. This should
|
||
actually be much more reliable than the current state of the podcast lookup
|
||
which depends on the file to be name properly.
|
||
|
||
|
||
* Version 26.0 [3/3]
|
||
** DONE Clean up templates for scrobble details :vrobbler:personal:bug:templates:
|
||
:PROPERTIES:
|
||
:ID: 43dc1e02-c110-5b49-0ac7-4c4f7656d1aa
|
||
:END:
|
||
** DONE Add named locations visited to dashboard :vrobbler:personal:feature:locations:templates:
|
||
:PROPERTIES:
|
||
:ID: ebc365a1-cef4-f75d-569f-c24b072ef5a4
|
||
:END:
|
||
** DONE Add moods to dashboard :vrobbler:moods:feature:templates:personal:
|
||
:PROPERTIES:
|
||
:ID: c03a38ce-b337-f4fa-adba-aee08d4329f5
|
||
:END:
|
||
|
||
* Version 25.0 [3/3]
|
||
** DONE Add basic food templates and fix urls :food:vrobbler:personal:project:bug:urls:
|
||
:PROPERTIES:
|
||
:ID: 3de3459e-8e7e-abba-e068-b919a819d3e3
|
||
:END:
|
||
** DONE [#C] Fix how elapsed time is calculated :vrobbler:personal:project:scrobbles:bug:
|
||
:PROPERTIES:
|
||
:ID: cff58fc4-06ac-8016-4eae-130b51e3c9b7
|
||
:END:
|
||
** DONE Fix templates for videos and dashboard links :personal:feature:project:vrobbler:templates:
|
||
:PROPERTIES:
|
||
:ID: 7debfbaf-cdd8-f49b-57ff-804bfe7c9236
|
||
:END:
|
||
|
||
* Version 24.0 [2/2]
|
||
** DONE Clean up logdata for various media :personal:feature:project:vrobbler:logdata:
|
||
:PROPERTIES:
|
||
:ID: d5cce807-1f45-ef19-45a4-9f7069fa2a93
|
||
:END:
|
||
** DONE Removed sidebar and add links to headers :personal:feature:templates:scrobbles:
|
||
:PROPERTIES:
|
||
:ID: 1a1c0aa6-0313-c8be-1676-5d6adddef0a4
|
||
:END:
|
||
|
||
|
||
* Version 23.0 [3/3]
|
||
** DONE Add dynamic forms for LogData classes :personal:feature:vrobbler:project:forms:logdata:
|
||
:PROPERTIES:
|
||
:ID: 0db889a1-f262-fba2-7fed-ed99eded1c88
|
||
:END:
|
||
** DONE Look in comments for a timestamp for start from BG stats if the time is missing :vrobbler:feature:boardgames:project:personal:
|
||
** DONE Fix long play scrobbles to provide better data :vrobbler:feature:scrobbles:longplay:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 99f6bd77-dc8f-6ed1-0321-32a52c944264
|
||
:END:
|
||
|
||
* Version 19.0 [1/1]
|
||
** DONE Add periodic check for mood :vrobbler:feature:moods:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 55404488-c69f-0dd5-838e-1d1e15c873eb
|
||
:END:
|
||
|
||
* Version 18.7 [1/1]
|
||
** DONE Use the timezone history log to fix old Scrobbles that fall into those timezone blocks :vrobbler:chore:scrobbles:project:personal:
|
||
:PROPERTIES:
|
||
:ID: 9d055ac1-584b-20c8-7ad9-9ce36b329dc7
|
||
:END:
|
||
|
||
* Version 18.4 [2/2]
|
||
** DONE Track timezone changes for profiles :vrobbler:feature:profiles:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 89ec867f-29fd-82f1-be17-b49dddc30c78
|
||
:END:
|
||
[2025-07-11 14:23]
|
||
** DONE Only create a LastFM import if there are files to import :vrobbler:feature:lastfm:importers:project:personal:
|
||
:PROPERTIES:
|
||
:ID: 7a1456af-c5f1-6385-b34f-0be24a6b65b0
|
||
:END:
|
||
- Note taken on [2025-07-20 Sun 16:21]
|
||
|
||
This thing is kicking my butt. As it stands it works, but the scrobbles are not assigned to the tracks properly.
|
||
|
||
* Version 18.3 [1/1]
|
||
** DONE Add timezone awarness to IMAP importer :personal:project:vrobbler:feature:importer:imap:timezones:
|
||
:PROPERTIES:
|
||
:ID: 05837b7c-96aa-6190-3678-e2ae7c7cac75
|
||
:END:
|
||
|
||
* Version 18 [4/4]
|
||
** DONE Condense tracks of the same title by the same artist with multiple albums :vrobbler:feature:music:project:personal:
|
||
:PROPERTIES:
|
||
:ID: b39fcec8-59fd-eab0-5809-b8144c7d2708
|
||
:END:
|
||
** DONE Import from BG stats a "learning" log field when "Learning to play" is in the comment :vrobbler:feature:boardgames:project:personal:
|
||
:PROPERTIES:
|
||
:ID: fda59fab-4349-e99e-54c6-9f1392a1c474
|
||
:END:
|
||
** DONE [#A] Add email importer for BG stats file uploads :vrobbler:feature:boardgames:personal:project:
|
||
:PROPERTIES:
|
||
:ID: 116fe738-7966-615c-d195-ccff0337b101
|
||
:END:
|
||
#+begin_src json example of a file
|
||
{
|
||
"about": "This is a Play file that can be read by Board Game Stats. If you see this text, try to use a share, export or open-in function to open it with Board Game Stats.",
|
||
"players": [
|
||
{
|
||
"uuid": "31f8b92e-11d8-4162-88b1-fd9c79eea249",
|
||
"id": 2,
|
||
"name": "Colin",
|
||
"isAnonymous": false,
|
||
"modificationDate": "2025-07-01 18:10:32",
|
||
"metaData": "{\"isNpc\":0}"
|
||
},
|
||
{
|
||
"uuid": "00074700-cf4e-4ad3-b334-d35805bb0d90",
|
||
"id": 4,
|
||
"name": "Asa Sewell",
|
||
"isAnonymous": false,
|
||
"modificationDate": "2025-07-01 18:03:37"
|
||
}
|
||
],
|
||
"locations": [
|
||
{
|
||
"uuid": "14f7389c-767f-4725-9b35-906c407b293c",
|
||
"id": 3,
|
||
"name": "Timberwyck Farm",
|
||
"modificationDate": "2025-07-01 18:03:38"
|
||
}
|
||
],
|
||
"games": [
|
||
{
|
||
"uuid": "043a2851-f201-467a-a60c-0b0a7e9c33d2",
|
||
"id": 333,
|
||
"name": "Ghost Fightin' Treasure Hunters: Anniversary Edition",
|
||
"modificationDate": "2025-07-02 01:37:14",
|
||
"cooperative": true,
|
||
"highestWins": true,
|
||
"noPoints": false,
|
||
"usesTeams": false,
|
||
"urlThumb": "https://cf.geekdo-images.com/DHA-mcH3zzw_OjfDxOPj1A__thumb/img/UhaIm4KIDIiraUc44QIvSAbMUXI=/fit-in/200x150/filters:strip_icc()/pic8266874.jpg",
|
||
"urlImage": "https://cf.geekdo-images.com/DHA-mcH3zzw_OjfDxOPj1A__original/img/2-Lb6nLePhn0I0Hh2j1pOtbO4rg=/0x0/filters:format(jpeg)/pic8266874.jpg",
|
||
"bggName": "Ghost Fightin' Treasure Hunters: Anniversary Edition",
|
||
"bggYear": 2024,
|
||
"bggId": 422668,
|
||
"designers": "Brian Yu",
|
||
"isBaseGame": 1,
|
||
"isExpansion": 0,
|
||
"rating": 75,
|
||
"minPlayerCount": 2,
|
||
"maxPlayerCount": 5,
|
||
"minPlayTime": 30,
|
||
"maxPlayTime": 0,
|
||
"minAge": 8
|
||
}
|
||
],
|
||
"plays": [
|
||
{
|
||
"uuid": "bae3f29e-5e1e-45d8-b409-47a665c8d5b5",
|
||
"modificationDate": "2025-07-02 01:37:59",
|
||
"entryDate": "2025-07-02 01:31:38",
|
||
"playDate": "2025-07-02 01:31:38",
|
||
"usesTeams": false,
|
||
"durationMin": 23,
|
||
"ignored": false,
|
||
"manualWinner": true,
|
||
"rounds": 3,
|
||
"scoresheet": "{\"bggId\":244711,\"version\":1,\"langCode\":\"en\",\"scoreType\":\"bestTotalWins\",\"groups\":[{\"templateId\":\"1\",\"maxRepeat\":-1,\"repetition\":1,\"hasSubTotal\":false,\"hideSingleGroupLabel\":false,\"isExtra\":false,\"rows\":[{\"templateId\":\"vptrack\",\"label\":\"VP track\",\"repetition\":1,\"repeatable\":false,\"negative\":false,\"isExtra\":false,\"scores\":{}},{\"templateId\":\"objectives\",\"label\":\"Objectives\",\"repetition\":1,\"repeatable\":false,\"negative\":false,\"isExtra\":false,\"scores\":{}},{\"templateId\":\"mastercards\",\"label\":\"Master cards\",\"repetition\":1,\"repeatable\":false,\"negative\":false,\"isExtra\":false,\"scores\":{}}]}]}",
|
||
"locationRefId": 3,
|
||
"gameRefId": 333,
|
||
"board": "",
|
||
"scoringSetting": 4,
|
||
"metaData": "{\"playUsedGameCopy\":2}",
|
||
"playerScores": [
|
||
{
|
||
"score": "",
|
||
"winner": true,
|
||
"newPlayer": true,
|
||
"startPlayer": false,
|
||
"playerRefId": 4,
|
||
"role": "",
|
||
"rank": 0,
|
||
"seatOrder": 0,
|
||
"metaData": "{\"scoreUuid\":\"00074700-cf4e-4ad3-b334-d35805bb0d90\"}"
|
||
},
|
||
{
|
||
"score": "",
|
||
"winner": true,
|
||
"newPlayer": true,
|
||
"startPlayer": false,
|
||
"playerRefId": 2,
|
||
"role": "",
|
||
"rank": 0,
|
||
"seatOrder": 0,
|
||
"metaData": "{\"scoreUuid\":\"31f8b92e-11d8-4162-88b1-fd9c79eea249\"}"
|
||
}
|
||
],
|
||
"expansionPlays": []
|
||
}
|
||
],
|
||
"userInfo": {
|
||
"meRefId": 2
|
||
}
|
||
}
|
||
|
||
#+end_src
|
||
** DONE [#B] Fix task app to only use one tag for the context a task was done in and allow configurable contexts by user profile :personal:vrobbler:feature:tasks:project:
|
||
:PROPERTIES:
|
||
:ID: 23f485e3-988c-6198-c79d-91fdf92f001c
|
||
:END:
|
||
|
||
* Version 17.0 [6/6]
|
||
** DONE [#A] Fix bug in new task label lookup for Emacs/Org-mode :vrobbler:bug:tasks:
|
||
:PROPERTIES:
|
||
:ID: 683fb109-dfc4-85e4-80f0-ea618434f61e
|
||
:END:
|
||
** DONE [#C] Replace commas in the bandcamp URL for artists with nothing :vrobbler:music:bug:personal:
|
||
:PROPERTIES:
|
||
:ID: 9b30d67b-91f0-a480-dfaa-5d9dc090e76c
|
||
:END:
|
||
|
||
- Note taken on [2025-06-16 Mon 09:36]
|
||
|
||
This firt appeared with Black Country, New Road, where the RYM slug generator
|
||
leaves commas in and ends up sending you to a 404. I suspect this wont be the
|
||
first tweak we'll need to this, as the RYM link creator is really just
|
||
guessing based on the artist name at the path.
|
||
|
||
** DONE [#A] Investigate new source of video metadata :personal:project:video:imdb:
|
||
:PROPERTIES:
|
||
:ID: df2b486c-1170-5199-c312-9bc87760d962
|
||
:END:
|
||
|
||
Cinemagoer broke and I probably should find a more reilable source of video data.
|
||
|
||
- Note taken on [2025-06-13 Fri 11:19]
|
||
|
||
TMDB is much more reliable, but does require an API key. That's all setup now,
|
||
so hopefully this breaking IMDB crap is over.
|
||
|
||
** DONE [#A] IMDB video lookups are failing :personal:bug:video:imdb:
|
||
:PROPERTIES:
|
||
:ID: 38f1081f-37b4-f4f2-79aa-c1e87eca4b69
|
||
:END:
|
||
<2025-06-13 Fri>
|
||
|
||
- Note taken on [2025-06-13 Fri 08:24]
|
||
|
||
Looks like Cinemagoer is broken: https://github.com/cinemagoer/cinemagoer/issues/537
|
||
|
||
** DONE [#A] Emacs is not syncing notes :personal:scrobbling:emacs:bug:
|
||
:PROPERTIES:
|
||
:ID: c79cd491-b30f-0945-d84b-b8cac7562791
|
||
:END:
|
||
<2025-06-12 Thu 9:30>
|
||
|
||
Not sure if the problem is in my Emacs hook sending or Vrobbler itself.
|
||
|
||
- Note taken on [2025-06-12 Thu 09:47]
|
||
|
||
Adding a quick note to check on it
|
||
|
||
- Note taken on [2025-06-12 Thu 09:50]
|
||
|
||
Ah ha. All the messing about with the source field meant that I was looking
|
||
for `emacs` as a source but the hook was initially setting sources to
|
||
`orgmode` I think I prefer `orgmode` as the source, so updating it thusly.
|
||
|
||
Fixed in `490d60cbbb1f8bf90b5fc47d8685b15bdc1d485b`
|
||
|
||
** DONE [#A] Show the description of a task in the string rep for a scrobble of a Task :personal:project:scrobbling:vrobbler:feature:
|
||
:PROPERTIES:
|
||
:ID: df58f8d0-fa4a-2037-c7d7-e5388c239042
|
||
:END:
|
||
|
||
* Version 0.16.0 [19/19]
|
||
** DONE [#A] Jellyfin, bandcamp tracks from Mopidy create duplicate music tracks :bug:scrobbling:music:
|
||
:PROPERTIES:
|
||
:ID: 670e8634-49b5-dce9-1684-14f2ffb797f1
|
||
:END:
|
||
Effectively, any track that comes in without a MusicBrainz ID does some funky
|
||
lookup where it doesn't find a track without an MB id and the track title /
|
||
artist combination and creates a new track every time. This has to be cleaned up
|
||
by condensing the duplicated tracks into the original proper track.
|
||
|
||
But it opens a bigger question about how much MB id should the drive the app
|
||
lookup. If it can't be depended on to exist from all sources, it really can't be
|
||
canonical. Instead, the combination of track title / artist is really the best
|
||
we can do. Last.fm also has this problem, where it doesn't know about albums and
|
||
definitely does not know or care about MB ids.
|
||
|
||
** DONE Add a user profile page with ability to change settings :profiles:improvement:
|
||
- Note taken on [2025-04-04 Fri 10:51]
|
||
[[orgit-rev:~/src/code.unbl.ink/secstate/vrobbler/::93c16d80ecff4cd1663cf9ec40fbe6d8f58c3e44][~/src/code.unbl.ink/secstate/vrobbler/ (magit-rev 93c16d8)]]
|
||
|
||
https://code.unbl.ink/secstate/vrobbler/commit/93c16d80ecff4cd1663cf9ec40fbe6d8f58c3e44
|
||
|
||
** DONE What to do with Youtube videos from LastFM and web-scrobbler :bug:source:lastfm:
|
||
- Note taken on [2025-04-04 Fri 10:46]
|
||
|
||
Nothing. Over the last few months I built out a youtube model in videos and
|
||
use a bookmarklet scrobbling pattern. Now web-scrobbler is just disabled for
|
||
Youtube.
|
||
|
||
May want to revisit this at some point and only scrobble tracks from Youtube,
|
||
because many people use YT for music listening.
|
||
|
||
** DONE [#C] Consider a purge command for duplicated and stuck in-progress scrobbles :utililty:improvement:
|
||
CLOSED: [2023-04-06 Thu 14:09]
|
||
** DONE Add a "stop_timestamp" so we don't rely on content length :improvement:scrobbling:
|
||
CLOSED: [2023-04-02 Sun 23:58]
|
||
|
||
Essentially, we currently have the timestamp as when the content began
|
||
scrobbling and then calculate the finish time from the length of the content.
|
||
This works pretty well because we know how long most things are.
|
||
|
||
But in some cases, sports events or long podcasts, we may start mid-way through
|
||
an event or finish halfway through but still want to mark it as done. In these
|
||
cases, knowing the finish time could be useful, especially when interfacing with
|
||
other scrobblers which may have different definitions of when a scrobble
|
||
finishes or started.
|
||
** DONE Fix bug with Various Artist albums being labeled with first artist as album artist :scrobbling:bug:music:
|
||
CLOSED: [2023-03-27 Mon 20:18]
|
||
:LOGBOOK:
|
||
CLOCK: [2023-03-26 Sun 22:01]--[2023-03-27 Mon 01:07] => 3:06
|
||
:END:
|
||
** DONE Fix bug with weekly aggregator being blank on Sundays :aggregators:music:bug:
|
||
CLOSED: [2023-03-26 Sun 13:52]
|
||
** DONE Fix KoReader scrobbling to use pages rather than time of last read :scrobbling:books:improvement:
|
||
CLOSED: [2023-03-26 Sun 13:51]
|
||
:LOGBOOK:
|
||
CLOCK: [2023-03-26 Sun 13:11]--[2023-03-26 Sun 13:51] => 0:40
|
||
:END:
|
||
** DONE [#A] Add django-storage to store files on S3 :settings:improvement:
|
||
CLOSED: [2023-03-24 Fri 14:46]
|
||
:LOGBOOK:
|
||
CLOCK: [2023-03-24 Fri 10:47]--[2023-03-24 Fri 14:46] => 3:59
|
||
CLOCK: [2023-03-24 Fri 10:36]--[2023-03-24 Fri 10:40] => 0:04
|
||
:END:
|
||
** DONE Fix vrobbler settings not using booleans :settings:bug:
|
||
CLOSED: [2023-03-24 Fri 10:45]
|
||
:LOGBOOK:
|
||
CLOCK: [2023-03-24 Fri 10:40]--[2023-03-24 Fri 10:46] => 0:06
|
||
:END:
|
||
** DONE Update weekly live chart to be 7-day continuous rather than weekly :views:bug:
|
||
CLOSED: [2023-03-24 Fri 00:31]
|
||
The live view will be blank every Monday, no reason to tie it to a day of the
|
||
week. It should be "the last 7 days"
|
||
** DONE [#B] Implement a detail view for TV shows :improvement:views:
|
||
CLOSED: [2023-03-22 Wed 17:05]
|
||
** DONE [#B] Implement a detail view for Movies :improvement:views:
|
||
CLOSED: [2023-03-22 Wed 17:05]
|
||
** DONE Add "service provider" to TV Series, and use that for source when available :bug:scrobbling:
|
||
CLOSED: [2023-03-22 Wed 17:04]
|
||
** DONE Add view for long-play content (books, video games) to restart them :views:improvement:
|
||
CLOSED: [2023-03-22 Wed 17:01]
|
||
** DONE Add live chart view like Maloja :improvement:views:
|
||
CLOSED: [2023-03-07 Tue 11:13]
|
||
** DONE [#C] Figure out how to add to web-scrobbler :improvement:scrobbling:
|
||
CLOSED: [2023-03-22 Wed 17:06]
|
||
|
||
An example:
|
||
https://github.com/web-scrobbler/web-scrobbler/blob/master/src/core/background/scrobbler/maloja-scrobbler.js
|
||
|
||
This is actually going to be moot because we can import from LastFM, and
|
||
web-scrobbler integrates well with LastFM. The only thing to think through here
|
||
now is what to do with all the garbage web-scrobbler sometimes pushes to LastFM
|
||
from Youtube (all videos get pushed, sigh).
|
||
|
||
** DONE Add Amazon scraper to look up books when OL fails :books:improvement:
|
||
This turned out to be a non-starter ... Amazon is aggressive at disallowing
|
||
scraping quality. And all the OSS tools out there are stuck in an arms race
|
||
trying to keep them from breaking.
|
||
|
||
That said, Google Books actually has a decent API (for now), and I've built this
|
||
out using that.
|
||
|
||
** DONE Fix bug in Jellyfin scrobbles that spam more scrobbles after completion :scrobbling:videos:bug:
|
||
This was fixed a while ago, but there's a new manifested bug. Going to create a
|
||
separate bug tracking ticket for that.
|
||
|
||
* Version 0.11.4 [9/9]
|
||
** DONE Add rudimentary video game scrobbling :improvement:content:videogames:
|
||
CLOSED: [2023-03-07 Tue 11:11]
|
||
** DONE Add ability to scrobble from KOReader statistics files :improvement:books:content:
|
||
CLOSED: [2023-03-07 Tue 11:11]
|
||
|
||
** DONE [#A] Fix fetching artwork without release group :bug:
|
||
CLOSED: [2023-01-29 Sun 14:27]
|
||
|
||
When we get artwork from Musicbrianz, and it's not found, we should check for
|
||
release groups as well. This will stop issues with missing artwork because of
|
||
obscure MB release matches.
|
||
|
||
** DONE [#A] Fix Jellyfin music scrobbling N+1 past 90 completion percent :bug:
|
||
CLOSED: [2023-01-30 Mon 18:31]
|
||
:LOGBOOK:
|
||
CLOCK: [2023-01-30 Mon 18:00]--[2023-01-30 Mon 18:31] => 0:31
|
||
:END:
|
||
|
||
If we play music from Jellyfin and the track reaches 90% completion, the
|
||
scrobbling goes crazy and starts creating new scrobbles with every update.
|
||
|
||
The cause is pretty simple, but the solution is hard. We want to mark a scrobble
|
||
as complete for the following conditions:
|
||
|
||
- Play stopped and percent played beyond 90%
|
||
- Play completely finished
|
||
|
||
But if we keep listening beyond 90, we should basically ignore updates (or just
|
||
update the existing scrobble)
|
||
** DONE [#A] Add support for Audioscrobbler tab-separated file uploads :improvement:
|
||
CLOSED: [2023-02-03 Fri 16:52]
|
||
|
||
An example of the format:
|
||
#+begin_src csv
|
||
,
|
||
#AUDIOSCROBBLER/1.1
|
||
#TZ/UNKNOWN
|
||
#CLIENT/Rockbox sansaclipplus $Revision$
|
||
75 Dollar Bill I Was Real I Was Real 4 1015 S 1740494944 64ff5f53-d187-4512-827e-7606c69e66ff
|
||
75 Dollar Bill I Was Real I Was Real 4 1015 S 1740494990 64ff5f53-d187-4512-827e-7606c69e66ff
|
||
311 311 Down 1 173 S 1740495003 00476c23-fd9e-464b-9b27-a62d69f3d4f4
|
||
311 311 Down 1 173 L 1740495049 00476c23-fd9e-464b-9b27-a62d69f3d4f4
|
||
311 311 Down 1 173 L 1740495113 00476c23-fd9e-464b-9b27-a62d69f3d4f4
|
||
311 311 Random 2 187 S 1740495190 530c09f3-46fe-4d90-b11f-7b63bcb4b373
|
||
311 311 Random 2 187 L 1740495194 530c09f3-46fe-4d90-b11f-7b63bcb4b373
|
||
311 311 Jackolantern’s Weather 3 204 L 1740495382 cc3b2dec-5d99-47ea-8930-20bf258be4ea
|
||
311 311 All Mixed Up 4 182 L 1740495586 980a78b5-5bdd-4f50-9e3a-e13261e2817b
|
||
311 311 Hive 5 179 L 1740495768 18f6dc98-d3a2-4f81-b967-97359d14c68c
|
||
311 311 Guns (Are for Pussies) 6 137 L 1740495948 5e97ed9f-c8cc-4282-9cbe-f8e17aee5128
|
||
311 311 Misdirected Hostility 7 179 S 1740496085 61ff2c1a-fc9c-44c3-8da1-5e50a44245af
|
||
,
|
||
#+end_src
|
||
** DONE [#B] Allow scrobbling music without MB IDs by grabbing them before scrobble :improvement:
|
||
CLOSED: [2023-02-17 Fri 00:10]
|
||
|
||
This would allow a few nice flows. One, you'd be able to record the play of an
|
||
entire album by just dropping the muscibrainz_id in. This could be helpful for
|
||
offline listening. It would also mean bad metadata from mopidy would not break
|
||
scrobbling.
|
||
** DONE When updating musicbrainz IDs, clear and run fetch artwrok :improvement:
|
||
CLOSED: [2023-02-17 Fri 00:11]
|
||
** DONE [#A] Add ability to manually scrobble albums or tracks from MB :improvement:
|
||
CLOSED: [2023-03-07 Tue 11:09]
|
||
|
||
Given a UUID from musicbrainz, we should be able to scrobble an album or
|
||
individual track.
|
||
|
||
** DONE [#C] Implement keeping track of week/month/year chart-toppers :improvement:
|
||
CLOSED: [2023-03-07 Tue 11:10]
|
||
:LOGBOOK:
|
||
CLOCK: [2023-01-30 Mon 16:30]--[2023-01-30 Mon 18:00] => 1:30
|
||
:END:
|
||
|
||
Maloja does this cool thing where artists and tracks get recorded as the top
|
||
track of a given week, month or year. They get gold, silver or bronze stars for
|
||
their place in the time period.
|
||
|
||
I could see this being implemented as a separate Chart table which gets
|
||
populated at the end of a time period and has a start and end date that defines
|
||
a period, along with a one, two, three instance.
|
||
|
||
Of course, it could also be a data model without a table, where it runs some fun
|
||
calculations, stores it's values in Redis as a long-term lookup table and just
|
||
has to re-populate when the server restarts.
|