mirror of
https://github.com/gabehf/Koito.git
synced 2026-03-07 21:48:18 -08:00
fix: associate tracks with release when scrobbling (#118)
This commit is contained in:
parent
d327729bff
commit
c346c7cb31
12 changed files with 58 additions and 1794 deletions
|
|
@ -27,14 +27,15 @@ FROM tracks_with_title t
|
||||||
JOIN artist_tracks at ON t.id = at.track_id
|
JOIN artist_tracks at ON t.id = at.track_id
|
||||||
WHERE at.artist_id = $1;
|
WHERE at.artist_id = $1;
|
||||||
|
|
||||||
-- name: GetTrackByTitleAndArtists :one
|
-- name: GetTrackByTrackInfo :one
|
||||||
SELECT t.*
|
SELECT t.*
|
||||||
FROM tracks_with_title t
|
FROM tracks_with_title t
|
||||||
JOIN artist_tracks at ON at.track_id = t.id
|
JOIN artist_tracks at ON at.track_id = t.id
|
||||||
WHERE t.title = $1
|
WHERE t.title = $1
|
||||||
AND at.artist_id = ANY($2::int[])
|
AND at.artist_id = ANY($3::int[])
|
||||||
|
AND t.release_id = $2
|
||||||
GROUP BY t.id, t.title, t.musicbrainz_id, t.duration, t.release_id
|
GROUP BY t.id, t.title, t.musicbrainz_id, t.duration, t.release_id
|
||||||
HAVING COUNT(DISTINCT at.artist_id) = cardinality($2::int[]);
|
HAVING COUNT(DISTINCT at.artist_id) = cardinality($3::int[]);
|
||||||
|
|
||||||
-- name: GetTopTracksPaginated :many
|
-- name: GetTopTracksPaginated :many
|
||||||
SELECT
|
SELECT
|
||||||
|
|
|
||||||
|
|
@ -1,977 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"ts": "2025-04-28T21:04:35Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 1603,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "only my railgun",
|
|
||||||
"master_metadata_album_artist_name": "fripSide",
|
|
||||||
"master_metadata_album_album_name": "infinite synthesis",
|
|
||||||
"spotify_track_uri": "spotify:track:3aJ2aJz5xL03hpaqdPS7Ah",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745874272,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-28T21:04:49Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 10953,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "LEVEL5-judgelight-",
|
|
||||||
"master_metadata_album_artist_name": "fripSide",
|
|
||||||
"master_metadata_album_album_name": "infinite synthesis",
|
|
||||||
"spotify_track_uri": "spotify:track:0hjif67e3mBkrPIlRDXHLS",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745874274,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-28T21:16:38Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 93283,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Red Liberation",
|
|
||||||
"master_metadata_album_artist_name": "fripSide",
|
|
||||||
"master_metadata_album_album_name": "infinite Resonance 2",
|
|
||||||
"spotify_track_uri": "spotify:track:2B8geqnq9YIym0ixYn83Pd",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "logout",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": false,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745874288,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-28T22:29:29Z",
|
|
||||||
"platform": "android",
|
|
||||||
"ms_played": 9640,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "New Genesis",
|
|
||||||
"master_metadata_album_artist_name": "Ado",
|
|
||||||
"master_metadata_album_album_name": "UTA'S SONGS ONE PIECE FILM RED",
|
|
||||||
"spotify_track_uri": "spotify:track:6A8NfypDHuwiLWbo4a1yca",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "logout",
|
|
||||||
"shuffle": true,
|
|
||||||
"skipped": false,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745878757,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T00:37:09Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 181028,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Clairvoyant",
|
|
||||||
"master_metadata_album_artist_name": "The Story So Far",
|
|
||||||
"master_metadata_album_album_name": "The Story So Far / Stick To Your Guns Split",
|
|
||||||
"spotify_track_uri": "spotify:track:5fgnsSQYKIlEn2KTQcGjh2",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "playbtn",
|
|
||||||
"reason_end": "trackdone",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": false,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745886847,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T00:59:36Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 824,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Clairvoyant",
|
|
||||||
"master_metadata_album_artist_name": "The Story So Far",
|
|
||||||
"master_metadata_album_album_name": "The Story So Far / Stick To Your Guns Split",
|
|
||||||
"spotify_track_uri": "spotify:track:5fgnsSQYKIlEn2KTQcGjh2",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "trackdone",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745887028,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T01:15:07Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 4443,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "比翼の羽根",
|
|
||||||
"master_metadata_album_artist_name": "eufonius",
|
|
||||||
"master_metadata_album_album_name": "比翼の羽根",
|
|
||||||
"spotify_track_uri": "spotify:track:6FFshKmfm9h5MBpnsRO73c",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": true,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745888374,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T01:16:02Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 36093,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "ファジーネーブル",
|
|
||||||
"master_metadata_album_artist_name": "Conton Candy",
|
|
||||||
"master_metadata_album_album_name": "melt pop",
|
|
||||||
"spotify_track_uri": "spotify:track:3FniX6mJvTQWruKp5PDexD",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745889306,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T01:25:35Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 54615,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Bad Spanish",
|
|
||||||
"master_metadata_album_artist_name": "Nervous Dater",
|
|
||||||
"master_metadata_album_album_name": "Don't Be a Stranger",
|
|
||||||
"spotify_track_uri": "spotify:track:793ILNfrm9dQyp3k0P53HG",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745889361,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T01:28:08Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 153153,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Fight Song",
|
|
||||||
"master_metadata_album_artist_name": "Rachel Platten",
|
|
||||||
"master_metadata_album_album_name": "Wildfire",
|
|
||||||
"spotify_track_uri": "spotify:track:37f4ITSlgPX81ad2EvmVQr",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745889934,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T01:29:19Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 70473,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Cake By The Ocean",
|
|
||||||
"master_metadata_album_artist_name": "DNCE",
|
|
||||||
"master_metadata_album_album_name": "DNCE",
|
|
||||||
"spotify_track_uri": "spotify:track:76hfruVvmfQbw0eYn1nmeC",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745890087,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T01:31:08Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 108465,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "The Sweet Escape",
|
|
||||||
"master_metadata_album_artist_name": "Gwen Stefani",
|
|
||||||
"master_metadata_album_album_name": "The Sweet Escape",
|
|
||||||
"spotify_track_uri": "spotify:track:66ZcOcouenzZEnzTJvoFmH",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745890158,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T01:33:19Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 130353,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "two",
|
|
||||||
"master_metadata_album_artist_name": "bbno$",
|
|
||||||
"master_metadata_album_album_name": "two",
|
|
||||||
"spotify_track_uri": "spotify:track:6DRZmJa38MaMNthwG3fCBD",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745890267,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T01:37:48Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 35993,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "C’est La Vie (with bbno$ & Rich Brian)",
|
|
||||||
"master_metadata_album_artist_name": "Yung Gravy",
|
|
||||||
"master_metadata_album_album_name": "Marvelous",
|
|
||||||
"spotify_track_uri": "spotify:track:3QqOcLtTU8zzlQRJCZzttP",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745890398,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T02:23:28Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 22337,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Metal",
|
|
||||||
"master_metadata_album_artist_name": "The Beths",
|
|
||||||
"master_metadata_album_album_name": "Metal",
|
|
||||||
"spotify_track_uri": "spotify:track:6KF6TkyYpEWKg6BZ3OYJz7",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "logout",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": false,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745890667,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:14:32Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 21414,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "SHINUNA!",
|
|
||||||
"master_metadata_album_artist_name": "Kocchi no Kento",
|
|
||||||
"master_metadata_album_album_name": "SHINUNA!",
|
|
||||||
"spotify_track_uri": "spotify:track:5QSo4Jbok8O9EgeDkumK9q",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "logout",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": false,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745905178,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:36:54Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 53063,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "I'm getting on the bus to the other world, see ya!",
|
|
||||||
"master_metadata_album_artist_name": "TUYU",
|
|
||||||
"master_metadata_album_album_name": "It's Raining After All",
|
|
||||||
"spotify_track_uri": "spotify:track:3rCJptQKkXrTx6qUXqz7dD",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745947869,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:37:41Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 28193,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Harukaze",
|
|
||||||
"master_metadata_album_artist_name": "Matsuri",
|
|
||||||
"master_metadata_album_album_name": "Harukaze",
|
|
||||||
"spotify_track_uri": "spotify:track:21Jj7td1D5HQYr18MLZTLS",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948214,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:38:16Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 10763,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Otona no Jijo",
|
|
||||||
"master_metadata_album_artist_name": "Za Ninngenn",
|
|
||||||
"master_metadata_album_album_name": "Sanman",
|
|
||||||
"spotify_track_uri": "spotify:track:6BfDkvp3wJq7cA0xDWDHAI",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948260,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:39:06Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 4393,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Mela!",
|
|
||||||
"master_metadata_album_artist_name": "Ryokuoushoku Shakai",
|
|
||||||
"master_metadata_album_album_name": "Mela!",
|
|
||||||
"spotify_track_uri": "spotify:track:6IO5nn84TKArsi3cjpIqaD",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948296,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:41:01Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 12676,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "moved along",
|
|
||||||
"master_metadata_album_artist_name": "wilt",
|
|
||||||
"master_metadata_album_album_name": "moved along",
|
|
||||||
"spotify_track_uri": "spotify:track:3CZZnpgvHNR71M4QnkQjzl",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": true,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948346,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:42:44Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 33263,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Air Guitar",
|
|
||||||
"master_metadata_album_artist_name": "Sobs",
|
|
||||||
"master_metadata_album_album_name": "Air Guitar",
|
|
||||||
"spotify_track_uri": "spotify:track:1ZL73Fic49PdXUSvL69wh8",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": true,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948460,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:42:56Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 9943,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Pharmacist",
|
|
||||||
"master_metadata_album_artist_name": "Alvvays",
|
|
||||||
"master_metadata_album_album_name": "Blue Rev",
|
|
||||||
"spotify_track_uri": "spotify:track:3r2vyNnqFKr6IraCqLtoBI",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": true,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948563,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:44:41Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 28573,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "freequent letdown",
|
|
||||||
"master_metadata_album_artist_name": "illuminati hotties",
|
|
||||||
"master_metadata_album_album_name": "FREE I.H: This Is Not the One You've Been Waiting For",
|
|
||||||
"spotify_track_uri": "spotify:track:5ZJfOkp2r5AbLjRdnu3UQd",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": true,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948576,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:46:12Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 6041,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Choke",
|
|
||||||
"master_metadata_album_artist_name": "I DONT KNOW HOW BUT THEY FOUND ME",
|
|
||||||
"master_metadata_album_album_name": "Choke",
|
|
||||||
"spotify_track_uri": "spotify:track:37mfTcSlX60JtAvAETytGs",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948680,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:47:27Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 28523,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "We Own the Night",
|
|
||||||
"master_metadata_album_artist_name": "Dance Gavin Dance",
|
|
||||||
"master_metadata_album_album_name": "Instant Gratification",
|
|
||||||
"spotify_track_uri": "spotify:track:7xCcUcMcGsIYGKUVgBZUw5",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948771,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:52:13Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 72901,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "鏡面の波",
|
|
||||||
"master_metadata_album_artist_name": "YURiKA",
|
|
||||||
"master_metadata_album_album_name": "鏡面の波",
|
|
||||||
"spotify_track_uri": "spotify:track:17pYAFEZjKZFU5PHiUMzqx",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745948847,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:52:34Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 15443,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "パレイド",
|
|
||||||
"master_metadata_album_artist_name": "syh",
|
|
||||||
"master_metadata_album_album_name": "パレイド",
|
|
||||||
"spotify_track_uri": "spotify:track:7uXzW6dPhkd4NbRv8sLNS6",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745949133,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:53:33Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 40213,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Burning Friday Night",
|
|
||||||
"master_metadata_album_artist_name": "Lucky Kilimanjaro",
|
|
||||||
"master_metadata_album_album_name": "FULLCOLOR",
|
|
||||||
"spotify_track_uri": "spotify:track:1NlkoYEA1ndLQIKzXTPh9V",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745949154,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:53:45Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 11946,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Better Things",
|
|
||||||
"master_metadata_album_artist_name": "aespa",
|
|
||||||
"master_metadata_album_album_name": "Drama - The 4th Mini Album",
|
|
||||||
"spotify_track_uri": "spotify:track:330IIz7d75eqAsKq1xhzXR",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745949212,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:53:57Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 9953,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Thirsty",
|
|
||||||
"master_metadata_album_artist_name": "aespa",
|
|
||||||
"master_metadata_album_album_name": "MY WORLD - The 3rd Mini Album",
|
|
||||||
"spotify_track_uri": "spotify:track:6nICBdDevG4NZysIqDFPEa",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745949225,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:54:47Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 44470,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Lucid Dream",
|
|
||||||
"master_metadata_album_artist_name": "aespa",
|
|
||||||
"master_metadata_album_album_name": "Savage - The 1st Mini Album",
|
|
||||||
"spotify_track_uri": "spotify:track:285Bh5EkbxGGE76ge8JDbH",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745949237,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:55:59Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 70353,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Girls Never Die",
|
|
||||||
"master_metadata_album_artist_name": "tripleS",
|
|
||||||
"master_metadata_album_album_name": "<ASSEMBLE24>",
|
|
||||||
"spotify_track_uri": "spotify:track:45OflED18VsURGw2z0Y6Cv",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745949286,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T17:58:34Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 8546,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Midas Touch",
|
|
||||||
"master_metadata_album_artist_name": "KISS OF LIFE",
|
|
||||||
"master_metadata_album_album_name": "Midas Touch",
|
|
||||||
"spotify_track_uri": "spotify:track:0vaxYDAuAO1nPolC6bQp7V",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745949358,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T19:59:23Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 3033,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "I Will Go To You Like the First Snow",
|
|
||||||
"master_metadata_album_artist_name": "AILEE",
|
|
||||||
"master_metadata_album_album_name": "Guardian (Original Television Soundtrack), Pt. 9",
|
|
||||||
"spotify_track_uri": "spotify:track:2BPXILn0MqOe5WroVXlvN1",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "logout",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": false,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745949513,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T21:55:06Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 45964,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Ready or Not",
|
|
||||||
"master_metadata_album_artist_name": "Bridgit Mendler",
|
|
||||||
"master_metadata_album_album_name": "Hello My Name Is...",
|
|
||||||
"spotify_track_uri": "spotify:track:5xvUgoVED1F4mBu8FL0HaW",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745963659,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T22:04:53Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 44523,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "お勉強しといてよ",
|
|
||||||
"master_metadata_album_artist_name": "ZUTOMAYO",
|
|
||||||
"master_metadata_album_album_name": "お勉強しといてよ",
|
|
||||||
"spotify_track_uri": "spotify:track:6k90ibcH1z8Mx9684nfuLW",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745963706,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T22:06:52Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 8893,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "Finale.",
|
|
||||||
"master_metadata_album_artist_name": "eill",
|
|
||||||
"master_metadata_album_album_name": "my dream box",
|
|
||||||
"spotify_track_uri": "spotify:track:2uGJ89l8tciHkYxzJF3xv6",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "endplay",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": true,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745964293,
|
|
||||||
"incognito_mode": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ts": "2025-04-29T23:12:45Z",
|
|
||||||
"platform": "windows",
|
|
||||||
"ms_played": 5883,
|
|
||||||
"conn_country": "US",
|
|
||||||
"ip_addr": "x.x.x.x",
|
|
||||||
"master_metadata_track_name": "ただ君に晴れ",
|
|
||||||
"master_metadata_album_artist_name": "ヨルシカ",
|
|
||||||
"master_metadata_album_album_name": "負け犬にアンコールはいらない",
|
|
||||||
"spotify_track_uri": "spotify:track:3wJHCry960drNlAUGrJLmz",
|
|
||||||
"episode_name": null,
|
|
||||||
"episode_show_name": null,
|
|
||||||
"spotify_episode_uri": null,
|
|
||||||
"audiobook_title": null,
|
|
||||||
"audiobook_uri": null,
|
|
||||||
"audiobook_chapter_uri": null,
|
|
||||||
"audiobook_chapter_title": null,
|
|
||||||
"reason_start": "clickrow",
|
|
||||||
"reason_end": "logout",
|
|
||||||
"shuffle": false,
|
|
||||||
"skipped": false,
|
|
||||||
"offline": false,
|
|
||||||
"offline_timestamp": 1745964412,
|
|
||||||
"incognito_mode": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
Binary file not shown.
|
|
@ -1,771 +0,0 @@
|
||||||
{
|
|
||||||
"maloja": {
|
|
||||||
"export_time": 1748738994
|
|
||||||
},
|
|
||||||
"scrobbles": [
|
|
||||||
{
|
|
||||||
"time": 1746434410,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"title": "\u4f0a\u5439",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746434682,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"title": "\u673d\u3061\u306a\u3044\u51a0",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746434899,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "\u30ad\u30df\u3060\u3051\u306e",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746435135,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"title": "Kokoro",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746435351,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"title": "Tsunagu",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746435518,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata",
|
|
||||||
"Philip Shibata"
|
|
||||||
],
|
|
||||||
"title": "\u4e3b\u306e\u5fa1\u540d\u3092",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata",
|
|
||||||
"Philip Shibata"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746435766,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"title": "\u306a\u3093\u3069\u3067\u3082",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746436009,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "Yomichi",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746436289,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "\u5341\u5b57\u67b6\u306e\u9670\u306b",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746436515,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Philip Shibata",
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"title": "\u3042\u306a\u305f\u3060\u3051\u304c",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Philip Shibata",
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746565073,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"title": "Kokoro",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746565287,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"title": "Tsunagu",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746565454,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata",
|
|
||||||
"Philip Shibata"
|
|
||||||
],
|
|
||||||
"title": "\u4e3b\u306e\u5fa1\u540d\u3092",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata",
|
|
||||||
"Philip Shibata"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746565702,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"title": "\u306a\u3093\u3069\u3067\u3082",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746565942,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "Yomichi",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746675800,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"title": "\u4f0a\u5439",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746676072,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"title": "\u673d\u3061\u306a\u3044\u51a0",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746676289,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "\u30ad\u30df\u3060\u3051\u306e",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746676518,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"title": "Kokoro",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746676732,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"title": "Tsunagu",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746838922,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"title": "\u4f0a\u5439",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746839194,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"title": "\u673d\u3061\u306a\u3044\u51a0",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746839410,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "\u30ad\u30df\u3060\u3051\u306e",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746839640,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"title": "Kokoro",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746839853,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"title": "Tsunagu",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746840020,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata",
|
|
||||||
"Philip Shibata"
|
|
||||||
],
|
|
||||||
"title": "\u4e3b\u306e\u5fa1\u540d\u3092",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata",
|
|
||||||
"Philip Shibata"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746840268,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"title": "\u306a\u3093\u3069\u3067\u3082",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1746840511,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "Yomichi",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747139500,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"title": "\u4f0a\u5439",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747139772,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"title": "\u673d\u3061\u306a\u3044\u51a0",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747139988,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "\u30ad\u30df\u3060\u3051\u306e",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747140218,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"title": "Kokoro",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Magnify Tokyo \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747140431,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"title": "Tsunagu",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Kanade Ishihara",
|
|
||||||
"Magnify Tokyo \u2022 Kanade Ishihara"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747140598,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata",
|
|
||||||
"Philip Shibata"
|
|
||||||
],
|
|
||||||
"title": "\u4e3b\u306e\u5fa1\u540d\u3092",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata",
|
|
||||||
"Philip Shibata"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747140846,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"title": "\u306a\u3093\u3069\u3067\u3082",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Magnify Tokyo \u2022 J.Rio",
|
|
||||||
"J.Rio"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747141089,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "Yomichi",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747141369,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"title": "\u5341\u5b57\u67b6\u306e\u9670\u306b",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Cherish",
|
|
||||||
"Magnify Tokyo \u2022 Cherish"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": 1747141595,
|
|
||||||
"track": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Philip Shibata",
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"title": "\u3042\u306a\u305f\u3060\u3051\u304c",
|
|
||||||
"album": {
|
|
||||||
"artists": [
|
|
||||||
"Lauren Horii",
|
|
||||||
"Philip Shibata",
|
|
||||||
"Magnify Tokyo \u2022 Philip Shibata \u2022 Lauren Horii"
|
|
||||||
],
|
|
||||||
"albumtitle": "Magnify Tokyo"
|
|
||||||
},
|
|
||||||
"length": null
|
|
||||||
},
|
|
||||||
"duration": null,
|
|
||||||
"origin": "client:default"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -61,7 +61,9 @@ func TestImportSpotify(t *testing.T) {
|
||||||
|
|
||||||
a, err := store.GetArtist(context.Background(), db.GetArtistOpts{Name: "The Story So Far"})
|
a, err := store.GetArtist(context.Background(), db.GetArtistOpts{Name: "The Story So Far"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
track, err := store.GetTrack(context.Background(), db.GetTrackOpts{Title: "Clairvoyant", ArtistIDs: []int32{a.ID}})
|
r, err := store.GetAlbum(context.Background(), db.GetAlbumOpts{ArtistID: a.ID, Title: "The Story So Far / Stick To Your Guns Split"})
|
||||||
|
require.NoError(t, err)
|
||||||
|
track, err := store.GetTrack(context.Background(), db.GetTrackOpts{Title: "Clairvoyant", ReleaseID: r.ID, ArtistIDs: []int32{a.ID}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Log(track)
|
t.Log(track)
|
||||||
assert.Equal(t, "Clairvoyant", track.Title)
|
assert.Equal(t, "Clairvoyant", track.Title)
|
||||||
|
|
@ -107,15 +109,15 @@ func TestImportLastFM(t *testing.T) {
|
||||||
artist, err := store.GetArtist(context.Background(), db.GetArtistOpts{MusicBrainzID: uuid.MustParse("4b00640f-3be6-43f8-9b34-ff81bd89320a")})
|
artist, err := store.GetArtist(context.Background(), db.GetArtistOpts{MusicBrainzID: uuid.MustParse("4b00640f-3be6-43f8-9b34-ff81bd89320a")})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "OurR", artist.Name)
|
assert.Equal(t, "OurR", artist.Name)
|
||||||
artist, err = store.GetArtist(context.Background(), db.GetArtistOpts{Name: "CHUU"})
|
artist, err = store.GetArtist(context.Background(), db.GetArtistOpts{Name: "Necry Talkie"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
track, err := store.GetTrack(context.Background(), db.GetTrackOpts{Title: "because I'm stupid?", ArtistIDs: []int32{artist.ID}})
|
track, err := store.GetTrack(context.Background(), db.GetTrackOpts{Title: "放課後の記憶", ReleaseID: album.ID, ArtistIDs: []int32{artist.ID}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Log(track)
|
t.Log(track)
|
||||||
listens, err := store.GetListensPaginated(context.Background(), db.GetItemsOpts{TrackID: int(track.ID), Timeframe: db.Timeframe{Period: db.PeriodAllTime}})
|
listens, err := store.GetListensPaginated(context.Background(), db.GetItemsOpts{TrackID: int(track.ID), Timeframe: db.Timeframe{Period: db.PeriodAllTime}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, listens.Items, 1)
|
require.Len(t, listens.Items, 1)
|
||||||
assert.WithinDuration(t, time.Unix(1749776100, 0), listens.Items[0].Time, 1*time.Second)
|
assert.WithinDuration(t, time.Unix(1749774900, 0), listens.Items[0].Time, 1*time.Second)
|
||||||
|
|
||||||
truncateTestData(t)
|
truncateTestData(t)
|
||||||
}
|
}
|
||||||
|
|
@ -141,15 +143,15 @@ func TestImportLastFM_MbzDisabled(t *testing.T) {
|
||||||
artist, err := store.GetArtist(context.Background(), db.GetArtistOpts{MusicBrainzID: uuid.MustParse("4b00640f-3be6-43f8-9b34-ff81bd89320a")})
|
artist, err := store.GetArtist(context.Background(), db.GetArtistOpts{MusicBrainzID: uuid.MustParse("4b00640f-3be6-43f8-9b34-ff81bd89320a")})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "OurR", artist.Name)
|
assert.Equal(t, "OurR", artist.Name)
|
||||||
artist, err = store.GetArtist(context.Background(), db.GetArtistOpts{Name: "CHUU"})
|
artist, err = store.GetArtist(context.Background(), db.GetArtistOpts{Name: "Necry Talkie"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
track, err := store.GetTrack(context.Background(), db.GetTrackOpts{Title: "because I'm stupid?", ArtistIDs: []int32{artist.ID}})
|
track, err := store.GetTrack(context.Background(), db.GetTrackOpts{Title: "放課後の記憶", ReleaseID: album.ID, ArtistIDs: []int32{artist.ID}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
t.Log(track)
|
t.Log(track)
|
||||||
listens, err := store.GetListensPaginated(context.Background(), db.GetItemsOpts{TrackID: int(track.ID), Timeframe: db.Timeframe{Period: db.PeriodAllTime}})
|
listens, err := store.GetListensPaginated(context.Background(), db.GetItemsOpts{TrackID: int(track.ID), Timeframe: db.Timeframe{Period: db.PeriodAllTime}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, listens.Items, 1)
|
require.Len(t, listens.Items, 1)
|
||||||
assert.WithinDuration(t, time.Unix(1749776100, 0), listens.Items[0].Time, 1*time.Second)
|
assert.WithinDuration(t, time.Unix(1749774900, 0), listens.Items[0].Time, 1*time.Second)
|
||||||
|
|
||||||
truncateTestData(t)
|
truncateTestData(t)
|
||||||
}
|
}
|
||||||
|
|
@ -284,11 +286,11 @@ func TestImportKoito(t *testing.T) {
|
||||||
|
|
||||||
// ensure all artists are saved
|
// ensure all artists are saved
|
||||||
_, err = store.GetArtist(ctx, db.GetArtistOpts{Name: "American Football"})
|
_, err = store.GetArtist(ctx, db.GetArtistOpts{Name: "American Football"})
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
_, err = store.GetArtist(ctx, db.GetArtistOpts{Name: "Rachel Goswell"})
|
_, err = store.GetArtist(ctx, db.GetArtistOpts{Name: "Rachel Goswell"})
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
_, err = store.GetArtist(ctx, db.GetArtistOpts{Name: "Elizabeth Powell"})
|
_, err = store.GetArtist(ctx, db.GetArtistOpts{Name: "Elizabeth Powell"})
|
||||||
require.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// ensure artist aliases are saved
|
// ensure artist aliases are saved
|
||||||
artist, err := store.GetArtist(ctx, db.GetArtistOpts{MusicBrainzID: suzukiMBID})
|
artist, err := store.GetArtist(ctx, db.GetArtistOpts{MusicBrainzID: suzukiMBID})
|
||||||
|
|
@ -323,7 +325,9 @@ func TestImportKoito(t *testing.T) {
|
||||||
|
|
||||||
artist, err = store.GetArtist(ctx, db.GetArtistOpts{MusicBrainzID: suzukiMBID})
|
artist, err = store.GetArtist(ctx, db.GetArtistOpts{MusicBrainzID: suzukiMBID})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
_, err = store.GetTrack(ctx, db.GetTrackOpts{Title: "GIRI GIRI", ArtistIDs: []int32{artist.ID}})
|
album, err = store.GetAlbum(ctx, db.GetAlbumOpts{ArtistID: artist.ID, Title: "GIRI GIRI"})
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = store.GetTrack(ctx, db.GetTrackOpts{Title: "GIRI GIRI", ReleaseID: album.ID, ArtistIDs: []int32{artist.ID}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
count, err := store.CountTracks(ctx, db.Timeframe{Period: db.PeriodAllTime})
|
count, err := store.CountTracks(ctx, db.Timeframe{Period: db.PeriodAllTime})
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func AssociateTrack(ctx context.Context, d db.DB, opts AssociateTrackOpts) (*mod
|
||||||
return matchTrackByMbzID(ctx, d, opts)
|
return matchTrackByMbzID(ctx, d, opts)
|
||||||
} else {
|
} else {
|
||||||
l.Debug().Msgf("Associating track '%s' by title and artist", opts.TrackName)
|
l.Debug().Msgf("Associating track '%s' by title and artist", opts.TrackName)
|
||||||
return matchTrackByTitleAndArtist(ctx, d, opts)
|
return matchTrackByTrackInfo(ctx, d, opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ func matchTrackByMbzID(ctx context.Context, d db.DB, opts AssociateTrackOpts) (*
|
||||||
return nil, fmt.Errorf("matchTrackByMbzID: %w", err)
|
return nil, fmt.Errorf("matchTrackByMbzID: %w", err)
|
||||||
} else {
|
} else {
|
||||||
l.Debug().Msgf("Track '%s' could not be found by MusicBrainz ID", opts.TrackName)
|
l.Debug().Msgf("Track '%s' could not be found by MusicBrainz ID", opts.TrackName)
|
||||||
track, err := matchTrackByTitleAndArtist(ctx, d, opts)
|
track, err := matchTrackByTrackInfo(ctx, d, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("matchTrackByMbzID: %w", err)
|
return nil, fmt.Errorf("matchTrackByMbzID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -73,28 +73,30 @@ func matchTrackByMbzID(ctx context.Context, d db.DB, opts AssociateTrackOpts) (*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchTrackByTitleAndArtist(ctx context.Context, d db.DB, opts AssociateTrackOpts) (*models.Track, error) {
|
func matchTrackByTrackInfo(ctx context.Context, d db.DB, opts AssociateTrackOpts) (*models.Track, error) {
|
||||||
l := logger.FromContext(ctx)
|
l := logger.FromContext(ctx)
|
||||||
// try provided track title
|
// try provided track title
|
||||||
track, err := d.GetTrack(ctx, db.GetTrackOpts{
|
track, err := d.GetTrack(ctx, db.GetTrackOpts{
|
||||||
Title: opts.TrackName,
|
Title: opts.TrackName,
|
||||||
|
ReleaseID: opts.AlbumID,
|
||||||
ArtistIDs: opts.ArtistIDs,
|
ArtistIDs: opts.ArtistIDs,
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
l.Debug().Msgf("Track '%s' found by title and artist match", track.Title)
|
l.Debug().Msgf("Track '%s' found by title, release and artist match", track.Title)
|
||||||
return track, nil
|
return track, nil
|
||||||
} else if !errors.Is(err, pgx.ErrNoRows) {
|
} else if !errors.Is(err, pgx.ErrNoRows) {
|
||||||
return nil, fmt.Errorf("matchTrackByTitleAndArtist: %w", err)
|
return nil, fmt.Errorf("matchTrackByTrackInfo: %w", err)
|
||||||
} else {
|
} else {
|
||||||
if opts.TrackMbzID != uuid.Nil {
|
if opts.TrackMbzID != uuid.Nil {
|
||||||
mbzTrack, err := opts.Mbzc.GetTrack(ctx, opts.TrackMbzID)
|
mbzTrack, err := opts.Mbzc.GetTrack(ctx, opts.TrackMbzID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
track, err := d.GetTrack(ctx, db.GetTrackOpts{
|
track, err := d.GetTrack(ctx, db.GetTrackOpts{
|
||||||
Title: mbzTrack.Title,
|
Title: mbzTrack.Title,
|
||||||
|
ReleaseID: opts.AlbumID,
|
||||||
ArtistIDs: opts.ArtistIDs,
|
ArtistIDs: opts.ArtistIDs,
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
l.Debug().Msgf("Track '%s' found by MusicBrainz title and artist match", opts.TrackName)
|
l.Debug().Msgf("Track '%s' found by MusicBrainz title, release and artist match", opts.TrackName)
|
||||||
return track, nil
|
return track, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -108,7 +110,7 @@ func matchTrackByTitleAndArtist(ctx context.Context, d db.DB, opts AssociateTrac
|
||||||
Duration: opts.Duration,
|
Duration: opts.Duration,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("matchTrackByTitleAndArtist: %w", err)
|
return nil, fmt.Errorf("matchTrackByTrackInfo: %w", err)
|
||||||
}
|
}
|
||||||
if opts.TrackMbzID == uuid.Nil {
|
if opts.TrackMbzID == uuid.Nil {
|
||||||
l.Info().Msgf("Created track '%s' with title and artist", opts.TrackName)
|
l.Info().Msgf("Created track '%s' with title and artist", opts.TrackName)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ type GetTrackOpts struct {
|
||||||
ID int32
|
ID int32
|
||||||
MusicBrainzID uuid.UUID
|
MusicBrainzID uuid.UUID
|
||||||
Title string
|
Title string
|
||||||
|
ReleaseID int32
|
||||||
ArtistIDs []int32
|
ArtistIDs []int32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,15 @@ func (d *Psql) GetTrack(ctx context.Context, opts db.GetTrackOpts) (*models.Trac
|
||||||
AlbumID: t.ReleaseID,
|
AlbumID: t.ReleaseID,
|
||||||
Duration: t.Duration,
|
Duration: t.Duration,
|
||||||
}
|
}
|
||||||
} else if len(opts.ArtistIDs) > 0 {
|
} else if len(opts.ArtistIDs) > 0 && opts.ReleaseID != 0 {
|
||||||
l.Debug().Msgf("Fetching track from DB with title '%s' and artist id(s) '%v'", opts.Title, opts.ArtistIDs)
|
l.Debug().Msgf("Fetching track from DB from release id %d with title '%s' and artist id(s) '%v'", opts.ReleaseID, opts.Title, opts.ArtistIDs)
|
||||||
t, err := d.q.GetTrackByTitleAndArtists(ctx, repository.GetTrackByTitleAndArtistsParams{
|
t, err := d.q.GetTrackByTrackInfo(ctx, repository.GetTrackByTrackInfoParams{
|
||||||
Title: opts.Title,
|
Title: opts.Title,
|
||||||
Column2: opts.ArtistIDs,
|
ReleaseID: opts.ReleaseID,
|
||||||
|
Column3: opts.ArtistIDs,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("GetTrack: GetTrackByTitleAndArtists: %w", err)
|
return nil, fmt.Errorf("GetTrack: GetTrackByTrackInfo: %w", err)
|
||||||
}
|
}
|
||||||
track = models.Track{
|
track = models.Track{
|
||||||
ID: t.ID,
|
ID: t.ID,
|
||||||
|
|
|
||||||
|
|
@ -16,55 +16,55 @@ func testDataForTracks(t *testing.T) {
|
||||||
|
|
||||||
// Insert artists
|
// Insert artists
|
||||||
err := store.Exec(context.Background(),
|
err := store.Exec(context.Background(),
|
||||||
`INSERT INTO artists (musicbrainz_id)
|
`INSERT INTO artists (musicbrainz_id)
|
||||||
VALUES ('00000000-0000-0000-0000-000000000001'),
|
VALUES ('00000000-0000-0000-0000-000000000001'),
|
||||||
('00000000-0000-0000-0000-000000000002')`)
|
('00000000-0000-0000-0000-000000000002')`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Insert artist aliases
|
// Insert artist aliases
|
||||||
err = store.Exec(context.Background(),
|
err = store.Exec(context.Background(),
|
||||||
`INSERT INTO artist_aliases (artist_id, alias, source, is_primary)
|
`INSERT INTO artist_aliases (artist_id, alias, source, is_primary)
|
||||||
VALUES (1, 'Artist One', 'Testing', true),
|
VALUES (1, 'Artist One', 'Testing', true),
|
||||||
(2, 'Artist Two', 'Testing', true)`)
|
(2, 'Artist Two', 'Testing', true)`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Insert release groups
|
// Insert release groups
|
||||||
err = store.Exec(context.Background(),
|
err = store.Exec(context.Background(),
|
||||||
`INSERT INTO releases (musicbrainz_id)
|
`INSERT INTO releases (musicbrainz_id)
|
||||||
VALUES ('00000000-0000-0000-0000-000000000011'),
|
VALUES ('00000000-0000-0000-0000-000000000011'),
|
||||||
('00000000-0000-0000-0000-000000000022')`)
|
('00000000-0000-0000-0000-000000000022')`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Insert release aliases
|
// Insert release aliases
|
||||||
err = store.Exec(context.Background(),
|
err = store.Exec(context.Background(),
|
||||||
`INSERT INTO release_aliases (release_id, alias, source, is_primary)
|
`INSERT INTO release_aliases (release_id, alias, source, is_primary)
|
||||||
VALUES (1, 'Release Group One', 'Testing', true),
|
VALUES (1, 'Release Group One', 'Testing', true),
|
||||||
(2, 'Release Group Two', 'Testing', true)`)
|
(2, 'Release Group Two', 'Testing', true)`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Insert tracks
|
// Insert tracks
|
||||||
err = store.Exec(context.Background(),
|
err = store.Exec(context.Background(),
|
||||||
`INSERT INTO tracks (musicbrainz_id, release_id, duration)
|
`INSERT INTO tracks (musicbrainz_id, release_id, duration)
|
||||||
VALUES ('11111111-1111-1111-1111-111111111111', 1, 100),
|
VALUES ('11111111-1111-1111-1111-111111111111', 1, 100),
|
||||||
('22222222-2222-2222-2222-222222222222', 2, 100)`)
|
('22222222-2222-2222-2222-222222222222', 2, 100)`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Insert track aliases
|
// Insert track aliases
|
||||||
err = store.Exec(context.Background(),
|
err = store.Exec(context.Background(),
|
||||||
`INSERT INTO track_aliases (track_id, alias, source, is_primary)
|
`INSERT INTO track_aliases (track_id, alias, source, is_primary)
|
||||||
VALUES (1, 'Track One', 'Testing', true),
|
VALUES (1, 'Track One', 'Testing', true),
|
||||||
(2, 'Track Two', 'Testing', true)`)
|
(2, 'Track Two', 'Testing', true)`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Associate tracks with artists
|
// Associate tracks with artists
|
||||||
err = store.Exec(context.Background(),
|
err = store.Exec(context.Background(),
|
||||||
`INSERT INTO artist_tracks (artist_id, track_id)
|
`INSERT INTO artist_tracks (artist_id, track_id)
|
||||||
VALUES (1, 1), (2, 2)`)
|
VALUES (1, 1), (2, 2)`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Associate tracks with artists
|
// Associate tracks with artists
|
||||||
err = store.Exec(context.Background(),
|
err = store.Exec(context.Background(),
|
||||||
`INSERT INTO listens (user_id, track_id, listened_at)
|
`INSERT INTO listens (user_id, track_id, listened_at)
|
||||||
VALUES (1, 1, NOW()), (1, 2, NOW())`)
|
VALUES (1, 1, NOW()), (1, 2, NOW())`)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
@ -88,9 +88,10 @@ func TestGetTrack(t *testing.T) {
|
||||||
assert.Equal(t, "Track Two", track.Title)
|
assert.Equal(t, "Track Two", track.Title)
|
||||||
assert.EqualValues(t, 100, track.TimeListened)
|
assert.EqualValues(t, 100, track.TimeListened)
|
||||||
|
|
||||||
// Test GetTrack by Title and ArtistIDs
|
// Test GetTrack by Title, Release and ArtistIDs
|
||||||
track, err = store.GetTrack(ctx, db.GetTrackOpts{
|
track, err = store.GetTrack(ctx, db.GetTrackOpts{
|
||||||
Title: "Track One",
|
Title: "Track One",
|
||||||
|
ReleaseID: 1,
|
||||||
ArtistIDs: []int32{1},
|
ArtistIDs: []int32{1},
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
@ -99,7 +100,7 @@ func TestGetTrack(t *testing.T) {
|
||||||
assert.EqualValues(t, 100, track.TimeListened)
|
assert.EqualValues(t, 100, track.TimeListened)
|
||||||
|
|
||||||
// Test GetTrack with insufficient information
|
// Test GetTrack with insufficient information
|
||||||
_, err = store.GetTrack(ctx, db.GetTrackOpts{})
|
_, err = store.GetTrack(ctx, db.GetTrackOpts{Title: "Track One"})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
func TestSaveTrack(t *testing.T) {
|
func TestSaveTrack(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@ func ImportKoitoFile(ctx context.Context, store db.DB, filename string) error {
|
||||||
track, err := store.GetTrack(ctx, db.GetTrackOpts{
|
track, err := store.GetTrack(ctx, db.GetTrackOpts{
|
||||||
MusicBrainzID: mbid,
|
MusicBrainzID: mbid,
|
||||||
Title: getPrimaryAliasFromAliasSlice(data.Listens[i].Track.Aliases),
|
Title: getPrimaryAliasFromAliasSlice(data.Listens[i].Track.Aliases),
|
||||||
|
ReleaseID: albumId,
|
||||||
ArtistIDs: artistIds,
|
ArtistIDs: artistIds,
|
||||||
})
|
})
|
||||||
if errors.Is(err, pgx.ErrNoRows) {
|
if errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
|
|
||||||
|
|
@ -417,23 +417,25 @@ func (q *Queries) GetTrackByMbzID(ctx context.Context, musicbrainzID *uuid.UUID)
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTrackByTitleAndArtists = `-- name: GetTrackByTitleAndArtists :one
|
const getTrackByTrackInfo = `-- name: GetTrackByTrackInfo :one
|
||||||
SELECT t.id, t.musicbrainz_id, t.duration, t.release_id, t.title
|
SELECT t.id, t.musicbrainz_id, t.duration, t.release_id, t.title
|
||||||
FROM tracks_with_title t
|
FROM tracks_with_title t
|
||||||
JOIN artist_tracks at ON at.track_id = t.id
|
JOIN artist_tracks at ON at.track_id = t.id
|
||||||
WHERE t.title = $1
|
WHERE t.title = $1
|
||||||
AND at.artist_id = ANY($2::int[])
|
AND at.artist_id = ANY($3::int[])
|
||||||
|
AND t.release_id = $2
|
||||||
GROUP BY t.id, t.title, t.musicbrainz_id, t.duration, t.release_id
|
GROUP BY t.id, t.title, t.musicbrainz_id, t.duration, t.release_id
|
||||||
HAVING COUNT(DISTINCT at.artist_id) = cardinality($2::int[])
|
HAVING COUNT(DISTINCT at.artist_id) = cardinality($3::int[])
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetTrackByTitleAndArtistsParams struct {
|
type GetTrackByTrackInfoParams struct {
|
||||||
Title string
|
Title string
|
||||||
Column2 []int32
|
ReleaseID int32
|
||||||
|
Column3 []int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetTrackByTitleAndArtists(ctx context.Context, arg GetTrackByTitleAndArtistsParams) (TracksWithTitle, error) {
|
func (q *Queries) GetTrackByTrackInfo(ctx context.Context, arg GetTrackByTrackInfoParams) (TracksWithTitle, error) {
|
||||||
row := q.db.QueryRow(ctx, getTrackByTitleAndArtists, arg.Title, arg.Column2)
|
row := q.db.QueryRow(ctx, getTrackByTrackInfo, arg.Title, arg.ReleaseID, arg.Column3)
|
||||||
var i TracksWithTitle
|
var i TracksWithTitle
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
&i.ID,
|
&i.ID,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue