mirror of
https://git.sr.ht/~phw/scotty
synced 2025-04-16 10:09:28 +02:00
Funkwhale: Implemented LovesExport
This commit is contained in:
parent
48c8843f91
commit
9316838d59
6 changed files with 446 additions and 13 deletions
|
@ -49,20 +49,39 @@ func NewClient(serverUrl string, token string) Client {
|
|||
return client
|
||||
}
|
||||
|
||||
func (c Client) GetHistoryListenings(user string, page int, perPage int) (ListeningsResult, error) {
|
||||
func (c Client) GetHistoryListenings(user string, page int, perPage int) (result ListeningsResult, err error) {
|
||||
const path = "/api/v1/history/listenings"
|
||||
result := &ListeningsResult{}
|
||||
response, err := c.HttpClient.R().
|
||||
SetQueryParams(map[string]string{
|
||||
"username": user,
|
||||
"page": strconv.Itoa(page),
|
||||
"page_size": strconv.Itoa(perPage),
|
||||
"ordering": "-creation_date",
|
||||
}).
|
||||
SetResult(result).
|
||||
SetResult(&result).
|
||||
Get(path)
|
||||
|
||||
if response.StatusCode() != 200 {
|
||||
return *result, errors.New(response.String())
|
||||
err = errors.New(response.String())
|
||||
return
|
||||
}
|
||||
return *result, err
|
||||
return
|
||||
}
|
||||
|
||||
func (c Client) GetFavoriteTracks(page int, perPage int) (result FavoriteTracksResult, err error) {
|
||||
const path = "/api/v1/favorites/tracks"
|
||||
response, err := c.HttpClient.R().
|
||||
SetQueryParams(map[string]string{
|
||||
"page": strconv.Itoa(page),
|
||||
"page_size": strconv.Itoa(perPage),
|
||||
"ordering": "-creation_date",
|
||||
}).
|
||||
SetResult(&result).
|
||||
Get(path)
|
||||
|
||||
if response.StatusCode() != 200 {
|
||||
err = errors.New(response.String())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ func TestGetHistoryListenings(t *testing.T) {
|
|||
|
||||
assert := assert.New(t)
|
||||
assert.Equal(2204, result.Count)
|
||||
require.Len(t, result.Results, 2)
|
||||
listen1 := result.Results[0]
|
||||
assert.Equal("2023-11-09T23:59:29.022005Z", listen1.CreationDate)
|
||||
assert.Equal("Way to Eden", listen1.Track.Title)
|
||||
|
@ -62,6 +63,30 @@ func TestGetHistoryListenings(t *testing.T) {
|
|||
assert.Equal("phw", listen1.User.UserName)
|
||||
}
|
||||
|
||||
func TestGetFavoriteTracks(t *testing.T) {
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
token := "thetoken"
|
||||
serverUrl := "https://funkwhale.example.com"
|
||||
client := funkwhale.NewClient(serverUrl, token)
|
||||
setupHttpMock(t, client.HttpClient.GetClient(),
|
||||
"https://funkwhale.example.com/api/v1/favorites/tracks",
|
||||
"testdata/favorite-tracks.json")
|
||||
|
||||
result, err := client.GetFavoriteTracks(0, 2)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert := assert.New(t)
|
||||
assert.Equal(76, result.Count)
|
||||
require.Len(t, result.Results, 2)
|
||||
fav1 := result.Results[0]
|
||||
assert.Equal("2023-11-05T20:32:32.339738Z", fav1.CreationDate)
|
||||
assert.Equal("Reign", fav1.Track.Title)
|
||||
assert.Equal("Home Economics", fav1.Track.Album.Title)
|
||||
assert.Equal("Prinzhorn Dance School", fav1.Track.Artist.Name)
|
||||
assert.Equal("phw", fav1.User.UserName)
|
||||
}
|
||||
|
||||
func setupHttpMock(t *testing.T, client *http.Client, url string, testDataPath string) {
|
||||
httpmock.ActivateNonDefault(client)
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ func (b FunkwhaleApiBackend) ExportListens(oldestTimestamp time.Time) ([]models.
|
|||
page := 1
|
||||
perPage := MaxItemsPerGet
|
||||
|
||||
listens := make([]models.Listen, 0)
|
||||
listens := make([]models.Listen, 0, 2*MaxItemsPerGet)
|
||||
|
||||
out:
|
||||
for {
|
||||
|
@ -64,7 +64,7 @@ out:
|
|||
}
|
||||
|
||||
for _, fwListen := range result.Results {
|
||||
listen := ListenFromFunkwhale(fwListen)
|
||||
listen := fwListen.ToListen()
|
||||
if listen.ListenedAt.Unix() > oldestTimestamp.Unix() {
|
||||
listens = append(listens, listen)
|
||||
} else {
|
||||
|
@ -84,10 +84,49 @@ out:
|
|||
return listens, nil
|
||||
}
|
||||
|
||||
func ListenFromFunkwhale(fwListen Listening) models.Listen {
|
||||
track := fwListen.Track
|
||||
func (b FunkwhaleApiBackend) ExportLoves(oldestTimestamp time.Time) ([]models.Love, error) {
|
||||
page := 1
|
||||
perPage := MaxItemsPerGet
|
||||
|
||||
loves := make([]models.Love, 0, 2*MaxItemsPerGet)
|
||||
|
||||
out:
|
||||
for {
|
||||
result, err := b.client.GetFavoriteTracks(page, perPage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
count := len(result.Results)
|
||||
if count == 0 {
|
||||
break out
|
||||
}
|
||||
|
||||
for _, favorite := range result.Results {
|
||||
love := favorite.ToLove()
|
||||
if love.Created.Unix() > oldestTimestamp.Unix() {
|
||||
loves = append(loves, love)
|
||||
} else {
|
||||
break out
|
||||
}
|
||||
}
|
||||
|
||||
if result.Next == "" {
|
||||
// No further results
|
||||
break out
|
||||
}
|
||||
|
||||
page += 1
|
||||
}
|
||||
|
||||
slices.Reverse(loves)
|
||||
return loves, nil
|
||||
}
|
||||
|
||||
func (l Listening) ToListen() models.Listen {
|
||||
track := l.Track
|
||||
listen := models.Listen{
|
||||
UserName: fwListen.User.UserName,
|
||||
UserName: l.User.UserName,
|
||||
Track: models.Track{
|
||||
TrackName: track.Title,
|
||||
ReleaseName: track.Album.Title,
|
||||
|
@ -103,7 +142,7 @@ func ListenFromFunkwhale(fwListen Listening) models.Listen {
|
|||
},
|
||||
}
|
||||
|
||||
listenedAt, err := time.Parse(time.RFC3339, fwListen.CreationDate)
|
||||
listenedAt, err := time.Parse(time.RFC3339, l.CreationDate)
|
||||
if err == nil {
|
||||
listen.ListenedAt = listenedAt
|
||||
}
|
||||
|
@ -114,3 +153,36 @@ func ListenFromFunkwhale(fwListen Listening) models.Listen {
|
|||
|
||||
return listen
|
||||
}
|
||||
|
||||
func (f FavoriteTrack) ToLove() models.Love {
|
||||
track := f.Track
|
||||
recordingMbid := models.MBID(track.RecordingMbid)
|
||||
love := models.Love{
|
||||
UserName: f.User.UserName,
|
||||
RecordingMbid: recordingMbid,
|
||||
Track: models.Track{
|
||||
TrackName: track.Title,
|
||||
ReleaseName: track.Album.Title,
|
||||
ArtistNames: []string{track.Artist.Name},
|
||||
TrackNumber: track.Position,
|
||||
RecordingMbid: recordingMbid,
|
||||
ReleaseMbid: models.MBID(track.Album.ReleaseMbid),
|
||||
ArtistMbids: []models.MBID{models.MBID(track.Artist.ArtistMbid)},
|
||||
Tags: track.Tags,
|
||||
AdditionalInfo: map[string]any{
|
||||
"media_player": FunkwhaleClientName,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
created, err := time.Parse(time.RFC3339, f.CreationDate)
|
||||
if err == nil {
|
||||
love.Created = created
|
||||
}
|
||||
|
||||
if len(track.Uploads) > 0 {
|
||||
love.Track.Duration = time.Duration(track.Uploads[0].Duration * int(time.Second))
|
||||
}
|
||||
|
||||
return love
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
"go.uploadedlobster.com/scotty/models"
|
||||
)
|
||||
|
||||
func TestListenFromFunkwhale(t *testing.T) {
|
||||
func TestFunkwhaleListeningToListen(t *testing.T) {
|
||||
fwListen := funkwhale.Listening{
|
||||
CreationDate: "2023-11-09T23:59:29.022005Z",
|
||||
User: funkwhale.User{
|
||||
|
@ -57,7 +57,7 @@ func TestListenFromFunkwhale(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
listen := funkwhale.ListenFromFunkwhale(fwListen)
|
||||
listen := fwListen.ToListen()
|
||||
assert.Equal(t, time.Unix(1699574369, 0).Unix(), listen.ListenedAt.Unix())
|
||||
assert.Equal(t, fwListen.User.UserName, listen.UserName)
|
||||
assert.Equal(t, time.Duration(414*time.Second), listen.Duration)
|
||||
|
@ -72,3 +72,45 @@ func TestListenFromFunkwhale(t *testing.T) {
|
|||
assert.Equal(t, models.MBID(fwListen.Track.Artist.ArtistMbid), listen.ArtistMbids[0])
|
||||
assert.Equal(t, funkwhale.FunkwhaleClientName, listen.AdditionalInfo["media_player"])
|
||||
}
|
||||
|
||||
func TestFunkwhaleFavoriteTrackToLove(t *testing.T) {
|
||||
favorite := funkwhale.FavoriteTrack{
|
||||
CreationDate: "2023-11-09T23:59:29.022005Z",
|
||||
User: funkwhale.User{
|
||||
UserName: "outsidecontext",
|
||||
},
|
||||
Track: funkwhale.Track{
|
||||
Title: "Oweynagat",
|
||||
RecordingMbid: "c0a1fc94-5f04-4a5f-bc09-e5de0c49cd12",
|
||||
Position: 5,
|
||||
DiscNumber: 1,
|
||||
Tags: []string{"foo", "bar"},
|
||||
Artist: funkwhale.Artist{
|
||||
Name: "Dool",
|
||||
ArtistMbid: "24412926-c7bd-48e8-afad-8a285b42e131",
|
||||
},
|
||||
Album: funkwhale.Album{
|
||||
Title: "Here Now, There Then",
|
||||
ReleaseMbid: "d7f22677-9803-4d21-ba42-081b633a6f68",
|
||||
},
|
||||
Uploads: []funkwhale.Upload{
|
||||
{
|
||||
Duration: 414,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
love := favorite.ToLove()
|
||||
assert.Equal(t, time.Unix(1699574369, 0).Unix(), love.Created.Unix())
|
||||
assert.Equal(t, favorite.User.UserName, love.UserName)
|
||||
assert.Equal(t, time.Duration(414*time.Second), love.Duration)
|
||||
assert.Equal(t, favorite.Track.Title, love.TrackName)
|
||||
assert.Equal(t, favorite.Track.Album.Title, love.ReleaseName)
|
||||
assert.Equal(t, []string{favorite.Track.Artist.Name}, love.ArtistNames)
|
||||
assert.Equal(t, favorite.Track.Position, love.Track.TrackNumber)
|
||||
assert.Equal(t, favorite.Track.Tags, love.Track.Tags)
|
||||
assert.Equal(t, models.MBID(favorite.Track.RecordingMbid), love.RecordingMbid)
|
||||
assert.Equal(t, models.MBID(favorite.Track.Album.ReleaseMbid), love.ReleaseMbid)
|
||||
assert.Equal(t, models.MBID(favorite.Track.Artist.ArtistMbid), love.ArtistMbids[0])
|
||||
assert.Equal(t, funkwhale.FunkwhaleClientName, love.AdditionalInfo["media_player"])
|
||||
}
|
||||
|
|
|
@ -35,6 +35,20 @@ type Listening struct {
|
|||
CreationDate string `json:"creation_date"`
|
||||
}
|
||||
|
||||
type FavoriteTracksResult struct {
|
||||
Count int `json:"count"`
|
||||
Previous string `json:"previous"`
|
||||
Next string `json:"next"`
|
||||
Results []FavoriteTrack `json:"results"`
|
||||
}
|
||||
|
||||
type FavoriteTrack struct {
|
||||
Id int `json:"int"`
|
||||
User User `json:"user"`
|
||||
Track Track `json:"track"`
|
||||
CreationDate string `json:"creation_date"`
|
||||
}
|
||||
|
||||
type Track struct {
|
||||
Id int `json:"int"`
|
||||
Artist Artist `json:"artist"`
|
||||
|
|
261
backends/funkwhale/testdata/favorite-tracks.json
vendored
Normal file
261
backends/funkwhale/testdata/favorite-tracks.json
vendored
Normal file
|
@ -0,0 +1,261 @@
|
|||
{
|
||||
"count": 76,
|
||||
"next": "https://music.uploadedlobster.com/api/v1/favorites/tracks/?page=2&page_size=2",
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 80,
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "phw",
|
||||
"name": "",
|
||||
"date_joined": "2020-11-13T16:22:52.464109Z",
|
||||
"avatar": {
|
||||
"uuid": "8f87ca98-fe9e-4f7e-aa54-aa8276c25fd4",
|
||||
"size": 262868,
|
||||
"mimetype": "image/png",
|
||||
"creation_date": "2021-08-30T12:02:20.962405Z",
|
||||
"urls": {
|
||||
"source": null,
|
||||
"original": "https://music.uploadedlobster.com/media/attachments/4b/e2/c3/canned-ape.png",
|
||||
"medium_square_crop": "https://music.uploadedlobster.com/media/__sized__/attachments/4b/e2/c3/canned-ape-crop-c0-5__0-5-200x200.png",
|
||||
"large_square_crop": "https://music.uploadedlobster.com/media/__sized__/attachments/4b/e2/c3/canned-ape-crop-c0-5__0-5-600x600.png"
|
||||
}
|
||||
}
|
||||
},
|
||||
"track": {
|
||||
"artist": {
|
||||
"id": 211,
|
||||
"fid": "https://music.uploadedlobster.com/federation/music/artists/92ab65ce-95d4-405f-a162-959e9a69ec3e",
|
||||
"mbid": "a1f2450a-c076-4a0d-ac9c-764bfc4225f7",
|
||||
"name": "Prinzhorn Dance School",
|
||||
"creation_date": "2020-11-14T08:27:27.964479Z",
|
||||
"modification_date": "2020-11-14T08:27:27.964602Z",
|
||||
"is_local": true,
|
||||
"content_category": "music",
|
||||
"description": null,
|
||||
"attachment_cover": null,
|
||||
"channel": null
|
||||
},
|
||||
"album": {
|
||||
"id": 237,
|
||||
"fid": "https://music.uploadedlobster.com/federation/music/albums/d301df18-c0b0-4608-8c68-bba86a65eabc",
|
||||
"mbid": "7cb1093c-bfa5-4ffc-b3ac-943fb5c7f39f",
|
||||
"title": "Home Economics",
|
||||
"artist": {
|
||||
"id": 211,
|
||||
"fid": "https://music.uploadedlobster.com/federation/music/artists/92ab65ce-95d4-405f-a162-959e9a69ec3e",
|
||||
"mbid": "a1f2450a-c076-4a0d-ac9c-764bfc4225f7",
|
||||
"name": "Prinzhorn Dance School",
|
||||
"creation_date": "2020-11-14T08:27:27.964479Z",
|
||||
"modification_date": "2020-11-14T08:27:27.964602Z",
|
||||
"is_local": true,
|
||||
"content_category": "music",
|
||||
"description": null,
|
||||
"attachment_cover": null,
|
||||
"channel": null
|
||||
},
|
||||
"release_date": "2015-06-08",
|
||||
"cover": {
|
||||
"uuid": "e2022441-b120-431d-912c-aa930c668cd5",
|
||||
"size": 279103,
|
||||
"mimetype": "image/jpeg",
|
||||
"creation_date": "2023-03-30T07:51:33.366860Z",
|
||||
"urls": {
|
||||
"source": null,
|
||||
"original": "https://music.uploadedlobster.com/media/attachments/98/0a/af/attachment_cover-d301df18-c0b0-4608-8c68-bba86a65eabc.jpg",
|
||||
"medium_square_crop": "https://music.uploadedlobster.com/media/__sized__/attachments/98/0a/af/attachment_cover-d301df18-c0b0-4608-8c68-bba86a65eabc-crop-c0-5__0-5-200x200-95.jpg",
|
||||
"large_square_crop": "https://music.uploadedlobster.com/media/__sized__/attachments/98/0a/af/attachment_cover-d301df18-c0b0-4608-8c68-bba86a65eabc-crop-c0-5__0-5-600x600-95.jpg"
|
||||
}
|
||||
},
|
||||
"creation_date": "2020-11-14T08:27:28.805848Z",
|
||||
"is_local": true,
|
||||
"tracks_count": 6
|
||||
},
|
||||
"uploads": [
|
||||
{
|
||||
"uuid": "6647a0d0-5119-4dd0-bf1f-dfc64a1d956c",
|
||||
"listen_url": "/api/v1/listen/b4cb522f-ce1b-49fb-81b8-0cc0d1cb5495/?upload=6647a0d0-5119-4dd0-bf1f-dfc64a1d956c",
|
||||
"size": 11147671,
|
||||
"duration": 271,
|
||||
"bitrate": 320000,
|
||||
"mimetype": "audio/mpeg",
|
||||
"extension": "mp3",
|
||||
"is_local": true
|
||||
}
|
||||
],
|
||||
"listen_url": "/api/v1/listen/b4cb522f-ce1b-49fb-81b8-0cc0d1cb5495/",
|
||||
"tags": [],
|
||||
"attributed_to": {
|
||||
"fid": "https://music.uploadedlobster.com/federation/actors/phw",
|
||||
"url": null,
|
||||
"creation_date": "2020-11-13T16:54:45.182645Z",
|
||||
"summary": null,
|
||||
"preferred_username": "phw",
|
||||
"name": "phw",
|
||||
"last_fetch_date": "2020-11-13T16:54:45.182661Z",
|
||||
"domain": "music.uploadedlobster.com",
|
||||
"type": "Person",
|
||||
"manually_approves_followers": false,
|
||||
"full_username": "phw@music.uploadedlobster.com",
|
||||
"is_local": true
|
||||
},
|
||||
"id": 2833,
|
||||
"fid": "https://music.uploadedlobster.com/federation/music/tracks/b4cb522f-ce1b-49fb-81b8-0cc0d1cb5495",
|
||||
"mbid": "b59cf4e7-caee-4019-a844-79d2c58d4dff",
|
||||
"title": "Reign",
|
||||
"creation_date": "2020-11-14T08:27:28.954529Z",
|
||||
"is_local": true,
|
||||
"position": 1,
|
||||
"disc_number": 1,
|
||||
"downloads_count": 3,
|
||||
"copyright": null,
|
||||
"license": null,
|
||||
"cover": null,
|
||||
"is_playable": true
|
||||
},
|
||||
"creation_date": "2023-11-05T20:32:32.339738Z",
|
||||
"actor": {
|
||||
"fid": "https://music.uploadedlobster.com/federation/actors/phw",
|
||||
"url": null,
|
||||
"creation_date": "2020-11-13T16:54:45.182645Z",
|
||||
"summary": null,
|
||||
"preferred_username": "phw",
|
||||
"name": "phw",
|
||||
"last_fetch_date": "2020-11-13T16:54:45.182661Z",
|
||||
"domain": "music.uploadedlobster.com",
|
||||
"type": "Person",
|
||||
"manually_approves_followers": false,
|
||||
"full_username": "phw@music.uploadedlobster.com",
|
||||
"is_local": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 79,
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "phw",
|
||||
"name": "",
|
||||
"date_joined": "2020-11-13T16:22:52.464109Z",
|
||||
"avatar": {
|
||||
"uuid": "8f87ca98-fe9e-4f7e-aa54-aa8276c25fd4",
|
||||
"size": 262868,
|
||||
"mimetype": "image/png",
|
||||
"creation_date": "2021-08-30T12:02:20.962405Z",
|
||||
"urls": {
|
||||
"source": null,
|
||||
"original": "https://music.uploadedlobster.com/media/attachments/4b/e2/c3/canned-ape.png",
|
||||
"medium_square_crop": "https://music.uploadedlobster.com/media/__sized__/attachments/4b/e2/c3/canned-ape-crop-c0-5__0-5-200x200.png",
|
||||
"large_square_crop": "https://music.uploadedlobster.com/media/__sized__/attachments/4b/e2/c3/canned-ape-crop-c0-5__0-5-600x600.png"
|
||||
}
|
||||
}
|
||||
},
|
||||
"track": {
|
||||
"artist": {
|
||||
"id": 3800,
|
||||
"fid": "https://music.uploadedlobster.com/federation/music/artists/2ef92f34-f4bc-4bf5-85de-a6847ea51a62",
|
||||
"mbid": "055b6082-b9cc-4688-85c4-8153c0ef2d70",
|
||||
"name": "Crippled Black Phoenix",
|
||||
"creation_date": "2023-07-19T06:39:22.078159Z",
|
||||
"modification_date": "2023-07-19T06:39:22.078238Z",
|
||||
"is_local": true,
|
||||
"content_category": "music",
|
||||
"description": null,
|
||||
"attachment_cover": null,
|
||||
"channel": null
|
||||
},
|
||||
"album": {
|
||||
"id": 2684,
|
||||
"fid": "https://music.uploadedlobster.com/federation/music/albums/138bd960-8e94-4794-adaa-51de5fba33c3",
|
||||
"mbid": "97509ec0-93cc-47ca-9033-1ac27678d799",
|
||||
"title": "Ellengæst",
|
||||
"artist": {
|
||||
"id": 3800,
|
||||
"fid": "https://music.uploadedlobster.com/federation/music/artists/2ef92f34-f4bc-4bf5-85de-a6847ea51a62",
|
||||
"mbid": "055b6082-b9cc-4688-85c4-8153c0ef2d70",
|
||||
"name": "Crippled Black Phoenix",
|
||||
"creation_date": "2023-07-19T06:39:22.078159Z",
|
||||
"modification_date": "2023-07-19T06:39:22.078238Z",
|
||||
"is_local": true,
|
||||
"content_category": "music",
|
||||
"description": null,
|
||||
"attachment_cover": null,
|
||||
"channel": null
|
||||
},
|
||||
"release_date": "2020-11-04",
|
||||
"cover": {
|
||||
"uuid": "2c191778-0c1c-467e-9bf1-9949e3d98507",
|
||||
"size": 129633,
|
||||
"mimetype": "image/jpeg",
|
||||
"creation_date": "2023-07-19T06:39:22.102600Z",
|
||||
"urls": {
|
||||
"source": null,
|
||||
"original": "https://music.uploadedlobster.com/media/attachments/e5/d6/bf/attachment_cover-138bd960-8e94-4794-adaa-51de5fba33c3.jpg",
|
||||
"medium_square_crop": "https://music.uploadedlobster.com/media/__sized__/attachments/e5/d6/bf/attachment_cover-138bd960-8e94-4794-adaa-51de5fba33c3-crop-c0-5__0-5-200x200-95.jpg",
|
||||
"large_square_crop": "https://music.uploadedlobster.com/media/__sized__/attachments/e5/d6/bf/attachment_cover-138bd960-8e94-4794-adaa-51de5fba33c3-crop-c0-5__0-5-600x600-95.jpg"
|
||||
}
|
||||
},
|
||||
"creation_date": "2023-07-19T06:39:22.094428Z",
|
||||
"is_local": true,
|
||||
"tracks_count": 8
|
||||
},
|
||||
"uploads": [
|
||||
{
|
||||
"uuid": "f28de29b-6928-4879-a9da-32dcf9dd5ee4",
|
||||
"listen_url": "/api/v1/listen/9263d5c0-dee3-4273-beef-7585e1d0041a/?upload=f28de29b-6928-4879-a9da-32dcf9dd5ee4",
|
||||
"size": 12065231,
|
||||
"duration": 491,
|
||||
"bitrate": 0,
|
||||
"mimetype": "audio/opus",
|
||||
"extension": "opus",
|
||||
"is_local": true
|
||||
}
|
||||
],
|
||||
"listen_url": "/api/v1/listen/9263d5c0-dee3-4273-beef-7585e1d0041a/",
|
||||
"tags": [],
|
||||
"attributed_to": {
|
||||
"fid": "https://music.uploadedlobster.com/federation/actors/phw",
|
||||
"url": null,
|
||||
"creation_date": "2020-11-13T16:54:45.182645Z",
|
||||
"summary": null,
|
||||
"preferred_username": "phw",
|
||||
"name": "phw",
|
||||
"last_fetch_date": "2020-11-13T16:54:45.182661Z",
|
||||
"domain": "music.uploadedlobster.com",
|
||||
"type": "Person",
|
||||
"manually_approves_followers": false,
|
||||
"full_username": "phw@music.uploadedlobster.com",
|
||||
"is_local": true
|
||||
},
|
||||
"id": 28095,
|
||||
"fid": "https://music.uploadedlobster.com/federation/music/tracks/9263d5c0-dee3-4273-beef-7585e1d0041a",
|
||||
"mbid": "14d612f0-4022-4adc-8cef-87a569e2d65c",
|
||||
"title": "Lost",
|
||||
"creation_date": "2023-07-19T06:39:22.459072Z",
|
||||
"is_local": true,
|
||||
"position": 2,
|
||||
"disc_number": 1,
|
||||
"downloads_count": 2,
|
||||
"copyright": null,
|
||||
"license": null,
|
||||
"cover": null,
|
||||
"is_playable": true
|
||||
},
|
||||
"creation_date": "2023-10-25T16:14:36.112517Z",
|
||||
"actor": {
|
||||
"fid": "https://music.uploadedlobster.com/federation/actors/phw",
|
||||
"url": null,
|
||||
"creation_date": "2020-11-13T16:54:45.182645Z",
|
||||
"summary": null,
|
||||
"preferred_username": "phw",
|
||||
"name": "phw",
|
||||
"last_fetch_date": "2020-11-13T16:54:45.182661Z",
|
||||
"domain": "music.uploadedlobster.com",
|
||||
"type": "Person",
|
||||
"manually_approves_followers": false,
|
||||
"full_username": "phw@music.uploadedlobster.com",
|
||||
"is_local": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Add table
Reference in a new issue