mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2024-11-22 04:58:01 +01:00
#58: Implemented a more stable and useful track details endpoint.
This commit is contained in:
parent
29cd3de86e
commit
dba9ae1b15
5 changed files with 177 additions and 42 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pony.fm - A community for pony fan music.
|
* Pony.fm - A community for pony fan music.
|
||||||
* Copyright (C) 2015 Peter Deltchev
|
* Copyright (C) 2015-2017 Peter Deltchev
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
@ -75,38 +75,59 @@ class TracksController extends ApiControllerBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a stable representation of a track for the API. This is very
|
||||||
|
* similar to the radio representation below but finds tracks by ID and is
|
||||||
|
* expected to be more stable.
|
||||||
|
*
|
||||||
|
* @param int $id track ID
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
|
public function getTrackDetails($id) {
|
||||||
|
/** @var Track|null $track */
|
||||||
|
$track = Track
|
||||||
|
::with('user', 'album', 'user.avatar', 'cover', 'genre')
|
||||||
|
->published()
|
||||||
|
->where('id', $id)->first();
|
||||||
|
|
||||||
|
if (!$track) {
|
||||||
|
return Response::json(['message' => 'Track not found.'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response::json(static::trackToJson($track, false, true), 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a serialized version of a track for use by radios.
|
||||||
|
*
|
||||||
|
* @deprecated in favour of getTrackDetails
|
||||||
|
* @param $hash
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
|
*/
|
||||||
public function getTrackRadioDetails($hash)
|
public function getTrackRadioDetails($hash)
|
||||||
{
|
{
|
||||||
|
/** @var Track|null $track */
|
||||||
$track = Track
|
$track = Track
|
||||||
::with('user', 'album', 'user.avatar', 'cover', 'comments', 'genre')
|
::with('user', 'album', 'user.avatar', 'cover', 'comments', 'genre')
|
||||||
->published()
|
->published()
|
||||||
->whereHash($hash)->first();
|
->where('hash', $hash)->first();
|
||||||
|
|
||||||
if (!$track) {
|
if (!$track) {
|
||||||
return Response::json(['message' => 'Track not found.'], 403);
|
return Response::json(['message' => 'Track not found.'], 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
$comments = [];
|
return Response::json(static::trackToJson($track, true, false), 200);
|
||||||
foreach ($track->comments as $comment) {
|
}
|
||||||
$comments[] = [
|
|
||||||
'id' => $comment->id,
|
|
||||||
'created_at' => $comment->created_at,
|
|
||||||
'content' => $comment->content,
|
|
||||||
'user' => [
|
|
||||||
'name' => $comment->user->display_name,
|
|
||||||
'id' => $comment->user->id,
|
|
||||||
'url' => $comment->user->url,
|
|
||||||
'avatars' => [
|
|
||||||
'normal' => $comment->user->getAvatarUrl(Image::NORMAL),
|
|
||||||
'thumbnail' => $comment->user->getAvatarUrl(Image::THUMBNAIL),
|
|
||||||
'small' => $comment->user->getAvatarUrl(Image::SMALL),
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return Response::json([
|
/**
|
||||||
|
* Helper method to form the serialized version of a track for the V1 API.
|
||||||
|
*
|
||||||
|
* @param Track $track
|
||||||
|
* @param bool $includeComments if true, includes the track's comments in the serialization
|
||||||
|
* @return array serialized track
|
||||||
|
*/
|
||||||
|
private static function trackToJson(Track $track, bool $includeComments, bool $includeStreamUrl) {
|
||||||
|
$trackResponse = [
|
||||||
'id' => $track->id,
|
'id' => $track->id,
|
||||||
'title' => $track->title,
|
'title' => $track->title,
|
||||||
'description' => $track->description,
|
'description' => $track->description,
|
||||||
|
@ -141,19 +162,52 @@ class TracksController extends ApiControllerBase
|
||||||
'name' => $track->genre->name
|
'name' => $track->genre->name
|
||||||
] : null,
|
] : null,
|
||||||
'type' => [
|
'type' => [
|
||||||
'id' => $track->track_type->id,
|
'id' => $track->trackType->id,
|
||||||
'name' => $track->track_type->title
|
'name' => $track->trackType->title
|
||||||
],
|
],
|
||||||
'covers' => [
|
'covers' => [
|
||||||
'thumbnail' => $track->getCoverUrl(Image::THUMBNAIL),
|
'thumbnail' => $track->getCoverUrl(Image::THUMBNAIL),
|
||||||
'small' => $track->getCoverUrl(Image::SMALL),
|
'small' => $track->getCoverUrl(Image::SMALL),
|
||||||
'normal' => $track->getCoverUrl(Image::NORMAL)
|
'normal' => $track->getCoverUrl(Image::NORMAL)
|
||||||
],
|
],
|
||||||
'comments' => $comments,
|
|
||||||
|
|
||||||
// As of 2015-10-28, this should be expected to produce either
|
// As of 2017-10-28, this should be expected to produce
|
||||||
// "direct_upload" or "mlpma" for all tracks.
|
// "direct_upload", "mlpma", or "eqbeats" for all tracks.
|
||||||
'source' => $track->source
|
'source' => $track->source
|
||||||
], 200);
|
];
|
||||||
|
|
||||||
|
if ($includeComments) {
|
||||||
|
$comments = [];
|
||||||
|
foreach ($track->comments as $comment) {
|
||||||
|
$comments[] = [
|
||||||
|
'id' => $comment->id,
|
||||||
|
'created_at' => $comment->created_at,
|
||||||
|
'content' => $comment->content,
|
||||||
|
'user' => [
|
||||||
|
'name' => $comment->user->display_name,
|
||||||
|
'id' => $comment->user->id,
|
||||||
|
'url' => $comment->user->url,
|
||||||
|
'avatars' => [
|
||||||
|
'normal' => $comment->user->getAvatarUrl(Image::NORMAL),
|
||||||
|
'thumbnail' => $comment->user->getAvatarUrl(Image::THUMBNAIL),
|
||||||
|
'small' => $comment->user->getAvatarUrl(Image::SMALL),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$trackResponse['comments'] = $comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($includeStreamUrl) {
|
||||||
|
$trackResponse['streams'] = [
|
||||||
|
'mp3' => [
|
||||||
|
'url' => $track->getStreamUrl('MP3', session('api_client_id')),
|
||||||
|
'mime_type' => Track::$Formats['MP3']['mime_type'],
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $trackResponse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pony.fm - A community for pony fan music.
|
* Pony.fm - A community for pony fan music.
|
||||||
* Copyright (C) 2015 Peter Deltchev
|
* Copyright (C) 2015-2017 Peter Deltchev
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
@ -890,11 +890,19 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
* be used by the on-site player.
|
* be used by the on-site player.
|
||||||
*
|
*
|
||||||
* @param string $format one of the format keys from the `$Formats` array
|
* @param string $format one of the format keys from the `$Formats` array
|
||||||
|
* @param string $apiClientId if a URL is being requested for the third-party
|
||||||
|
* API, this should be set to the requesting app's
|
||||||
|
* client ID.
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getStreamUrl($format = 'MP3')
|
public function getStreamUrl(string $format = 'MP3', string $apiClientId = null)
|
||||||
{
|
{
|
||||||
return action('TracksController@getStream', ['id' => $this->id, 'extension' => self::$Formats[$format]['extension']]);
|
return action('TracksController@getStream',
|
||||||
|
[
|
||||||
|
'id' => $this->id,
|
||||||
|
'extension' => self::$Formats[$format]['extension']
|
||||||
|
] + ($apiClientId !== null ? ['api_client_id' => $apiClientId] : [])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pony.fm - A community for pony fan music.
|
* Pony.fm - A community for pony fan music.
|
||||||
* Copyright (C) 2015 Peter Deltchev
|
* Copyright (C) 2015-2017 Peter Deltchev
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
@ -52,9 +52,8 @@ $factory->define(\Poniverse\Ponyfm\Models\Track::class, function(\Faker\Generato
|
||||||
'user_id' => $user->id,
|
'user_id' => $user->id,
|
||||||
'hash' => $faker->md5,
|
'hash' => $faker->md5,
|
||||||
'title' => $faker->sentence(5),
|
'title' => $faker->sentence(5),
|
||||||
|
'slug' => $faker->slug,
|
||||||
'track_type_id' => \Poniverse\Ponyfm\Models\TrackType::UNCLASSIFIED_TRACK,
|
'track_type_id' => \Poniverse\Ponyfm\Models\TrackType::UNCLASSIFIED_TRACK,
|
||||||
'genre' => $faker->word,
|
|
||||||
'album' => $faker->sentence(5),
|
|
||||||
'track_number' => null,
|
'track_number' => null,
|
||||||
'description' => $faker->paragraph(5),
|
'description' => $faker->paragraph(5),
|
||||||
'lyrics' => $faker->paragraph(5),
|
'lyrics' => $faker->paragraph(5),
|
||||||
|
@ -62,6 +61,39 @@ $factory->define(\Poniverse\Ponyfm\Models\Track::class, function(\Faker\Generato
|
||||||
'is_explicit' => false,
|
'is_explicit' => false,
|
||||||
'is_downloadable' => true,
|
'is_downloadable' => true,
|
||||||
'is_listed' => true,
|
'is_listed' => true,
|
||||||
'metadata' => '{"this":{"is":["very","random","metadata"]}}'
|
'metadata' => '{"this":{"is":["very","random","metadata"]}}',
|
||||||
|
'duration' => $faker->randomFloat(null, 30, 600)
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
$factory->define(\Poniverse\Ponyfm\Models\Genre::class, function(\Faker\Generator $faker) {
|
||||||
|
return [
|
||||||
|
'name' => $faker->word,
|
||||||
|
'slug' => $faker->slug,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @property integer $id
|
||||||
|
* @property integer $user_id
|
||||||
|
* @property string $title
|
||||||
|
* @property string $slug
|
||||||
|
* @property string $description
|
||||||
|
* @property integer $cover_id
|
||||||
|
* @property integer $track_count
|
||||||
|
* @property integer $view_count
|
||||||
|
* @property integer $download_count
|
||||||
|
* @property integer $favourite_count
|
||||||
|
* @property integer $comment_count
|
||||||
|
* @property \Carbon\Carbon $created_at
|
||||||
|
* @property string $updated_at
|
||||||
|
* @property \Carbon\Carbon $deleted_at
|
||||||
|
*/
|
||||||
|
$factory->define(\Poniverse\Ponyfm\Models\Album::class, function(\Faker\Generator $faker) {
|
||||||
|
return [
|
||||||
|
'title' => $faker->sentence(5),
|
||||||
|
'slug' => $faker->slug,
|
||||||
|
'description' => $faker->paragraph(5),
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pony.fm - A community for pony fan music.
|
* Pony.fm - A community for pony fan music.
|
||||||
* Copyright (C) 2015 Peter Deltchev
|
* Copyright (C) 2015-2017 Peter Deltchev
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
@ -89,12 +89,13 @@ Route::group(['prefix' => 'notifications/email'], function() {
|
||||||
Route::get('oembed', 'TracksController@getOembed');
|
Route::get('oembed', 'TracksController@getOembed');
|
||||||
|
|
||||||
Route::group(['prefix' => 'api/v1', 'middleware' => 'json-exceptions'], function () {
|
Route::group(['prefix' => 'api/v1', 'middleware' => 'json-exceptions'], function () {
|
||||||
Route::get('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails');
|
Route::get( '/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails');
|
||||||
Route::post('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails');
|
Route::post('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails');
|
||||||
|
Route::get( '/tracks/{id}', 'Api\V1\TracksController@getTrackDetails')->where('id', '\d+');
|
||||||
|
|
||||||
Route::group(['middleware' => 'auth.oauth:ponyfm:tracks:upload'], function () {
|
Route::group(['middleware' => 'auth.oauth:ponyfm:tracks:upload'], function () {
|
||||||
Route::post('tracks', 'Api\V1\TracksController@postUploadTrack');
|
Route::post('tracks', 'Api\V1\TracksController@postUploadTrack');
|
||||||
Route::get('/tracks/{id}/upload-status', 'Api\V1\TracksController@getUploadStatus');
|
Route::get( '/tracks/{id}/upload-status', 'Api\V1\TracksController@getUploadStatus');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pony.fm - A community for pony fan music.
|
* Pony.fm - A community for pony fan music.
|
||||||
* Copyright (C) 2015 Peter Deltchev
|
* Copyright (C) 2015-2017 Peter Deltchev
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
@ -18,8 +18,11 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||||
|
use Poniverse\Ponyfm\Models\Album;
|
||||||
|
use Poniverse\Ponyfm\Models\Genre;
|
||||||
use Poniverse\Ponyfm\Models\Track;
|
use Poniverse\Ponyfm\Models\Track;
|
||||||
use Poniverse\Ponyfm\Models\User;
|
use Poniverse\Ponyfm\Models\User;
|
||||||
|
|
||||||
|
@ -74,13 +77,18 @@ class ApiTest extends TestCase
|
||||||
|
|
||||||
public function testUploadWithOptionalData()
|
public function testUploadWithOptionalData()
|
||||||
{
|
{
|
||||||
|
/** @var Track $track */
|
||||||
$track = factory(Track::class)->make();
|
$track = factory(Track::class)->make();
|
||||||
|
/** @var Genre $genre */
|
||||||
|
$genre = factory(Genre::class)->make();
|
||||||
|
/** @var Album $album */
|
||||||
|
$album = factory(Album::class)->make();
|
||||||
|
|
||||||
$this->callUploadWithParameters([
|
$this->callUploadWithParameters([
|
||||||
'title' => $track->title,
|
'title' => $track->title,
|
||||||
'track_type_id' => $track->track_type_id,
|
'track_type_id' => $track->track_type_id,
|
||||||
'genre' => $track->genre,
|
'genre' => $genre->name,
|
||||||
'album' => $track->album,
|
'album' => $album->title,
|
||||||
'released_at' => \Carbon\Carbon::create(2015, 1, 1, 1, 1, 1)->toIso8601String(),
|
'released_at' => \Carbon\Carbon::create(2015, 1, 1, 1, 1, 1)->toIso8601String(),
|
||||||
'description' => $track->description,
|
'description' => $track->description,
|
||||||
'lyrics' => $track->lyrics,
|
'lyrics' => $track->lyrics,
|
||||||
|
@ -94,11 +102,11 @@ class ApiTest extends TestCase
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->seeInDatabase('genres', [
|
$this->seeInDatabase('genres', [
|
||||||
'name' => $track->genre
|
'name' => $genre->name
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->seeInDatabase('albums', [
|
$this->seeInDatabase('albums', [
|
||||||
'title' => $track->album
|
'title' => $album->title
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->seeInDatabase('images', [
|
$this->seeInDatabase('images', [
|
||||||
|
@ -121,4 +129,36 @@ class ApiTest extends TestCase
|
||||||
'metadata' => $track->metadata
|
'metadata' => $track->metadata
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetTrackDetails()
|
||||||
|
{
|
||||||
|
/** @var Track $track */
|
||||||
|
$track = factory(Track::class)->create();
|
||||||
|
/** @var Genre $genre */
|
||||||
|
$genre = factory(Genre::class)->create();
|
||||||
|
|
||||||
|
$track->genre()->associate($genre);
|
||||||
|
$this->seeInDatabase('tracks', ['id' => $track->id]);
|
||||||
|
|
||||||
|
$track->published_at = Carbon::now();
|
||||||
|
$track->save();
|
||||||
|
|
||||||
|
|
||||||
|
$response = $this
|
||||||
|
->withSession(['api_client_id' => 'ponyponyponyponypony'])
|
||||||
|
->get("/api/v1/tracks/{$track->id}");
|
||||||
|
|
||||||
|
$response
|
||||||
|
->assertResponseStatus(200)
|
||||||
|
->seeJsonSubset([
|
||||||
|
'title' => $track->title,
|
||||||
|
'description' => $track->description,
|
||||||
|
'streams' => [
|
||||||
|
'mp3' => [
|
||||||
|
'url' => $track->getStreamUrl('MP3', 'ponyponyponyponypony'),
|
||||||
|
'mime_type' => Track::$Formats['MP3']['mime_type']
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue