diff --git a/api/funkwhale_api/radios/radios.py b/api/funkwhale_api/radios/radios.py index a85111983..5f37dc7e4 100644 --- a/api/funkwhale_api/radios/radios.py +++ b/api/funkwhale_api/radios/radios.py @@ -278,7 +278,7 @@ class LessListenedRadio(SessionRadio): ) -@registry.register(name="actor_content") +@registry.register(name="actor-content") class ActorContentRadio(RelatedObjectRadio): """ Play content from given actor libraries diff --git a/api/tests/radios/test_radios.py b/api/tests/radios/test_radios.py index 38a1ac831..f64fcac5f 100644 --- a/api/tests/radios/test_radios.py +++ b/api/tests/radios/test_radios.py @@ -248,7 +248,7 @@ def test_can_start_actor_content_radio(factories): session = radio.start_session( actor_library.actor.user, related_object=actor_library.actor ) - assert session.radio_type == "actor_content" + assert session.radio_type == "actor-content" for i in range(3): assert radio.pick() in good_tracks @@ -261,14 +261,14 @@ def test_can_start_actor_content_radio_from_api( url = reverse("api:v1:radios:sessions-list") response = logged_in_api_client.post( - url, {"radio_type": "actor_content", "related_object_id": actor.full_username} + url, {"radio_type": "actor-content", "related_object_id": actor.full_username} ) assert response.status_code == 201 session = models.RadioSession.objects.latest("id") - assert session.radio_type == "actor_content" + assert session.radio_type == "actor-content" assert session.related_object == actor diff --git a/docs/api/definitions.yml b/docs/api/definitions.yml index 6cc41dccb..249eb7a75 100644 --- a/docs/api/definitions.yml +++ b/docs/api/definitions.yml @@ -462,6 +462,36 @@ AlbumTrack: description: "List of uploads associated with this track" items: $ref: "#/Upload" + + +ListeningCreate: + type: "object" + properties: + id: + type: "integer" + format: "int64" + example: 66 + creation_date: + $ref: "./properties.yml#creation_date" + track: + type: "integer" + format: "int64" + example: 94 + +Listening: + type: "object" + properties: + id: + type: "integer" + format: "int64" + example: 66 + creation_date: + $ref: "./properties.yml#creation_date" + track: + $ref: "#/Track" + actor: + $ref: "#/Actor" + Track: type: "object" allOf: @@ -818,6 +848,37 @@ Permissions: type: "boolean" example: false description: A boolean indicating if the user can manage instance settings and users + +RadioSessionCreate: + type: "object" + properties: + radio_type: + type: "string" + description: | + The type of radio to start. Depending of the type, the `related_object_id` field + will need to be set to a non null value: + + - tag: tag `name` + - artist: artist `id` + - library: library `uuid` + + enum: + - random + - favorites + - tag + - similar + - artist + - less-listened + - actor-content + - library + + related_object_id: + type: string + default: null + description: + Value may be an integer depending of the `radio_type`. + Please refer to the `radio_type` documentation. + RateLimitStatus: type: "object" properties: diff --git a/docs/swagger.yml b/docs/swagger.yml index e2d364d25..e4b5563d4 100644 --- a/docs/swagger.yml +++ b/docs/swagger.yml @@ -1,14 +1,10 @@ -# Undocumented endpoints: -# /api/v1/radios -# /api/v1/history - openapi: "3.0.2" info: description: | Interactive documentation for [Funkwhale](https://funkwhale.audio) API. - The API is **not** freezed yet, but we will document breaking changes in our changelog, - and try to avoid those as much as possible. + Backward compatibility between minor versions (1.X to 1.Y) is guaranteed for all the + endpoints documented here. Usage ----- @@ -193,6 +189,8 @@ tags: url: https://docs.funkwhale.audio/users/upload.html#using-a-channel - name: Content curation description: Favorites, playlists, radios + - name: User activity + description: Listenings - name: Other description: Other endpoints that don't fit in the categories above @@ -1335,9 +1333,60 @@ paths: 204: $ref: "#/responses/204" + + ################# + # User activity # + ################# + + /api/v1/history/listenings: + get: + tags: + - "User activity" + parameters: + - $ref: "./api/parameters.yml#/Search" + - $ref: "./api/parameters.yml#/PageNumber" + - $ref: "./api/parameters.yml#/PageSize" + - $ref: "./api/parameters.yml#/Scope" + + responses: + 200: + content: + application/json: + schema: + allOf: + - $ref: "./api/definitions.yml#/ResultPage" + - type: "object" + properties: + results: + type: "array" + items: + $ref: "./api/definitions.yml#/Listening" + post: + summary: Record a track in your history + tags: + - "User activity" + requestBody: + required: true + content: + application/json: + schema: + type: "object" + properties: + track: + type: "integer" + format: "int64" + example: 98 + responses: + 201: + content: + application/json: + schema: + $ref: "./api/definitions.yml#/ListeningCreate" + ########## # Others # ########## + /api/v1/search: get: tags: @@ -1696,6 +1745,38 @@ paths: - "Content curation" responses: 204: + /api/v1/radios/sessions: + post: + tags: + - "Content curation" + description: Start a new radio session + responses: + 201: + $ref: "#/responses/201" + 400: + $ref: "#/responses/400" + requestBody: + required: true + content: + application/json: + schema: + $ref: "./api/definitions.yml#/RadioSessionCreate" + /api/v1/radios/tracks: + post: + tags: + - "Content curation" + description: Get a new track for a radio session + responses: + 201: + $ref: "#/responses/201" + 400: + $ref: "#/responses/400" + requestBody: + required: true + content: + application/json: + schema: + $ref: "./api/definitions.yml#/Track" responses: 200: description: Success diff --git a/front/src/components/library/Radios.vue b/front/src/components/library/Radios.vue index f96c25272..fb0467192 100644 --- a/front/src/components/library/Radios.vue +++ b/front/src/components/library/Radios.vue @@ -10,7 +10,7 @@ Instance radios
- + diff --git a/front/src/store/radios.js b/front/src/store/radios.js index d07ad59cb..9cd48e769 100644 --- a/front/src/store/radios.js +++ b/front/src/store/radios.js @@ -12,7 +12,7 @@ export default { getters: { types: state => { return { - actor_content: { + 'actor-content': { name: 'Your content', description: "Picks from your own libraries" },