diff --git a/AGENTS.md b/AGENTS.md
index eb2c74fc..9f60b0d4 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -22,7 +22,6 @@
- Kotlin: `2.3.0`, JVM target: `11` (compile/target compatibility in both `composeApp/build.gradle.kts` and `plugin_interfaces/build.gradle.kts`).
## Codegen and plugin packaging
-- OpenAPI client generated from `composeApp/specs/listenbrainz-openapi.yaml` via KMPGen tasks (`kmpgenPrepare`, `kmpgenGenerateAll`) in `:composeApp`.
- JS plugin bundles: `:js_plugin_example:packageDevelopmentPlugin` and `:js_plugin_example:packageProductionPlugin`. Output is `.smplug` files in `js_plugin_example/build/distributions/`.
- Zipline plugin entrypoint: `mainFunction = "dev.krtirtho.js_plugin_example.main"` in `js_plugin_example/build.gradle.kts`. Plugin metadata from `js_plugin_example/plugin.json`.
diff --git a/build.gradle.kts b/build.gradle.kts
index c2b11201..eb5958c7 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -29,6 +29,5 @@ plugins {
alias(libs.plugins.androidKotlinMultiplatformLibrary) apply false
alias(libs.plugins.zipline.gradle.plugin) apply false
alias(libs.plugins.spotubeGradle) apply false
- alias(libs.plugins.kmpgen) apply false
alias(libs.plugins.vlcjBundler) apply false
}
\ No newline at end of file
diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts
index c0a1fd96..5252f648 100644
--- a/composeApp/build.gradle.kts
+++ b/composeApp/build.gradle.kts
@@ -29,7 +29,6 @@ plugins {
alias(libs.plugins.composeHotReload)
alias(libs.plugins.kotlinSerialization)
alias(libs.plugins.zipline.gradle.plugin)
- alias(libs.plugins.kmpgen)
alias(libs.plugins.vlcjBundler)
}
@@ -38,14 +37,6 @@ vlcjBundler {
objectName = "VLCBundleLoaderGenerated" // or rename the object
}
-kmpgen {
- spec(
- packageName = "dev.krtirtho.spotube.listenbrainz"
- ) {
- specFile = file("./specs/listenbrainz-openapi.yaml")
- }
-}
-
kotlin {
// Note: For Android application modules, androidTarget() is still required as of AGP 8.x.
// The deprecation warning is expected. For libraries, use the androidKotlinMultiplatformLibrary plugin instead.
@@ -103,6 +94,8 @@ kotlin {
// ktor
implementation(libs.ktor.client.core)
implementation(libs.ktor.client.logging)
+ implementation(libs.ktor.client.content.negotiation)
+ implementation(libs.ktor.client.serialization.kotlinx.json)
implementation(libs.ktor.client.cio)
implementation(libs.ktor.server.core)
implementation(libs.ktor.server.cio)
diff --git a/composeApp/specs/listenbrainz-openapi.yaml b/composeApp/specs/listenbrainz-openapi.yaml
deleted file mode 100644
index 73ed71bc..00000000
--- a/composeApp/specs/listenbrainz-openapi.yaml
+++ /dev/null
@@ -1,12322 +0,0 @@
-# Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-openapi: 3.0.3
-info:
- description: OpenAPI client defintion.
- license:
- name: Apache 2.0
- url: http://www.apache.org/licenses/LICENSE-2.0.html
- termsOfService: https://listenbrainz.org/terms-of-service/
- title: ListenBrainz Swagger - OpenAPI 3.0
- version: v-2025-11-04.0
-servers:
-- url: https://api.listenbrainz.org
-tags:
-- description: |-
- ListenBrainz has a statistics infrastructure that collects and computes
- statistics from the listen data that has been stored in the database.
- The endpoints in this section offer a way to get this data programmatically.
- name: lbStats
-- description: The ListenBrainz server supports the following end-points for submitting
- and fetching listens.
- name: lbCore
-- description: The playlists API allows for the creation and editing of lists of recordings.
- name: lbPlaylists
-- description: Feedback API and Pinned Recording API.
- name: lbRecordings
-- description: The popularity APIs return the total listen and listeners count for
- various entities and also a way to query top entities for a given artist.
- name: lbPopularity
-- description: The metadata API looks up MusicBrainz metadata for recordings.
- name: lbMetadata
-- description: These api endpoints allow to create and fetch timeline events for a
- user.
- name: lbSocial
-- description: "ListenBrainz uses collaborative filtering to generate recording recommendations,\
- \ which may be further processed to generate playlists for users."
- name: lbRecommendations
-- description: Various ListenBrainz API endpoints that are not documented elsewhere.
- name: lbMisc
-- description: ListenBrainz has a (cover) art infrastructure that creates new cover
- art from a user's statistics or a user's instructions on how to composite a cover
- art grid.
- name: lbArt
-paths:
- /1/search/users:
- get:
- operationId: searchUsers
- parameters:
- - description: Input on which search operation is to be performed.
- in: query
- name: search_term
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/searchUsers"
- description: Successful operation.
- summary: Search a ListenBrainz-registered user.
- tags:
- - lbCore
- /1/submit-listens:
- post:
- operationId: submitListens
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/submitListens"
- required: true
- responses:
- "200":
- description: Listen(s) accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- security:
- - ApiKeyAuth: []
- summary: Submit listens to the server.
- tags:
- - lbCore
- /1/validate-token:
- get:
- operationId: validateToken
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/validateToken"
- description: The user token is valid/invalid.
- "400":
- description: No token was sent to the endpoint.
- security:
- - ApiKeyAuth: []
- summary: Check whether a User Token is a valid entry in the database.
- tags:
- - lbCore
- /1/user/{user_name}/listens:
- get:
- operationId: listensForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - description: "If you specify a 'max_ts' timestamp, listens with listened_at\
- \ less than (but not including) this value will be returned."
- in: query
- name: max_ts
- schema:
- type: integer
- - description: "If you specify a 'min_ts' timestamp, listens with listened_at\
- \ greater than (but not including) this value will be returned."
- in: query
- name: min_ts
- schema:
- type: integer
- - description: "Optional, number of listens to return."
- in: query
- name: count
- required: false
- schema:
- default: 25
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/listensForUser"
- description: "Yay, you have data!"
- "404":
- description: The requested user was not found.
- summary: Get listens for user 'user_name'.
- tags:
- - lbCore
- /1/user/{user_name}/listen-count:
- get:
- operationId: listenCountForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/listenCountForUser"
- description: "Yay, you have listen counts!"
- "404":
- description: The requested user was not found.
- summary: Get the number of listens for a user 'user_name'.
- tags:
- - lbCore
- /1/user/{user_name}/playing-now:
- get:
- operationId: playingNowForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/playingNowForUser"
- description: "Yay, you have data!"
- "404":
- description: The requested user was not found.
- summary: Get the listen being played right now for user 'user_name'
- tags:
- - lbCore
- /1/user/{user_name}/similar-users:
- get:
- operationId: similarUsersForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/similarUsersForUser"
- description: "Yay, you have data!"
- "404":
- description: The requested user was not found.
- summary: Get the listen being played right now for user 'user_name'.
- tags:
- - lbCore
- /1/user/{user_name}/similar-to/{other_user_name}:
- get:
- operationId: similarityOfUserForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: path
- name: other_user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/similarityOfUserForUser"
- description: "Yay, you have data!"
- "404":
- description: The requested user was not found.
- summary: "Get the similarity of 'user_name' and 'other_user_name', based on\
- \ their listening history."
- tags:
- - lbCore
- /1/delete-listen:
- post:
- operationId: deleteListen
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/deleteListen"
- required: true
- responses:
- "200":
- description: Listen deleted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- security:
- - ApiKeyAuth: []
- summary: Delete a particular listen from a user's listen history.
- tags:
- - lbCore
- /1/latest-import:
- get:
- operationId: latestImport
- parameters:
- - description: The MusicBrainz ID of the user whose data is needed.
- in: query
- name: user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/latestImport"
- description: "Yay, you have data!"
- security:
- - ApiKeyAuth: []
- summary: Get the timestamp of the newest listen submitted by a user in previous
- imports to ListenBrainz.
- tags:
- - lbCore
- /1/user/{user_name}/services:
- get:
- operationId: servicesForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/servicesForUser"
- description: "Yay, you have data!"
- "401":
- description: Invalid authorization.
- "403":
- description: "Forbidden, you do not have permissions to view this user's\
- \ information."
- "404":
- description: The requested user was not found.
- security:
- - ApiKeyAuth: []
- summary: Get list of services which are connected to a given user's account.
- tags:
- - lbCore
- /1/user/{playlist_user_name}/playlists/recommendations:
- get:
- operationId: recommendationPlaylistsForUser
- parameters:
- - in: path
- name: playlist_user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/playlists"
- description: Success.
- "404":
- description: User not found.
- summary: Fetch recommendation playlist metadata in JSPF format without recordings
- for 'playlist_user_name'. This endpoint only lists playlists that are to be
- shown on the listenbrainz.org recommendations pages.
- tags:
- - lbCore
- /1/user/{playlist_user_name}/playlists/search:
- get:
- operationId: searchPlaylistForUser
- parameters:
- - in: path
- name: playlist_user_name
- required: true
- schema:
- type: string
- - in: query
- name: query
- required: true
- schema:
- type: string
- - description: The number of playlists to return (for pagination).
- in: query
- name: count
- required: false
- schema:
- default: 25
- type: integer
- - description: The offset of into the list of playlists to return (for pagination).
- in: query
- name: offset
- required: false
- schema:
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/playlists"
- description: "Yay, you have data!"
- "404":
- description: The requested user was not found.
- summary: Search for a playlist by name for a user.
- tags:
- - lbCore
- /1/lb-radio/artist/{seed_artist_mbid}:
- get:
- operationId: lbRadioRecordingsForArtist
- parameters:
- - in: path
- name: seed_artist_mbid
- required: true
- schema:
- format: uuid
- type: string
- - description: "The mode that LB radio should use. Must be easy, medium or hard."
- in: query
- name: mode
- required: true
- schema:
- $ref: "#/components/schemas/Mode"
- - description: The maximum number of similar artists to return recordings for.
- in: query
- name: max_similar_artists
- required: true
- schema:
- type: integer
- - description: "The maximum number of recordings to return for each artist.\
- \ If there are aren’t enough recordings, all available recordings will be\
- \ returned."
- in: query
- name: max_recordings_per_artist
- required: true
- schema:
- type: integer
- - description: "Popularity range percentage lower bound. A popularity range\
- \ is given to narrow down the recordings into a smaller target group. The\
- \ most popular recording(s) on LB have a pop percent of 100. The least popular\
- \ recordings have a score of 0. This range is not coupled to the specified\
- \ mode, but the mode would often determine the popularity range, so that\
- \ less popular recordings can be returned on the medium and harder modes."
- in: query
- name: pop_begin
- required: true
- schema:
- type: integer
- - description: Popularity range percentage upper bound.
- in: query
- name: pop_end
- required: true
- schema:
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/lbRadioRecordingsForArtist"
- description: "Yay, you have data!"
- "400":
- description: Invalid or missing param in request.
- summary: "Get recordings for use in LB radio with the given seed artist. The\
- \ endpoint returns a dict of all the similar artists, including the seed artist.\
- \ For each artists, there will be a list of dicts that contain recording_mbid,\
- \ similar_artist_mbid and total_listen_count."
- tags:
- - lbCore
- /1/lb-radio/tags:
- get:
- operationId: lbRadioTags
- parameters:
- - description: "The MusicBrainz tag to fetch recordings for, this parameter\
- \ can be specified multiple times. if more than one tag is specified, the\
- \ operator param should also be specified."
- in: query
- name: tag
- required: true
- schema:
- type: string
- - description: "Specify AND to retrieve recordings that have all the tags, otherwise\
- \ specify OR to retrieve recordings that have any one of the tags."
- in: query
- name: operator
- required: false
- schema:
- $ref: "#/components/schemas/Operator"
- - description: "Popularity range percentage lower bound. A popularity range\
- \ is given to narrow down the recordings into a smaller target group. The\
- \ most popular recording(s) on LB have a pop percent of 100. The least popular\
- \ recordings have a score of 0. This range is not coupled to the specified\
- \ mode, but the mode would often determine the popularity range, so that\
- \ less popular recordings can be returned on the medium and harder modes."
- in: query
- name: pop_begin
- required: true
- schema:
- type: integer
- - description: Popularity range percentage upper bound.
- in: query
- name: pop_end
- required: true
- schema:
- type: integer
- - description: "Optional, number of listens to return."
- in: query
- name: count
- required: true
- schema:
- default: 25
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/lbRadioTags"
- description: "Yay, you have data!"
- "400":
- description: Invalid or missing param in request.
- summary: Get recordings for use in LB radio with the specified tags that match
- the requested criteria.
- tags:
- - lbCore
- /1/stats/user/{user_name}/artists:
- get:
- operationId: topArtistsForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of artists to return"
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of artists to skip from the beginning, for\
- \ pagination"
- type: integer
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/topArtistsForUser"
- description: successful operation
- "204":
- description: "Statistics for the user haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: User not found.
- summary: Get top artists for user 'user_name'.
- tags:
- - lbStats
- /1/stats/user/{user_name}/releases:
- get:
- operationId: topReleasesForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of artists to return"
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of artists to skip from the beginning, for\
- \ pagination"
- type: integer
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/topReleasesForUser"
- description: "Successful query, you have data!"
- "204":
- description: "Statistics for the user haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: User not found.
- summary: Get top releases for user 'user_name'.
- tags:
- - lbStats
- /1/stats/user/{user_name}/release-groups:
- get:
- operationId: topReleaseGroupsForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of artists to return"
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of artists to skip from the beginning, for\
- \ pagination"
- type: integer
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/topReleaseGroupsForUser"
- description: successful operation
- "204":
- description: "Statistics for the user haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: User not found
- summary: Get top release groups for user 'user_name'.
- tags:
- - lbStats
- /1/stats/user/{user_name}/recordings:
- get:
- operationId: topRecordingsForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of artists to return"
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of artists to skip from the beginning, for\
- \ pagination"
- type: integer
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/topRecordingsForUser"
- description: successful operation
- "204":
- description: "Statistics for the user haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: User not found.
- summary: Get top recordings for user 'user_name'.
- tags:
- - lbStats
- /1/stats/user/{user_name}/listening-activity:
- get:
- operationId: listeningActivityForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/listeningActivityForUser"
- description: successful operation
- "204":
- description: "Statistics for the user haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: User not found.
- summary: Get the listening activity for user 'user_name'.
- tags:
- - lbStats
- /1/stats/user/{user_name}/daily-activity:
- get:
- operationId: dailyActivityForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/dailyActivityForUser"
- description: successful operation
- "204":
- description: "Statistics for the user haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: User not found.
- summary: Get the daily activity for user 'user_name'.
- tags:
- - lbStats
- /1/stats/user/{user_name}/artist-map:
- get:
- operationId: artistMapForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- - description: "Optional, recalculate the data instead of returning the cached\
- \ result."
- in: query
- name: force_recalculate
- required: false
- schema:
- default: false
- type: boolean
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/artistMapForUser"
- description: successful operation
- "204":
- description: "Statistics for the user haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: User not found.
- summary: Get the artist map for user 'user_name'.
- tags:
- - lbStats
- /1/stats/artist/{artist_mbid}/listeners:
- get:
- operationId: listenersForArtist
- parameters:
- - in: path
- name: artist_mbid
- required: true
- schema:
- format: uuid
- type: string
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/listenersForArtist"
- description: successful operation
- "204":
- description: "Statistics for the artist haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: Entity not found.
- summary: Get top listeners for artist 'artist_mbid'.
- tags:
- - lbStats
- /1/stats/release-group/{release_group_mbid}/listeners:
- get:
- operationId: listenersForReleaseGroup
- parameters:
- - in: path
- name: release_group_mbid
- required: true
- schema:
- format: uuid
- type: string
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/listenersForReleaseGroup"
- description: successful operation
- "204":
- description: "Statistics for the artist haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: Entity not found.
- summary: Get top listeners for release group 'release_group_mbid'.
- tags:
- - lbStats
- /1/stats/sitewide/artists:
- get:
- operationId: sitewideTopArtists
- parameters:
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of artists to return."
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of artists to skip from the beginning, for\
- \ pagination."
- type: integer
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/sitewideTopArtists"
- description: successful operation
- "204":
- description: "Statistics for the artist haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: Entity not found.
- summary: Get sitewide top artists.
- tags:
- - lbStats
- /1/stats/sitewide/releases:
- get:
- operationId: sitewideTopReleases
- parameters:
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of artists to return."
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of artists to skip from the beginning, for\
- \ pagination."
- type: integer
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/sitewideTopReleases"
- description: successful operation
- "204":
- description: "Statistics for the artist haven't been calculated, empty response\
- \ will be returned."
- "400":
- description: Bad request.
- "404":
- description: Entity not found.
- summary: Get sitewide top releases.
- tags:
- - lbStats
- /1/stats/sitewide/release-groups:
- get:
- operationId: sitewideTopReleaseGroups
- parameters:
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of artists to return."
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of artists to skip from the beginning, for\
- \ pagination."
- type: integer
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/sitewideTopReleaseGroups"
- description: successful operation
- "204":
- description: "Statistics haven't been calculated, empty response will be\
- \ returned."
- "400":
- description: Bad request.
- summary: Get sitewide top release groups.
- tags:
- - lbStats
- /1/stats/sitewide/recordings:
- get:
- operationId: sitewideTopRecordings
- parameters:
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of artists to return."
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of artists to skip from the beginning, for\
- \ pagination."
- type: integer
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/sitewideTopRecordings"
- description: successful operation
- "204":
- description: "Statistics haven't been calculated, empty response will be\
- \ returned."
- "400":
- description: Bad request.
- summary: Get sitewide top recordings.
- tags:
- - lbStats
- /1/stats/sitewide/listening-activity:
- get:
- operationId: sitewideListeningActivity
- parameters:
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/sitewideListeningActivity"
- description: successful operation
- "204":
- description: "Statistics haven't been calculated, empty response will be\
- \ returned."
- "400":
- description: Bad request.
- summary: Get sitewide top recordings.
- tags:
- - lbStats
- /1/stats/sitewide/artist-map:
- get:
- operationId: sitewideArtistMap
- parameters:
- - in: query
- name: range
- required: false
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- - description: "Optional, recalculate the data instead of returning the cached\
- \ result."
- in: query
- name: force_recalculate
- required: false
- schema:
- default: false
- type: boolean
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/sitewideArtistMap"
- description: successful operation
- "204":
- description: "Statistics haven't been calculated, empty response will be\
- \ returned."
- "400":
- description: Bad request.
- summary: Get sitewide top recordings.
- tags:
- - lbStats
- /1/stats/user/{user_name}/year-in-music/{year}:
- get:
- operationId: yearInMusicForUser
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: path
- name: year
- required: true
- schema:
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/yearInMusicForUser"
- description: "Successful query, you have data!"
- "204":
- description: "Statistics haven't been calculated, empty response will be\
- \ returned."
- "400":
- description: Bad request.
- summary: Get sitewide top recordings.
- tags:
- - lbStats
- /1/user/{playlist_user_name}/playlists:
- get:
- operationId: playlistsForUser
- parameters:
- - in: path
- name: playlist_user_name
- required: true
- schema:
- type: string
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: The number of playlists to return (for pagination).
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- description: The offset of into the list of playlists to return (for pagination).
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/playlists"
- description: "Yay, you have data!"
- "404":
- description: The requested user was not found.
- summary: Fetch playlist metadata in JSPF format without recordings for the given
- user.
- tags:
- - lbPlaylists
- /1/user/{playlist_user_name}/playlists/collaborator:
- get:
- operationId: playlistsForUserCollaborator
- parameters:
- - in: path
- name: playlist_user_name
- required: true
- schema:
- type: string
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: The number of playlists to return (for pagination).
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- description: The offset of into the list of playlists to return (for pagination).
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/playlists"
- description: "Yay, you have data!"
- "404":
- description: User not found.
- summary: "Fetch playlist metadata in JSPF format without recordings for which\
- \ a user is a collaborator. If a playlist is private, it will only be returned\
- \ if the caller is authorized to edit that playlist."
- tags:
- - lbPlaylists
- /1/user/{playlist_user_name}/playlists/createdfor:
- get:
- operationId: playlistsCreatedForUser
- parameters:
- - in: path
- name: playlist_user_name
- required: true
- schema:
- type: string
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: The number of playlists to return (for pagination).
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- description: The offset of into the list of playlists to return (for pagination).
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/playlists"
- description: "Yay, you have data!"
- "404":
- description: The requested user was not found.
- summary: Fetch playlist metadata in JSPF format without recordings that have
- been created for the user.
- tags:
- - lbPlaylists
- /1/playlist/create:
- post:
- description: |-
- Create a playlist. The playlist must be in JSPF format with MusicBrainz extensions, which is defined here: https://musicbrainz.org/doc/jspf . To create an empty playlist, you can send an empty playlist with only the title field filled out. If you would like to create a playlist populated with recordings, each of the track items in the playlist must have an identifier element that contains the MusicBrainz recording that includes the recording MBID.
-
- When creating a playlist, only the playlist title and the track identifier elements will be used - all other elements in the posted JSPF wil be ignored.
-
- If a created_for field is found and the user is not an approved playlist bot, then a 403 forbidden will be raised.
- operationId: createPlaylist
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/createPlaylist_request"
- required: true
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/createPlaylist_200_response"
- description: Playlist accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- "403":
- description: The submitting user is not allowed to create playlists for
- other users.
- security:
- - ApiKeyAuth: []
- summary: Create a playlist
- tags:
- - lbPlaylists
- /1/playlist/search:
- get:
- operationId: searchPlaylists
- parameters:
- - in: query
- name: query
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/playlists"
- description: "Yay, you have data!"
- "400":
- description: "Invalid query string, see error message for details."
- "401":
- description: Invalid authorization. See error message for details.
- summary: Search for playlists by name or description. The search query must
- be at least 3 characters long.
- tags:
- - lbPlaylists
- /1/playlist/edit/{playlist_mbid}:
- post:
- operationId: editPlaylist
- parameters:
- - description: The playlist mbid to edit.
- in: path
- name: playlist_mbid
- required: true
- schema:
- format: uuid
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/createPlaylist_request"
- required: true
- responses:
- "200":
- description: Playlist accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- "403":
- description: The submitting user is not allowed to create playlists for
- other users.
- security:
- - ApiKeyAuth: []
- summary: |-
- Create a playlist. The playlist must be in JSPF format with MusicBrainz extensions, which is defined here: https://musicbrainz.org/doc/jspf . To create an empty playlist, you can send an empty playlist with only the title field filled out. If you would like to create a playlist populated with recordings, each of the track items in the playlist must have an identifier element that contains the MusicBrainz recording that includes the recording MBID.
-
- When creating a playlist, only the playlist title and the track identifier elements will be used - all other elements in the posted JSPF wil be ignored.
-
- If a created_for field is found and the user is not an approved playlist bot, then a 403 forbidden will be raised.
- tags:
- - lbPlaylists
- /1/playlist/{playlist_mbid}:
- get:
- operationId: fetchPlaylist
- parameters:
- - description: The playlist mbid to fetch.
- in: path
- name: playlist_mbid
- required: true
- schema:
- format: uuid
- type: string
- - description: "Optional, pass value ‘false' to skip lookup up recording metadata."
- in: query
- name: fetch_metadata
- required: false
- schema:
- type: boolean
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/createPlaylist_request"
- description: "Yay, you have data!"
- "401":
- description: Invalid authorization. See error message for details.
- "404":
- description: Playlist not found.
- summary: Fetch the given playlist.
- tags:
- - lbPlaylists
- /1/playlist/{playlist_mbid}/item/add/{offset}:
- post:
- operationId: appendRecordings
- parameters:
- - description: The playlist mbid to append to.
- in: path
- name: playlist_mbid
- required: true
- schema:
- format: uuid
- type: string
- - description: Offset.
- in: path
- name: offset
- required: true
- schema:
- type: integer
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/playlist"
- required: true
- responses:
- "200":
- description: Playlist accepted.
- "400":
- description: "Invalid JSON sent, see error message for details."
- "401":
- description: Invalid authorization. See error message for details.
- "403":
- description: Forbidden. The requesting user was not allowed to carry out
- this operation.
- security:
- - ApiKeyAuth: []
- summary: |-
- Append recordings to an existing playlist by posting a playlist with one of more recordings in it. The playlist must be in JSPF format with MusicBrainz extensions, which is defined here: https://musicbrainz.org/doc/jspf .
-
- If the offset is provided in the URL, then the recordings will be added at that offset, otherwise they will be added at the end of the playlist.
- tags:
- - lbPlaylists
- /1/playlist/{playlist_mbid}/item/move:
- post:
- operationId: moveItem
- parameters:
- - description: The playlist mbid to append to.
- in: path
- name: playlist_mbid
- required: true
- schema:
- format: uuid
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/moveItem_request"
- required: true
- responses:
- "200":
- description: Move operation succeeded.
- "400":
- description: "Invalid JSON sent, see error message for details."
- "401":
- description: Invalid authorization. See error message for details.
- "403":
- description: Forbidden. The requesting user was not allowed to carry out
- this operation.
- security:
- - ApiKeyAuth: []
- summary: "To move an item in a playlist, the POST data needs to specify the\
- \ recording MBID and current index of the track to move (from), where to move\
- \ it to (to) and how many tracks from that position should be moved (count)."
- tags:
- - lbPlaylists
- /1/playlist/{playlist_mbid}/item/delete:
- post:
- description: "To delete an item in a playlist, the POST data needs to specify\
- \ the recording MBID and current index of the track to delete, and how many\
- \ tracks from that position should be moved deleted."
- operationId: itemDelete
- parameters:
- - description: The playlist mbid to fetch.
- in: path
- name: playlist_mbid
- required: true
- schema:
- format: uuid
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/itemDelete_request"
- required: true
- responses:
- "200":
- description: Playlist accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- "403":
- description: The requesting user was not allowed to carry out this operation.
- security:
- - ApiKeyAuth: []
- summary: Delete an item in a playlist.
- tags:
- - lbPlaylists
- /1/playlist/{playlist_mbid}/delete:
- post:
- description: POST body data does not need to contain anything.
- operationId: deletePlaylist
- parameters:
- - description: The playlist mbid to fetch.
- in: path
- name: playlist_mbid
- required: true
- schema:
- format: uuid
- type: string
- responses:
- "200":
- description: Playlist deleted.
- "401":
- description: Invalid authorization.
- "403":
- description: The requesting user was not allowed to carry out this operation.
- "404":
- description: Playlist not found.
- security:
- - ApiKeyAuth: []
- summary: Delete a playlist.
- tags:
- - lbPlaylists
- /1/playlist/{playlist_mbid}/copy:
- post:
- operationId: copyPlaylist
- parameters:
- - description: The playlist mbid to append to.
- in: path
- name: playlist_mbid
- required: true
- schema:
- format: uuid
- type: string
- responses:
- "200":
- description: Playlist copied.
- "401":
- description: Invalid authorization. See error message for details.
- "403":
- description: Forbidden. The requesting user was not allowed to carry out
- this operation.
- "404":
- description: Playlist not found.
- security:
- - ApiKeyAuth: []
- summary: Copy a playlist - the new playlist will be given the name “Copy of
- ”. POST body data does not need to contain anything.
- tags:
- - lbPlaylists
- /1/feedback/recording-feedback:
- post:
- operationId: recordingFeedback
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/recordingFeedback_request"
- required: true
- responses:
- "200":
- description: Feedback accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- security:
- - ApiKeyAuth: []
- summary: Submit recording feedback (love/hate) to the server. A user token (found
- on https://listenbrainz.org/settings/ ) must be provided in the Authorization
- header! Each request should contain only one feedback in the payload.
- tags:
- - lbRecordings
- /1/feedback/user/{user_name}/get-feedback:
- get:
- operationId: getFeedback
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: score
- required: false
- schema:
- description: "Optional, If 1 then returns the loved recordings, if -1 returns\
- \ hated recordings."
- type: integer
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of feedback items to return."
- maximum: 1000
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of feedback items to skip from the beginning,\
- \ for pagination. Ex. An offset of 5 means the top 5 feedback will be\
- \ skipped, defaults to 0."
- type: integer
- - in: query
- name: metadata
- required: false
- schema:
- description: "Optional, 'true' or 'false' if this call should return the\
- \ metadata for the feedback."
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedbackResponse"
- description: "Yay, you have data!"
- summary: |-
- Get feedback given by user 'user_name'. The format for the JSON returned is defined in our Feedback JSON Documentation.
-
- If the optional argument score is not given, this endpoint will return all the feedback submitted by the user. Otherwise filters the feedback to be returned by score.
- tags:
- - lbRecordings
- /1/feedback/recording/{recording_mbid}/get-feedback-mbid:
- get:
- operationId: getFeedbackMbid
- parameters:
- - in: path
- name: recording_mbid
- required: true
- schema:
- format: uuid
- type: string
- - in: query
- name: score
- required: false
- schema:
- description: "Optional, If 1 then returns the loved recordings, if -1 returns\
- \ hated recordings."
- type: integer
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of feedback items to return."
- maximum: 1000
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of feedback items to skip from the beginning,\
- \ for pagination. Ex. An offset of 5 means the top 5 feedback will be\
- \ skipped, defaults to 0."
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedbackResponse"
- description: "Yay, you have data!"
- summary: Get feedback for recording with given recording_mbid.
- tags:
- - lbRecordings
- /1/feedback/user/{recording_msid}/get-feedback:
- get:
- operationId: getFeedbackMsid
- parameters:
- - in: path
- name: recording_msid
- required: true
- schema:
- type: string
- - in: query
- name: score
- required: false
- schema:
- description: "Optional, If 1 then returns the loved recordings, if -1 returns\
- \ hated recordings."
- type: integer
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of feedback items to return."
- maximum: 1000
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of feedback items to skip from the beginning,\
- \ for pagination. Ex. An offset of 5 means the top 5 feedback will be\
- \ skipped, defaults to 0."
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedbackResponse"
- description: "Yay, you have data!"
- summary: Get feedback for recording with given recording_msid.
- tags:
- - lbRecordings
- /1/feedback/user/{user_name}/get-feedback-for-recordings:
- get:
- operationId: getFeedbackForRecordings
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - description: Comma separated list of recording_msids for which feedback records
- are to be fetched.
- in: query
- name: recording_msids
- required: false
- schema:
- items:
- format: uuid
- type: string
- type: array
- - description: Comma separated list of recording_mbids for which feedback records
- are to be fetched.
- in: query
- name: recording_mbids
- required: false
- schema:
- items:
- format: uuid
- type: string
- type: array
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedbackResponse"
- description: "Yay, you have data!"
- summary: Get feedback given by user user_name for the list of recordings supplied.
- tags:
- - lbRecordings
- /1/pin:
- post:
- operationId: pin
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/pin_request"
- required: true
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/pin_200_response"
- description: Feedback accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- security:
- - ApiKeyAuth: []
- summary: Pin a recording for user. A user token (found on https://listenbrainz.org/settings/)
- must be provided in the Authorization header! Each request should contain
- only one pinned recording item in the payload.
- tags:
- - lbRecordings
- /1/unpin:
- post:
- operationId: unpin
- responses:
- "200":
- description: Recording unpinned.
- "401":
- description: Invalid authorization.
- "404":
- description: Could not find the active recording to unpin for the user.
- security:
- - ApiKeyAuth: []
- summary: Unpins the currently active pinned recording for the user. A user token
- (found on https://listenbrainz.org/settings/) must be provided in the Authorization
- header!
- tags:
- - lbRecordings
- /1/pin/delete/{row_id}:
- post:
- operationId: pinDelete
- parameters:
- - in: path
- name: row_id
- required: true
- schema:
- type: integer
- responses:
- "200":
- description: Recording unpinned.
- "401":
- description: Invalid authorization.
- "404":
- description: The requested row_id for the user was not found.
- security:
- - ApiKeyAuth: []
- summary: Deletes the pinned recording with given row_id from the server. A user
- token (found on https://listenbrainz.org/settings/) must be provided in the
- Authorization header!
- tags:
- - lbRecordings
- /1/{user_name}/pins:
- get:
- operationId: getPins
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of feedback items to return."
- maximum: 1000
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of pinned recording items to skip from the\
- \ beginning, for pagination. Ex. An offset of 5 means the top 5 feedback\
- \ will be skipped, defaults to 0."
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/getPins"
- description: "Yay, you have data!"
- "400":
- description: "Invalid query parameters, see error message for details."
- "404":
- description: The requested user was not found.
- summary: Get a list of all recordings ever pinned by a user with given user_name
- in descending order of the time they were originally pinned.
- tags:
- - lbRecordings
- /1/{user_name}/pins/following:
- get:
- operationId: getPinsFollowing
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of feedback items to return."
- maximum: 1000
- type: integer
- - in: query
- name: offset
- required: false
- schema:
- default: 0
- description: "Optional, number of pinned recording items to skip from the\
- \ beginning, for pagination. Ex. An offset of 5 means the top 5 feedback\
- \ will be skipped, defaults to 0."
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/getPins"
- description: "Yay, you have data!"
- "400":
- description: "Invalid query parameters, see error message for details."
- "404":
- description: The requested user was not found.
- summary: Get a list containing the active pinned recordings for all users in
- a user's user_name following list. The returned pinned recordings are sorted
- in descending order of the time they were pinned.
- tags:
- - lbRecordings
- /1/{user_name}/pins/current:
- get:
- operationId: getPinsCurrent
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/getPinsCurrent_200_response"
- description: "Yay, you have data!"
- "400":
- description: "Invalid query parameters, see error message for details."
- "404":
- description: The requested user was not found.
- summary: Get the currently pinned recording by a user with given user_name.
- tags:
- - lbRecordings
- /1/pin/update/{row_id}:
- post:
- operationId: updatePin
- parameters:
- - in: path
- name: row_id
- required: true
- schema:
- type: integer
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/updatePin_request"
- required: true
- responses:
- "200":
- description: Feedback accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- security:
- - ApiKeyAuth: []
- summary: Updates the blurb content of a pinned recording for the user. A user
- token (found on https://listenbrainz.org/settings/) must be provided in the
- Authorization header! Each request should contain only one pinned recording
- item in the payload.
- tags:
- - lbRecordings
- /1/popularity/top-recordings-for-artist/{artist_mbid}:
- get:
- operationId: topRecordingsForArtist
- parameters:
- - in: path
- name: artist_mbid
- required: true
- schema:
- format: uuid
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/topRecordingsForArtist"
- description: "Yay, you have data!"
- "400":
- description: "Invalid query parameters, see error message for details."
- "404":
- description: The requested user was not found.
- summary: Get a list of all recordings ever pinned by a user with given user_name
- in descending order of the time they were originally pinned.
- tags:
- - lbPopularity
- /1/popularity/top-release-groups-for-artist/{artist_mbid}:
- get:
- operationId: topReleaseGroupForArtist
- parameters:
- - in: path
- name: artist_mbid
- required: true
- schema:
- format: uuid
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/topReleaseGroupsForArtist"
- description: "Yay, you have data!"
- "400":
- description: "Invalid query parameters, see error message for details."
- "404":
- description: The requested user was not found.
- summary: Get the top release groups by listen count for a given artist.
- tags:
- - lbPopularity
- /1/popularity/recording:
- post:
- operationId: recording
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/recording_request"
- required: true
- responses:
- "200":
- content:
- application/json:
- schema:
- items:
- $ref: "#/components/schemas/recording_200_response_inner"
- type: array
- description: Feedback accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- summary: |-
- Get the total listen count and total unique listeners count for a given recording.
-
- A JSON document with a list of recording_mbids and inc string must be POSTed. Up to MAX_ITEMS_PER_GET items can be requested at once.
- tags:
- - lbPopularity
- /1/popularity/artist:
- post:
- operationId: artist
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/artist_request"
- required: true
- responses:
- "200":
- content:
- application/json:
- schema:
- items:
- $ref: "#/components/schemas/artist_200_response_inner"
- type: array
- description: Feedback accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- summary: |-
- Get the total listen count and total unique listeners count for a given artist.
-
- A JSON document with a list of artists and inc string must be POSTed. Up to MAX_ITEMS_PER_GET items can be requested at once.
- tags:
- - lbPopularity
- /1/popularity/release:
- post:
- operationId: release
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/release_request"
- required: true
- responses:
- "200":
- content:
- application/json:
- schema:
- items:
- $ref: "#/components/schemas/release_200_response_inner"
- type: array
- description: Feedback accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- summary: |-
- Get the total listen count and total unique listeners count for a given release.
-
- A JSON document with a list of releases and inc string must be POSTed. Up to MAX_ITEMS_PER_GET items can be requested at once.
- tags:
- - lbPopularity
- /1/popularity/release-group:
- post:
- operationId: releaseGroup
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/releaseGroup_request"
- required: true
- responses:
- "200":
- content:
- application/json:
- schema:
- items:
- $ref: "#/components/schemas/releaseGroup_200_response_inner"
- type: array
- description: Feedback accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- summary: |-
- Get the total listen count and total unique listeners count for a given release group.
-
- A JSON document with a list of release groups and inc string must be POSTed. Up to MAX_ITEMS_PER_GET items can be requested at once.
- tags:
- - lbPopularity
- /1/metadata/recording/:
- get:
- operationId: recordingMetadata
- parameters:
- - description: A comma separated list of recording_mbids.
- in: query
- name: recording_mbids
- required: true
- schema:
- items:
- format: uuid
- type: string
- type: array
- - description: "A space separated list of “artist”, “tag” and/or “release” to\
- \ indicate which portions of metadata you're interested in fetching. We\
- \ encourage users to only fetch the data they plan to consume."
- in: query
- name: inc
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- additionalProperties:
- $ref: "#/components/schemas/recordingMetadata"
- type: object
- description: "Yay, you have data!"
- "400":
- description: "Invalid query parameters, see error message for details."
- "404":
- description: The requested user was not found.
- summary: "This endpoint takes in a list of recording_mbids and returns an array\
- \ of dicts that contain recording metadata suitable for showing in a context\
- \ that requires as much detail about a recording and the artist. Using the\
- \ inc parameter, you can control which portions of metadata to fetch."
- tags:
- - lbMetadata
- /1/metadata/release_group/:
- get:
- operationId: releaseGroupMetadata
- parameters:
- - description: A comma separated list of release_group_mbids.
- explode: false
- in: query
- name: release_group_mbids
- required: true
- schema:
- items:
- format: uuid
- type: string
- type: array
- style: form
- - description: "A space separated list of “artist”, “tag” and/or “release” to\
- \ indicate which portions of metadata you're interested in fetching. We\
- \ encourage users to only fetch the data they plan to consume."
- in: query
- name: inc
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- additionalProperties:
- $ref: "#/components/schemas/releaseGroupMetadata"
- type: object
- description: "Yay, you have data!"
- "400":
- description: "Invalid query parameters, see error message for details."
- summary: "This endpoint takes in a list of release_group_mbids and returns an\
- \ array of dicts that contain release_group metadata suitable for showing\
- \ in a context that requires as much detail about a release_group and the\
- \ artist. Using the inc parameter, you can control which portions of metadata\
- \ to fetch."
- tags:
- - lbMetadata
- /1/metadata/lookup/:
- get:
- operationId: lookup
- parameters:
- - description: Artist name of the listen.
- in: query
- name: artist_name
- required: true
- schema:
- type: string
- - description: Track name of the listen.
- in: query
- name: recording_name
- required: true
- schema:
- type: string
- - description: Release name of the listen.
- in: query
- name: release_name
- required: false
- schema:
- type: string
- - description: "Should extra metadata be also returned if a match is found,\
- \ see /metadata/recording for details."
- in: query
- name: metadata
- required: true
- schema:
- type: boolean
- - description: "A space separated list of “artist”, “tag” and/or “release” to\
- \ indicate which portions of metadata you're interested in fetching. We\
- \ encourage users to only fetch the data they plan to consume."
- in: query
- name: inc
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/lookup"
- description: "Yay, you have data!"
- "400":
- description: Invalid arguments.
- summary: "This endpoint looks up mbid metadata for the given artist, recording\
- \ and optionally a release name. The total number of characters in the artist\
- \ name, recording name and release name query arguments should be less than\
- \ or equal to MAX_MAPPING_QUERY_LENGTH."
- tags:
- - lbMetadata
- /1/metadata/submit_manual_mapping/:
- post:
- operationId: submitManualMapping
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/submitManualMapping"
- required: true
- responses:
- "200":
- description: Listen(s) accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- security:
- - ApiKeyAuth: []
- summary: Submit a manual mapping of a recording messybrainz ID to a musicbrainz
- recording id.
- tags:
- - lbMetadata
- /1/metadata/get_manual_mapping/:
- get:
- operationId: getManualMapping
- parameters:
- - in: query
- name: recording_msid
- required: true
- schema:
- format: uuid
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/getManualMapping"
- description: "Yay, you have data!"
- "404":
- description: No such mapping for this user/recording msid.
- security:
- - ApiKeyAuth: []
- summary: Get the manual mapping of a recording messybrainz ID that a user added.
- tags:
- - lbMetadata
- /1/metadata/artist/:
- get:
- operationId: artistMetadata
- parameters:
- - description: A comma separated list of recording_mbids.
- in: query
- name: artist_mbids
- required: true
- schema:
- items:
- format: uuid
- type: string
- type: array
- - description: "A space separated list of “artist”, “tag” and/or “release” to\
- \ indicate which portions of metadata you're interested in fetching. We\
- \ encourage users to only fetch the data they plan to consume."
- in: query
- name: inc
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- items:
- $ref: "#/components/schemas/artistMetadata"
- type: array
- description: "Yay, you have data!"
- "400":
- description: Invalid arguments.
- summary: "This endpoint takes in a list of artist_mbids and returns an array\
- \ of dicts that contain recording metadata suitable for showing in a context\
- \ that requires as much detail about a recording and the artist. Using the\
- \ inc parameter, you can control which portions of metadata to fetch."
- tags:
- - lbMetadata
- /1/user/{user_name}/timeline-event/create/recording:
- post:
- operationId: recommendRecording
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/recommendRecording_request"
- required: true
- responses:
- "200":
- description: "Successful query, recording has been recommended!"
- "400":
- description: Bad request.
- "401":
- description: "Unauthorized, you do not have permissions to recommend recordings\
- \ on the behalf of this user."
- "403":
- description: "Forbidden, you are not an approved user."
- "404":
- description: User not found.
- security:
- - ApiKeyAuth: []
- summary: Make the user recommend a recording to their followers.
- tags:
- - lbSocial
- /1/user/{user_name}/timeline-event/create/notification:
- post:
- operationId: createNotification
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/createNotification_request"
- required: true
- responses:
- "200":
- description: "Successful query, message has been posted!"
- "400":
- description: Bad request.
- "401":
- description: "Unauthorized, you do not have permissions to recommend recordings\
- \ on the behalf of this user."
- "403":
- description: "Forbidden, you are not an approved user."
- "404":
- description: User not found.
- security:
- - ApiKeyAuth: []
- summary: Post a message with a link on a user's timeline. Only approved users
- are allowed to perform this action.
- tags:
- - lbSocial
- /1/user/{user_name}/timeline-event/create/review:
- post:
- operationId: createReview
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/createReview_request"
- required: true
- responses:
- "200":
- description: "Successful query, message has been posted!"
- "400":
- description: Bad request.
- "403":
- description: "Forbidden, you have not linked with a CritiqueBrainz account."
- "404":
- description: User not found.
- security:
- - ApiKeyAuth: []
- summary: Creates a CritiqueBrainz review event for the user. This also creates
- a corresponding review in CritiqueBrainz. Users need to have linked their
- ListenBrainz account with CritiqueBrainz first to use this endpoint successfully.
- tags:
- - lbSocial
- /1/user/{user_name}/feed/events:
- get:
- operationId: feedEvents
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- description: The MusicBrainz ID of the user whose timeline is being requested.
- type: string
- - description: "If you specify a 'max_ts' timestamp, events with timestamps\
- \ less than the value will be returned."
- in: query
- name: max_ts
- schema:
- type: integer
- - description: "If you specify a 'min_ts' timestamp, events with timestamps\
- \ greater than the value will be returned."
- in: query
- name: min_ts
- schema:
- type: integer
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of listens to return."
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedEvents"
- description: "Successful query, you have feed events!"
- "400":
- description: Bad request.
- "401":
- description: "Unauthorized, you do not have permission to view this user's\
- \ feed."
- "403":
- description: "Forbidden, you do not have permission to view this user's\
- \ feed."
- "404":
- description: User not found.
- security:
- - ApiKeyAuth: []
- summary: CreatGet feed events for a user's timeline.
- tags:
- - lbSocial
- /1/user/{user_name}/feed/events/listens/following:
- get:
- operationId: feedEventsListensFollowing
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- description: The MusicBrainz ID of the user whose timeline is being requested.
- type: string
- - description: "If you specify a 'max_ts' timestamp, events with timestamps\
- \ less than the value will be returned."
- in: query
- name: max_ts
- schema:
- type: integer
- - description: "If you specify a 'min_ts' timestamp, events with timestamps\
- \ greater than the value will be returned."
- in: query
- name: min_ts
- schema:
- type: integer
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of listens to return."
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedEvents"
- description: "Successful query, you have feed listen-events!"
- "400":
- description: Bad request.
- "401":
- description: Invalid authorization. See error message for details.
- "403":
- description: "Forbidden, you do not have permission to view this user's\
- \ feed."
- "404":
- description: User not found.
- security:
- - ApiKeyAuth: []
- summary: Get feed's listen events for followed users.
- tags:
- - lbSocial
- /1/user/{user_name}/feed/events/listens/similar:
- get:
- operationId: feedEventsListensSimilar
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- description: The MusicBrainz ID of the user whose timeline is being requested.
- type: string
- - description: "If you specify a 'max_ts' timestamp, events with timestamps\
- \ less than the value will be returned."
- in: query
- name: max_ts
- schema:
- type: integer
- - description: "If you specify a 'min_ts' timestamp, events with timestamps\
- \ greater than the value will be returned."
- in: query
- name: min_ts
- schema:
- type: integer
- - in: query
- name: count
- required: false
- schema:
- default: 25
- description: "Optional, number of listens to return."
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedEventsListensSimilar"
- description: "Successful query, you have feed listen-events!"
- "400":
- description: Bad request.
- "401":
- description: Invalid authorization. See error message for details.
- "403":
- description: "Forbidden, you do not have permission to view this user's\
- \ feed."
- "404":
- description: User not found.
- security:
- - ApiKeyAuth: []
- summary: Get feed's listen events for similar users.
- tags:
- - lbSocial
- /1/user/{user_name}/feed/events/delete:
- post:
- operationId: feedEventsDelete
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedEventsDelete_request"
- required: true
- responses:
- "200":
- description: Successful deletion.
- "400":
- description: Bad request.
- "401":
- description: Unauthorized.
- "403":
- description: "Forbidden, you do not have permission to delete from this\
- \ user's feed."
- "404":
- description: User not found.
- "500":
- description: API Internal Server Error.
- security:
- - ApiKeyAuth: []
- summary: "Delete those events from user's feed that belong to them. Supports\
- \ deletion of recommendation and notification. Along with the authorization\
- \ token, post the event type and event id."
- tags:
- - lbSocial
- /1/user/{user_name}/feed/events/hide:
- post:
- operationId: feedEventsHide
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedEventsDelete_request"
- required: true
- responses:
- "200":
- description: Event hidden successfully.
- "400":
- description: Bad request.
- "401":
- description: Unauthorized.
- "403":
- description: "Forbidden, you don't have permissions to hide events from\
- \ this user's timeline."
- "404":
- description: User not found.
- "500":
- description: API Internal Server Error.
- security:
- - ApiKeyAuth: []
- summary: "Hide events from the user feed, only recording_recommendation and\
- \ recording_pin events that have been generated by the people one is following\
- \ can be deleted via this endpoint."
- tags:
- - lbSocial
- /1/user/{user_name}/feed/events/unhide:
- post:
- operationId: feedEventsUnhide
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedEventsDelete_request"
- required: true
- responses:
- "200":
- description: Event unhidden successfully.
- "400":
- description: Bad request.
- "401":
- description: Unauthorized.
- "403":
- description: Forbidden.
- "404":
- description: User not found.
- "500":
- description: API Internal Server Error.
- security:
- - ApiKeyAuth: []
- summary: "Delete hidden events from the user feed, aka unhide events."
- tags:
- - lbSocial
- /1/user/{user_name}/timeline-event/create/recommend-personal:
- post:
- operationId: recommendPersonalRecording
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/recommendPersonalRecording_request"
- required: true
- responses:
- "200":
- description: "Successful query, recording has been recommended!"
- "400":
- description: Bad request.
- "401":
- description: "Unauthorized, you do not have permissions to recommend."
- security:
- - ApiKeyAuth: []
- summary: "Make the user recommend a recording to their followers. The request\
- \ should post the following data about the recording being recommended (either\
- \ one of recording_msid or recording_mbid is sufficient), and also the list\
- \ of followers getting recommended."
- tags:
- - lbSocial
- /1/user/{user_name}/followers:
- get:
- operationId: followers
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- description: The MusicBrainz ID of the user whose timeline is being requested.
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/followers"
- description: "Yay, you have data!"
- "400":
- description: Bad request.
- "404":
- description: User not found.
- security:
- - ApiKeyAuth: []
- summary: Fetch the list of followers of the user 'user_name'.
- tags:
- - lbSocial
- /1/user/{user_name}/following:
- get:
- operationId: following
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- description: The MusicBrainz ID of the user whose timeline is being requested.
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/following"
- description: "Yay, you have data!"
- "400":
- description: Bad request.
- "404":
- description: User not found.
- security:
- - ApiKeyAuth: []
- summary: Fetch the list of users followed by the user 'user_name'.
- tags:
- - lbSocial
- /1/user/{user_name}/follow:
- post:
- operationId: follow
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- description: Successfully followed the user 'user_name'.
- "400":
- description: "Already following the user user_name, or trying to follow\
- \ yourself."
- "401":
- description: Invalid authorization. See error message for details.
- security:
- - ApiKeyAuth: []
- summary: Follow the user 'user_name'. A user token (found on https://listenbrainz.org/settings/
- ) must be provided in the Authorization header!
- tags:
- - lbSocial
- /1/user/{user_name}/unfollow:
- post:
- operationId: unfollow
- parameters:
- - in: path
- name: user_name
- required: true
- schema:
- type: string
- responses:
- "200":
- description: Successfully unfollowed the user 'user_name'.
- "401":
- description: Invalid authorization. See error message for details.
- security:
- - ApiKeyAuth: []
- summary: Unfollow the user 'user_name'. A user token (found on https://listenbrainz.org/settings/
- ) must be provided in the Authorization header!
- tags:
- - lbSocial
- /1/cf/recommendation/user/{user_name}/recording:
- get:
- operationId: recordingRecommendations
- parameters:
- - description: The MusicBrainz ID of the user whose timeline is being requested.
- in: path
- name: user_name
- required: true
- schema:
- type: string
- - description: "Optional, number of recording mbids to return."
- in: query
- name: count
- schema:
- default: 25
- type: integer
- - description: "Optional, number of mbids to skip from the beginning, for pagination.\
- \ Ex. An offset of 5 means the 5 mbids will be skipped."
- in: query
- name: offset
- schema:
- default: 25
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/recordingRecommendations"
- description: "Successful query, you have data!"
- "204":
- description: "Recommendations for the user haven't been generated, empty\
- \ response will be returned."
- "400":
- description: Bad request.
- "404":
- description: User not found.
- summary: Get recommendations sorted on rating and ratings for user 'user_name'.
- tags:
- - lbRecommendations
- /1/recommendation/feedback/submit:
- post:
- operationId: submitFeedback
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/submitFeedback_request"
- required: true
- responses:
- "200":
- description: Feedback accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- security:
- - ApiKeyAuth: []
- summary: Submit recommendation feedback. A user token (found on https://listenbrainz.org/settings/
- ) must be provided in the Authorization header! Each request should contain
- only one feedback in the payload.
- tags:
- - lbRecommendations
- /1/recommendations/feedback/delete:
- post:
- operationId: deleteFeedback
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/deleteFeedback_request"
- required: true
- responses:
- "200":
- description: Feedback accepted.
- "400":
- description: Invalid JSON sent.
- "401":
- description: Invalid authorization.
- security:
- - ApiKeyAuth: []
- summary: Delete feedback for a user. A user token (found on https://listenbrainz.org/settings/
- ) must be provided in the Authorization header! Each request should contain
- only one recording mbid in the payload.
- tags:
- - lbRecommendations
- /1/recommendations/feedback/user/{user_name}:
- get:
- operationId: feedbackGivenBy
- parameters:
- - description: The MusicBrainz ID of the user whose timeline is being requested.
- in: path
- name: user_name
- required: true
- schema:
- type: string
- - description: "Optional, refer to db/model/recommendation_feedback.py for allowed\
- \ rating values."
- in: query
- name: rating
- required: false
- schema:
- type: string
- - description: "Optional, number of recording mbids to return."
- in: query
- name: count
- required: false
- schema:
- default: 25
- type: integer
- - description: "Optional, number of mbids to skip from the beginning, for pagination.\
- \ Ex. An offset of 5 means the 5 mbids will be skipped."
- in: query
- name: offset
- required: false
- schema:
- default: 25
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/feedbackGivenBy"
- description: "Yay, you have data!"
- "204":
- description: "Recommendations for the user haven't been generated, empty\
- \ response will be returned."
- "400":
- description: Bad request.
- "404":
- description: User not found.
- summary: Get feedback given by user 'user_name'.
- tags:
- - lbRecommendations
- /1/recommendations/feedback/user/{user_name}/recordings:
- get:
- operationId: recordingsFeedbackGivenBy
- parameters:
- - description: The MusicBrainz ID of the user whose timeline is being requested.
- in: path
- name: user_name
- required: true
- schema:
- type: string
- - description: Comma separated list of recording_mbids for which feedback records
- are to be fetched.
- in: query
- name: mbids
- required: true
- schema:
- items:
- format: uuid
- type: string
- type: array
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/recordingsFeedbackGivenBy"
- description: "Yay, you have data!"
- "400":
- description: Bad request.
- "404":
- description: User not found.
- summary: Get feedback given by user 'user_name' for the list of recordings supplied.
- tags:
- - lbRecommendations
- /1/explore/fresh-releases/:
- get:
- operationId: freshReleases
- parameters:
- - description: Fresh releases will be shown around this pivot date. Must be
- in YYYY-MM-DD format.
- in: query
- name: release_date
- required: false
- schema:
- type: string
- - description: The number of days of fresh releases to show. Max 90 days.
- in: query
- name: days
- required: false
- schema:
- type: integer
- - description: The sort order of the results.
- in: query
- name: sort
- required: false
- schema:
- default: release_name
- enum:
- - release_date
- - artist_credit_name
- - release_name
- type: string
- - description: Whether to show releases in the past.
- in: query
- name: past
- required: false
- schema:
- default: true
- type: boolean
- - description: Whether to show releases in the future.
- in: query
- name: future
- required: false
- schema:
- default: true
- type: boolean
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/freshReleases"
- description: "Yay, you have data!"
- "400":
- description: Invalid date or number of days passed.
- summary: This endpoint fetches upcoming and recently released (fresh) releases.
- tags:
- - lbMisc
- /1/explore/color/{color}:
- get:
- operationId: color
- parameters:
- - description: Color must be a 6 digit hex color code.
- in: path
- name: color
- required: true
- schema:
- type: string
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/color"
- description: Success.
- summary: Fetch a list of releases that have cover art that has a predominant
- color that is close to the given color.
- tags:
- - lbMisc
- /1/explore/lb-radio:
- get:
- operationId: lbRadio
- parameters:
- - description: The LB Radio prompt from which to generate playlists.
- in: query
- name: prompt
- required: true
- schema:
- type: string
- - description: "The mode that LB radio should use. Must be easy, medium or hard."
- in: query
- name: mode
- required: true
- schema:
- $ref: "#/components/schemas/Mode"
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/lbRadio"
- description: Success.
- summary: Generate a playlist with LB Radio.
- tags:
- - lbMisc
- /1/status/get-dump-info:
- get:
- operationId: getDumpInfo
- parameters:
- - description: "Integer specifying the ID of the dump, if not provided, the\
- \ endpoint returns information about the latest data dump."
- in: query
- name: id
- required: false
- schema:
- type: integer
- responses:
- "200":
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/getDumpInfo"
- description: Success.
- "400":
- description: You did not provide a valid dump ID. See error message for
- details.
- "404":
- description: Dump with given ID does not exist.
- summary: Get information about ListenBrainz data dumps. You need to pass the
- id parameter in a GET request to get data about that particular dump.
- tags:
- - lbMisc
- /1/art/grid/:
- post:
- operationId: createCoverArtGrid
- requestBody:
- content:
- application/json:
- schema:
- $ref: "#/components/schemas/createCoverArtGrid"
- required: true
- responses:
- "200":
- content:
- image/svg+xml:
- schema:
- format: binary
- type: string
- description: Cover art created successfully.
- "400":
- description: Invalid JSON or invalid options in JSON passed.
- summary: Create a cover art grid SVG file from the POSTed JSON data to this
- endpoint.
- tags:
- - lbArt
- /1/art/grid-stats/{user_name}/{time_range}/{dimension}/{layout}/{image_size}:
- get:
- operationId: createCoverArtGridForUser
- parameters:
- - description: The name of the user for whom to create the cover art.
- in: path
- name: user_name
- required: true
- schema:
- type: string
- - description: Must be a statistics time range.
- in: path
- name: time_range
- required: true
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- - description: "The dimension to use for this grid. A grid of dimension 3 has\
- \ 3 images across and 3 images down, for a total of 9 images."
- in: path
- name: dimension
- required: true
- schema:
- type: integer
- - description: "The layout to be used for this grid. Layout 0 is always a simple\
- \ grid, but other layouts may have image images be of different sizes. See\
- \ https://art.listenbrainz.org for examples of the available layouts."
- in: path
- name: layout
- required: true
- schema:
- type: integer
- - description: The size of the cover art image.
- in: path
- name: image_size
- required: true
- schema:
- type: integer
- responses:
- "200":
- content:
- image/svg+xml:
- schema:
- format: binary
- type: string
- description: Cover art created successfully.
- "400":
- description: Invalid JSON or invalid options in JSON passed.
- summary: Create a cover art grid SVG file from the stats of a given user.
- tags:
- - lbArt
- /1/art/{custom_name}/{user_name}/{time_range}/{image_size}:
- get:
- operationId: createCustomCoverArt
- parameters:
- - description: The name of cover art to be generated.
- in: path
- name: custom_name
- required: true
- schema:
- $ref: "#/components/schemas/CoverTypes"
- - description: The name of the user for whom to create the cover art.
- in: path
- name: user_name
- required: true
- schema:
- type: string
- - description: Must be a statistics time range.
- in: path
- name: time_range
- required: true
- schema:
- $ref: "#/components/schemas/AllowedStatisticsRange"
- - description: The size of the cover art image.
- in: path
- name: image_size
- required: true
- schema:
- type: integer
- responses:
- "200":
- content:
- image/svg+xml:
- schema:
- format: binary
- type: string
- description: Cover art created successfully.
- "400":
- description: Invalid JSON or invalid options in JSON passed.
- summary: Create a custom cover art SVG file from the stats of a given user.
- tags:
- - lbArt
- /1/art/year-in-music/{year}/{user_name}:
- get:
- operationId: yearInMusic
- parameters:
- - in: path
- name: year
- required: true
- schema:
- type: integer
- - description: The name of the user for whom to create the cover art.
- in: path
- name: user_name
- required: true
- schema:
- type: string
- - in: query
- name: image
- required: true
- schema:
- $ref: "#/components/schemas/YearInMusicImage"
- responses:
- "200":
- content:
- image/svg+xml:
- schema:
- format: binary
- type: string
- description: Cover art created successfully.
- "400":
- description: Invalid JSON or invalid options in JSON passed.
- summary: Create the shareable svg image using YIM stats.
- tags:
- - lbArt
-components:
- schemas:
- YearInMusicImage:
- enum:
- - overview
- - stats
- - artists
- - albums
- - tracks
- - discovery-playlist
- - missed-playlist
- type: string
- ListenType:
- enum:
- - single
- - playing_now
- - import
- type: string
- Mode:
- description: mode is the LB radio mode to be used for this query
- enum:
- - easy
- - medium
- - hard
- type: string
- AllowedStatisticsRange:
- enum:
- - all_time
- - month
- - week
- - year
- - quarter
- - half_yearly
- - this_week
- - this_month
- - this_year
- type: string
- Operator:
- enum:
- - AND
- - OR
- type: string
- AllowedRatings:
- enum:
- - like
- - love
- - dislike
- - hate
- - bad_recommendation
- type: string
- CoverTypes:
- enum:
- - designer-top-5
- - designer-top-10
- - lps-on-the-floor
- - grid-stats
- - grid-stats-special
- type: string
- searchUsers:
- example:
- users:
- - user_name: user_name
- - user_name: user_name
- properties:
- users:
- items:
- $ref: "#/components/schemas/searchUsers_users_inner"
- type: array
- required:
- - users
- type: object
- submitListens:
- properties:
- listen_type:
- $ref: "#/components/schemas/ListenType"
- payload:
- items:
- $ref: "#/components/schemas/submitListens_payload_inner"
- type: array
- required:
- - listen_type
- - payload
- type: object
- validateToken:
- example:
- valid: true
- code: 0
- user_name: user_name
- message: message
- properties:
- code:
- type: integer
- message:
- type: string
- valid:
- type: boolean
- user_name:
- type: string
- required:
- - code
- - message
- - valid
- type: object
- listensForUser:
- example:
- payload:
- listens:
- - recording_msid: recording_msid
- listened_at: 5
- user_name: user_name
- inserted_at: 1
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- - recording_msid: recording_msid
- listened_at: 5
- user_name: user_name
- inserted_at: 1
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- user_id: user_id
- latest_listen_ts: 6
- count: 0
- oldest_listen_ts: 2
- properties:
- payload:
- $ref: "#/components/schemas/listensForUser_payload"
- required:
- - payload
- type: object
- listenCountForUser:
- example:
- payload:
- count: 0
- properties:
- payload:
- $ref: "#/components/schemas/listenCountForUser_payload"
- required:
- - payload
- type: object
- playingNowForUser:
- example:
- payload:
- listens:
- - playing_now: true
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- - playing_now: true
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- playing_now: true
- user_id: user_id
- count: 0
- properties:
- payload:
- $ref: "#/components/schemas/playingNowForUser_payload"
- required:
- - payload
- type: object
- similarUsersForUser:
- example:
- payload:
- - similarity: 0
- user_name: user_name
- - similarity: 0
- user_name: user_name
- properties:
- payload:
- items:
- $ref: "#/components/schemas/similarUsersForUser_payload_inner"
- type: array
- required:
- - payload
- type: object
- similarityOfUserForUser:
- example:
- payload:
- similarity: 0
- user_name: user_name
- properties:
- payload:
- $ref: "#/components/schemas/similarityOfUserForUser_payload"
- required:
- - payload
- type: object
- deleteListen:
- properties:
- listened_at:
- type: integer
- recording_msid:
- type: string
- required:
- - listened_at
- - recording_msid
- type: object
- latestImport:
- example:
- latest_import: latest_import
- musicbrainz_id: musicbrainz_id
- status:
- count: 0
- state: state
- properties:
- musicbrainz_id:
- description: the MusicBrainz ID of the user
- type: string
- latest_import:
- description: the timestamp of the newest listen submitted in previous imports.
- Defaults to 0
- type: string
- status:
- $ref: "#/components/schemas/latestImport_status"
- required:
- - latest_import
- - musicbrainz_id
- type: object
- servicesForUser:
- example:
- user_name: user_name
- services:
- - services
- - services
- properties:
- services:
- items:
- type: string
- type: array
- user_name:
- type: string
- required:
- - services
- - user_name
- type: object
- playlists:
- example:
- playlist_count: 1
- offset: 6
- count: 0
- playlists:
- - playlist:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - playlist:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- properties:
- count:
- type: integer
- offset:
- type: integer
- playlist_count:
- type: integer
- playlists:
- items:
- $ref: "#/components/schemas/createPlaylist_request"
- type: array
- type: object
- lbRadioRecordingsForArtist:
- additionalProperties:
- items:
- $ref: "#/components/schemas/lbRadioRecordingsForArtist_value_inner"
- type: array
- type: object
- lbRadioTags:
- items:
- $ref: "#/components/schemas/lbRadioTags_inner"
- type: array
- topArtistsForUser:
- example:
- payload:
- last_updated: 5
- offset: 5
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- to_ts: 2
- user_id: user_id
- from_ts: 1
- count: 6
- range: range
- total_artist_count: 7
- properties:
- payload:
- $ref: "#/components/schemas/topArtistsForUser_payload"
- required:
- - payload
- type: object
- topReleasesForUser:
- example:
- payload:
- last_updated: 1
- offset: 5
- to_ts: 7
- user_id: user_id
- from_ts: 6
- count: 0
- total_release_count: 9
- range: range
- releases:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- payload:
- $ref: "#/components/schemas/topReleasesForUser_payload"
- required:
- - payload
- type: object
- topReleaseGroupsForUser:
- example:
- payload:
- total_release_group_count: 3
- last_updated: 1
- offset: 5
- to_ts: 9
- user_id: user_id
- from_ts: 6
- count: 0
- range: range
- release_groups:
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- payload:
- $ref: "#/components/schemas/topReleaseGroupsForUser_payload"
- required:
- - payload
- type: object
- topRecordingsForUser:
- example:
- payload:
- last_updated: 1
- offset: 5
- recordings:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- to_ts: 7
- user_id: user_id
- from_ts: 6
- count: 0
- range: range
- total_recording_count: 9
- properties:
- payload:
- $ref: "#/components/schemas/topRecordingsForUser_payload"
- required:
- - payload
- type: object
- listeningActivityForUser:
- example:
- payload:
- last_updated: 6
- listening_activity:
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- to_ts: 2
- user_id: user_id
- from_ts: 0
- range: range
- properties:
- payload:
- $ref: "#/components/schemas/listeningActivityForUser_payload"
- required:
- - payload
- type: object
- dailyActivityForUser:
- example:
- payload:
- last_updated: 5
- to_ts: 5
- user_id: user_id
- from_ts: 1
- range: range
- daily_activity:
- Monday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Thursday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Friday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Sunday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Wednesday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Tuesday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Saturday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- properties:
- payload:
- $ref: "#/components/schemas/dailyActivityForUser_payload"
- required:
- - payload
- type: object
- artistMapForUser:
- example:
- payload:
- last_updated: 5
- artist_map:
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- to_ts: 5
- user_id: user_id
- from_ts: 1
- range: range
- properties:
- payload:
- $ref: "#/components/schemas/artistMapForUser_payload"
- required:
- - payload
- type: object
- listenersForArtist:
- example:
- payload:
- last_updated: 6
- listeners:
- - listen_count: 1
- user_name: user_name
- - listen_count: 1
- user_name: user_name
- artist_name: artist_name
- to_ts: 5
- from_ts: 0
- total_listen_count: 5
- total_user_count: 2
- stats_range: stats_range
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- payload:
- $ref: "#/components/schemas/listenersForArtist_payload"
- required:
- - payload
- type: object
- listenersForReleaseGroup:
- example:
- payload:
- last_updated: 1
- caa_id: 0
- listeners:
- - listen_count: 1
- user_name: user_name
- - listen_count: 1
- user_name: user_name
- artist_name: artist_name
- from_ts: 6
- total_listen_count: 5
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- total_user_count: 2
- stats_range: stats_range
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- to_ts: 5
- release_group_name: release_group_name
- properties:
- payload:
- $ref: "#/components/schemas/listenersForReleaseGroup_payload"
- required:
- - payload
- type: object
- sitewideTopArtists:
- example:
- payload:
- last_updated: 1
- offset: 5
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- to_ts: 5
- from_ts: 6
- count: 0
- range: range
- total_artist_count: 2
- properties:
- payload:
- $ref: "#/components/schemas/sitewideTopArtists_payload"
- required:
- - payload
- type: object
- sitewideTopReleases:
- example:
- payload:
- last_updated: 1
- offset: 5
- to_ts: 7
- from_ts: 6
- count: 0
- total_release_count: 9
- range: range
- releases:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artists: artists
- artist_name: artist_name
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artists: artists
- artist_name: artist_name
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- payload:
- $ref: "#/components/schemas/sitewideTopReleases_payload"
- required:
- - payload
- type: object
- sitewideTopReleaseGroups:
- example:
- payload:
- total_release_group_count: 2
- last_updated: 1
- offset: 5
- to_ts: 5
- from_ts: 6
- count: 0
- range: range
- release_groups:
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- payload:
- $ref: "#/components/schemas/sitewideTopReleaseGroups_payload"
- required:
- - payload
- type: object
- sitewideTopRecordings:
- example:
- payload:
- last_updated: 1
- offset: 5
- recordings:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artists:
- - artists
- - artists
- artist_name: artist_name
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artists:
- - artists
- - artists
- artist_name: artist_name
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- to_ts: 7
- from_ts: 6
- count: 0
- range: range
- total_recording_count: 9
- properties:
- payload:
- $ref: "#/components/schemas/sitewideTopRecordings_payload"
- required:
- - payload
- type: object
- sitewideListeningActivity:
- example:
- payload:
- last_updated: 6
- listening_activity:
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- to_ts: 1
- from_ts: 0
- range: range
- properties:
- payload:
- $ref: "#/components/schemas/sitewideListeningActivity_payload"
- required:
- - payload
- type: object
- sitewideArtistMap:
- example:
- payload:
- last_updated: 6
- artist_map:
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- to_ts: 1
- from_ts: 0
- stats_range: stats_range
- properties:
- payload:
- $ref: "#/components/schemas/sitewideArtistMap_payload"
- required:
- - payload
- type: object
- yearInMusicForUser:
- example:
- payload:
- data:
- most_listened_year:
- key: 0
- top_release_groups:
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- total_new_artists_discovered: 3
- similar_users:
- key: 1
- listens_per_day:
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- total_listen_count: 7
- total_artists_count: 2
- total_recordings_count: 2
- new_releases_of_top_artists:
- - artist_credit_name: artist_credit_name
- caa_id: 6
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- title: title
- artist_credit_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- caa_id: 6
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- title: title
- artist_credit_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- top_artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- top_recordings:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- total_listening_time: 9
- playlist-top-missed-recordings-for-year:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- artist_map:
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- top_genres:
- - genre_count_percent: 5
- genre_count: 5
- genre: genre
- - genre_count_percent: 5
- genre_count: 5
- genre: genre
- total_release_groups_count: 4
- playlist-top-discoveries-for-year:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- day_of_week: day_of_week
- user_name: user_name
- properties:
- payload:
- $ref: "#/components/schemas/yearInMusicForUser_payload"
- required:
- - payload
- type: object
- playlist:
- example:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- properties:
- album:
- type: string
- annotation:
- type: string
- creator:
- type: string
- date:
- type: string
- duration:
- type: integer
- extension:
- $ref: "#/components/schemas/playlist-extension"
- identifier:
- type: string
- title:
- type: string
- track:
- items:
- $ref: "#/components/schemas/playlist_track_inner"
- type: array
- type: object
- feedbackResponse:
- example:
- feedback:
- - score: 1
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- user_id: user_id
- created: 6
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- - score: 1
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- user_id: user_id
- created: 6
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- offset: 5
- total_count: 5
- count: 0
- properties:
- count:
- type: integer
- feedback:
- items:
- $ref: "#/components/schemas/feedback"
- type: array
- offset:
- type: integer
- total_count:
- type: integer
- type: object
- trackMetadata:
- example:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- additional_info:
- $ref: "#/components/schemas/additionalInfo"
- artist_name:
- type: string
- brainzplayer_metadata:
- $ref: "#/components/schemas/trackMetadata_brainzplayer_metadata"
- mbid_mapping:
- $ref: "#/components/schemas/mbidMapping"
- release_name:
- type: string
- track_name:
- type: string
- type: object
- getPins:
- example:
- offset: 6
- total_count: 2
- user_name: user_name
- count: 0
- pinned_recordings:
- - recording_msid: recording_msid
- pinned_until: 5
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 1
- blurb_content: blurb_content
- row_id: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- - recording_msid: recording_msid
- pinned_until: 5
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 1
- blurb_content: blurb_content
- row_id: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- count:
- type: integer
- offset:
- type: integer
- pinned_recordings:
- items:
- $ref: "#/components/schemas/getPins_pinned_recordings_inner"
- type: array
- total_count:
- type: integer
- user_name:
- type: string
- required:
- - count
- - offset
- - pinned_recordings
- - user_name
- type: object
- topRecordingsForArtist:
- items:
- $ref: "#/components/schemas/topRecordingsForArtist_inner"
- type: array
- topReleaseGroupsForArtist:
- items:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner"
- type: array
- recordingMetadata:
- properties:
- artist:
- $ref: "#/components/schemas/recordingMetadata_artist"
- recording:
- $ref: "#/components/schemas/recordingMetadata_recording"
- tag:
- $ref: "#/components/schemas/recordingMetadata_tag"
- type: object
- releaseGroupMetadata:
- properties:
- release_group:
- $ref: "#/components/schemas/releaseGroupMetadata_release_group"
- tag:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner_tag"
- artist:
- $ref: "#/components/schemas/releaseGroupMetadata_artist"
- release:
- $ref: "#/components/schemas/releaseGroupMetadata_release_group"
- type: object
- lookup:
- example:
- artist_credit_name: artist_credit_name
- metadata:
- artist:
- artist_credit_id: 0
- artists:
- - area: area
- join_phrase: join_phrase
- name: name
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- - area: area
- join_phrase: join_phrase
- name: name
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- name: name
- release:
- caa_id: 5
- mbid: mbid
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- year: 5
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- name: name
- album_artist_name: album_artist_name
- recording:
- isrcs:
- - isrcs
- - isrcs
- first_release_date: 2000-01-23
- length: 1
- name: name
- items: items
- rels:
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tag:
- artist:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording:
- - count: 2
- tag: tag
- - count: 2
- tag: tag
- release_group:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- recording_name: recording_name
- release_name: release_name
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_credit_name:
- type: string
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- metadata:
- $ref: "#/components/schemas/lookup_metadata"
- recording_mbid:
- format: uuid
- type: string
- recording_name:
- type: string
- release_mbid:
- format: uuid
- type: string
- release_name:
- type: string
- type: object
- submitManualMapping:
- properties:
- recording_mbid:
- format: uuid
- type: string
- recording_msid:
- format: uuid
- type: string
- required:
- - a
- - b
- type: object
- getManualMapping:
- example:
- mapping:
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- user_id: 0
- created: created
- status: status
- properties:
- mapping:
- $ref: "#/components/schemas/getManualMapping_mapping"
- status:
- type: string
- required:
- - mapping
- - status
- type: object
- artistMetadata:
- example:
- area: area
- mbid: mbid
- gender: gender
- name: name
- tag:
- artist:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 0
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- properties:
- area:
- type: string
- artist_mbid:
- format: uuid
- type: string
- begin_year:
- type: integer
- gender:
- type: string
- mbid:
- type: string
- name:
- type: string
- rels:
- $ref: "#/components/schemas/rels_1"
- tag:
- $ref: "#/components/schemas/artistMetadata_tag"
- type:
- type: string
- type: object
- feedEvents:
- example:
- payload:
- user_id: user_id
- count: 0
- events:
- - metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- user_name: user_name
- similarity: 7.061401241503109
- id: 1
- message: message
- - metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- user_name: user_name
- similarity: 7.061401241503109
- id: 1
- message: message
- properties:
- payload:
- $ref: "#/components/schemas/feedEvents_payload"
- type: object
- feedEventsListensSimilar:
- example:
- payload:
- user_id: user_id
- count: 0
- events:
- - metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- similarity: 1
- user_name: user_name
- id: id
- - metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- similarity: 1
- user_name: user_name
- id: id
- properties:
- payload:
- $ref: "#/components/schemas/feedEventsListensSimilar_payload"
- required:
- - payload
- type: object
- followers:
- example:
- followers:
- - followers
- - followers
- user: user
- properties:
- followers:
- items:
- type: string
- type: array
- user:
- type: string
- required:
- - followers
- - user
- type: object
- following:
- example:
- following:
- - following
- - following
- user: user
- properties:
- following:
- items:
- type: string
- type: array
- user:
- type: string
- required:
- - following
- - user
- type: object
- recordingRecommendations:
- example:
- payload:
- last_updated: 6
- model_url: model_url
- offset: 5
- user_name: user_name
- count: 0
- model_id: model_id
- mbids:
- - score: 1
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- latest_listened_at: latest_listened_at
- - score: 1
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- latest_listened_at: latest_listened_at
- total_mbid_count: 5
- entity: entity
- properties:
- payload:
- $ref: "#/components/schemas/recordingRecommendations_payload"
- required:
- - payload
- type: object
- feedbackGivenBy:
- example:
- feedback:
- - recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 6
- rating: rating
- - recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 6
- rating: rating
- offset: 1
- total_count: 5
- user_name: user_name
- count: 0
- properties:
- count:
- type: integer
- feedback:
- items:
- $ref: "#/components/schemas/feedbackGivenBy_feedback_inner"
- type: array
- offset:
- type: integer
- total_count:
- type: integer
- user_name:
- type: string
- required:
- - count
- - feedback
- - offset
- - total_count
- - user_name
- type: object
- recordingsFeedbackGivenBy:
- example:
- feedback:
- - recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 6
- rating: rating
- - recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 6
- rating: rating
- user_name: user_name
- properties:
- feedback:
- items:
- $ref: "#/components/schemas/feedbackGivenBy_feedback_inner"
- type: array
- user_name:
- type: string
- required:
- - feedback
- - user_name
- type: object
- freshReleases:
- example:
- payload:
- total_count: 6
- releases:
- - artist_credit_name: artist_credit_name
- listen_count: 0
- release_name: release_name
- release_date: release_date
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_tags:
- - key: release_tags
- - key: release_tags
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_primary_type: release_group_primary_type
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 0
- release_name: release_name
- release_date: release_date
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_tags:
- - key: release_tags
- - key: release_tags
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_primary_type: release_group_primary_type
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- payload:
- $ref: "#/components/schemas/freshReleases_payload"
- required:
- - payload
- type: object
- color:
- example:
- payload:
- releases:
- - caa_id: 0
- color:
- - 6
- - 6
- release_name: release_name
- artist_name: artist_name
- recordings:
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- dist: 1
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - caa_id: 0
- color:
- - 6
- - 6
- release_name: release_name
- artist_name: artist_name
- recordings:
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- dist: 1
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- payload:
- $ref: "#/components/schemas/color_payload"
- required:
- - payload
- type: object
- lbRadio:
- example:
- payload:
- feedback:
- - feedback
- - feedback
- jspf:
- playlist:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- properties:
- payload:
- $ref: "#/components/schemas/lbRadio_payload"
- required:
- - payload
- type: object
- getDumpInfo:
- example:
- id: 0
- timestamp: timestamp
- properties:
- id:
- type: integer
- timestamp:
- type: string
- required:
- - id
- - timestamp
- type: object
- createCoverArtGrid:
- properties:
- background:
- description: The background for the cover art.
- enum:
- - transparent
- - white
- - black
- type: string
- image_size:
- description: The size of the cover art image.
- type: integer
- dimension:
- description: "The dimension to use for this grid. A grid of dimension 3\
- \ has 3 images across and 3 images down, for a total of 9 images."
- type: integer
- skip-missing:
- description: "If cover art is missing for a given release_mbid, skip it\
- \ and move on to the next one, if true is passed. If false, the show-caa\
- \ option will decide what happens."
- type: boolean
- show-caa:
- description: "If cover art is missing and skip-missing is false, then show-caa\
- \ will determine if a blank square is shown or if the Cover Art Archive\
- \ missing image is shown."
- type: boolean
- tiles:
- description: "The tiles paramater is a list of strings that determines the\
- \ location where cover art images should be placed. Each string is a comma\
- \ separated list of image cells. A grid of dimension 3 has 9 cells, from\
- \ 0 in the upper left hand corner, 2 in the upper right hand corner, 6\
- \ in the lower left corner and 8 in the lower right corner. Specifying\
- \ only a single cell will have the image cover that cell exactly. If more\
- \ than one cell is specified, the image will cover the area defined by\
- \ the bounding box of all the given cells. These tiles only define bounding\
- \ box areas - no clipping of images that may fall outside of these tiles\
- \ will be performed."
- items:
- type: string
- type: array
- release_mbids:
- description: An ordered list of release_mbids. The images will be loaded
- and processed in the order that this list is in. The cover art for the
- release_mbids will be placed on the tiles defined by the tiles parameter.
- items:
- format: uuid
- type: string
- type: array
- required:
- - background
- - dimension
- - image_size
- - release_mbids
- - show-caa
- - skip-missing
- - tiles
- type: object
- releaseGroups:
- items:
- $ref: "#/components/schemas/releaseGroups_inner"
- type: array
- playlist-extension:
- example:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- properties:
- https://musicbrainz.org/doc/jspf#playlist:
- $ref: "#/components/schemas/playlistExtensionPayload"
- type: object
- feedback:
- example:
- score: 1
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- user_id: user_id
- created: 6
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- created:
- type: integer
- recording_mbid:
- format: uuid
- type: string
- recording_msid:
- format: uuid
- type: string
- score:
- type: integer
- track_metadata:
- $ref: "#/components/schemas/trackMetadata"
- user_id:
- type: string
- type: object
- additionalInfo:
- additionalProperties:
- type: string
- example:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- properties:
- media_player:
- type: string
- media_player_version:
- type: string
- submission_client:
- type: string
- submission_client_version:
- type: string
- music_service:
- type: string
- music_service_name:
- type: string
- origin_url:
- type: string
- release_mbid:
- format: uuid
- type: string
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- recording_mbid:
- format: uuid
- type: string
- recording_msid:
- format: uuid
- type: string
- tags:
- items:
- type: string
- type: array
- duration:
- type: integer
- duration_ms:
- type: integer
- tracknumber:
- type: integer
- release_group_mbid:
- format: uuid
- type: string
- track_mbid:
- format: uuid
- type: string
- work_mbids:
- items:
- format: uuid
- type: string
- type: array
- isrc:
- type: string
- spotify_id:
- type: string
- discnumber:
- type: integer
- listening_from:
- type: string
- release_artist_name:
- type: string
- release_artist_names:
- items:
- type: string
- type: array
- spotify_album_artist_ids:
- items:
- type: string
- type: array
- spotify_album_id:
- type: string
- spotify_artist_ids:
- items:
- type: string
- type: array
- youtube_id:
- type: string
- albumartist:
- type: string
- comment:
- type: string
- date:
- type: string
- genre:
- type: string
- artist_names:
- items:
- type: string
- type: array
- trackNumber:
- type: string
- type: object
- mbidMapping:
- example:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- artists:
- items:
- $ref: "#/components/schemas/topReleasesForUser_payload_releases_inner_artists_inner"
- type: array
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- recording_mbid:
- format: uuid
- type: string
- recording_name:
- type: string
- release_mbid:
- format: uuid
- type: string
- type: object
- musicBrainzArtist:
- example:
- area: area
- gender: gender
- join_phrase: join_phrase
- name: name
- type: type
- end_year: 1
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- properties:
- area:
- type: string
- artist_mbid:
- format: uuid
- type: string
- begin_year:
- type: integer
- end_year:
- type: integer
- gender:
- type: string
- join_phrase:
- type: string
- name:
- type: string
- rels:
- $ref: "#/components/schemas/rels_1"
- type:
- type: string
- type: object
- rels:
- example:
- artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbid:
- format: uuid
- type: string
- artist_name:
- type: string
- instrument:
- type: string
- type:
- type: string
- type: object
- rels_1:
- example:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- properties:
- free streaming:
- type: string
- lyrics:
- type: string
- official homepage:
- type: string
- purchase for download:
- type: string
- download for free:
- type: string
- purchase for mail-order:
- type: string
- social network:
- type: string
- streaming:
- type: string
- wikidata:
- type: string
- youtube:
- type: string
- patronage:
- type: string
- crowdfunding:
- type: string
- blog:
- type: string
- type: object
- metadata:
- additionalProperties:
- type: string
- example:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- created:
- type: integer
- relationship_type:
- type: string
- message:
- type: string
- blurb_content:
- type: string
- inserted_at:
- type: integer
- listened_at:
- type: integer
- listened_at_iso:
- type: string
- playing_now:
- type: boolean
- track_metadata:
- $ref: "#/components/schemas/trackMetadata"
- user_name:
- type: string
- type: object
- createPlaylist_request:
- example:
- playlist:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- properties:
- playlist:
- $ref: "#/components/schemas/playlist"
- type: object
- createPlaylist_200_response:
- example:
- playlist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- status: status
- properties:
- playlist_mbid:
- format: uuid
- type: string
- status:
- type: string
- type: object
- moveItem_request:
- properties:
- mbid:
- format: uuid
- type: string
- from:
- type: integer
- to:
- type: integer
- count:
- type: integer
- type: object
- itemDelete_request:
- properties:
- index:
- type: integer
- count:
- type: integer
- type: object
- recordingFeedback_request:
- properties:
- recording_mbid:
- format: uuid
- type: string
- recording_msid:
- format: uuid
- type: string
- score:
- maximum: 1
- minimum: -1
- type: integer
- type: object
- pin_request:
- properties:
- recording_msid:
- format: uuid
- type: string
- recording_mbid:
- format: uuid
- type: string
- blurb_content:
- type: string
- pinned_until:
- format: int64
- type: integer
- type: object
- pin_200_response_pinned_recording:
- example:
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- pinned_until: 6
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 0
- blurb_content: blurb_content
- row_id: 1
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- created:
- type: integer
- pinned_until:
- type: integer
- recording_mbid:
- format: uuid
- type: string
- recording_msid:
- format: uuid
- type: string
- row_id:
- type: integer
- blurb_content:
- type: string
- track_metadata:
- $ref: "#/components/schemas/trackMetadata"
- type: object
- pin_200_response:
- example:
- pinned_recording:
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- pinned_until: 6
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 0
- blurb_content: blurb_content
- row_id: 1
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- pinned_recording:
- $ref: "#/components/schemas/pin_200_response_pinned_recording"
- type: object
- getPinsCurrent_200_response_pinned_recording:
- example:
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- pinned_until: 6
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 0
- blurb_content: blurb_content
- row_id: 1
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- blurb_content:
- type: string
- created:
- type: integer
- pinned_until:
- type: integer
- recording_mbid:
- format: uuid
- type: string
- recording_msid:
- format: uuid
- type: string
- row_id:
- type: integer
- track_metadata:
- $ref: "#/components/schemas/trackMetadata"
- type: object
- getPinsCurrent_200_response:
- example:
- pinned_recording:
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- pinned_until: 6
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 0
- blurb_content: blurb_content
- row_id: 1
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- user_name: user_name
- properties:
- pinned_recording:
- $ref: "#/components/schemas/getPinsCurrent_200_response_pinned_recording"
- user_name:
- type: string
- type: object
- updatePin_request:
- properties:
- blurb_content:
- type: string
- type: object
- recording_request:
- properties:
- recording_mbids:
- items:
- format: uuid
- type: string
- maxItems: 1000
- type: array
- required:
- - recording_mbids
- type: object
- recording_200_response_inner:
- example:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- total_listen_count: 0
- total_user_count: 6
- properties:
- recording_mbid:
- format: uuid
- type: string
- total_listen_count:
- type: integer
- total_user_count:
- type: integer
- type: object
- artist_request:
- properties:
- artist_mbids:
- items:
- format: uuid
- type: string
- maxItems: 1000
- type: array
- required:
- - artist_mbids
- type: object
- artist_200_response_inner:
- example:
- total_listen_count: 0
- total_user_count: 6
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbid:
- format: uuid
- type: string
- total_listen_count:
- type: integer
- total_user_count:
- type: integer
- type: object
- release_request:
- properties:
- release_mbids:
- items:
- format: uuid
- type: string
- maxItems: 1000
- type: array
- required:
- - release_mbids
- type: object
- release_200_response_inner:
- example:
- total_listen_count: 0
- total_user_count: 6
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- release_mbid:
- format: uuid
- type: string
- total_listen_count:
- type: integer
- total_user_count:
- type: integer
- type: object
- releaseGroup_request:
- properties:
- release_group_mbids:
- items:
- format: uuid
- type: string
- maxItems: 1000
- type: array
- required:
- - release_group_mbids
- type: object
- releaseGroup_200_response_inner:
- example:
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- total_listen_count: 0
- total_user_count: 6
- properties:
- release_group_mbid:
- format: uuid
- type: string
- total_listen_count:
- type: integer
- total_user_count:
- type: integer
- type: object
- recommendRecording_request_metadata:
- properties:
- recording_msid:
- format: uuid
- type: string
- recording_mbid:
- format: uuid
- type: string
- type: object
- recommendRecording_request:
- properties:
- metadata:
- $ref: "#/components/schemas/recommendRecording_request_metadata"
- type: object
- createNotification_request_metadata:
- properties:
- message:
- type: string
- type: object
- createNotification_request:
- properties:
- metadata:
- $ref: "#/components/schemas/createNotification_request_metadata"
- type: object
- createReview_request_metadata:
- properties:
- entity_name:
- type: string
- entity_id:
- type: string
- entity_type:
- type: string
- text:
- type: string
- language:
- type: string
- rating:
- type: integer
- type: object
- createReview_request:
- properties:
- metadata:
- $ref: "#/components/schemas/createReview_request_metadata"
- type: object
- feedEventsDelete_request:
- properties:
- event_type:
- type: string
- id:
- type: integer
- type: object
- recommendPersonalRecording_request_metadata:
- properties:
- recording_msid:
- format: uuid
- type: string
- recording_mbid:
- format: uuid
- type: string
- users:
- type: string
- blurb_content:
- type: string
- type: object
- recommendPersonalRecording_request:
- properties:
- metadata:
- $ref: "#/components/schemas/recommendPersonalRecording_request_metadata"
- type: object
- submitFeedback_request:
- properties:
- recording_mbid:
- format: uuid
- type: string
- rating:
- $ref: "#/components/schemas/AllowedRatings"
- type: object
- deleteFeedback_request:
- properties:
- recording_mbid:
- format: uuid
- type: string
- type: object
- searchUsers_users_inner:
- example:
- user_name: user_name
- properties:
- user_name:
- type: string
- type: object
- submitListens_payload_inner:
- properties:
- listened_at:
- format: int32
- minimum: 0
- type: integer
- track_metadata:
- $ref: "#/components/schemas/trackMetadata"
- type: object
- listensForUser_payload_listens_inner:
- example:
- recording_msid: recording_msid
- listened_at: 5
- user_name: user_name
- inserted_at: 1
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- inserted_at:
- type: integer
- listened_at:
- type: integer
- recording_msid:
- type: string
- track_metadata:
- $ref: "#/components/schemas/trackMetadata"
- user_name:
- type: string
- type: object
- listensForUser_payload:
- example:
- listens:
- - recording_msid: recording_msid
- listened_at: 5
- user_name: user_name
- inserted_at: 1
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- - recording_msid: recording_msid
- listened_at: 5
- user_name: user_name
- inserted_at: 1
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- user_id: user_id
- latest_listen_ts: 6
- count: 0
- oldest_listen_ts: 2
- properties:
- count:
- type: integer
- latest_listen_ts:
- type: integer
- listens:
- items:
- $ref: "#/components/schemas/listensForUser_payload_listens_inner"
- type: array
- oldest_listen_ts:
- type: integer
- user_id:
- type: string
- type: object
- listenCountForUser_payload:
- example:
- count: 0
- properties:
- count:
- type: integer
- required:
- - count
- type: object
- playingNowForUser_payload_listens_inner:
- example:
- playing_now: true
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- playing_now:
- type: boolean
- track_metadata:
- $ref: "#/components/schemas/trackMetadata"
- type: object
- playingNowForUser_payload:
- example:
- listens:
- - playing_now: true
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- - playing_now: true
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- playing_now: true
- user_id: user_id
- count: 0
- properties:
- count:
- type: integer
- listens:
- items:
- $ref: "#/components/schemas/playingNowForUser_payload_listens_inner"
- type: array
- playing_now:
- type: boolean
- user_id:
- type: string
- required:
- - count
- - listens
- - playing_now
- - user_id
- type: object
- similarUsersForUser_payload_inner:
- example:
- similarity: 0
- user_name: user_name
- properties:
- similarity:
- type: integer
- user_name:
- type: string
- type: object
- similarityOfUserForUser_payload:
- example:
- similarity: 0
- user_name: user_name
- properties:
- similarity:
- type: integer
- user_name:
- type: string
- required:
- - similarity
- - user_name
- type: object
- latestImport_status:
- example:
- count: 0
- state: state
- properties:
- state:
- description: a short string denoting the state of the import
- type: string
- count:
- description: the number of listens that have been imported for the user
- by the importer
- type: integer
- type: object
- lbRadioRecordingsForArtist_value_inner:
- properties:
- recording_mbid:
- format: uuid
- type: string
- similar_artist_mbid:
- format: uuid
- type: string
- similar_artist_name:
- type: string
- total_listen_count:
- type: integer
- type: object
- lbRadioTags_inner:
- example:
- tag_count: 6
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- source: source
- percent: 0
- properties:
- percent:
- type: integer
- recording_mbid:
- format: uuid
- type: string
- source:
- type: string
- tag_count:
- type: integer
- type: object
- topArtistsForUser_payload_artists_inner:
- example:
- listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbid:
- format: uuid
- type: string
- artist_name:
- type: string
- listen_count:
- type: integer
- type: object
- topArtistsForUser_payload:
- example:
- last_updated: 5
- offset: 5
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- to_ts: 2
- user_id: user_id
- from_ts: 1
- count: 6
- range: range
- total_artist_count: 7
- properties:
- artists:
- items:
- $ref: "#/components/schemas/topArtistsForUser_payload_artists_inner"
- type: array
- count:
- type: integer
- from_ts:
- type: integer
- last_updated:
- type: integer
- offset:
- type: integer
- range:
- type: string
- to_ts:
- type: integer
- total_artist_count:
- type: integer
- user_id:
- type: string
- required:
- - artists
- - count
- - from_ts
- - last_updated
- - offset
- - range
- - to_ts
- - total_artist_count
- - user_id
- type: object
- topReleasesForUser_payload_releases_inner_artists_inner:
- example:
- artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_credit_name:
- type: string
- artist_mbid:
- format: uuid
- type: string
- join_phrase:
- type: string
- type: object
- topReleasesForUser_payload_releases_inner:
- example:
- listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- artist_name:
- type: string
- artists:
- items:
- $ref: "#/components/schemas/topReleasesForUser_payload_releases_inner_artists_inner"
- type: array
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- listen_count:
- type: integer
- release_mbid:
- format: uuid
- type: string
- release_name:
- type: string
- type: object
- topReleasesForUser_payload:
- example:
- last_updated: 1
- offset: 5
- to_ts: 7
- user_id: user_id
- from_ts: 6
- count: 0
- total_release_count: 9
- range: range
- releases:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- count:
- type: integer
- from_ts:
- type: integer
- last_updated:
- type: integer
- offset:
- type: integer
- range:
- type: string
- releases:
- items:
- $ref: "#/components/schemas/topReleasesForUser_payload_releases_inner"
- type: array
- to_ts:
- type: integer
- total_release_count:
- type: integer
- user_id:
- type: string
- required:
- - count
- - from_ts
- - last_updated
- - offset
- - range
- - releases
- - to_ts
- - total_release_count
- - user_id
- type: object
- topReleaseGroupsForUser_payload:
- example:
- total_release_group_count: 3
- last_updated: 1
- offset: 5
- to_ts: 9
- user_id: user_id
- from_ts: 6
- count: 0
- range: range
- release_groups:
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- count:
- type: integer
- from_ts:
- type: integer
- last_updated:
- type: integer
- offset:
- type: integer
- range:
- type: string
- release_groups:
- items:
- $ref: "#/components/schemas/releaseGroups_inner"
- type: array
- to_ts:
- type: integer
- total_release_group_count:
- type: integer
- user_id:
- type: string
- required:
- - count
- - from_ts
- - last_updated
- - offset
- - range
- - release_groups
- - to_ts
- - total_release_group_count
- - user_id
- type: object
- topRecordingsForUser_payload_recordings_inner:
- example:
- listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- properties:
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- artist_name:
- type: string
- artists:
- items:
- $ref: "#/components/schemas/topReleasesForUser_payload_releases_inner_artists_inner"
- type: array
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- listen_count:
- type: integer
- recording_mbid:
- format: uuid
- type: string
- release_mbid:
- format: uuid
- type: string
- release_name:
- type: string
- track_name:
- type: string
- type: object
- topRecordingsForUser_payload:
- example:
- last_updated: 1
- offset: 5
- recordings:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- to_ts: 7
- user_id: user_id
- from_ts: 6
- count: 0
- range: range
- total_recording_count: 9
- properties:
- count:
- type: integer
- from_ts:
- type: integer
- last_updated:
- type: integer
- offset:
- type: integer
- range:
- type: string
- recordings:
- items:
- $ref: "#/components/schemas/topRecordingsForUser_payload_recordings_inner"
- type: array
- to_ts:
- type: integer
- total_recording_count:
- type: integer
- user_id:
- type: string
- required:
- - count
- - from_ts
- - last_updated
- - offset
- - range
- - recordings
- - to_ts
- - total_recording_count
- - user_id
- type: object
- listeningActivityForUser_payload_listening_activity_inner:
- example:
- listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- properties:
- from_ts:
- type: integer
- listen_count:
- type: integer
- time_range:
- type: string
- to_ts:
- type: integer
- type: object
- listeningActivityForUser_payload:
- example:
- last_updated: 6
- listening_activity:
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- to_ts: 2
- user_id: user_id
- from_ts: 0
- range: range
- properties:
- from_ts:
- type: integer
- last_updated:
- type: integer
- listening_activity:
- items:
- $ref: "#/components/schemas/listeningActivityForUser_payload_listening_activity_inner"
- type: array
- range:
- type: string
- to_ts:
- type: integer
- user_id:
- type: string
- required:
- - from_ts
- - last_updated
- - listening_activity
- - range
- - to_ts
- - user_id
- type: object
- dailyActivityForUser_payload_daily_activity_Friday_inner:
- example:
- listen_count: 6
- hour: 0
- properties:
- hour:
- type: integer
- listen_count:
- type: integer
- type: object
- dailyActivityForUser_payload_daily_activity:
- example:
- Monday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Thursday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Friday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Sunday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Wednesday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Tuesday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Saturday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- properties:
- Friday:
- items:
- $ref: "#/components/schemas/dailyActivityForUser_payload_daily_activity_Friday_inner"
- type: array
- Monday:
- items:
- $ref: "#/components/schemas/dailyActivityForUser_payload_daily_activity_Friday_inner"
- type: array
- Saturday:
- items:
- $ref: "#/components/schemas/dailyActivityForUser_payload_daily_activity_Friday_inner"
- type: array
- Sunday:
- items:
- $ref: "#/components/schemas/dailyActivityForUser_payload_daily_activity_Friday_inner"
- type: array
- Thursday:
- items:
- $ref: "#/components/schemas/dailyActivityForUser_payload_daily_activity_Friday_inner"
- type: array
- Tuesday:
- items:
- $ref: "#/components/schemas/dailyActivityForUser_payload_daily_activity_Friday_inner"
- type: array
- Wednesday:
- items:
- $ref: "#/components/schemas/dailyActivityForUser_payload_daily_activity_Friday_inner"
- type: array
- required:
- - Friday
- - Monday
- - Saturday
- - Sunday
- - Thursday
- - Tuesday
- - Wednesday
- type: object
- dailyActivityForUser_payload:
- example:
- last_updated: 5
- to_ts: 5
- user_id: user_id
- from_ts: 1
- range: range
- daily_activity:
- Monday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Thursday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Friday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Sunday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Wednesday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Tuesday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- Saturday:
- - listen_count: 6
- hour: 0
- - listen_count: 6
- hour: 0
- properties:
- daily_activity:
- $ref: "#/components/schemas/dailyActivityForUser_payload_daily_activity"
- from_ts:
- type: integer
- last_updated:
- type: integer
- range:
- type: string
- to_ts:
- type: integer
- user_id:
- type: string
- required:
- - daily_activity
- - from_ts
- - last_updated
- - range
- - to_ts
- - user_id
- type: object
- artistMapForUser_payload_artist_map_inner:
- example:
- listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- properties:
- artist_count:
- type: integer
- artists:
- items:
- $ref: "#/components/schemas/topArtistsForUser_payload_artists_inner"
- type: array
- country:
- type: string
- listen_count:
- type: integer
- type: object
- artistMapForUser_payload:
- example:
- last_updated: 5
- artist_map:
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- to_ts: 5
- user_id: user_id
- from_ts: 1
- range: range
- properties:
- artist_map:
- items:
- $ref: "#/components/schemas/artistMapForUser_payload_artist_map_inner"
- type: array
- from_ts:
- type: integer
- last_updated:
- type: integer
- range:
- type: string
- to_ts:
- type: integer
- user_id:
- type: string
- required:
- - artist_map
- - from_ts
- - last_updated
- - range
- - to_ts
- - user_id
- type: object
- listenersForArtist_payload_listeners_inner:
- example:
- listen_count: 1
- user_name: user_name
- properties:
- listen_count:
- type: integer
- user_name:
- type: string
- type: object
- listenersForArtist_payload:
- example:
- last_updated: 6
- listeners:
- - listen_count: 1
- user_name: user_name
- - listen_count: 1
- user_name: user_name
- artist_name: artist_name
- to_ts: 5
- from_ts: 0
- total_listen_count: 5
- total_user_count: 2
- stats_range: stats_range
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbid:
- format: uuid
- type: string
- artist_name:
- type: string
- from_ts:
- type: integer
- last_updated:
- type: integer
- listeners:
- items:
- $ref: "#/components/schemas/listenersForArtist_payload_listeners_inner"
- type: array
- stats_range:
- type: string
- to_ts:
- type: integer
- total_listen_count:
- type: integer
- total_user_count:
- type: integer
- required:
- - artist_mbid
- - artist_name
- - from_ts
- - last_updated
- - listeners
- - stats_range
- - to_ts
- - total_listen_count
- - total_user_count
- type: object
- listenersForReleaseGroup_payload:
- example:
- last_updated: 1
- caa_id: 0
- listeners:
- - listen_count: 1
- user_name: user_name
- - listen_count: 1
- user_name: user_name
- artist_name: artist_name
- from_ts: 6
- total_listen_count: 5
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- total_user_count: 2
- stats_range: stats_range
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- to_ts: 5
- release_group_name: release_group_name
- properties:
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- artist_name:
- type: string
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- from_ts:
- type: integer
- last_updated:
- type: integer
- listeners:
- items:
- $ref: "#/components/schemas/listenersForArtist_payload_listeners_inner"
- type: array
- release_group_mbid:
- format: uuid
- type: string
- release_group_name:
- type: string
- stats_range:
- type: string
- to_ts:
- type: integer
- total_listen_count:
- type: integer
- total_user_count:
- type: integer
- required:
- - artist_mbids
- - artist_name
- - caa_id
- - caa_release_mbid
- - from_ts
- - last_updated
- - listeners
- - release_group_mbid
- - release_group_name
- - stats_range
- - to_ts
- - total_listen_count
- - total_user_count
- type: object
- sitewideTopArtists_payload:
- example:
- last_updated: 1
- offset: 5
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- to_ts: 5
- from_ts: 6
- count: 0
- range: range
- total_artist_count: 2
- properties:
- artists:
- items:
- $ref: "#/components/schemas/topArtistsForUser_payload_artists_inner"
- type: array
- count:
- type: integer
- from_ts:
- type: integer
- last_updated:
- type: integer
- offset:
- type: integer
- range:
- type: string
- to_ts:
- type: integer
- total_artist_count:
- type: integer
- required:
- - artists
- - count
- - from_ts
- - last_updated
- - offset
- - range
- - to_ts
- - total_artist_count
- type: object
- sitewideTopReleases_payload_releases_inner:
- example:
- listen_count: 2
- caa_id: 5
- release_name: release_name
- artists: artists
- artist_name: artist_name
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artists:
- nullable: true
- type: string
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- artist_name:
- type: string
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- listen_count:
- type: integer
- release_mbid:
- format: uuid
- type: string
- release_name:
- type: string
- type: object
- sitewideTopReleases_payload:
- example:
- last_updated: 1
- offset: 5
- to_ts: 7
- from_ts: 6
- count: 0
- total_release_count: 9
- range: range
- releases:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artists: artists
- artist_name: artist_name
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artists: artists
- artist_name: artist_name
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- count:
- type: integer
- from_ts:
- type: integer
- last_updated:
- type: integer
- offset:
- type: integer
- range:
- type: string
- releases:
- items:
- $ref: "#/components/schemas/sitewideTopReleases_payload_releases_inner"
- type: array
- to_ts:
- type: integer
- total_release_count:
- type: integer
- required:
- - count
- - from_ts
- - last_updated
- - offset
- - range
- - releases
- - to_ts
- - total_release_count
- type: object
- sitewideTopReleaseGroups_payload:
- example:
- total_release_group_count: 2
- last_updated: 1
- offset: 5
- to_ts: 5
- from_ts: 6
- count: 0
- range: range
- release_groups:
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- count:
- type: integer
- from_ts:
- type: integer
- last_updated:
- type: integer
- offset:
- type: integer
- range:
- type: string
- release_groups:
- items:
- $ref: "#/components/schemas/releaseGroups_inner"
- type: array
- to_ts:
- type: integer
- total_release_group_count:
- type: integer
- required:
- - count
- - from_ts
- - last_updated
- - offset
- - range
- - release_groups
- - to_ts
- - total_release_group_count
- type: object
- sitewideTopRecordings_payload_recordings_inner:
- example:
- listen_count: 2
- caa_id: 5
- release_name: release_name
- artists:
- - artists
- - artists
- artist_name: artist_name
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- properties:
- artists:
- items:
- type: string
- type: array
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- artist_name:
- type: string
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- listen_count:
- type: integer
- recording_mbid:
- format: uuid
- type: string
- release_mbid:
- format: uuid
- type: string
- release_name:
- type: string
- track_name:
- type: string
- type: object
- sitewideTopRecordings_payload:
- example:
- last_updated: 1
- offset: 5
- recordings:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artists:
- - artists
- - artists
- artist_name: artist_name
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artists:
- - artists
- - artists
- artist_name: artist_name
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- to_ts: 7
- from_ts: 6
- count: 0
- range: range
- total_recording_count: 9
- properties:
- count:
- type: integer
- from_ts:
- type: integer
- last_updated:
- type: integer
- offset:
- type: integer
- range:
- type: string
- recordings:
- items:
- $ref: "#/components/schemas/sitewideTopRecordings_payload_recordings_inner"
- type: array
- to_ts:
- type: integer
- total_recording_count:
- type: integer
- required:
- - count
- - from_ts
- - last_updated
- - offset
- - range
- - recordings
- - to_ts
- - total_recording_count
- type: object
- sitewideListeningActivity_payload:
- example:
- last_updated: 6
- listening_activity:
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- to_ts: 1
- from_ts: 0
- range: range
- properties:
- from_ts:
- type: integer
- last_updated:
- type: integer
- listening_activity:
- items:
- $ref: "#/components/schemas/listeningActivityForUser_payload_listening_activity_inner"
- type: array
- range:
- type: string
- to_ts:
- type: integer
- required:
- - from_ts
- - last_updated
- - listening_activity
- - range
- - to_ts
- type: object
- sitewideArtistMap_payload:
- example:
- last_updated: 6
- artist_map:
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- to_ts: 1
- from_ts: 0
- stats_range: stats_range
- properties:
- artist_map:
- items:
- $ref: "#/components/schemas/artistMapForUser_payload_artist_map_inner"
- type: array
- from_ts:
- type: integer
- last_updated:
- type: integer
- stats_range:
- type: string
- to_ts:
- type: integer
- required:
- - artist_map
- - from_ts
- - last_updated
- - range
- - to_ts
- type: object
- yearInMusicForUser_payload_data_new_releases_of_top_artists_inner:
- example:
- artist_credit_name: artist_credit_name
- caa_id: 6
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- title: title
- artist_credit_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_credit_mbids:
- items:
- format: uuid
- type: string
- type: array
- artist_credit_name:
- type: string
- artists:
- items:
- $ref: "#/components/schemas/topReleasesForUser_payload_releases_inner_artists_inner"
- type: array
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- release_group_mbid:
- format: uuid
- type: string
- title:
- type: string
- type: object
- yearInMusicForUser_payload_data_top_genres_inner:
- example:
- genre_count_percent: 5
- genre_count: 5
- genre: genre
- properties:
- genre:
- type: string
- genre_count:
- type: integer
- genre_count_percent:
- type: integer
- type: object
- yearInMusicForUser_payload_data:
- example:
- most_listened_year:
- key: 0
- top_release_groups:
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- total_new_artists_discovered: 3
- similar_users:
- key: 1
- listens_per_day:
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- total_listen_count: 7
- total_artists_count: 2
- total_recordings_count: 2
- new_releases_of_top_artists:
- - artist_credit_name: artist_credit_name
- caa_id: 6
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- title: title
- artist_credit_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- caa_id: 6
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- title: title
- artist_credit_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- top_artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- top_recordings:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- total_listening_time: 9
- playlist-top-missed-recordings-for-year:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- artist_map:
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- top_genres:
- - genre_count_percent: 5
- genre_count: 5
- genre: genre
- - genre_count_percent: 5
- genre_count: 5
- genre: genre
- total_release_groups_count: 4
- playlist-top-discoveries-for-year:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- day_of_week: day_of_week
- properties:
- artist_map:
- items:
- $ref: "#/components/schemas/artistMapForUser_payload_artist_map_inner"
- type: array
- day_of_week:
- type: string
- listens_per_day:
- items:
- $ref: "#/components/schemas/listeningActivityForUser_payload_listening_activity_inner"
- type: array
- most_listened_year:
- additionalProperties:
- type: integer
- type: object
- new_releases_of_top_artists:
- items:
- $ref: "#/components/schemas/yearInMusicForUser_payload_data_new_releases_of_top_artists_inner"
- type: array
- playlist-top-discoveries-for-year:
- $ref: "#/components/schemas/playlist"
- playlist-top-missed-recordings-for-year:
- $ref: "#/components/schemas/playlist"
- similar_users:
- additionalProperties:
- type: integer
- type: object
- top_artists:
- items:
- $ref: "#/components/schemas/topArtistsForUser_payload_artists_inner"
- type: array
- top_genres:
- items:
- $ref: "#/components/schemas/yearInMusicForUser_payload_data_top_genres_inner"
- type: array
- top_recordings:
- items:
- $ref: "#/components/schemas/topRecordingsForUser_payload_recordings_inner"
- type: array
- top_release_groups:
- items:
- $ref: "#/components/schemas/releaseGroups_inner"
- type: array
- total_artists_count:
- type: integer
- total_listen_count:
- type: integer
- total_listening_time:
- type: integer
- total_new_artists_discovered:
- type: integer
- total_recordings_count:
- type: integer
- total_release_groups_count:
- type: integer
- required:
- - artist_map
- - day_of_week
- - listens_per_day
- - most_listened_year
- - new_releases_of_top_artists
- - playlist-top-discoveries-for-year
- - playlist-top-missed-recordings-for-year
- - similar_users
- - top_artists
- - top_genres
- - top_recordings
- - top_release_groups
- - total_artists_count
- - total_listen_count
- - total_listening_time
- - total_new_artists_discovered
- - total_recordings_count
- - total_release_groups_count
- type: object
- yearInMusicForUser_payload:
- example:
- data:
- most_listened_year:
- key: 0
- top_release_groups:
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- total_new_artists_discovered: 3
- similar_users:
- key: 1
- listens_per_day:
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- - listen_count: 5
- time_range: time_range
- to_ts: 5
- from_ts: 1
- total_listen_count: 7
- total_artists_count: 2
- total_recordings_count: 2
- new_releases_of_top_artists:
- - artist_credit_name: artist_credit_name
- caa_id: 6
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- title: title
- artist_credit_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- caa_id: 6
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- title: title
- artist_credit_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- top_artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- top_recordings:
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- - listen_count: 2
- caa_id: 5
- release_name: release_name
- artist_name: artist_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- track_name: track_name
- total_listening_time: 9
- playlist-top-missed-recordings-for-year:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- artist_map:
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- - listen_count: 6
- country: country
- artists:
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - listen_count: 0
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_count: 0
- top_genres:
- - genre_count_percent: 5
- genre_count: 5
- genre: genre
- - genre_count_percent: 5
- genre_count: 5
- genre: genre
- total_release_groups_count: 4
- playlist-top-discoveries-for-year:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- day_of_week: day_of_week
- user_name: user_name
- properties:
- data:
- $ref: "#/components/schemas/yearInMusicForUser_payload_data"
- user_name:
- type: string
- required:
- - data
- - user_name
- type: object
- playlist_track_inner_extension_https___musicbrainz_org_doc_jspf_track_additional_metadata:
- example:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- caa_release_mbid:
- format: uuid
- type: string
- caa_id:
- type: integer
- artists:
- items:
- $ref: "#/components/schemas/topReleasesForUser_payload_releases_inner_artists_inner"
- type: array
- type: object
- playlist_track_inner_extension_https___musicbrainz_org_doc_jspf_track:
- example:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_identifiers:
- items:
- type: string
- type: array
- release_identifier:
- type: string
- added_at:
- type: string
- added_by:
- type: string
- additional_metadata:
- $ref: "#/components/schemas/playlist_track_inner_extension_https___musicbrainz_org_doc_jspf_track_additional_metadata"
- type: object
- playlist_track_inner_extension:
- example:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- https://musicbrainz.org/doc/jspf#track:
- $ref: "#/components/schemas/playlist_track_inner_extension_https___musicbrainz_org_doc_jspf_track"
- required:
- - https://musicbrainz.org/doc/jspf#track
- type: object
- playlist_track_inner:
- example:
- duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- properties:
- album:
- type: string
- creator:
- type: string
- duration:
- type: integer
- extension:
- $ref: "#/components/schemas/playlist_track_inner_extension"
- identifier:
- items:
- type: string
- type: array
- title:
- type: string
- type: object
- trackMetadata_brainzplayer_metadata:
- example:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- properties:
- artist_name:
- type: string
- release_name:
- type: string
- track_name:
- type: string
- type: object
- getPins_pinned_recordings_inner:
- example:
- recording_msid: recording_msid
- pinned_until: 5
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 1
- blurb_content: blurb_content
- row_id: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- properties:
- blurb_content:
- type: string
- created:
- type: integer
- pinned_until:
- type: integer
- recording_mbid:
- format: uuid
- type: string
- recording_msid:
- type: string
- row_id:
- format: uuid
- type: integer
- track_metadata:
- $ref: "#/components/schemas/trackMetadata"
- type: object
- topRecordingsForArtist_inner_release_color:
- example:
- red: 5
- green: 5
- blue: 1
- properties:
- blue:
- type: integer
- green:
- type: integer
- red:
- type: integer
- type: object
- topRecordingsForArtist_inner_tags_inner:
- example:
- genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- properties:
- count:
- type: integer
- genre_mbid:
- format: uuid
- type: string
- tag:
- type: string
- type: object
- topRecordingsForArtist_inner:
- example:
- recording_name: recording_name
- caa_id: 0
- artist_name: artist_name
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- total_listen_count: 2
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- length: 6
- total_user_count: 7
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tags:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- release_name: release_name
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_color:
- red: 5
- green: 5
- blue: 1
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- artist_name:
- type: string
- artists:
- items:
- $ref: "#/components/schemas/topReleasesForUser_payload_releases_inner_artists_inner"
- type: array
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- length:
- type: integer
- recording_mbid:
- format: uuid
- type: string
- recording_name:
- type: string
- release_color:
- $ref: "#/components/schemas/topRecordingsForArtist_inner_release_color"
- release_mbid:
- format: uuid
- type: string
- release_name:
- type: string
- total_listen_count:
- type: integer
- total_user_count:
- type: integer
- tags:
- items:
- $ref: "#/components/schemas/topRecordingsForArtist_inner_tags_inner"
- type: array
- type: object
- topReleaseGroupsForArtist_inner_artist:
- example:
- artist_credit_id: 0
- artists:
- - area: area
- gender: gender
- join_phrase: join_phrase
- name: name
- type: type
- end_year: 1
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- - area: area
- gender: gender
- join_phrase: join_phrase
- name: name
- type: type
- end_year: 1
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- name: name
- properties:
- artist_credit_id:
- type: integer
- artists:
- items:
- $ref: "#/components/schemas/musicBrainzArtist"
- type: array
- name:
- type: string
- type: object
- topReleaseGroupsForArtist_inner_release:
- example:
- date: date
- caa_id: 5
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- name: name
- type: type
- rels:
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- rels:
- items:
- $ref: "#/components/schemas/rels"
- type: array
- date:
- type: string
- name:
- type: string
- type:
- type: string
- type: object
- topReleaseGroupsForArtist_inner_release_group:
- example:
- date: date
- caa_id: 5
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- name: name
- type: type
- rels:
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- date:
- type: string
- name:
- type: string
- type:
- type: string
- rels:
- items:
- $ref: "#/components/schemas/rels"
- type: array
- type: object
- topReleaseGroupsForArtist_inner_tag_artist_inner:
- example:
- genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbid:
- format: uuid
- type: string
- count:
- type: integer
- genre_mbid:
- format: uuid
- type: string
- tag:
- type: string
- type: object
- topReleaseGroupsForArtist_inner_tag:
- example:
- artist:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- properties:
- artist:
- items:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner_tag_artist_inner"
- type: array
- release_group:
- items:
- $ref: "#/components/schemas/topRecordingsForArtist_inner_tags_inner"
- type: array
- type: object
- topReleaseGroupsForArtist_inner:
- example:
- artist:
- artist_credit_id: 0
- artists:
- - area: area
- gender: gender
- join_phrase: join_phrase
- name: name
- type: type
- end_year: 1
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- - area: area
- gender: gender
- join_phrase: join_phrase
- name: name
- type: type
- end_year: 1
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- name: name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release:
- date: date
- caa_id: 5
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- name: name
- type: type
- rels:
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- total_listen_count: 7
- release_color:
- red: 5
- green: 5
- blue: 1
- total_user_count: 9
- release_group:
- date: date
- caa_id: 5
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- name: name
- type: type
- rels:
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tag:
- artist:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- properties:
- artist:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner_artist"
- release:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner_release"
- release_color:
- $ref: "#/components/schemas/topRecordingsForArtist_inner_release_color"
- release_group:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner_release_group"
- release_group_mbid:
- format: uuid
- type: string
- tag:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner_tag"
- total_listen_count:
- type: integer
- total_user_count:
- type: integer
- type: object
- recordingMetadata_artist_artists_inner:
- example:
- area: area
- join_phrase: join_phrase
- name: name
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- properties:
- area:
- type: string
- artist_mbid:
- format: uuid
- type: string
- begin_year:
- type: integer
- join_phrase:
- type: string
- name:
- type: string
- rels:
- $ref: "#/components/schemas/rels_1"
- type:
- type: string
- type: object
- recordingMetadata_artist:
- example:
- artist_credit_id: 0
- artists:
- - area: area
- join_phrase: join_phrase
- name: name
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- - area: area
- join_phrase: join_phrase
- name: name
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- name: name
- properties:
- artist_credit_id:
- type: integer
- artists:
- items:
- $ref: "#/components/schemas/recordingMetadata_artist_artists_inner"
- type: array
- name:
- type: string
- type: object
- recordingMetadata_recording:
- example:
- isrcs:
- - isrcs
- - isrcs
- first_release_date: 2000-01-23
- length: 1
- name: name
- items: items
- rels:
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- first_release_date:
- format: date
- type: string
- isrcs:
- items:
- description: TODO default missing array inner type to string
- type: string
- type: array
- items:
- type: string
- length:
- type: integer
- name:
- type: string
- rels:
- items:
- $ref: "#/components/schemas/rels"
- type: array
- type: object
- recordingMetadata_tag:
- properties:
- artist:
- items:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner_tag_artist_inner"
- type: array
- recording:
- items:
- $ref: "#/components/schemas/topRecordingsForArtist_inner_tags_inner"
- type: array
- release_group:
- items:
- $ref: "#/components/schemas/topRecordingsForArtist_inner_tags_inner"
- type: array
- type: object
- releaseGroupMetadata_release_group:
- properties:
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- date:
- type: string
- name:
- type: string
- rels:
- items:
- additionalProperties:
- type: string
- type: object
- type: array
- type:
- type: string
- type: object
- releaseGroupMetadata_artist_artists_inner:
- properties:
- area:
- type: string
- artist_mbid:
- format: uuid
- type: string
- begin_year:
- type: integer
- end_year:
- type: integer
- join_phrase:
- type: string
- name:
- type: string
- rels:
- $ref: "#/components/schemas/rels_1"
- type:
- type: string
- type: object
- releaseGroupMetadata_artist:
- properties:
- artist_credit_id:
- type: integer
- artists:
- items:
- $ref: "#/components/schemas/releaseGroupMetadata_artist_artists_inner"
- type: array
- name:
- type: string
- type: object
- lookup_metadata_release:
- example:
- caa_id: 5
- mbid: mbid
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- year: 5
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- name: name
- album_artist_name: album_artist_name
- properties:
- album_artist_name:
- type: string
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- mbid:
- type: string
- name:
- type: string
- release_group_mbid:
- format: uuid
- type: string
- year:
- type: integer
- type: object
- lookup_metadata_tag_recording_inner:
- example:
- count: 2
- tag: tag
- properties:
- count:
- type: integer
- tag:
- type: string
- type: object
- lookup_metadata_tag:
- example:
- artist:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording:
- - count: 2
- tag: tag
- - count: 2
- tag: tag
- release_group:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- properties:
- artist:
- items:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner_tag_artist_inner"
- type: array
- recording:
- items:
- $ref: "#/components/schemas/lookup_metadata_tag_recording_inner"
- type: array
- release_group:
- items:
- $ref: "#/components/schemas/topRecordingsForArtist_inner_tags_inner"
- type: array
- type: object
- lookup_metadata:
- example:
- artist:
- artist_credit_id: 0
- artists:
- - area: area
- join_phrase: join_phrase
- name: name
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- - area: area
- join_phrase: join_phrase
- name: name
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- begin_year: 6
- rels:
- youtube: youtube
- download for free: download for free
- free streaming: free streaming
- purchase for download: purchase for download
- blog: blog
- social network: social network
- streaming: streaming
- official homepage: official homepage
- crowdfunding: crowdfunding
- purchase for mail-order: purchase for mail-order
- patronage: patronage
- lyrics: lyrics
- wikidata: wikidata
- name: name
- release:
- caa_id: 5
- mbid: mbid
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- year: 5
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- name: name
- album_artist_name: album_artist_name
- recording:
- isrcs:
- - isrcs
- - isrcs
- first_release_date: 2000-01-23
- length: 1
- name: name
- items: items
- rels:
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_name: artist_name
- instrument: instrument
- type: type
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tag:
- artist:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording:
- - count: 2
- tag: tag
- - count: 2
- tag: tag
- release_group:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 9
- tag: tag
- properties:
- artist:
- $ref: "#/components/schemas/recordingMetadata_artist"
- recording:
- $ref: "#/components/schemas/recordingMetadata_recording"
- release:
- $ref: "#/components/schemas/lookup_metadata_release"
- tag:
- $ref: "#/components/schemas/lookup_metadata_tag"
- type: object
- getManualMapping_mapping:
- example:
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- user_id: 0
- created: created
- properties:
- created:
- type: string
- recording_mbid:
- format: uuid
- type: string
- recording_msid:
- format: uuid
- type: string
- user_id:
- type: integer
- required:
- - created
- - recording_mbid
- - recording_msid
- - user_id
- type: object
- artistMetadata_tag:
- example:
- artist:
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - genre_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- count: 2
- tag: tag
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist:
- items:
- $ref: "#/components/schemas/topReleaseGroupsForArtist_inner_tag_artist_inner"
- type: array
- required:
- - artist
- type: object
- feedEvents_payload_events_inner:
- example:
- metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- user_name: user_name
- similarity: 7.061401241503109
- id: 1
- message: message
- properties:
- created:
- type: integer
- event_type:
- type: string
- hidden:
- type: boolean
- id:
- type: integer
- message:
- type: string
- metadata:
- $ref: "#/components/schemas/metadata"
- user_name:
- type: string
- similarity:
- type: number
- type: object
- feedEvents_payload:
- example:
- user_id: user_id
- count: 0
- events:
- - metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- user_name: user_name
- similarity: 7.061401241503109
- id: 1
- message: message
- - metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- user_name: user_name
- similarity: 7.061401241503109
- id: 1
- message: message
- properties:
- count:
- type: integer
- events:
- items:
- $ref: "#/components/schemas/feedEvents_payload_events_inner"
- type: array
- user_id:
- type: string
- type: object
- feedEventsListensSimilar_payload_events_inner:
- example:
- metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- similarity: 1
- user_name: user_name
- id: id
- properties:
- id:
- type: string
- created:
- type: integer
- event_type:
- type: string
- hidden:
- type: boolean
- metadata:
- $ref: "#/components/schemas/metadata"
- similarity:
- type: integer
- user_name:
- type: string
- type: object
- feedEventsListensSimilar_payload:
- example:
- user_id: user_id
- count: 0
- events:
- - metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- similarity: 1
- user_name: user_name
- id: id
- - metadata:
- relationship_type: relationship_type
- playing_now: true
- listened_at: 2
- listened_at_iso: listened_at_iso
- created: 5
- user_name: user_name
- blurb_content: blurb_content
- message: message
- inserted_at: 5
- track_metadata:
- release_name: release_name
- additional_info:
- date: date
- artist_names:
- - artist_names
- - artist_names
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_artist_name: release_artist_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- work_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- duration: 5
- discnumber: 9
- spotify_album_artist_ids:
- - spotify_album_artist_ids
- - spotify_album_artist_ids
- genre: genre
- media_player_version: media_player_version
- origin_url: origin_url
- submission_client: submission_client
- trackNumber: trackNumber
- spotify_id: spotify_id
- spotify_album_id: spotify_album_id
- submission_client_version: submission_client_version
- isrc: isrc
- release_artist_names:
- - release_artist_names
- - release_artist_names
- youtube_id: youtube_id
- tags:
- - tags
- - tags
- duration_ms: 2
- spotify_artist_ids:
- - spotify_artist_ids
- - spotify_artist_ids
- music_service_name: music_service_name
- recording_msid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- comment: comment
- music_service: music_service
- track_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- listening_from: listening_from
- media_player: media_player
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- tracknumber: 7
- albumartist: albumartist
- artist_name: artist_name
- mbid_mapping:
- recording_name: recording_name
- caa_id: 3
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- brainzplayer_metadata:
- release_name: release_name
- artist_name: artist_name
- track_name: track_name
- track_name: track_name
- event_type: event_type
- hidden: true
- created: 6
- similarity: 1
- user_name: user_name
- id: id
- properties:
- count:
- type: integer
- events:
- items:
- $ref: "#/components/schemas/feedEventsListensSimilar_payload_events_inner"
- type: array
- user_id:
- type: string
- required:
- - count
- - events
- - user_id
- type: object
- recordingRecommendations_payload_mbids_inner:
- example:
- score: 1
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- latest_listened_at: latest_listened_at
- properties:
- latest_listened_at:
- type: string
- recording_mbid:
- format: uuid
- type: string
- score:
- type: integer
- type: object
- recordingRecommendations_payload:
- example:
- last_updated: 6
- model_url: model_url
- offset: 5
- user_name: user_name
- count: 0
- model_id: model_id
- mbids:
- - score: 1
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- latest_listened_at: latest_listened_at
- - score: 1
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- latest_listened_at: latest_listened_at
- total_mbid_count: 5
- entity: entity
- properties:
- count:
- type: integer
- entity:
- type: string
- last_updated:
- type: integer
- mbids:
- items:
- $ref: "#/components/schemas/recordingRecommendations_payload_mbids_inner"
- type: array
- model_id:
- type: string
- model_url:
- type: string
- offset:
- type: integer
- total_mbid_count:
- type: integer
- user_name:
- type: string
- required:
- - count
- - entity
- - last_updated
- - mbids
- - model_id
- - model_url
- - offset
- - total_mbid_count
- - user_name
- type: object
- feedbackGivenBy_feedback_inner:
- example:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- created: 6
- rating: rating
- properties:
- created:
- type: integer
- rating:
- type: string
- recording_mbid:
- format: uuid
- type: string
- type: object
- freshReleases_payload_releases_inner:
- example:
- artist_credit_name: artist_credit_name
- listen_count: 0
- release_name: release_name
- release_date: release_date
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_tags:
- - key: release_tags
- - key: release_tags
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_primary_type: release_group_primary_type
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_credit_name:
- type: string
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- listen_count:
- type: integer
- release_date:
- type: string
- release_group_mbid:
- format: uuid
- type: string
- release_group_primary_type:
- type: string
- release_mbid:
- format: uuid
- type: string
- release_name:
- type: string
- release_tags:
- items:
- additionalProperties:
- type: string
- type: object
- type: array
- type: object
- freshReleases_payload:
- example:
- total_count: 6
- releases:
- - artist_credit_name: artist_credit_name
- listen_count: 0
- release_name: release_name
- release_date: release_date
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_tags:
- - key: release_tags
- - key: release_tags
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_primary_type: release_group_primary_type
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 0
- release_name: release_name
- release_date: release_date
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_tags:
- - key: release_tags
- - key: release_tags
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_primary_type: release_group_primary_type
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- releases:
- items:
- $ref: "#/components/schemas/freshReleases_payload_releases_inner"
- type: array
- total_count:
- type: integer
- required:
- - releases
- - total_count
- type: object
- color_payload_releases_inner_recordings_inner_track_metadata_additional_info:
- example:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- recording_mbid:
- format: uuid
- type: string
- release_mbid:
- format: uuid
- type: string
- required:
- - artist_mbids
- - recording_mbid
- - release_mbid
- type: object
- color_payload_releases_inner_recordings_inner_track_metadata:
- example:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- properties:
- additional_info:
- $ref: "#/components/schemas/color_payload_releases_inner_recordings_inner_track_metadata_additional_info"
- artist_name:
- type: string
- release_name:
- type: string
- track_name:
- type: string
- required:
- - additional_info
- - artist_name
- - release_name
- - track_name
- type: object
- color_payload_releases_inner_recordings_inner:
- example:
- track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- properties:
- track_metadata:
- $ref: "#/components/schemas/color_payload_releases_inner_recordings_inner_track_metadata"
- type: object
- color_payload_releases_inner:
- example:
- caa_id: 0
- color:
- - 6
- - 6
- release_name: release_name
- artist_name: artist_name
- recordings:
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- dist: 1
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_name:
- type: string
- caa_id:
- type: integer
- color:
- items:
- type: integer
- type: array
- dist:
- type: integer
- recordings:
- items:
- $ref: "#/components/schemas/color_payload_releases_inner_recordings_inner"
- type: array
- release_mbid:
- format: uuid
- type: string
- release_name:
- type: string
- type: object
- color_payload:
- example:
- releases:
- - caa_id: 0
- color:
- - 6
- - 6
- release_name: release_name
- artist_name: artist_name
- recordings:
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- dist: 1
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - caa_id: 0
- color:
- - 6
- - 6
- release_name: release_name
- artist_name: artist_name
- recordings:
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- - track_metadata:
- release_name: release_name
- additional_info:
- recording_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- track_name: track_name
- dist: 1
- release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- releases:
- items:
- $ref: "#/components/schemas/color_payload_releases_inner"
- type: array
- required:
- - releases
- type: object
- lbRadio_payload:
- example:
- feedback:
- - feedback
- - feedback
- jspf:
- playlist:
- annotation: annotation
- date: date
- duration: 5
- identifier: identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#playlist:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- album: album
- title: title
- track:
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- - duration: 5
- identifier:
- - identifier
- - identifier
- creator: creator
- extension:
- https://musicbrainz.org/doc/jspf#track:
- added_at: added_at
- added_by: added_by
- release_identifier: release_identifier
- artist_identifiers:
- - artist_identifiers
- - artist_identifiers
- additional_metadata:
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- join_phrase: join_phrase
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- album: album
- title: title
- properties:
- feedback:
- items:
- type: string
- type: array
- jspf:
- $ref: "#/components/schemas/createPlaylist_request"
- required:
- - feedback
- - jspf
- type: object
- releaseGroups_inner_artists_inner:
- example:
- artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artist_mbid:
- format: uuid
- type: string
- artist_name:
- type: string
- artist_credit_name:
- type: string
- listen_count:
- type: integer
- join_phrase:
- type: string
- type: object
- releaseGroups_inner:
- example:
- listen_count: 7
- caa_id: 2
- artists:
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - artist_credit_name: artist_credit_name
- listen_count: 5
- join_phrase: join_phrase
- artist_name: artist_name
- artist_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- artist_name: artist_name
- release_group_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- caa_release_mbid: 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- release_group_name: release_group_name
- artist_mbids:
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- - 046b6c7f-0b8a-43b9-b35d-6489e6daee91
- properties:
- artists:
- items:
- $ref: "#/components/schemas/releaseGroups_inner_artists_inner"
- type: array
- artist_mbids:
- items:
- format: uuid
- type: string
- type: array
- artist_name:
- type: string
- caa_id:
- type: integer
- caa_release_mbid:
- format: uuid
- type: string
- listen_count:
- type: integer
- release_group_mbid:
- format: uuid
- type: string
- release_group_name:
- type: string
- type: object
- playlistExtensionPayload_additional_metadata_algorithm_metadata:
- example:
- source_patch: source_patch
- properties:
- source_patch:
- type: string
- type: object
- playlistExtensionPayload_additional_metadata:
- additionalProperties:
- type: string
- example:
- algorithm_metadata:
- source_patch: source_patch
- properties:
- algorithm_metadata:
- $ref: "#/components/schemas/playlistExtensionPayload_additional_metadata_algorithm_metadata"
- type: object
- playlistExtensionPayload:
- example:
- creator: creator
- created_for: created_for
- public: true
- collaborators:
- - collaborators
- - collaborators
- copied_from: copied_from
- copied_from_deleted: true
- last_modified_at: last_modified_at
- additional_metadata:
- algorithm_metadata:
- source_patch: source_patch
- properties:
- created_for:
- type: string
- creator:
- type: string
- collaborators:
- items:
- type: string
- type: array
- copied_from:
- type: string
- copied_from_deleted:
- type: boolean
- public:
- type: boolean
- last_modified_at:
- type: string
- additional_metadata:
- $ref: "#/components/schemas/playlistExtensionPayload_additional_metadata"
- title: playlistExtensionPayload
- type: object
- securitySchemes:
- ApiKeyAuth:
- in: header
- name: Authorization
- type: apiKey
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/BuiltInPluginService.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/BuiltInPluginService.kt
index 3d9b19f6..a2be45f6 100644
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/BuiltInPluginService.kt
+++ b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/BuiltInPluginService.kt
@@ -21,27 +21,20 @@ import app.cash.zipline.ZiplineService
import dev.krtirtho.plugin_interfaces.plugin_apis.audio.AudioAPI
import dev.krtirtho.plugin_interfaces.plugin_apis.core.CoreAPI
import dev.krtirtho.plugin_interfaces.plugin_apis.lyrics.LyricsAPI
-import dev.krtirtho.spotube.core.webview.WebViewController
-import dev.krtirtho.spotube.core.zipline.host_apis.RealPersistedStorageAPI
import dev.krtirtho.spotube.core.zipline.plugin_apis.common.RealCoreAPI
import dev.krtirtho.spotube.core.zipline.plugin_apis.lrclib.RealLRCLibLyricsAPI
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.createMusicbrainzListenbrainzPluginAPIs
import dev.krtirtho.spotube.core.zipline.plugin_apis.newpipe_yt.RealNewPipeAudioAPI
import dev.krtirtho.spotube.modules.plugin.LRCLIB_BUILT_IN_PLUGIN
-import dev.krtirtho.spotube.modules.plugin.MUSICBRAINZ_LISTENBRAINZ_BUILT_IN_PLUGIN
import dev.krtirtho.spotube.modules.plugin.NEWPIPE_YOUTUBE_BUILT_IN_PLUGIN
import dev.krtirtho.spotube.modules.plugin.PluginEntry
-import io.ktor.client.HttpClient
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent
-import org.koin.core.component.inject
import kotlin.reflect.KClass
class BuiltInPluginService(
@@ -52,10 +45,10 @@ class BuiltInPluginService(
override val loggedInFlow = loggedInStateFlow.asStateFlow()
val servicesRegistry = mutableMapOf, ZiplineService>()
- val webViewController: WebViewController by inject()
+// val webViewController: WebViewController by inject()
+// val persistedStorage by lazy { RealPersistedStorageAPI(pluginInfo) }
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
- val persistedStorage by lazy { RealPersistedStorageAPI(pluginInfo) }
private fun runLogInFlowObservers() = scope.launch {
val coreAPI = servicesRegistry[CoreAPI::class] as CoreAPI?
@@ -72,17 +65,6 @@ class BuiltInPluginService(
servicesRegistry[AudioAPI::class] = RealNewPipeAudioAPI()
}
- MUSICBRAINZ_LISTENBRAINZ_BUILT_IN_PLUGIN -> {
- servicesRegistry.putAll(
- createMusicbrainzListenbrainzPluginAPIs(
- scope = scope,
- httpClient = HttpClient(),
- webViewController = webViewController,
- persistedStorage = persistedStorage
- )
- )
- }
-
LRCLIB_BUILT_IN_PLUGIN -> {
servicesRegistry[CoreAPI::class] = RealCoreAPI()
servicesRegistry[LyricsAPI::class] = RealLRCLibLyricsAPI()
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/EmulatedAlbumArtist.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/EmulatedAlbumArtist.kt
deleted file mode 100644
index 1a18bf2b..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/EmulatedAlbumArtist.kt
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import arrow.core.Either
-import dev.krtirtho.plugin_interfaces.host_apis.PersistedStorageAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbum
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtist
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationStrategy
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationResult
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzRepository
-import dev.krtirtho.spotube.listenbrainz.Api
-import dev.krtirtho.spotube.listenbrainz.Auth
-import dev.krtirtho.spotube.listenbrainz.api.LbCoreApi
-import dev.krtirtho.spotube.listenbrainz.api.LbPlaylistsApi
-import dev.krtirtho.spotube.listenbrainz.models.CreatePlaylistRequest
-import dev.krtirtho.spotube.listenbrainz.models.ItemDeleteRequest
-import dev.krtirtho.spotube.listenbrainz.models.Playlist
-import dev.krtirtho.spotube.listenbrainz.models.PlaylistExtension
-import dev.krtirtho.spotube.listenbrainz.models.PlaylistExtensionPayload
-import dev.krtirtho.spotube.listenbrainz.models.PlaylistTrackInner
-import kotlin.uuid.Uuid
-
-class EmulatedAlbumArtist(
- private val musicbrainzRepository: MusicbrainzRepository,
- private val persistedStorage: PersistedStorageAPI,
-) {
- private val playlistCache = mutableMapOf>()
- private var cachedUsername: String? = null
-
- suspend fun savedAlbums(
- pagination: PaginationStrategy?,
- filterIds: List
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
-
- val username = requireUsername()
- val playlistId = getOrCreatePlaylistId(username)
- val tracks = getPlaylistTracks(playlistId, fetchMetadata = true)
- val albums = tracks.toAlbums()
-
- val filtered = if (filterIds.isNotEmpty()) {
- albums.filter { filterIds.contains(it.id) }
- } else albums
-
- val slice = filtered.drop(paging.offset).take(paging.limit)
- val nextOffset = if (paging.offset + paging.limit < filtered.size) {
- paging.offset + paging.limit
- } else null
-
- cacheSavedAlbumIdsFromAlbumsDetailed(albums)
-
- return PaginationResult(
- items = slice,
- totalCount = filtered.size,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) },
- )
- }
-
- suspend fun isSavedAlbums(ids: List): List {
- val cached = persistedStorage.getString("saved_album_ids")?.takeIf { it.isNotBlank() }
- ?.split(",")
- ?.filter { it.isNotBlank() }
- val savedIds = cached ?: loadSavedAlbumIds()
- return ids.map { savedIds.contains(it) }
- }
-
- suspend fun saveAlbums(ids: List) {
- if (ids.isEmpty()) return
- val alreadySaved = isSavedAlbums(ids)
- if (alreadySaved.any { it }) {
- throw IllegalStateException("Some albums are already saved")
- }
-
- val username = requireUsername()
- val playlistId = getOrCreatePlaylistId(username)
-
- val recordingIds = ids.mapNotNull { albumId ->
- musicbrainzRepository.searchRecordings(query = "rgid:$albumId", limit = 1, offset = 0)
- .recordings
- .firstOrNull()?.id
- }
-
- if (recordingIds.isEmpty()) return
-
- val body = Playlist(
- track = recordingIds.map { recId ->
- PlaylistTrackInner(
- identifier = listOf("https://musicbrainz.org/recording/$recId")
- )
- }
- )
-
- val tracks = getPlaylistTracks(playlistId, false)
- val offset = tracks.size.toLong()
-
- LbPlaylistsApi.appendRecordings(Uuid.parse(playlistId), offset, body)
-
- playlistCache.remove(playlistId)
- cacheSavedAlbumIds(loadSavedAlbumIds().plus(ids).distinct())
- }
-
- suspend fun removeSavedAlbums(ids: List) {
- if (ids.isEmpty()) return
- val username = requireUsername()
- val playlistId = getOrCreatePlaylistId(username)
- val tracks = getPlaylistTracks(playlistId, fetchMetadata = true)
-
- val releaseIds = tracks.mapNotNull { it.extractReleaseId() }
- val releaseGroups = musicbrainzRepository.searchReleases(
- query = releaseIds.joinToString(" OR ") { "reid:$it" },
- limit = releaseIds.size,
- offset = 0
- ).releases
-
- val releaseIdToGroup = releaseGroups.associate { release ->
- val releaseId = release.id
- val groupId = release.releaseGroup?.id ?: release.id
- releaseId to groupId
- }
-
- val indexes = tracks.mapIndexedNotNull { idx, track ->
- val releaseId = track.extractReleaseId()
- val groupId = releaseIdToGroup[releaseId]
- if (groupId != null && ids.contains(groupId)) idx else null
- }
-
- if (indexes.isEmpty()) return
-
- indexes.forEach { index ->
- LbPlaylistsApi.itemDelete(
- Uuid.parse(playlistId),
- ItemDeleteRequest(
- index = index.toLong(),
- count = 1
- )
- )
- }
-
- playlistCache.remove(playlistId)
- cacheSavedAlbumIds(loadSavedAlbumIds().filterNot { ids.contains(it) })
- }
-
- private suspend fun loadSavedAlbumIds(): List {
- val username = requireUsername()
- val playlistId = getOrCreatePlaylistId(username)
- val tracks = getPlaylistTracks(playlistId, fetchMetadata = true)
- val releaseIds = tracks.mapNotNull { it.extractReleaseId() }
- if (releaseIds.isEmpty()) return emptyList()
-
- val releases = musicbrainzRepository.searchReleases(
- query = releaseIds.joinToString(" OR ") { "reid:$it" },
- limit = releaseIds.size,
- offset = 0
- ).releases
-
- val albumIds = releases.map { it.releaseGroup?.id ?: it.id }
- cacheSavedAlbumIds(albumIds)
- return albumIds
- }
-
- private suspend fun getOrCreatePlaylistId(username: String, type: String = "album"): String {
- val key = "saved_${type}_playlist_id"
- persistedStorage.getString(key)?.takeIf { it.isNotBlank() }?.let { return it }
-
- val playlistName = "$username saved ${type}s by Spotube"
- val existing = searchPlaylist(username, playlistName)
- val playlistId = existing ?: createPlaylist(playlistName, type)
- persistedStorage.putString(key, playlistId)
- return playlistId
- }
-
- private suspend fun searchPlaylist(username: String, name: String): String? {
- val response = LbCoreApi.searchPlaylistForUser(
- playlistUserName = username,
- query = name,
- count = 1,
- offset = 0
- )
-
- val playlists = response.getOrNull()?.data?.playlists
- val match = playlists?.firstOrNull { element ->
- val playlist = element.playlist
- val creator = playlist?.creator
- val title = playlist?.title
- creator == username && title == name
- }
-
- return match?.playlist?.identifier?.substringAfterLast('/')
- }
-
- private suspend fun createPlaylist(name: String, type: String): String {
- val body = CreatePlaylistRequest(
- playlist = Playlist(
- title = name,
- annotation = "This playlist contains all ${type}s saved by Spotube. Autogenerated. Do not edit.",
- extension = PlaylistExtension(
- httpsMusicbrainzOrgDocJspfPlaylist = PlaylistExtensionPayload(
- collaborators = emptyList(),
- public = false
- )
- )
- )
- )
-
- val response = LbPlaylistsApi.createPlaylist(body)
-
- val bodyJson = response.getOrNull()?.data
- return bodyJson?.playlistMbid?.toString()
- ?: throw IllegalStateException("Unable to create playlist")
- }
-
- private suspend fun getPlaylistTracks(
- playlistId: String,
- fetchMetadata: Boolean
- ): List {
- playlistCache[playlistId]?.let { return it }
-
- val response = LbPlaylistsApi.fetchPlaylist(
- playlistMbid = Uuid.parse(playlistId),
- fetchMetadata = fetchMetadata
- )
-
- val tracks = response.getOrNull()?.data?.playlist?.track
- ?: emptyList()
-
- playlistCache[playlistId] = tracks
- return tracks
- }
-
- private suspend fun requireUsername(): String {
- cachedUsername?.let { return it }
-
- // Setup auth provider globally
- val auth = Auth.ApiKeyAuth {
- val token =
- persistedStorage.getString("listenbrainz_auth_token") ?: return@ApiKeyAuth null
- if (token.startsWith("Token ", ignoreCase = true)) token else "Token $token"
- }
- Api.setAuthProvider(auth)
-
- val username = when (val res = LbCoreApi.validateToken()) {
- is Either.Left -> throw IllegalStateException("Unable to resolve ListenBrainz username: ${res.value}")
- is Either.Right -> res.value.data.userName
- }
- cachedUsername = username!!
- return username
- }
-
- private fun PlaylistTrackInner.extractReleaseId(): String? {
- val extension = this.extension?.httpsMusicbrainzOrgDocJspfTrack
- ?: return null
- val additional = extension.additionalMetadata ?: return null
- return additional.caaReleaseMbid?.toString()
- }
-
- private suspend fun List.toAlbums(): List {
- val releaseIds = mapNotNull { it.extractReleaseId() }
- if (releaseIds.isEmpty()) return emptyList()
-
- val releases = try {
- musicbrainzRepository.searchReleases(
- query = releaseIds.joinToString(" OR ") { "reid:$it" },
- limit = releaseIds.size,
- offset = 0
- ).releases
- } catch (_: Throwable) {
- emptyList()
- }
-
- return releases
- .groupBy { it.releaseGroup?.id ?: it.id }
- .values
- .mapNotNull { group ->
- val release = group.firstOrNull() ?: return@mapNotNull null
- val releaseGroupId = release.releaseGroup?.id ?: release.id
- release.toMetadataAlbumDetailed(releaseGroupId)
- }
- }
-
- private suspend fun cacheSavedAlbumIdsFromAlbumsDetailed(albums: List) {
- cacheSavedAlbumIds(albums.map { it.id })
- }
-
- private suspend fun cacheSavedAlbumIds(ids: List) {
- persistedStorage.putString("saved_album_ids", ids.distinct().joinToString(","))
- }
-
- suspend fun savedArtists(
- pagination: PaginationStrategy,
- filterIds: List
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- val username = requireUsername()
- val playlistId = getOrCreatePlaylistId(username, "artist")
- val tracks = getPlaylistTracks(playlistId, fetchMetadata = true)
- val artists = tracks.toArtists()
-
- val filtered = if (filterIds.isNotEmpty()) {
- artists.filter { filterIds.contains(it.id) }
- } else artists
-
- val slice = filtered.drop(paging.offset).take(paging.limit)
- val nextOffset = if (paging.offset + paging.limit < filtered.size) {
- paging.offset + paging.limit
- } else null
-
- cacheSavedArtistIdsFromArtistsDetailed(artists)
-
- return PaginationResult(
- items = slice,
- totalCount = filtered.size,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) },
- )
- }
-
- suspend fun isSavedArtists(ids: List): List {
- val cached = persistedStorage.getString("saved_artist_ids")?.takeIf { it.isNotBlank() }
- ?.split(",")
- ?.filter { it.isNotBlank() }
- val savedIds = cached ?: loadSavedArtistIds()
- return ids.map { savedIds.contains(it) }
- }
-
- suspend fun saveArtists(ids: List) {
- if (ids.isEmpty()) return
- val alreadySaved = isSavedArtists(ids)
- if (alreadySaved.any { it }) {
- throw IllegalStateException("Some artists are already saved")
- }
-
- val username = requireUsername()
- val playlistId = getOrCreatePlaylistId(username, "artist")
-
- val recordingIds = ids.mapNotNull { artistId ->
- musicbrainzRepository.searchRecordings(query = "arid:$artistId", limit = 1, offset = 0)
- .recordings
- .firstOrNull()?.id
- }
-
- if (recordingIds.isEmpty()) return
-
- val body = Playlist(
- track = recordingIds.map { recId ->
- PlaylistTrackInner(
- identifier = listOf("https://musicbrainz.org/recording/$recId")
- )
- }
- )
-
- val tracks = getPlaylistTracks(playlistId, false)
- val offset = tracks.size.toLong()
-
- LbPlaylistsApi.appendRecordings(Uuid.parse(playlistId), offset, body)
-
- playlistCache.remove(playlistId)
- cacheSavedArtistIds(loadSavedArtistIds().plus(ids).distinct())
- }
-
- suspend fun removeSavedArtists(ids: List) {
- if (ids.isEmpty()) return
- val username = requireUsername()
- val playlistId = getOrCreatePlaylistId(username, "artist")
- val tracks = getPlaylistTracks(playlistId, fetchMetadata = true)
-
- val trackArtistPairs = tracks.mapIndexedNotNull { index, track ->
- track.extractArtistId(musicbrainzRepository)?.let { artistId ->
- index to artistId
- }
- }
-
- val indexes = trackArtistPairs.filter { (_, artistId) -> ids.contains(artistId) }
- .map { it.first }
-
- if (indexes.isEmpty()) return
-
- indexes.forEach { index ->
- LbPlaylistsApi.itemDelete(
- Uuid.parse(playlistId),
- ItemDeleteRequest(
- index = index.toLong(),
- count = 1
- )
- )
- }
-
- playlistCache.remove(playlistId)
- cacheSavedArtistIds(loadSavedArtistIds().filterNot { ids.contains(it) })
- }
-
- private suspend fun loadSavedArtistIds(): List {
- val username = requireUsername()
- val playlistId = getOrCreatePlaylistId(username, "artist")
- val tracks = getPlaylistTracks(playlistId, fetchMetadata = true)
-
- val artists = tracks.toArtists()
- val ids = artists.map { it.id }
- cacheSavedArtistIds(ids)
- return ids
- }
-
- private suspend fun cacheSavedArtistIdsFromArtistsDetailed(artists: List) {
- cacheSavedArtistIds(artists.map { it.id })
- }
-
- private suspend fun cacheSavedArtistIds(ids: List) {
- persistedStorage.putString("saved_artist_ids", ids.distinct().joinToString(","))
- }
-
- private suspend fun PlaylistTrackInner.extractArtistId(repository: MusicbrainzRepository): String? {
- val idUrl = identifier?.firstOrNull() ?: return null
- val recordingId = idUrl.substringAfterLast("/")
- if (recordingId.isBlank()) return null
-
- return try {
- val recording =
- repository.getRecordingByMbid(recordingId, includes = listOf("artist-credits"))
- recording.artistCredit.firstOrNull()?.artist?.id
- } catch (_: Exception) {
- null
- }
- }
-
- private suspend fun List.toArtists(): List {
- val recordingIds = mapNotNull {
- val idUrl = it.identifier?.firstOrNull() ?: return@mapNotNull null
- idUrl.substringAfterLast("/").takeIf { it.isNotBlank() }
- }
-
- if (recordingIds.isEmpty()) return emptyList()
-
- val chunks = recordingIds.chunked(20)
- val artists = mutableListOf()
-
- chunks.forEach { chunk ->
- try {
- val query = chunk.joinToString(" OR ") { "rid:$it" }
- val response =
- musicbrainzRepository.searchRecordings(query, limit = chunk.size, offset = 0)
-
- response.recordings.forEach { rec ->
- val artist = rec.artistCredit.firstOrNull()?.artist
- if (artist != null) {
- artists.add(artist.toMetadataArtistDetailed())
- }
- }
- } catch (_: Exception) {
- // ignore
- }
- }
-
- return artists
- }
-}
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/MusicbrainzListenbrainzEnrich.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/MusicbrainzListenbrainzEnrich.kt
deleted file mode 100644
index 8455b03c..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/MusicbrainzListenbrainzEnrich.kt
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbum
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbumType
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtist
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.Thumbnail
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzArtist
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzRecording
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzRelease
-
-fun MusicbrainzRelease.toMetadataAlbum(groupId: String): MetadataAlbum.Detailed {
- val releaseGroupId = releaseGroup?.id ?: groupId
- val type = releaseGroup?.primaryType?.lowercase()?.let {
- when (it) {
- "single" -> MetadataAlbumType.Single
- "album" -> MetadataAlbumType.Album
- else -> MetadataAlbumType.Collection
- }
- } ?: MetadataAlbumType.Collection
-
- return MetadataAlbum.Detailed(
- releaseDate = date,
- genres = emptyList(),
- trackCount = trackCount ?: 0,
- id = releaseGroupId,
- title = releaseGroup?.title ?: title,
- description = null,
- thumbnails = listOf(
- Thumbnail(
- url = "https://coverartarchive.org/release-group/${releaseGroupId}/front-250.jpg",
- width = 250,
- height = 250
- ),
- Thumbnail(
- url = "https://coverartarchive.org/release-group/${releaseGroupId}/front-500.jpg",
- width = 500,
- height = 500
- ),
- ),
- albumType = type,
- artists = artistCredit.mapNotNull { credit ->
- credit.artist?.let {
- MetadataArtist.Basic(
- id = it.id,
- name = it.name,
- thumbnails = emptyList(),
- externalUri = "https://musicbrainz.org/artist/${it.id}"
- )
- }
- },
- externalUri = "https://musicbrainz.org/release-group/${releaseGroupId}"
- )
-}
-
-fun List.pickOfficialRelease(): MusicbrainzRelease? {
- return firstOrNull { release ->
- release.status == "Official" && release.country == "US" &&
- release.artistCredit.none { it.artist?.name == "Various Artists" }
- }
-}
-
-fun MusicbrainzRecording.toMetadataTrack(album: MetadataAlbum.Detailed): MetadataTrack {
- val explicit = disambiguation?.lowercase() == "explicit"
- return MetadataTrack(
- id = id,
- title = title,
- durationMs = (length ?: 0).toLong(),
- trackNumber = null,
- discNumber = null,
- artists = artistCredit.mapNotNull { credit ->
- credit.artist?.let {
- MetadataArtist.Basic(
- id = it.id,
- name = it.name,
- thumbnails = emptyList(),
- externalUri = "https://musicbrainz.org/artist/${it.id}"
- )
- }
- },
- album = album,
- explicit = explicit,
- popularity = null,
- isrcCode = isrcs.firstOrNull(),
- externalUri = "https://musicbrainz.org/recording/${id}",
- thumbnails = null,
- )
-}
-
-fun MusicbrainzRelease.toMetadataAlbumDetailed(groupId: String): MetadataAlbum.Detailed {
- val releaseGroupId = releaseGroup?.id ?: groupId
- val type = releaseGroup?.primaryType?.lowercase()?.let {
- when (it) {
- "single" -> MetadataAlbumType.Single
- "album" -> MetadataAlbumType.Album
- else -> MetadataAlbumType.Collection
- }
- } ?: MetadataAlbumType.Collection
-
- return MetadataAlbum.Detailed(
- releaseDate = date,
- genres = emptyList(),
- trackCount = trackCount ?: 0,
- id = releaseGroupId,
- title = releaseGroup?.title ?: title,
- description = null,
- thumbnails = listOf(
- Thumbnail(
- url = "https://coverartarchive.org/release-group/${releaseGroupId}/front-250.jpg",
- width = 250,
- height = 250
- ),
- Thumbnail(
- url = "https://coverartarchive.org/release-group/${releaseGroupId}/front-500.jpg",
- width = 500,
- height = 500
- ),
- ),
- albumType = type,
- artists = artistCredit.mapNotNull { credit ->
- credit.artist?.let {
- MetadataArtist.Basic(
- id = it.id,
- name = it.name,
- thumbnails = emptyList(),
- externalUri = "https://musicbrainz.org/artist/${it.id}"
- )
- }
- },
- externalUri = "https://musicbrainz.org/release-group/${releaseGroupId}"
- )
-}
-
-fun MusicbrainzArtist.toMetadataArtistDetailed(): MetadataArtist.Detailed {
- return MetadataArtist.Detailed(
- id = id,
- name = name,
- thumbnails = emptyList(),
- externalUri = "https://musicbrainz.org/artist/$id",
- genres = tags.map { it.name },
- biography = disambiguation,
- followersCount = null
- )
-}
-
-fun MusicbrainzArtist.toMetadataArtistBasic(): MetadataArtist.Basic {
- return MetadataArtist.Basic(
- id = id,
- name = name,
- thumbnails = emptyList(),
- externalUri = "https://musicbrainz.org/artist/$id"
- )
-}
-
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/MusicbrainzListenbrainzPlugin.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/MusicbrainzListenbrainzPlugin.kt
deleted file mode 100644
index 9fcf6c6e..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/MusicbrainzListenbrainzPlugin.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import app.cash.zipline.ZiplineService
-import dev.krtirtho.plugin_interfaces.host_apis.PersistedStorageAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.core.CoreAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbumAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtistAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.browse.MetadataBrowseAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.playlist.MetadataPlaylistAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.search.MetadataSearchAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrackAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.user.MetadataUserAPI
-import dev.krtirtho.spotube.core.webview.WebViewController
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.KtorMusicbrainzRepository
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzArtistEnricher
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.wikidata.WikidataRepository
-import io.ktor.client.HttpClient
-import kotlinx.coroutines.CoroutineScope
-import kotlin.reflect.KClass
-
-fun createMusicbrainzListenbrainzPluginAPIs(
- scope: CoroutineScope,
- httpClient: HttpClient,
- webViewController: WebViewController,
- persistedStorage: PersistedStorageAPI
-): Map, ZiplineService> {
- val repository = KtorMusicbrainzRepository(httpClient)
- val wikidataRepository = WikidataRepository(httpClient)
- val artistEnricher = MusicbrainzArtistEnricher(repository, wikidataRepository)
-
- return mapOf(
- CoreAPI::class to RealMusicbrainzListenbrainzCoreAPI(scope, webViewController, persistedStorage),
- MetadataBrowseAPI::class to RealMusicbrainzListenbrainzMetadataBrowseAPI(persistedStorage),
- MetadataPlaylistAPI::class to RealMusicbrainzListenbrainzMetadataPlaylistAPI(repository, persistedStorage),
- MetadataTrackAPI::class to RealMusicbrainzListenbrainzMetadataTrackAPI(repository, persistedStorage),
- MetadataAlbumAPI::class to RealMusicbrainzListenbrainzMetadataAlbumAPI(repository, persistedStorage),
- MetadataArtistAPI::class to RealMusicbrainzListenbrainzMetadataArtistAPI(repository, persistedStorage),
- MetadataSearchAPI::class to RealMusicbrainzListenbrainzMetadataSearchAPI(repository, artistEnricher, httpClient),
- MetadataUserAPI::class to RealMusicbrainsListenbrainzMetadataUserAPI(repository, persistedStorage)
- )
-}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainsListenbrainzMetadataUserAPI.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainsListenbrainzMetadataUserAPI.kt
deleted file mode 100644
index f4715d2e..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainsListenbrainzMetadataUserAPI.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import arrow.core.Either
-import com.kroegerama.openapi.kmp.gen.companion.appendSerializedQueryParameter
-import dev.krtirtho.plugin_interfaces.host_apis.PersistedStorageAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.user.MetadataUser
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.user.MetadataUserAPI
-import dev.krtirtho.spotube.core.zipline.host_apis.RealPersistedStorageAPI
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzRepository
-import dev.krtirtho.spotube.listenbrainz.Auth
-import dev.krtirtho.spotube.listenbrainz.api.LbCoreApi
-
-class RealMusicbrainsListenbrainzMetadataUserAPI(
- private val musicbrainzRepository: MusicbrainzRepository,
- private val persistedStorage: PersistedStorageAPI
-) : MetadataUserAPI {
- override suspend fun getUser(id: String): MetadataUser? {
- val token = persistedStorage.getString("listenbrainz_auth_token") ?: return null
- if(token.isEmpty()) return null
- when (val res = LbCoreApi.validateToken {
- appendSerializedQueryParameter("token", token)
- }) {
- is Either.Left -> {
- println("Error validating token: ${res.value}")
- return null
- }
-
- is Either.Right -> {
- val user = res.value.data
- return MetadataUser(
- id = user.userName as String,
- username = user.userName,
- displayName = user.userName,
- thumbnails = emptyList(),
- externalUri = "https://listenbrainz.org/user/${user.userName}",
- )
- }
- }
- }
-}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzCoreAPI.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzCoreAPI.kt
deleted file mode 100644
index db6914de..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzCoreAPI.kt
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import arrow.core.Either
-import com.kroegerama.openapi.kmp.gen.companion.appendSerializedQueryParameter
-import dev.krtirtho.plugin_interfaces.host_apis.PersistedStorageAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.core.CoreAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.core.PluginUpdateInfo
-import dev.krtirtho.spotube.core.webview.WebViewController
-import dev.krtirtho.spotube.listenbrainz.Api
-import dev.krtirtho.spotube.listenbrainz.Auth
-import dev.krtirtho.spotube.listenbrainz.api.LbCoreApi
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.launch
-import net.swiftzer.semver.SemVer
-
-class RealMusicbrainzListenbrainzCoreAPI(
- private val scope: CoroutineScope,
- private val webViewController: WebViewController,
- private val persistedStorage: PersistedStorageAPI
-) : CoreAPI {
- init {
- scope.launch {
- val token = persistedStorage.getString("listenbrainz_auth_token")
- if (token != null) {
- auth = Auth.ApiKeyAuth { token }
- Api.setAuthProvider(auth!!)
- loggedInState.value = true
- } else {
- loggedInState.value = false
- }
- }
- }
-
- override suspend fun checkPluginUpdates(currentVersion: SemVer): PluginUpdateInfo? {
- return null
- }
-
- override fun supportMarkdownText(currentVersion: SemVer): String {
- return "Keep supporting Spotube!"
- }
-
- override val requiresAuthentication = true
-
- private val loggedInState = MutableStateFlow(false)
- override val loggedInFlow = loggedInState.asStateFlow()
-
- private var auth: Auth? = null
-
- override suspend fun login() {
- webViewController.navigateToHTML(
- """
-
-
-
- Login to Listenbrainz
-
-
- Login to Listenbrainz
-
- Mirror:
-
-
-
- """.trimIndent()
- )
-
- println("[RealMusicbrainzListenbrainzCoreAPI.login] Waiting for postMessagesFlow message")
- val actualCreds = webViewController.postMessagesFlow
- .onEach {
- println("[postMessagesFlow.onEach] Received token from WebView: $it")
- }
- .filter { it.isNotBlank() }
- .first()
- println("Received token from WebView: $actualCreds")
- auth = Auth.ApiKeyAuth {
- actualCreds
- }
- Api.setAuthProvider(auth = auth!!)
- when (val res = LbCoreApi.validateToken {
- appendSerializedQueryParameter("token", actualCreds)
- }) {
- is Either.Left -> {
- webViewController.closeWebview()
- throw res.value
- }
-
- is Either.Right -> {
- if (!res.value.data.valid) {
- webViewController.closeWebview()
- throw Exception("Invalid token")
- }
- persistedStorage.putString("listenbrainz_auth_token", actualCreds)
- loggedInState.value = true
- webViewController.closeWebview()
- }
- }
- }
-
- override suspend fun logout() {
- if (auth == null) return
- Api.clearAuthProvider(auth!!)
- auth = null
- persistedStorage.remove("listenbrainz_auth_token")
- loggedInState.value = false
- }
-}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataAlbumAPI.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataAlbumAPI.kt
deleted file mode 100644
index 2c0711a5..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataAlbumAPI.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import dev.krtirtho.plugin_interfaces.host_apis.PersistedStorageAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbum
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbumAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationStrategy
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationResult
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzRepository
-
-
-class RealMusicbrainzListenbrainzMetadataAlbumAPI(
- private val musicbrainzRepository: MusicbrainzRepository,
- private val persistedStorage: PersistedStorageAPI
-) : MetadataAlbumAPI {
- private val emulator by lazy {
- EmulatedAlbumArtist(musicbrainzRepository, persistedStorage)
- }
-
- override suspend fun getAlbum(id: String): MetadataAlbum.Detailed {
- val release = musicbrainzRepository
- .searchReleases(query = "rgid:$id", limit = 1, offset = 0)
- .releases
- .firstOrNull()
- ?: throw IllegalArgumentException("Album $id not found")
-
- return release.toMetadataAlbumDetailed(id)
- }
-
- override suspend fun getTrackAlbum(track: MetadataTrack): MetadataAlbum.Detailed {
- TODO("Not yet implemented")
- }
-
- override suspend fun getAlbumTracks(
- id: String,
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging: PaginationStrategy.Offset =
- pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
-
- val releases = musicbrainzRepository.searchReleases(
- query = "rgid:$id",
- limit = 10,
- offset = 0
- ).releases
-
- val officialRelease = releases.pickOfficialRelease()
- ?: releases.firstOrNull()
- ?: throw IllegalArgumentException("Album $id not found")
-
- val recordings = musicbrainzRepository.searchRecordings(
- query = "reid:${officialRelease.id}",
- limit = paging.limit,
- offset = paging.offset,
- )
-
- val album = officialRelease.toMetadataAlbumDetailed(id)
- val items = recordings.recordings.map { it.toMetadataTrack(album) }
-
- val nextOffset = if (paging.offset + paging.limit < recordings.count) {
- paging.offset + paging.limit
- } else null
-
- return PaginationResult(
- items = items,
- totalCount = recordings.count,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) }
- )
- }
-
- override suspend fun savedAlbums(
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- return emulator.savedAlbums(paging, emptyList())
- }
-
- override suspend fun isSavedAlbums(ids: List): List {
- return emulator.isSavedAlbums(ids)
- }
-
- override suspend fun saveAlbums(ids: List) {
- emulator.saveAlbums(ids)
- }
-
- override suspend fun removeSavedAlbums(ids: List) {
- emulator.removeSavedAlbums(ids)
- }
-}
-
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataArtistAPI.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataArtistAPI.kt
deleted file mode 100644
index 3650cf0e..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataArtistAPI.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-
-import dev.krtirtho.plugin_interfaces.host_apis.PersistedStorageAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbum
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtist
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtistAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationStrategy
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationResult
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzRepository
-
-class RealMusicbrainzListenbrainzMetadataArtistAPI(
- private val musicbrainzRepository: MusicbrainzRepository,
- private val persistedStorage: PersistedStorageAPI
-) : MetadataArtistAPI {
-
- private val emulator by lazy {
- EmulatedAlbumArtist(musicbrainzRepository, persistedStorage)
- }
-
- override suspend fun getArtist(id: String): MetadataArtist.Detailed {
- val artist = musicbrainzRepository.getArtistByMbid(id, includes = listOf("url-rels"))
- return artist.toMetadataArtistDetailed()
- }
-
- override suspend fun getArtistTop10Tracks(id: String): List {
- val recordings = musicbrainzRepository.searchRecordings(
- query = "arid:$id",
- limit = 10,
- offset = 0
- ).recordings
-
- return recordings.mapNotNull { recording ->
- val release = recording.releases.pickOfficialRelease()
- ?: recording.releases.firstOrNull()
-
- release?.let {
- val groupId = it.releaseGroup?.id ?: it.id
- val album = it.toMetadataAlbumDetailed(groupId)
- recording.toMetadataTrack(album)
- }
- }
- }
-
- override suspend fun getArtistAlbums(
- id: String,
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- val releases = musicbrainzRepository.searchReleases(
- query = "arid:$id",
- limit = paging.limit,
- offset = paging.offset
- )
-
- val items = releases.releases.map { release ->
- val groupId = release.releaseGroup?.id ?: release.id
- release.toMetadataAlbumDetailed(groupId)
- }
-
- val nextOffset = if (paging.offset + paging.limit < releases.count) {
- paging.offset + paging.limit
- } else null
-
- return PaginationResult(
- items = items,
- totalCount = releases.count,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) }
- )
- }
-
- override suspend fun savedArtists(
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- return emulator.savedArtists(paging, emptyList())
- }
-
- override suspend fun isSavedArtists(ids: List): List {
- return emulator.isSavedArtists(ids)
- }
-
- override suspend fun saveArtists(ids: List) {
- emulator.saveArtists(ids)
- }
-
- override suspend fun removeSavedArtists(ids: List) {
- emulator.removeSavedArtists(ids)
- }
-}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataBrowseAPI.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataBrowseAPI.kt
deleted file mode 100644
index d8910d38..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataBrowseAPI.kt
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import arrow.core.Either
-import com.kroegerama.openapi.kmp.gen.companion.AuthPlugin.Plugin.authKeys
-import dev.krtirtho.plugin_interfaces.host_apis.PersistedStorageAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.browse.MetadataBrowseAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.browse.MetadataBrowseItem
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.browse.MetadataBrowseSection
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationStrategy
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationResult
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.Thumbnail
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.playlist.MetadataPlaylist
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.user.MetadataUser
-import dev.krtirtho.spotube.core.di.injectLogger
-import dev.krtirtho.spotube.listenbrainz.Api
-import dev.krtirtho.spotube.listenbrainz.Auth
-import dev.krtirtho.spotube.listenbrainz.api.LbCoreApi
-import dev.krtirtho.spotube.listenbrainz.api.LbMiscApi
-import dev.krtirtho.spotube.listenbrainz.api.LbPlaylistsApi
-import dev.krtirtho.spotube.listenbrainz.api.LbStatsApi
-import dev.krtirtho.spotube.listenbrainz.models.AllowedStatisticsRange
-import dev.krtirtho.spotube.listenbrainz.models.Mode
-import dev.krtirtho.spotube.listenbrainz.models.Playlist
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.json.Json
-import kotlin.time.Clock
-import org.koin.core.component.KoinComponent
-
-class RealMusicbrainzListenbrainzMetadataBrowseAPI(
- private val persistedStorage: PersistedStorageAPI,
-) : MetadataBrowseAPI, KoinComponent {
- private val logger by injectLogger()
- private var cachedUsername: String? = null
-
- @Serializable
- private data class LbRadioPlaylistCacheEntry(
- val cachedAtEpochMs: Long,
- val playlist: MetadataPlaylist,
- )
-
- @Serializable
- private data class BrowseSectionsCacheEntry(
- val cachedAtEpochMs: Long,
- val sections: List,
- )
-
- private val cacheJson = Json {
- ignoreUnknownKeys = true
- encodeDefaults = true
- }
-
- @Serializable
- private data class BrowseSectionData(
- val id: String,
- val title: String,
- val description: String? = null,
- val moreLink: String? = null,
- val items: List,
- )
-
- private data class MoodSeed(
- val key: String,
- val tag: String,
- val title: String,
- val annotation: String,
- )
-
- companion object {
- private const val SECTION_TOP_ARTIST_RADIOS = "top-artist-radios"
- private const val SECTION_MOOD_PLAYLISTS = "mood-playlists"
- private const val SECTION_CREATED_FOR = "created-for-playlists"
- private const val LB_RADIO_CACHE_TTL_MS = 3L * 24 * 60 * 60 * 1000
- private const val LB_RADIO_CACHE_KEY_PREFIX = "lb_radio_playlist_cache"
- private const val BROWSE_SECTIONS_CACHE_KEY_PREFIX = "lb_browse_sections_cache"
-
- private val moodSeeds = listOf(
- MoodSeed("chill", "ambient", "Chill playlist", "Yo chill my friend!"),
- MoodSeed("energetic", "energetic", "Pump it up!", "Get ready to move!"),
- MoodSeed("happy", "upbeat", "Happy Vibes", "Feel good tunes to brighten your day!"),
- MoodSeed("sad", "melancholy", "Melancholy Moments", "For those reflective times."),
- MoodSeed("focus", "instrumental", "Focus Beats", "Concentration is key."),
- MoodSeed("workout", "electronic", "Workout Jams", "Get pumped with these beats!"),
- MoodSeed("party", "dance", "Party Anthems", "Let's get this party started!"),
- MoodSeed("romantic", "romantic", "Romantic Evenings", "For those special moments."),
- )
- }
-
- override suspend fun featured(): List {
- logger.i("featured(): Starting to build featured items")
- try {
- val sections = buildSections()
- logger.d("featured(): Built ${sections.size} sections")
- val result = sections.flatMap { it.items }.take(12)
- logger.i("featured(): Returning ${result.size} featured items")
- return result
- } catch (e: Exception) {
- logger.e(e) { "featured(): Error building featured items" }
- return emptyList()
- }
- }
-
- override suspend fun list(pagination: PaginationStrategy?): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- logger.i("list(): Starting with offset=${paging.offset}, pageSize=${paging.limit}")
- try {
- val sections = buildSections()
- logger.d("list(): Built ${sections.size} total sections")
- val items = sections
- .drop(paging.offset)
- .take(paging.limit)
- .map {
- MetadataBrowseSection(
- title = it.title,
- description = it.description,
- items = it.items,
- moreLink = it.moreLink,
- )
- }
-
- val nextOffset = if (paging.offset + items.size < sections.size) {
- paging.offset + paging.limit
- } else {
- null
- }
-
- logger.d("list(): Returning ${items.size} items, nextOffset=$nextOffset")
- return PaginationResult(
- items = items,
- totalCount = sections.size,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) },
- )
- } catch (e: Exception) {
- logger.e(e) { "list(): Error fetching paginated sections" }
- return PaginationResult(
- items = emptyList(),
- totalCount = 0,
- nextPagination = null,
- )
- }
- }
-
- override suspend fun sublist(
- sectionId: String,
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- logger.i("sublist(): Fetching section=$sectionId with offset=${paging.offset}, pageSize=${paging.limit}")
- try {
- val allSections = buildSections()
- logger.d("sublist(): Built ${allSections.size} total sections")
- val sectionItems = allSections.firstOrNull { it.id == sectionId }?.items ?: emptyList()
- logger.d("sublist(): Found ${sectionItems.size} items in section $sectionId")
-
- val items = sectionItems.drop(paging.offset).take(paging.limit)
- val nextOffset = if (paging.offset + items.size < sectionItems.size) {
- paging.offset + paging.limit
- } else {
- null
- }
-
- logger.d("sublist(): Returning ${items.size} paginated items, nextOffset=$nextOffset")
- return PaginationResult(
- items = items,
- totalCount = sectionItems.size,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) },
- )
- } catch (e: Exception) {
- logger.e(e) { "sublist(): Error fetching sublist for section=$sectionId" }
- return PaginationResult(
- items = emptyList(),
- totalCount = 0,
- nextPagination = null,
- )
- }
- }
-
- private suspend fun buildSections(): List {
- logger.d("buildSections(): Starting section building process")
- val username = try {
- val user = requireUsername()
- logger.d("buildSections(): Successfully resolved username: $user")
- user
- } catch (e: Exception) {
- logger.w(e) { "buildSections(): Failed to retrieve username, returning empty sections" }
- return emptyList()
- }
-
- val nowEpochMs = Clock.System.now().toEpochMilliseconds()
- val sectionsCacheKey = buildBrowseSectionsCacheKey(username)
- val cachedSections = readCachedBrowseSections(sectionsCacheKey)
- if (cachedSections != null) {
- val ageMs = nowEpochMs - cachedSections.cachedAtEpochMs
- if (ageMs <= LB_RADIO_CACHE_TTL_MS) {
- logger.d("buildSections(): Returning cached sections for key=$sectionsCacheKey (ageMs=$ageMs)")
- return cachedSections.sections
- }
- logger.d("buildSections(): Cached sections stale for key=$sectionsCacheKey (ageMs=$ageMs), rebuilding")
- }
-
- return try {
- logger.d("buildSections(): Building Top Artist Radios section...")
- val topArtistRadios = buildTopArtistRadiosSection(username)
- logger.d("buildSections(): Built Top Artist Radios with ${topArtistRadios.items.size} items")
-
- logger.d("buildSections(): Building Mood Playlists section...")
- val moodPlaylists = buildMoodPlaylistsSection(username)
- logger.d("buildSections(): Built Mood Playlists with ${moodPlaylists.items.size} items")
-
- logger.d("buildSections(): Building Created For section...")
- val createdFor = buildCreatedForSection(username)
- logger.d("buildSections(): Built Created For with ${createdFor.items.size} items")
-
- val sections = listOf(topArtistRadios, moodPlaylists, createdFor)
- writeCachedBrowseSections(
- key = sectionsCacheKey,
- entry = BrowseSectionsCacheEntry(
- cachedAtEpochMs = nowEpochMs,
- sections = sections,
- )
- )
- logger.i("buildSections(): Successfully built ${sections.size} sections with ${sections.sumOf { it.items.size }} total items")
- sections
- } catch (e: Exception) {
- logger.e(e) { "buildSections(): Failed to build fresh sections" }
- if (cachedSections != null) {
- logger.w("buildSections(): Returning stale cached sections for key=$sectionsCacheKey")
- cachedSections.sections
- } else {
- emptyList()
- }
- }
- }
-
- private suspend fun buildTopArtistRadiosSection(username: String): BrowseSectionData {
- logger.d("buildTopArtistRadiosSection(): Fetching top artists for user: $username")
- try {
- val artistsResult = LbStatsApi.topArtistsForUser(
- userName = username,
- count = 10,
- offset = 0,
- range = AllowedStatisticsRange.QUARTER,
- )
- val artists = when (artistsResult) {
- is Either.Left -> {
- val error = artistsResult.value
- logger.e("buildTopArtistRadiosSection(): Failed to fetch top artists: $error")
- throw error
- }
-
- is Either.Right -> artistsResult.value.data.payload.artists
- }
- logger.d("buildTopArtistRadiosSection(): Retrieved ${artists.size} top artists")
-
- val playlists = artists.mapNotNull { artist ->
- val mbid = artist.artistMbid?.toString() ?: return@mapNotNull null
- val name = artist.artistName ?: return@mapNotNull null
- logger.d("buildTopArtistRadiosSection(): Generating radio playlist for artist: $name (mbid: $mbid)")
-
- generateLbRadioPlaylist(
- prompt = "artist:($mbid)",
- mode = Mode.EASY,
- title = "$name Radio",
- annotation = "A radio playlist based on $name's music",
- imageUrl = null,
- )
- }
- logger.d("buildTopArtistRadiosSection(): Generated ${playlists.size} radio playlists")
-
- return BrowseSectionData(
- id = SECTION_TOP_ARTIST_RADIOS,
- title = "Top Artist Radios",
- moreLink = "https://listenbrainz.org/explore/lb-radio",
- items = playlists.map { MetadataBrowseItem.Playlist(it) },
- )
- } catch (e: Exception) {
- logger.e(e) { "buildTopArtistRadiosSection(): Error building top artist radios section" }
- return BrowseSectionData(
- id = SECTION_TOP_ARTIST_RADIOS,
- title = "Top Artist Radios",
- items = emptyList(),
- )
- }
- }
-
- private suspend fun buildMoodPlaylistsSection(username: String): BrowseSectionData {
- logger.d("buildMoodPlaylistsSection(): Starting to build mood playlists (count: ${moodSeeds.size})")
- try {
- val playlists = moodSeeds.mapNotNull { mood ->
- logger.d("buildMoodPlaylistsSection(): Generating playlist for mood: ${mood.title} (tag: ${mood.tag})")
- generateLbRadioPlaylist(
- prompt = "tag:(${mood.tag}) stats:$username::all_time",
- mode = Mode.HARD,
- title = mood.title,
- annotation = mood.annotation,
- imageUrl = "https://res.cloudinary.com/dszpk1pk9/image/upload/t_media_lib_thumb/spotube-plugin-musicbrainz-listenbrainz/moods/${mood.key}.webp",
- )
- }
- logger.d("buildMoodPlaylistsSection(): Successfully generated ${playlists.size} mood playlists")
-
- return BrowseSectionData(
- id = SECTION_MOOD_PLAYLISTS,
- title = "Based on your mood",
- moreLink = "https://listenbrainz.org/explore/lb-radio",
- items = playlists.map { MetadataBrowseItem.Playlist(it) },
- )
- } catch (e: Exception) {
- logger.e(e) { "buildMoodPlaylistsSection(): Error building mood playlists section" }
- return BrowseSectionData(
- id = SECTION_MOOD_PLAYLISTS,
- title = "Based on your mood",
- items = emptyList(),
- )
- }
- }
-
- private suspend fun buildCreatedForSection(username: String): BrowseSectionData {
- logger.d("buildCreatedForSection(): Fetching playlists created for user: $username")
- try {
- val playlistsResult = LbPlaylistsApi.playlistsCreatedForUser(
- playlistUserName = username,
- count = 25,
- offset = 0,
- )
- val playlists = when (playlistsResult) {
- is Either.Left -> {
- val error = playlistsResult.value
- logger.e("buildCreatedForSection(): Failed to fetch created playlists: $error")
- throw error
- }
-
- is Either.Right -> playlistsResult.value.data.playlists.orEmpty()
- }
- logger.d("buildCreatedForSection(): Retrieved ${playlists.size} playlists")
-
- val items = playlists.mapNotNull { wrapper ->
- val playlist = wrapper.playlist ?: return@mapNotNull null
- val title = playlist.title.orEmpty()
- val imageName = if (title.contains("Weekly Exploration", ignoreCase = true)) {
- "weekly-exploration"
- } else {
- "weekly-jams"
- }
- logger.d("buildCreatedForSection(): Processing playlist: $title (imageName: $imageName)")
- val imageUrl =
- "https://res.cloudinary.com/dszpk1pk9/image/upload/t_media_lib_thumb/spotube-plugin-musicbrainz-listenbrainz/created_for/${imageName}.webp"
- playlist.toMetadataPlaylist(thumbnailOverride = imageUrl)
- }
- logger.d("buildCreatedForSection(): Successfully processed ${items.size} playlists")
-
- return BrowseSectionData(
- id = SECTION_CREATED_FOR,
- title = "Created for you",
- moreLink = "https://listenbrainz.org/user/$username/recommendations/",
- items = items.map { MetadataBrowseItem.Playlist(it) },
- )
- } catch (e: Exception) {
- logger.e(e) { "buildCreatedForSection(): Error building created for section" }
- return BrowseSectionData(
- id = SECTION_CREATED_FOR,
- title = "Created for you",
- items = emptyList(),
- )
- }
- }
-
- private suspend fun generateLbRadioPlaylist(
- prompt: String,
- mode: Mode,
- title: String,
- annotation: String?,
- imageUrl: String?,
- ): MetadataPlaylist? {
- logger.d("generateLbRadioPlaylist(): Generating playlist with prompt='$prompt', mode=$mode, title='$title'")
- val nowEpochMs = Clock.System.now().toEpochMilliseconds()
- val cacheKey = buildLbRadioCacheKey(prompt = prompt, mode = mode)
- val cachedEntry = readCachedLbRadioPlaylist(cacheKey)
- if (cachedEntry != null) {
- val ageMs = nowEpochMs - cachedEntry.cachedAtEpochMs
- if (ageMs <= LB_RADIO_CACHE_TTL_MS) {
- logger.d("generateLbRadioPlaylist(): Cache hit for key=$cacheKey (ageMs=$ageMs)")
- return cachedEntry.playlist
- }
- logger.d("generateLbRadioPlaylist(): Cache stale for key=$cacheKey (ageMs=$ageMs), refreshing")
- }
-
- try {
- val lbRadioResult = LbMiscApi.lbRadio(prompt = prompt, mode = mode) {
- authKeys(
- Auth.ApiKeyAuth.ID,
- )
- }
- val lbRadio = when (lbRadioResult) {
- is Either.Left -> {
- val error = lbRadioResult.value
- logger.e("generateLbRadioPlaylist(): API call failed with error: $error")
- throw error
- }
-
- is Either.Right -> lbRadioResult.value.data
- }
- val playlist = lbRadio.payload.jspf.playlist ?: run {
- logger.w("generateLbRadioPlaylist(): No playlist data in response for prompt='$prompt'")
- return null
- }
- val modeId = mode.name.lowercase()
- val syntheticId = "lb-radio-playlist-$prompt-$modeId"
-
- val normalizedPlaylist = playlist.copy(
- identifier = "https://listenbrainz.org/playlist/$syntheticId",
- title = title,
- annotation = annotation ?: playlist.annotation,
- )
-
- val result = normalizedPlaylist.toMetadataPlaylist(thumbnailOverride = imageUrl)
- if (result != null) {
- writeCachedLbRadioPlaylist(
- key = cacheKey,
- entry = LbRadioPlaylistCacheEntry(
- cachedAtEpochMs = nowEpochMs,
- playlist = result,
- )
- )
- }
- logger.d("generateLbRadioPlaylist(): Successfully generated playlist: $title")
- return result
- } catch (e: Exception) {
- logger.e(e) { "generateLbRadioPlaylist(): Error generating playlist for prompt='$prompt'" }
- if (cachedEntry != null) {
- logger.w("generateLbRadioPlaylist(): Returning stale cache for key=$cacheKey due to API failure")
- return cachedEntry.playlist
- }
- return null
- }
- }
-
- private fun buildLbRadioCacheKey(prompt: String, mode: Mode): String {
- val promptHash = prompt.hashCode().toUInt().toString(16)
- return "$LB_RADIO_CACHE_KEY_PREFIX:${mode.name.lowercase()}:$promptHash"
- }
-
- private fun buildBrowseSectionsCacheKey(username: String): String {
- val usernameHash = username.lowercase().hashCode().toUInt().toString(16)
- return "$BROWSE_SECTIONS_CACHE_KEY_PREFIX:$usernameHash"
- }
-
- private suspend fun readCachedLbRadioPlaylist(key: String): LbRadioPlaylistCacheEntry? {
- val raw = persistedStorage.getString(key) ?: return null
- return runCatching {
- cacheJson.decodeFromString(raw)
- }.onFailure { throwable ->
- logger.w(throwable) { "readCachedLbRadioPlaylist(): Corrupt cache entry for key=$key, removing" }
- persistedStorage.remove(key)
- }.getOrNull()
- }
-
- private suspend fun writeCachedLbRadioPlaylist(key: String, entry: LbRadioPlaylistCacheEntry) {
- runCatching {
- persistedStorage.putString(key, cacheJson.encodeToString(entry))
- }.onFailure { throwable ->
- logger.w(throwable) { "writeCachedLbRadioPlaylist(): Failed to persist cache for key=$key" }
- }
- }
-
- private suspend fun readCachedBrowseSections(key: String): BrowseSectionsCacheEntry? {
- val raw = persistedStorage.getString(key) ?: return null
- return runCatching {
- cacheJson.decodeFromString(raw)
- }.onFailure { throwable ->
- logger.w(throwable) { "readCachedBrowseSections(): Corrupt cache entry for key=$key, removing" }
- persistedStorage.remove(key)
- }.getOrNull()
- }
-
- private suspend fun writeCachedBrowseSections(key: String, entry: BrowseSectionsCacheEntry) {
- runCatching {
- persistedStorage.putString(key, cacheJson.encodeToString(entry))
- }.onFailure { throwable ->
- logger.w(throwable) { "writeCachedBrowseSections(): Failed to persist cache for key=$key" }
- }
- }
-
- private fun Playlist.toMetadataPlaylist(thumbnailOverride: String? = null): MetadataPlaylist? {
- val identifier = identifier ?: return null
- val id = identifier.substringAfterLast('/').takeIf { it.isNotBlank() } ?: return null
- val creator = creator ?: "Unknown"
-
- return MetadataPlaylist(
- id = id,
- title = title ?: "Untitled",
- description = annotation,
- thumbnails = listOf(
- Thumbnail(
- url = thumbnailOverride
- ?: "https://ui-avatars.com/api/?name=${title ?: "Playlist"}&background=random",
- width = 300,
- height = 300
- )
- ),
- trackCount = track?.size ?: 0,
- externalUri = identifier,
- owner = MetadataUser(
- id = creator,
- username = creator,
- displayName = creator,
- thumbnails = emptyList(),
- externalUri = "https://listenbrainz.org/user/$creator/",
- ),
- )
- }
-
- private suspend fun requireUsername(): String {
- logger.d("requireUsername(): Checking for cached username")
- cachedUsername?.let {
- logger.d("requireUsername(): Using cached username: $it")
- return it
- }
-
- logger.d("requireUsername(): Retrieving auth token from persistent storage")
- val auth = Auth.ApiKeyAuth {
- val token =
- persistedStorage.getString("listenbrainz_auth_token") ?: run {
- logger.w("requireUsername(): No auth token found in persistent storage")
- return@ApiKeyAuth null
- }
- logger.d("requireUsername(): Auth token retrieved, length: ${token.length}")
- if (token.startsWith("Token ", ignoreCase = true)) token else "Token $token"
- }
- Api.setAuthProvider(auth)
-
- logger.i("requireUsername(): Validating token with ListenBrainz API")
- val username = when (val res = LbCoreApi.validateToken()) {
- is Either.Left -> {
- val error = res.value
- logger.e("requireUsername(): Token validation failed with error: $error")
- throw error
- }
-
- is Either.Right -> {
- val user = res.value.data.userName
- logger.i("requireUsername(): Token validation successful, username: $user")
- user
- }
- }
- cachedUsername = username
- logger.d("requireUsername(): Caching username: $username")
- return username!!
- }
-
-}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataPlaylistAPI.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataPlaylistAPI.kt
deleted file mode 100644
index 7db28b5a..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataPlaylistAPI.kt
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import arrow.core.Either
-import dev.krtirtho.plugin_interfaces.host_apis.PersistedStorageAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationStrategy
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationResult
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.Thumbnail
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.playlist.MetadataPlaylist
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.playlist.MetadataPlaylistAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.user.MetadataUser
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzRepository
-import dev.krtirtho.spotube.listenbrainz.Api
-import dev.krtirtho.spotube.listenbrainz.Auth
-import dev.krtirtho.spotube.listenbrainz.api.LbCoreApi
-import dev.krtirtho.spotube.listenbrainz.api.LbPlaylistsApi
-import dev.krtirtho.spotube.listenbrainz.models.CreatePlaylistRequest
-import dev.krtirtho.spotube.listenbrainz.models.Playlist
-import dev.krtirtho.spotube.listenbrainz.models.PlaylistTrackInner
-import kotlin.uuid.Uuid
-
-class RealMusicbrainzListenbrainzMetadataPlaylistAPI(
- private val musicbrainzRepository: MusicbrainzRepository,
- private val persistedStorage: PersistedStorageAPI
-) : MetadataPlaylistAPI {
-
- private var cachedUsername: String? = null
-
- private suspend fun requireUsername(): String {
- cachedUsername?.let { return it }
-
- // Setup auth provider globally
- val auth = Auth.ApiKeyAuth {
- val token =
- persistedStorage.getString("listenbrainz_auth_token") ?: return@ApiKeyAuth null
- if (token.startsWith("Token ", ignoreCase = true)) token else "Token $token"
- }
- Api.setAuthProvider(auth)
-
- val username = when (val res = LbCoreApi.validateToken()) {
- is Either.Left -> throw IllegalStateException("Unable to resolve ListenBrainz username: ${res.value}")
- is Either.Right -> res.value.data.userName
- }
- cachedUsername = username!!
- return username
- }
-
- override suspend fun getPlaylist(id: String): MetadataPlaylist {
- // Ensure auth is set up if possible
- try {
- requireUsername()
- } catch (_: Exception) {
- }
-
- val response = LbPlaylistsApi.fetchPlaylist(
- playlistMbid = Uuid.parse(id),
- fetchMetadata = false
- )
-
- val playlist = response.getOrNull()?.data?.playlist
- ?: throw IllegalStateException("Playlist not found")
-
- return playlistToMetadata(playlist, id)
- ?: throw IllegalStateException("Invalid playlist data")
- }
-
- override suspend fun getPlaylistTracks(
- id: String,
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
-
- try {
- requireUsername()
- } catch (_: Exception) {
- }
-
- val tracks = try {
- LbPlaylistsApi.fetchPlaylist(
- playlistMbid = Uuid.parse(id),
- fetchMetadata = false
- ).getOrNull()?.data?.playlist?.track ?: emptyList()
- } catch (_: Exception) {
- return PaginationResult(
- items = emptyList(),
- totalCount = 0,
- nextPagination = null
- )
- }
-
- val slice = tracks.drop(paging.offset).take(paging.limit)
-
- val recordingIds = slice.mapNotNull { track ->
- track.identifier?.firstOrNull()?.substringAfterLast("/")?.takeIf { it.isNotBlank() }
- }
- val nextOffset = if (paging.offset + paging.limit < tracks.size) paging.offset + paging.limit else null
- if (recordingIds.isEmpty()) {
- return PaginationResult(
- items = emptyList(),
- totalCount = tracks.size,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) }
- )
- }
-
- val query = recordingIds.joinToString(" OR ") { "rid:$it" }
- val mbResponse = musicbrainzRepository.searchRecordings(
- query = query,
- limit = recordingIds.size,
- offset = 0
- )
-
- val recordingsMap = mbResponse.recordings.associateBy { it.id }
-
- val metadataTracks = recordingIds.mapNotNull { rid ->
- val recording = recordingsMap[rid] ?: return@mapNotNull null
- // We pick the first release as the album.
- val release = recording.releases.firstOrNull() ?: return@mapNotNull null
- val releaseGroupId = release.releaseGroup?.id ?: release.id
- val album = release.toMetadataAlbumDetailed(releaseGroupId)
-
- recording.toMetadataTrack(album)
- }
-
- return PaginationResult(
- items = metadataTracks,
- totalCount = tracks.size,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) }
- )
- }
-
- override suspend fun savedPlaylists(
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- // 1. Fetch User Playlists (Remote)
- // 2. Fetch Saved Playlists (Local - from ids)
-
- var username: String? = null
- try {
- username = requireUsername()
- } catch (_: Exception) {
- // If no username, we can't fetch remote user playlists
- }
-
- var remoteTotal = 0L
- var remoteItems: List = emptyList()
-
- if (username != null) {
- try {
- val countRes = LbPlaylistsApi.playlistsForUser(username, count = 1, offset = 0)
- remoteTotal = countRes.getOrNull()?.data?.playlistCount ?: 0L
-
- if (paging.offset < remoteTotal) {
- val limit = (paging.limit).toLong()
- val res = LbPlaylistsApi.playlistsForUser(
- username,
- count = limit,
- offset = paging.offset.toLong()
- )
- res.getOrNull()?.data?.let { data ->
- // playlistCount might be updated
- remoteTotal = data.playlistCount ?: remoteTotal
- remoteItems = data.playlists?.mapNotNull { req ->
- req.playlist?.let {
- playlistToMetadata(
- it,
- req.playlist.identifier?.substringAfterLast("/")
- .takeIf { id -> id != req.playlist.identifier } ?: "")
- }
- } ?: emptyList()
- }
- }
- } catch (_: Exception) {
- // e.printStackTrace() // Removed printStackTrace in KMP common code usually
- }
- }
-
- val ids = persistedStorage.getString(SAVED_PLAYLISTS_KEY)
- ?.split(",")
- ?.filter { it.isNotBlank() }
- ?: emptyList()
- val savedCount = ids.size
- val savedItems = mutableListOf()
-
- // Calculate how many slots in pageSize are left to fill from Saved items
- val remoteFetchedCount = remoteItems.size
- val neededFromSaved = paging.limit - remoteFetchedCount
-
- if (neededFromSaved > 0) {
- // We need checks:
- // 1. Did we exhaust remote? (pagination.offset + remoteFetchedCount >= remoteTotal)
- // 2. Or is pagination.offset already starting inside Saved list? (pagination.offset >= remoteTotal)
- val startInSaved: Long = if (paging.offset >= remoteTotal) {
- paging.offset - remoteTotal
- } else {
- // We were fetching from remote, and maybe it finished, so we append from start of saved
- 0
- }
-
- if (startInSaved < savedCount) {
- val endInSaved = (startInSaved + neededFromSaved).coerceAtMost(savedCount.toLong())
- val pageIds = ids.subList(startInSaved.toInt(), endInSaved.toInt())
-
- val fetchedSaved = pageIds.mapNotNull { id ->
- try {
- getPlaylist(id)
- } catch (_: Exception) {
- null
- }
- }
- savedItems.addAll(fetchedSaved)
- }
- }
-
- val allItems = remoteItems + savedItems
- val totalCount = remoteTotal + savedCount
-
- val nextOffset = if (paging.offset + allItems.size < totalCount) paging.offset + allItems.size else null
-
- return PaginationResult(
- items = allItems,
- totalCount = totalCount.toInt(),
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) }
- )
- }
-
- private fun playlistToMetadata(playlist: Playlist, id: String): MetadataPlaylist? {
- // Identifier usually contains URL, we need to extract ID if not passed
- val mbid = id.ifBlank {
- playlist.identifier?.substringAfterLast("/")
- ?.takeIf { it != playlist.identifier } ?: return null
- }
-
- val creator = playlist.creator ?: "Unknown"
-
- return MetadataPlaylist(
- id = mbid,
- title = playlist.title ?: "Untitled",
- description = playlist.annotation,
- thumbnails = listOf(
- Thumbnail(
- url = "https://ui-avatars.com/api/?name=${playlist.title}&background=random",
- width = 300,
- height = 300
- )
- ),
- trackCount = playlist.track?.size ?: 0,
- externalUri = playlist.identifier ?: "https://listenbrainz.org/playlist/$mbid",
- owner = MetadataUser(
- id = creator,
- username = creator,
- displayName = creator,
- thumbnails = emptyList(), // no avatar easily available
- externalUri = "https://listenbrainz.org/user/$creator/"
- )
- )
- }
-
- override suspend fun isSavedPlaylists(ids: List): List {
- val savedIds = persistedStorage.getString(SAVED_PLAYLISTS_KEY)
- ?.split(",")
- ?.toSet()
- ?: emptySet()
-
- return ids.map { savedIds.contains(it) }
- }
-
- override suspend fun savePlaylists(ids: List) {
- val savedIds = (persistedStorage.getString(SAVED_PLAYLISTS_KEY)
- ?.split(",")
- ?.filter { it.isNotBlank() }
- ?.toMutableSet()
- ?: mutableSetOf()).apply {
- addAll(ids)
- }
- persistedStorage.putString(SAVED_PLAYLISTS_KEY, savedIds.joinToString(","))
- }
-
- override suspend fun removeSavedPlaylists(ids: List) {
- val savedIds = (persistedStorage.getString(SAVED_PLAYLISTS_KEY)
- ?.split(",")
- ?.filter { it.isNotBlank() }
- ?.toMutableSet()
- ?: mutableSetOf()).apply {
- removeAll(ids.toSet())
- }
- persistedStorage.putString(SAVED_PLAYLISTS_KEY, savedIds.joinToString(","))
- }
-
- companion object {
- private const val SAVED_PLAYLISTS_KEY = "saved_playlists"
- }
-
- override suspend fun createPlaylist(
- name: String,
- description: String?,
- isPublic: Boolean,
- isCollaborating: Boolean,
- imageBase64: String,
- trackIds: List
- ): MetadataPlaylist {
- val username = requireUsername()
-
- val body = CreatePlaylistRequest(
- playlist = Playlist(
- title = name,
- annotation = description,
- track = trackIds.map {
- PlaylistTrackInner(
- identifier = listOf("https://musicbrainz.org/recording/$it")
- )
- }
- )
- )
-
- val res = LbPlaylistsApi.createPlaylist(body)
- val created =
- res.getOrNull()?.data ?: throw IllegalStateException("Failed to create playlist")
-
- // The create response usually contains the MBID
- val mbid =
- created.playlistMbid?.toString() ?: throw IllegalStateException("No MBID returned")
-
- return MetadataPlaylist(
- id = mbid,
- title = name,
- description = description,
- thumbnails = listOf(
- Thumbnail(
- url = "https://ui-avatars.com/api/?name=$name&background=random",
- width = 300,
- height = 300
- )
- ),
- trackCount = trackIds.size,
- externalUri = "https://listenbrainz.org/playlist/$mbid",
- owner = MetadataUser(
- id = username,
- username = username,
- displayName = username,
- thumbnails = emptyList(),
- externalUri = "https://listenbrainz.org/user/$username/"
- )
- )
- }
-
- override suspend fun updatePlaylist(
- id: String,
- name: String?,
- description: String?,
- isPublic: Boolean?,
- isCollaborating: Boolean?,
- imageBase64: String?,
- trackIds: List?
- ): MetadataPlaylist {
- requireUsername()
- // If we need to fetch first to get existing values?
- // LB edit API usually replaces fields.
-
- val body = CreatePlaylistRequest(
- playlist = Playlist(
- title = name ?: "Untitled",
- annotation = description,
- track = trackIds?.map {
- PlaylistTrackInner(
- identifier = listOf("https://musicbrainz.org/recording/$it")
- )
- }
- )
- )
-
- val res = LbPlaylistsApi.editPlaylist(Uuid.parse(id), body)
- if (res.isLeft()) throw IllegalStateException("Failed to update playlist: ${res.leftOrNull()}")
-
- return getPlaylist(id)
- }
-
- override suspend fun deletePlaylist(id: String) {
- requireUsername()
- LbPlaylistsApi.deletePlaylist(Uuid.parse(id))
- }
-
- override suspend fun addTracksToPlaylist(
- playlistId: String,
- trackIds: List
- ) {
- TODO("Not yet implemented")
- }
-
- override suspend fun removeTracksFromPlaylist(
- playlistId: String,
- trackIds: List
- ) {
- TODO("Not yet implemented")
- }
-
-}
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataSearchAPI.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataSearchAPI.kt
deleted file mode 100644
index e99fe3e9..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataSearchAPI.kt
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbum
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.album.MetadataAlbumType
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.artist.MetadataArtist
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationStrategy
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationResult
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.Thumbnail
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.playlist.MetadataPlaylist
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.search.MetadataSearchAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.search.MetadataSearchResult
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.search.MetadataSupportedSearchType
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.user.MetadataUser
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.listenbrainz.LBPlaylistSearchResponse
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzArtistEnricher
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzRepository
-import io.ktor.client.HttpClient
-import io.ktor.client.request.get
-import io.ktor.client.request.parameter
-import io.ktor.client.request.url
-import io.ktor.client.statement.bodyAsText
-import kotlinx.coroutines.async
-import kotlinx.coroutines.coroutineScope
-import kotlinx.serialization.json.Json
-
-class RealMusicbrainzListenbrainzMetadataSearchAPI(
- private val musicbrainzRepository: MusicbrainzRepository,
- private val artistEnricher: MusicbrainzArtistEnricher,
- private val httpClient: HttpClient
-): MetadataSearchAPI {
- private val json = Json { ignoreUnknownKeys = true; isLenient = true }
-
- override val supportedSearchTypes: List = listOf(
- MetadataSupportedSearchType.TRACK,
- MetadataSupportedSearchType.ARTIST,
- MetadataSupportedSearchType.ALBUM,
- MetadataSupportedSearchType.PLAYLIST,
- )
-
- override suspend fun search(query: String): List = coroutineScope {
- val playlists = async { searchPlaylists(query, PaginationStrategy.Offset(offset = 0, limit = 5)).items }
- val tracks = async { searchTracks(query, PaginationStrategy.Offset(offset = 0, limit = 5)).items }
- val artists = async { searchArtists(query, PaginationStrategy.Offset(offset = 0, limit = 5)).items }
- val albums = async { searchAlbums(query, PaginationStrategy.Offset(offset = 0, limit = 5)).items }
-
- val results = mutableListOf()
- results.addAll(playlists.await())
- results.addAll(tracks.await())
- results.addAll(artists.await())
- results.addAll(albums.await())
- results
- }
-
- override suspend fun searchTracks(
- query: String,
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
-
- val result = musicbrainzRepository.searchRecordings(
- query = query,
- limit = paging.limit,
- offset = paging.offset
- )
- val items = result.recordings.map { recording ->
- val release = recording.releases.firstOrNull()
- val releaseGroupId = release?.releaseGroup?.id ?: release?.id ?: recording.id
-
- val albumDetailed = MetadataAlbum.Detailed(
- id = releaseGroupId,
- title = release?.releaseGroup?.title ?: release?.title ?: recording.title, // Fallback
- description = null,
- thumbnails = listOf(
- Thumbnail("https://coverartarchive.org/release-group/$releaseGroupId/front-250.jpg", 250, 250),
- Thumbnail("https://coverartarchive.org/release-group/$releaseGroupId/front-500.jpg", 500, 500)
- ),
- albumType = MetadataAlbumType.Album, // Default
- artists = emptyList(), // Can populate if needed
- externalUri = "https://musicbrainz.org/release-group/$releaseGroupId",
- releaseDate = release?.date,
- genres = emptyList(),
- trackCount = release?.trackCount ?: 0
- )
-
- MetadataSearchResult.Track(
- data = MetadataTrack(
- id = recording.id,
- title = recording.title,
- durationMs = recording.length?.toLong() ?: 0L,
- trackNumber = null,
- discNumber = null,
- artists = recording.artistCredit.mapNotNull { credit ->
- credit.artist?.let { artist ->
- MetadataArtist.Basic(
- id = artist.id,
- name = artist.name,
- thumbnails = emptyList(),
- externalUri = "https://musicbrainz.org/artist/${artist.id}"
- )
- }
- },
- album = albumDetailed,
- explicit = recording.tags.any { it.name.contains("explicit", ignoreCase = true) },
- popularity = null,
- isrcCode = recording.isrcs.firstOrNull(),
- externalUri = "https://musicbrainz.org/recording/${recording.id}",
- thumbnails = null,
- )
- )
- }
-
- val nextOffset = if (paging.offset + paging.limit < result.count) {
- paging.offset + paging.limit
- } else null
-
- return PaginationResult(
- items = items,
- totalCount = result.count,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) },
- )
- }
-
- override suspend fun searchArtists(
- query: String,
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- val result = musicbrainzRepository.searchArtists(
- query = query,
- limit = paging.limit,
- offset = paging.offset
- )
-
- val artistIds = result.artists.map { it.id }
- val enriched = artistEnricher.getEnrichedArtists(artistIds)
-
- val items = enriched.map { (artist, images) ->
- MetadataSearchResult.Artist(
- data = MetadataArtist.Basic(
- id = artist.id,
- name = artist.name,
- thumbnails = images.map { Thumbnail(it, 300, 300) },
- externalUri = "https://musicbrainz.org/artist/${artist.id}"
- )
- )
- }
-
- val nextOffset = if (paging.offset + paging.limit < result.count) {
- paging.offset + paging.limit
- } else null
-
- return PaginationResult(
- items = items,
- totalCount = result.count,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) },
- )
- }
-
- override suspend fun searchAlbums(
- query: String,
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- val result = musicbrainzRepository.searchReleaseGroups(
- query = query,
- limit = paging.limit,
- offset = paging.offset
- )
-
- val items = result.releaseGroups.map { group ->
- MetadataSearchResult.Album(
- data = MetadataAlbum.Basic(
- id = group.id,
- title = group.title,
- description = null,
- thumbnails = listOf(
- Thumbnail("https://coverartarchive.org/release-group/${group.id}/front-250.jpg", 250, 250),
- Thumbnail("https://coverartarchive.org/release-group/${group.id}/front-500.jpg", 500, 500)
- ),
- albumType = when (group.primaryType?.lowercase()) {
- "album" -> MetadataAlbumType.Album
- "single" -> MetadataAlbumType.Single
- "compilation" -> MetadataAlbumType.Collection
- else -> MetadataAlbumType.Album
- },
- artists = emptyList(), // Populate?
- externalUri = "https://musicbrainz.org/release-group/${group.id}"
- )
- )
- }
-
- val nextOffset = if (paging.offset + paging.limit < result.count) {
- paging.offset + paging.limit
- } else null
-
- return PaginationResult(
- items = items,
- totalCount = result.count,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) },
- )
- }
-
- override suspend fun searchPlaylists(
- query: String,
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
- try {
- val responseText = httpClient.get {
- url("https://api.listenbrainz.org/1/playlist/search")
- parameter("query", query)
- parameter("count", paging.limit)
- parameter("offset", paging.offset)
- }.bodyAsText()
-
- val response = json.decodeFromString(responseText)
-
- val items = response.playlists.map { it.playlist }.map { playlist ->
- val id = playlist.identifier.substringAfterLast("/")
- MetadataSearchResult.Playlist(
- data = MetadataPlaylist(
- id = id,
- title = playlist.title,
- description = playlist.annotation,
- thumbnails = emptyList(), // Listenbrainz search doesn't return playlist covers usually
- trackCount = 0, // Not available in search result
- owner = MetadataUser(
- id = playlist.creator,
- username = playlist.creator,
- displayName = playlist.creator,
- thumbnails = emptyList(),
- externalUri = "https://listenbrainz.org/user/${playlist.creator}"
- ),
- externalUri = "https://listenbrainz.org/playlist/$id"
- )
- )
- }
-
- val nextOffset = if (paging.offset + paging.limit < response.count) {
- paging.offset + paging.limit
- } else null
-
- return PaginationResult(
- items = items,
- totalCount = response.count,
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) },
- )
- } catch (e: Exception) {
- e.printStackTrace()
- return PaginationResult(emptyList(), 0, null)
- }
- }
-
- override suspend fun searchUsers(
- query: String,
- pagination: PaginationStrategy?
- ): PaginationResult {
- return PaginationResult(emptyList(), 0, null)
- }
-
-}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataTrackAPI.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataTrackAPI.kt
deleted file mode 100644
index 1687af1b..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/RealMusicbrainzListenbrainzMetadataTrackAPI.kt
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz
-
-import arrow.core.Either
-import dev.krtirtho.plugin_interfaces.host_apis.PersistedStorageAPI
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationStrategy
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.common.PaginationResult
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrack
-import dev.krtirtho.plugin_interfaces.plugin_apis.metadata.track.MetadataTrackAPI
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz.MusicbrainzRepository
-import dev.krtirtho.spotube.listenbrainz.Api
-import dev.krtirtho.spotube.listenbrainz.Auth
-import dev.krtirtho.spotube.listenbrainz.api.LbCoreApi
-import dev.krtirtho.spotube.listenbrainz.api.LbRecordingsApi
-import dev.krtirtho.spotube.listenbrainz.models.RecordingFeedbackRequest
-import io.ktor.client.request.get
-import io.ktor.client.request.header
-import io.ktor.client.request.parameter
-import io.ktor.client.statement.bodyAsText
-import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.contentOrNull
-import kotlinx.serialization.json.jsonArray
-import kotlinx.serialization.json.jsonObject
-import kotlinx.serialization.json.jsonPrimitive
-import kotlin.uuid.Uuid
-
-class RealMusicbrainzListenbrainzMetadataTrackAPI(
- private val musicbrainzRepository: MusicbrainzRepository,
- private val persistedStorage: PersistedStorageAPI
-) : MetadataTrackAPI {
-
- private var cachedUsername: String? = null
-
- private suspend fun requireUsername(): String {
- cachedUsername?.let { return it }
-
- val auth = Auth.ApiKeyAuth {
- val token = persistedStorage.getString("listenbrainz_auth_token") ?: return@ApiKeyAuth null
- if (token.startsWith("Token ", ignoreCase = true)) token else "Token $token"
- }
- Api.setAuthProvider(auth)
-
- val username = when (val res = LbCoreApi.validateToken()) {
- is Either.Left -> throw IllegalStateException("Unable to resolve ListenBrainz username: ${res.value}")
- is Either.Right -> res.value.data.userName
- }
- cachedUsername = username!!
- return username
- }
-
- override suspend fun getTrack(id: String): MetadataTrack {
- val recording = musicbrainzRepository.getRecordingByMbid(
- mbid = id,
- includes = listOf("artists", "releases", "artist-credits", "release-groups")
- )
- val release = recording.releases.firstOrNull()
- ?: throw IllegalStateException("No release found for track")
-
- val album = release.toMetadataAlbumDetailed(release.releaseGroup?.id ?: release.id)
-
- // This creates basic track metadata from MusicBrainz
- return recording.toMetadataTrack(album)
- }
-
- override suspend fun savedTracks(
- pagination: PaginationStrategy?
- ): PaginationResult {
- val paging = pagination as? PaginationStrategy.Offset ?: PaginationStrategy.Offset(0, 20)
-
- val username = try {
- requireUsername()
- } catch (_: Exception) {
- return PaginationResult(
- items = emptyList(),
- totalCount = 0,
- nextPagination = null
- )
- }
-
- val res = LbRecordingsApi.getFeedback(
- userName = username,
- score = 1,
- count = paging.limit.toLong(),
- offset = paging.offset.toLong()
- )
-
- val feedbackResponse = res.getOrNull()?.data ?: return PaginationResult(
- items = emptyList(),
- totalCount = 0,
- nextPagination = null
- )
- val feedbacks = feedbackResponse.feedback ?: emptyList()
- val mbids = feedbacks.mapNotNull { it.recordingMbid?.toString() }
-
- if (mbids.isEmpty()) {
- return PaginationResult(
- items = emptyList(),
- totalCount = (feedbackResponse.totalCount ?: 0).toInt(),
- nextPagination = null
- )
- }
-
- // Batch fetch metadata
- val query = mbids.joinToString(" OR ") { "rid:$it" }
- val searchRes = musicbrainzRepository.searchRecordings(query, limit = mbids.size)
- val recordingMap = searchRes.recordings.associateBy { it.id }
-
- val tracks = mbids.mapNotNull { mbid ->
- val recording = recordingMap[mbid] ?: return@mapNotNull null
- val release = recording.releases.firstOrNull() ?: return@mapNotNull null
- val album = release.toMetadataAlbumDetailed(release.releaseGroup?.id ?: release.id)
- recording.toMetadataTrack(album)
- }
-
- val nextOffset = if ((paging.offset + paging.limit) < (feedbackResponse.totalCount ?: 0)) {
- paging.offset + paging.limit
- } else null
-
- return PaginationResult(
- items = tracks,
- totalCount = (feedbackResponse.totalCount ?: 0).toInt(),
- nextPagination = nextOffset?.let { PaginationStrategy.Offset(it, paging.limit) }
- )
- }
-
- override suspend fun isSavedTracks(ids: List): List {
- val username = try {
- requireUsername()
- } catch (_: Exception) {
- return ids.map { false }
- }
-
- val uuids = ids.mapNotNull {
- try { Uuid.parse(it) } catch(_: Exception) { null }
- }
- if (uuids.isEmpty()) return ids.map { false }
-
- val res = LbRecordingsApi.getFeedbackForRecordings(
- userName = username,
- recordingMbids = uuids
- )
-
- val feedbackMap = res.getOrNull()?.data?.feedback?.associateBy { it.recordingMbid.toString() } ?: emptyMap()
-
- return ids.map { id ->
- feedbackMap[id]?.score == 1L
- }
- }
-
- override suspend fun saveTracks(ids: List) {
- requireUsername()
- ids.forEach { id ->
- try {
- LbRecordingsApi.recordingFeedback(
- RecordingFeedbackRequest(
- recordingMbid = Uuid.parse(id),
- score = 1
- )
- )
- } catch (_: Exception) {}
- }
- }
-
- override suspend fun removeSavedTracks(ids: List) {
- requireUsername()
- ids.forEach { id ->
- try {
- LbRecordingsApi.recordingFeedback(
- RecordingFeedbackRequest(
- recordingMbid = Uuid.parse(id),
- score = 0
- )
- )
- } catch (_: Exception) {}
- }
- }
-
- override suspend fun recommendationsBasedOnTracks(
- seedTrackIds: List,
- limit: Int
- ): List {
- requireUsername()
- val idsParam = seedTrackIds.joinToString(",")
-
- val jsonStr = try {
- val response = Api.client.get("https://api.listenbrainz.org/1/recommendation/playground/recording_recommendations") {
- parameter("recording_mbids", idsParam)
- parameter("count", limit)
- val token = persistedStorage.getString("listenbrainz_auth_token")
- if (token != null) {
- header("Authorization", "Token $token")
- }
- }
- response.bodyAsText()
- } catch (_: Exception) {
- return emptyList()
- }
-
- val json = Json { ignoreUnknownKeys = true }
- val root = json.parseToJsonElement(jsonStr).jsonObject
- val payload = root["payload"]?.jsonObject
- val recordings = payload?.get("recordings")?.jsonArray ?: return emptyList()
-
- val mbids = recordings.mapNotNull {
- it.jsonObject["recording_mbid"]?.jsonPrimitive?.contentOrNull
- }
-
- if (mbids.isEmpty()) return emptyList()
-
- val query = mbids.joinToString(" OR ") { "rid:$it" }
- val searchRes = musicbrainzRepository.searchRecordings(query, limit = mbids.size)
- val recordingMap = searchRes.recordings.associateBy { it.id }
-
- return mbids.mapNotNull { mbid ->
- val recording = recordingMap[mbid] ?: return@mapNotNull null
- val release = recording.releases.firstOrNull() ?: return@mapNotNull null
- val album = release.toMetadataAlbumDetailed(release.releaseGroup?.id ?: release.id)
- recording.toMetadataTrack(album)
- }
- }
-}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/listenbrainz/ListenbrainzModels.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/listenbrainz/ListenbrainzModels.kt
deleted file mode 100644
index fb7f7a2f..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/listenbrainz/ListenbrainzModels.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.listenbrainz
-
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.json.JsonElement
-
-@Serializable
-data class LBPlaylistExtensionSpopf(
- @SerialName("public")
- val isPublic: Boolean? = null
-)
-
-@Serializable
-data class LBPlaylistExtension(
- @SerialName("https://musicbrainz.org/doc/jspf#playlist")
- val spopf: LBPlaylistExtensionSpopf? = null
-)
-
-@Serializable
-data class LBPlaylistUser(
- val name: String
-)
-
-@Serializable
-data class LBPlaylist(
- val identifier: String,
- val title: String,
- val annotation: String? = null,
- val creator: String, // In search response it is string (username)
- val extension: LBPlaylistExtension? = null,
- val date: String? = null,
-)
-
-@Serializable
-data class LBPlaylistObject(
- val playlist: LBPlaylist,
-)
-
-@Serializable
-data class LBPlaylistSearchResponse(
- @SerialName("playlist_count")
- val count: Int = 0,
- val offset: Int = 0,
- val playlists: List = emptyList(),
-)
-
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/musicbrainz/MusicBrainzModels.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/musicbrainz/MusicBrainzModels.kt
deleted file mode 100644
index 4d1a08dd..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/musicbrainz/MusicBrainzModels.kt
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz
-
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-
-@Serializable
-data class MusicbrainzTag(
- val name: String,
- val count: Int? = null,
-)
-
-@Serializable
-data class MusicbrainzLifeSpan(
- val begin: String? = null,
- val end: String? = null,
- val ended: Boolean? = null,
-)
-
-@Serializable
-data class MusicbrainzTextRepresentation(
- val language: String? = null,
- val script: String? = null,
-)
-
-@Serializable
-data class MusicbrainzArtist(
- val id: String,
- val name: String,
- val score: String? = null,
- @SerialName("sort-name")
- val sortName: String? = null,
- val country: String? = null,
- val type: String? = null,
- val gender: String? = null,
- val disambiguation: String? = null,
- @SerialName("life-span")
- val lifeSpan: MusicbrainzLifeSpan? = null,
- val tags: List = emptyList(),
-)
-
-@Serializable
-data class MusicbrainzArtistCredit(
- val name: String? = null,
- @SerialName("joinphrase")
- val joinPhrase: String? = null,
- val artist: MusicbrainzArtist? = null,
-)
-
-@Serializable
-data class MusicbrainzReleaseGroup(
- val id: String,
- val title: String,
- @SerialName("primary-type")
- val primaryType: String? = null,
- @SerialName("secondary-types")
- val secondaryTypes: List = emptyList(),
- @SerialName("first-release-date")
- val firstReleaseDate: String? = null,
-)
-
-@Serializable
-data class MusicbrainzRelease(
- val id: String,
- val title: String,
- val score: String? = null,
- val status: String? = null,
- val quality: String? = null,
- val date: String? = null,
- val country: String? = null,
- @SerialName("barcode")
- val barCode: String? = null,
- @SerialName("track-count")
- val trackCount: Int? = null,
- @SerialName("text-representation")
- val textRepresentation: MusicbrainzTextRepresentation? = null,
- @SerialName("artist-credit")
- val artistCredit: List = emptyList(),
- @SerialName("release-group")
- val releaseGroup: MusicbrainzReleaseGroup? = null,
-)
-
-@Serializable
-data class MusicbrainzRecording(
- val id: String,
- val title: String,
- val length: Int? = null,
- val disambiguation: String? = null,
- val video: Boolean? = null,
- val score: String? = null,
- @SerialName("first-release-date")
- val firstReleaseDate: String? = null,
- @SerialName("artist-credit")
- val artistCredit: List = emptyList(),
- val releases: List = emptyList(),
- val tags: List = emptyList(),
- val isrcs: List = emptyList(),
-)
-
-@Serializable
-data class MusicbrainzRecordingSearchResponse(
- val created: String? = null,
- val count: Int = 0,
- val offset: Int = 0,
- val recordings: List = emptyList(),
-)
-
-@Serializable
-data class MusicbrainzArtistSearchResponse(
- val created: String? = null,
- val count: Int = 0,
- val offset: Int = 0,
- val artists: List = emptyList(),
-)
-
-@Serializable
-data class MusicbrainzReleaseSearchResponse(
- val created: String? = null,
- val count: Int = 0,
- val offset: Int = 0,
- val releases: List = emptyList(),
-)
-
-@Serializable
-data class MusicbrainzReleaseGroupSearchResponse(
- val created: String? = null,
- val count: Int = 0,
- val offset: Int = 0,
- @SerialName("release-groups")
- val releaseGroups: List = emptyList(),
-)
-
-@Serializable
-data class MusicbrainzUrlRelation(
- val artist: MusicbrainzArtist? = null,
-)
-
-@Serializable
-data class MusicbrainzUrlRelationList(
- val relations: List = emptyList(),
-)
-
-@Serializable
-data class MusicbrainzUrl(
- val resource: String,
- @SerialName("relation-list")
- val relationList: List = emptyList(),
-)
-
-@Serializable
-data class MusicbrainzUrlResponse(
- val urls: List = emptyList(),
-)
-
-@Serializable
-data class MusicbrainzIsrcLookupResponse(
- val isrc: String,
- val recordings: List = emptyList(),
-)
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/musicbrainz/MusicbrainzArtistEnricher.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/musicbrainz/MusicbrainzArtistEnricher.kt
deleted file mode 100644
index 8ad20857..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/musicbrainz/MusicbrainzArtistEnricher.kt
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz
-
-import dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.wikidata.WikidataRepository
-
-class MusicbrainzArtistEnricher(
- private val musicbrainzRepository: MusicbrainzRepository,
- private val wikidataRepository: WikidataRepository
-) {
- suspend fun getArtistsWithImages(artistIds: List): List {
- if (artistIds.isEmpty()) return emptyList()
-
- // 1. Find Wikidata URLs for these artists
- val idsQuery = artistIds.joinToString(" OR ") { "targetid:$it" }
- val query = "relationtype:wikidata AND targettype:artist AND ($idsQuery)"
-
- val urlResponse = musicbrainzRepository.searchUrls(
- query = query,
- limit = artistIds.size
- )
-
- val urls = urlResponse.urls
- val wikidataIds = urls.map { it.resource.substringAfterLast("/") }
-
- // Map MBID to Wikidata ID based on response
- // The response structure for /url search is a bit complex.
- // It returns URLs, and each URL has relation-list -> relations -> artist -> id
-
- val mbidToWikidataId = mutableMapOf()
-
- urls.forEach { url ->
- val wikidataId = url.resource.substringAfterLast("/")
- val artistId = url.relationList.firstOrNull()?.relations?.firstOrNull()?.artist?.id
- if (artistId != null) {
- mbidToWikidataId[artistId] = wikidataId
- }
- }
-
- // 2. Fetch images for Wikidata IDs
- val imagesMap = wikidataRepository.getArtistImages(wikidataIds)
-
- // 3. Construct result
- // We need to return MusicbrainzArtist objects. We might need to fetch details if we don't have them.
- // But here we are enriching.
- // Logic in search.ht:
- // - Get wikidata IDs
- // - Fetch images
- // - Fetch artist details for artists WITHOUT wikidata link (using /artist search or lookup)
- // - Combine
-
- // Let's search/fetch artist details for all IDs using their MBIDs
- // Optimally we can batch fetch if possible, but MB API usually requires individual lookups or search.
- // search.ht uses search endpoint with "arid:ID OR arid:ID..."
-
- val artistsResponse = musicbrainzRepository.searchArtists(
- query = artistIds.joinToString(" OR ") { "arid:$it" },
- limit = artistIds.size
- )
-
- val artists = artistsResponse.artists.map { artist ->
- // Check if we have an image for this artist
- // We need to know which wikidata ID corresponds to this artist
- val wikidataId = mbidToWikidataId[artist.id]
- val imageUrl = wikidataId?.let { imagesMap[it] }
-
- // We don't have a field for 'images' in MusicbrainzArtist model yet.
- // We should probably return a Pair or a new model, or just rely on the fact that we can't modify MusicbrainzArtist easily if it's data class.
- // But wait, search.ht returns list of items which are maps.
-
- // I'll return MusicbrainzArtist, but I need to attach the image somehow.
- // I'll assume passing the image URL up is handled by the caller or I'll wrap it.
- // But MusicbrainzArtist is a data class.
-
- // Wait, Kotlin data classes are immutable.
- // references used in search.ht:
- // return { id: ..., name: ..., images: [url, ...] }
-
- // So this Enricher should probably return a data structure that holds Artist + Image list.
- EnrichedArtist(artist, imageUrl?.let { listOf(it) } ?: emptyList())
- }
-
- return artists.map { it.artist } // Wait, how to attach image?
- }
-
- data class EnrichedArtist(
- val artist: MusicbrainzArtist,
- val images: List
- )
-
- suspend fun getEnrichedArtists(artistIds: List): List {
- if (artistIds.isEmpty()) return emptyList()
-
- // 1. Find Wikidata URLs for these artists
- val idsQuery = artistIds.joinToString(" OR ") { "targetid:$it" }
- val query = "relationtype:wikidata AND targettype:artist AND ($idsQuery)"
-
- val urlResponse = musicbrainzRepository.searchUrls(
- query = query,
- limit = artistIds.size
- )
-
- val urls = urlResponse.urls
-
- val mbidToWikidataId = mutableMapOf()
- urls.forEach { url ->
- val wikidataId = url.resource.substringAfterLast("/")
- val artistId = url.relationList.firstOrNull()?.relations?.firstOrNull()?.artist?.id
- if (artistId != null) {
- mbidToWikidataId[artistId] = wikidataId
- }
- }
-
- val wikidataIds = mbidToWikidataId.values.toList()
-
- // 2. Fetch images for Wikidata IDs
- val imagesMap = if (wikidataIds.isNotEmpty()) {
- wikidataRepository.getArtistImages(wikidataIds)
- } else {
- emptyMap()
- }
-
- // 3. Fetch artist details
- // search.ht fetches "missingArtistIds" (artists without wikidata link) separately.
- // But here we can just fetch ALL artists using one query (arid:...) because we need details for all of them anyway.
- // search.ht fetches "artistWithImages" from wikidata info (it gets artist object from /url response relation),
- // and "artistWithoutImages" from /artist search.
- // The /url response relation includes the artist object!
-
- // Let's follow search.ht optimization:
- // Use artists from /url response for those that have wikidata.
- // Use /artist search for those that don't.
-
- val artistsFromUrl = urls.mapNotNull { url ->
- val artist = url.relationList.firstOrNull()?.relations?.firstOrNull()?.artist
- val wikidataId = url.resource.substringAfterLast("/")
- val imageUrl = imagesMap[wikidataId]
-
- if (artist != null) {
- EnrichedArtist(artist, imageUrl?.let { listOf(it) } ?: emptyList())
- } else null
- }
-
- val foundArtistIds = artistsFromUrl.map { it.artist.id }.toSet()
- val missingRequestIds = artistIds.filter { !foundArtistIds.contains(it) }
-
- val artistsFromSearch = if (missingRequestIds.isNotEmpty()) {
- val artistsResponse = musicbrainzRepository.searchArtists(
- query = missingRequestIds.joinToString(" OR ") { "arid:$it" },
- limit = missingRequestIds.size
- )
- artistsResponse.artists.map { EnrichedArtist(it, emptyList()) }
- } else {
- emptyList()
- }
-
- return artistsFromUrl + artistsFromSearch
- }
-}
-
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/musicbrainz/MusicbrainzRepository.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/musicbrainz/MusicbrainzRepository.kt
deleted file mode 100644
index 752f6e7c..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/musicbrainz/MusicbrainzRepository.kt
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.musicbrainz
-
-import io.ktor.client.HttpClient
-import io.ktor.client.request.get
-import io.ktor.client.request.header
-import io.ktor.client.request.parameter
-import io.ktor.client.request.url
-import io.ktor.client.statement.bodyAsText
-import io.ktor.client.statement.request
-import io.ktor.client.statement.HttpResponse
-import io.ktor.http.HttpHeaders
-import io.ktor.http.isSuccess
-import kotlinx.serialization.json.Json
-
-interface MusicbrainzRepository {
- suspend fun searchRecordings(
- query: String,
- limit: Int = 25,
- offset: Int = 0,
- ): MusicbrainzRecordingSearchResponse
-
- suspend fun searchArtists(
- query: String,
- limit: Int = 25,
- offset: Int = 0,
- ): MusicbrainzArtistSearchResponse
-
- suspend fun searchReleases(
- query: String,
- limit: Int = 25,
- offset: Int = 0,
- ): MusicbrainzReleaseSearchResponse
-
- suspend fun searchReleaseGroups(
- query: String,
- limit: Int = 25,
- offset: Int = 0,
- ): MusicbrainzReleaseGroupSearchResponse
-
- suspend fun searchUrls(
- query: String,
- limit: Int = 25,
- ): MusicbrainzUrlResponse
-
- suspend fun getRecordingByMbid(
- mbid: String,
- includes: List = emptyList(),
- ): MusicbrainzRecording
-
- suspend fun getArtistByMbid(
- mbid: String,
- includes: List = emptyList(),
- ): MusicbrainzArtist
-
- suspend fun getReleaseByMbid(
- mbid: String,
- includes: List = emptyList(),
- ): MusicbrainzRelease
-
- suspend fun lookupIsrc(
- isrc: String,
- includes: List = emptyList(),
- ): MusicbrainzIsrcLookupResponse
-}
-
-class KtorMusicbrainzRepository(
- private val httpClient: HttpClient,
- private val baseUrl: String = "https://musicbrainz.org",
- private val userAgent: String = "Spotube/0.1 (https://github.com/KRTirtho/spotube)",
-) : MusicbrainzRepository {
- private val json = Json {
- ignoreUnknownKeys = true
- isLenient = true
- }
-
- override suspend fun searchRecordings(
- query: String,
- limit: Int,
- offset: Int,
- ): MusicbrainzRecordingSearchResponse {
- val payload = fetch(
- endpoint = "recording",
- query = query,
- limit = limit,
- offset = offset,
- )
- return json.decodeFromString(payload)
- }
-
- override suspend fun searchArtists(
- query: String,
- limit: Int,
- offset: Int,
- ): MusicbrainzArtistSearchResponse {
- val payload = fetch(
- endpoint = "artist",
- query = query,
- limit = limit,
- offset = offset,
- )
- return json.decodeFromString(payload)
- }
-
- override suspend fun searchReleases(
- query: String,
- limit: Int,
- offset: Int,
- ): MusicbrainzReleaseSearchResponse {
- val payload = fetch(
- endpoint = "release",
- query = query,
- limit = limit,
- offset = offset,
- )
- return json.decodeFromString(payload)
- }
-
- override suspend fun searchReleaseGroups(
- query: String,
- limit: Int,
- offset: Int,
- ): MusicbrainzReleaseGroupSearchResponse {
- val payload = fetch(
- endpoint = "release-group",
- query = query,
- limit = limit,
- offset = offset,
- )
- return json.decodeFromString(payload)
- }
-
- override suspend fun searchUrls(
- query: String,
- limit: Int,
- ): MusicbrainzUrlResponse {
- val payload = fetch(
- endpoint = "url",
- query = query,
- limit = limit,
- )
- return json.decodeFromString(payload)
- }
-
- override suspend fun getRecordingByMbid(
- mbid: String,
- includes: List,
- ): MusicbrainzRecording {
- val payload = fetch(endpoint = "recording/${mbid.trim()}", inc = includes)
- return json.decodeFromString(payload)
- }
-
- override suspend fun getArtistByMbid(
- mbid: String,
- includes: List,
- ): MusicbrainzArtist {
- val payload = fetch(endpoint = "artist/${mbid.trim()}", inc = includes)
- return json.decodeFromString(payload)
- }
-
- override suspend fun getReleaseByMbid(
- mbid: String,
- includes: List,
- ): MusicbrainzRelease {
- val payload = fetch(endpoint = "release/${mbid.trim()}", inc = includes)
- return json.decodeFromString(payload)
- }
-
- override suspend fun lookupIsrc(
- isrc: String,
- includes: List,
- ): MusicbrainzIsrcLookupResponse {
- val payload = fetch(endpoint = "isrc/${isrc.trim()}", inc = includes)
- return json.decodeFromString(payload)
- }
-
- private suspend fun fetch(
- endpoint: String,
- query: String? = null,
- limit: Int? = null,
- offset: Int? = null,
- inc: List = emptyList(),
- ): String {
- val response = httpClient.get {
- url("${baseUrl.trimEnd('/')}/ws/2/$endpoint")
- header(HttpHeaders.Accept, "application/json")
- header(HttpHeaders.UserAgent, userAgent)
- parameter("fmt", "json")
- query?.takeIf { it.isNotBlank() }?.let { parameter("query", it) }
- limit?.let { parameter("limit", it) }
- offset?.let { parameter("offset", it) }
- inc.toMusicbrainzInc()?.let { parameter("inc", it) }
- }
-
- return response.requireBody()
- }
-}
-
-class MusicbrainzApiException(
- val statusCode: Int,
- message: String,
-) : RuntimeException(message)
-
-private suspend fun HttpResponse.requireBody(): String {
- val text = bodyAsText()
- if (status.isSuccess()) return text
-
- throw MusicbrainzApiException(
- statusCode = status.value,
- message = "MusicBrainz request failed (${status.value}) for ${request.url}. Response: ${text.take(512)}"
- )
-}
-
-private fun List.toMusicbrainzInc(): String? {
- val cleaned = map { it.trim() }.filter { it.isNotBlank() }
- if (cleaned.isEmpty()) return null
- return cleaned.joinToString(separator = "+")
-}
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/wikidata/WikidataModels.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/wikidata/WikidataModels.kt
deleted file mode 100644
index 4f256aa6..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/wikidata/WikidataModels.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.wikidata
-
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.json.JsonElement
-
-@Serializable
-data class WikidataEntityValue(
- val value: String? = null
-)
-
-@Serializable
-data class WikidataEntityDataValue(
- val value: String? = null // It can be object but for P18 (image) it is string (filename)
-)
-
-@Serializable
-data class WikidataEntitySnak(
- val datavalue: WikidataEntityDataValue? = null
-)
-
-@Serializable
-data class WikidataEntityClaim(
- val mainsnak: WikidataEntitySnak? = null
-)
-
-@Serializable
-data class WikidataEntity(
- val id: String,
- val claims: Map>? = null
-)
-
-@Serializable
-data class WikidataEntitiesResponse(
- val entities: Map = emptyMap()
-)
-
-@Serializable
-data class WikimediaImageInfo(
- val thumburl: String? = null,
- val thumbwidth: Int? = null,
- val thumbheight: Int? = null,
- val url: String? = null,
- val width: Int? = null,
- val height: Int? = null
-)
-
-@Serializable
-data class WikimediaPage(
- val pageid: Long,
- val title: String,
- val imageinfo: List? = null
-)
-
-@Serializable
-data class WikimediaQuery(
- val pages: Map = emptyMap()
-)
-
-@Serializable
-data class WikimediaResponse(
- val query: WikimediaQuery? = null
-)
-
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/wikidata/WikidataRepository.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/wikidata/WikidataRepository.kt
deleted file mode 100644
index fad7f7bc..00000000
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/core/zipline/plugin_apis/musicbrainz_listenbrainz/wikidata/WikidataRepository.kt
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2026 Kingkor Roy Tirtho and Spotube Contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package dev.krtirtho.spotube.core.zipline.plugin_apis.musicbrainz_listenbrainz.wikidata
-
-import io.ktor.client.HttpClient
-import io.ktor.client.request.get
-import io.ktor.client.request.parameter
-import io.ktor.client.request.url
-import io.ktor.client.statement.bodyAsText
-import kotlinx.serialization.json.Json
-
-class WikidataRepository(private val httpClient: HttpClient) {
- private val json = Json {
- ignoreUnknownKeys = true
- isLenient = true
- }
-
- suspend fun getArtistImages(wikidataIds: List): Map {
- if (wikidataIds.isEmpty()) return emptyMap()
-
- try {
- // 1. Get image filenames from Wikidata
- val wikidataResponseText = httpClient.get {
- url("https://www.wikidata.org/w/api.php")
- parameter("format", "json")
- parameter("props", "claims")
- parameter("ids", wikidataIds.joinToString("|"))
- parameter("action", "wbgetentities")
- }.bodyAsText()
-
- val wikidataResponse = json.decodeFromString(wikidataResponseText)
-
- val idsWithImageNames = wikidataIds.map { id ->
- val imageName = wikidataResponse.entities[id]?.claims?.get("P18")?.firstOrNull()?.mainsnak?.datavalue?.value
- id to imageName
- }
-
- val imageNames = idsWithImageNames.mapNotNull { it.second }
- if (imageNames.isEmpty()) return wikidataIds.associateWith { null }
-
- val titles = imageNames.map { "File:$it" }.joinToString("|")
-
- // 2. Get image URLs from Wikimedia Commons
- val commonsResponseText = httpClient.get {
- url("https://commons.wikimedia.org/w/api.php")
- parameter("prop", "imageinfo")
- parameter("action", "query")
- parameter("iiprop", "url|size")
- parameter("iiurlheight", 300)
- parameter("iiurlwidth", 300)
- parameter("format", "json")
- parameter("titles", titles)
- }.bodyAsText()
-
- val commonsResponse = json.decodeFromString(commonsResponseText)
- val pages = commonsResponse.query?.pages?.values ?: emptyList()
-
- val imagesMap = mutableMapOf()
-
- // Initialize all with null
- wikidataIds.forEach { imagesMap[it] = null }
-
- for (page in pages) {
- val imageName = page.title.removePrefix("File:")
- val imageUrl = page.imageinfo?.firstOrNull()?.thumburl ?: page.imageinfo?.firstOrNull()?.url
-
- // Find original Wikidata ID for this image name
- val wikidataId = idsWithImageNames.firstOrNull { it.second == imageName }?.first
- if (wikidataId != null) {
- imagesMap[wikidataId] = imageUrl
- }
- }
-
- return imagesMap
- } catch (e: Exception) {
- e.printStackTrace()
- return wikidataIds.associateWith { null }
- }
- }
-}
-
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/plugin/BuiltInPlugins.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/plugin/BuiltInPlugins.kt
index a78069cf..6ab97e80 100644
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/plugin/BuiltInPlugins.kt
+++ b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/plugin/BuiltInPlugins.kt
@@ -29,20 +29,6 @@ val NEWPIPE_YOUTUBE_BUILT_IN_PLUGIN = PluginEntry(
),
abilities = listOf(PluginAbility.AUDIO)
)
-val MUSICBRAINZ_LISTENBRAINZ_BUILT_IN_PLUGIN = PluginEntry(
- name = "MusicBrainz ListenBrainz",
- version = "0.1.0",
- apiVersion = PLUGIN_API_VERSION,
- description = "MusicBrainz ListenBrainz plugin for scrobbling tracks and fetching metadata.",
- author = "Spotube Team",
- capabilities = listOf(
- PluginCapability.NETWORK_REQUESTS,
- PluginCapability.PERSISTENT_STORAGE,
- PluginCapability.WEBVIEW,
- ),
- abilities = listOf(PluginAbility.METADATA, PluginAbility.SCROBBLE)
-)
-
val LRCLIB_BUILT_IN_PLUGIN = PluginEntry(
name = "LRCLib Lyrics",
version = "0.1.0",
@@ -55,7 +41,6 @@ val LRCLIB_BUILT_IN_PLUGIN = PluginEntry(
abilities = listOf(PluginAbility.LYRICS)
)
val BUILT_IN_PLUGINS = listOf(
- MUSICBRAINZ_LISTENBRAINZ_BUILT_IN_PLUGIN,
NEWPIPE_YOUTUBE_BUILT_IN_PLUGIN,
LRCLIB_BUILT_IN_PLUGIN,
)
diff --git a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/plugin/PluginManager.kt b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/plugin/PluginManager.kt
index 39087d0b..767959d5 100644
--- a/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/plugin/PluginManager.kt
+++ b/composeApp/src/commonMain/kotlin/dev/krtirtho/spotube/modules/plugin/PluginManager.kt
@@ -103,8 +103,8 @@ class PluginManager(
.map { p ->
val json = p[DatabaseKeys.PLUGINS_STATE_KEY]
val defaultSelectedPlugins = mapOf(
- PluginAbility.METADATA to MUSICBRAINZ_LISTENBRAINZ_BUILT_IN_PLUGIN,
PluginAbility.AUDIO to NEWPIPE_YOUTUBE_BUILT_IN_PLUGIN,
+ PluginAbility.SCROBBLE to LRCLIB_BUILT_IN_PLUGIN,
)
if (json == null) {
PluginManagerStates.Data(
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index dbc5c8f1..99253336 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -67,7 +67,6 @@ material3-window-size = "1.9.0"
kotlinx-datetime = "0.7.1"
media3 = "1.8.0"
androidx-datastore = "1.2.1"
-kmpgen = "1.3.0"
ksp = "2.3.5"
spotube-gradle = "0.1.0"
cryptography = "0.6.0"
@@ -127,6 +126,8 @@ ktor-client-logging = { module = "io.ktor:ktor-client-logging", version.ref = "k
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "ktor" }
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
+ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
+ktor-client-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
@@ -171,7 +172,6 @@ kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", versio
jetbrainsKotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "jetbrainsKotlinJvm" }
androidKotlinMultiplatformLibrary = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
zipline-gradle-plugin = { id = "app.cash.zipline", version.ref = "ziplineVersion" }
-kmpgen = { id = "com.kroegerama.openapi-kmp-gen", version.ref = "kmpgen" }
mavenPublish = { id = "maven-publish" }
spotubeGradle = { id = "dev.krtirtho.spotube.gradle-plugin", version.ref = "spotube-gradle" }
vlcjBundler = { id = "dev.krtirtho.vlcj-bundler.gradle-plugin", version.ref = "vlcjBundler" }
\ No newline at end of file