From 1f68c8dbcf8c512093eee32c9ea2539cc516b57b Mon Sep 17 00:00:00 2001 From: nelsonlaquet Date: Sun, 22 Sep 2013 22:44:37 -0500 Subject: [PATCH 1/7] Added radio station API endpoint --- app/controllers/Api/V1/TracksController.php | 92 +++++++++++++++++++ .../2013_09_23_031316_create_track_hashes.php | 23 +++++ app/library/Helpers.php | 9 ++ app/models/Entities/Track.php | 17 +++- app/routes.php | 4 + bootstrap/compiled.php | 64 ++++++++----- 6 files changed, 187 insertions(+), 22 deletions(-) create mode 100644 app/controllers/Api/V1/TracksController.php create mode 100644 app/database/migrations/2013_09_23_031316_create_track_hashes.php diff --git a/app/controllers/Api/V1/TracksController.php b/app/controllers/Api/V1/TracksController.php new file mode 100644 index 00000000..ae989272 --- /dev/null +++ b/app/controllers/Api/V1/TracksController.php @@ -0,0 +1,92 @@ +published() + ->whereHash($hash)->first(); + + if (!$track) + return Response::json(['message' => 'Track not found.'], 403); + + $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), + ] + ] + ]; + } + + return Response::json([ + 'id' => $track->id, + 'title' => $track->title, + 'user' => [ + 'id' => $track->user->id, + 'name' => $track->user->display_name, + 'url' => $track->user->url, + 'avatars' => [ + 'thumbnail' => $track->user->getAvatarUrl(Image::THUMBNAIL), + 'small' => $track->user->getAvatarUrl(Image::SMALL), + 'normal' => $track->user->getAvatarUrl(Image::NORMAL) + ] + ], + 'stats' => [ + 'views' => $track->view_count, + 'plays' => $track->play_count, + 'downloads' => $track->download_count, + 'comments' => $track->comment_count, + 'favourites' => $track->favourite_count + ], + 'url' => $track->url, + 'is_vocal' => !!$track->is_vocal, + 'is_explicit' => !!$track->is_explicit, + 'is_downloadable' => !!$track->is_downloadable, + 'published_at' => $track->published_at, + 'duration' => $track->duration, + 'genre' => $track->genre != null + ? + [ + 'id' => $track->genre->id, + 'name' => $track->genre->name + ] : null, + 'type' => [ + 'id' => $track->track_type->id, + 'name' => $track->track_type->title + ], + 'covers' => [ + 'thumbnail' => $track->getCoverUrl(Image::THUMBNAIL), + 'small' => $track->getCoverUrl(Image::SMALL), + 'normal' => $track->getCoverUrl(Image::NORMAL) + ], + 'comments' => $comments + ], 200); + } + } \ No newline at end of file diff --git a/app/database/migrations/2013_09_23_031316_create_track_hashes.php b/app/database/migrations/2013_09_23_031316_create_track_hashes.php new file mode 100644 index 00000000..88da6afa --- /dev/null +++ b/app/database/migrations/2013_09_23_031316_create_track_hashes.php @@ -0,0 +1,23 @@ +string('hash', 32)->notNullable()->indexed(); + }); + + foreach (Track::with('user')->get() as $track) { + $track->updateHash(); + $track->save(); + } + } + + public function down() { + Schema::table('tracks', function($table) { + $table->dropColumn('hash'); + }); + } +} \ No newline at end of file diff --git a/app/library/Helpers.php b/app/library/Helpers.php index 771cb787..cd2eee46 100644 --- a/app/library/Helpers.php +++ b/app/library/Helpers.php @@ -1,6 +1,15 @@ ['index' => 0, 'extension' => 'flac', 'tag_format' => 'metaflac', 'tag_method' => 'updateTagsWithGetId3', 'mime_type' => 'audio/flac', 'command' => 'ffmpeg 2>&1 -y -i {$source} -acodec flac -aq 8 -f flac {$target}'], @@ -257,6 +259,10 @@ return $this->belongsTo('Entities\Genre'); } + public function trackType() { + return $this->belongsTo('Entities\TrackType', 'track_type_id'); + } + public function comments(){ return $this->hasMany('Entities\Comment')->orderBy('created_at', 'desc'); } @@ -289,6 +295,11 @@ return date('Y', strtotime($this->release_date)); } + public function setTitleAttribute($value) { + $this->setTitleAttributeSlug($value);; + $this->updateHash(); + } + public function getFilesize($formatName) { return Cache::remember($this->getCacheKey('filesize-' . $formatName), 1440, function () use ($formatName) { $file = $this->getFileFor($formatName); @@ -401,6 +412,10 @@ return URL::to('/t' . $this->id . '/dl.' . $format['extension']); } + public function updateHash() { + $this->hash = md5(Helpers::sanitizeInputForHashing($this->user->display_name) . '-' . Helpers::sanitizeInputForHashing($this->title)); + } + public function updateTags() { foreach (self::$Formats as $format => $data) { $this->{$data['tag_method']}($format); diff --git a/app/routes.php b/app/routes.php index 203ac3f5..be0dc69c 100644 --- a/app/routes.php +++ b/app/routes.php @@ -49,6 +49,10 @@ Route::get('p{id}', 'PlaylistsController@getShortlink')->where('id', '\d+'); Route::get('p{id}/dl.{extension}', 'PlaylistsController@getDownload' ); + Route::group(['prefix' => 'api/v1'], function() { + Route::get('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails'); + }); + Route::group(['prefix' => 'api/web'], function() { Route::get('/taxonomies/all', 'Api\Web\TaxonomiesController@getAll'); diff --git a/bootstrap/compiled.php b/bootstrap/compiled.php index cb73d68f..2079b47f 100644 --- a/bootstrap/compiled.php +++ b/bootstrap/compiled.php @@ -302,7 +302,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpFoundation\RedirectResponse as SymfonyRedirect; class Application extends Container implements HttpKernelInterface, ResponsePreparerInterface { - const VERSION = '4.0.6'; + const VERSION = '4.0.7'; protected $booted = false; protected $bootingCallbacks = array(); protected $bootedCallbacks = array(); @@ -949,11 +949,19 @@ class Request $query = $parameters; break; } + $queryString = ''; if (isset($components['query'])) { parse_str(html_entity_decode($components['query']), $qs); - $query = array_replace($qs, $query); + if ($query) { + $query = array_replace($qs, $query); + $queryString = http_build_query($query, '', '&'); + } else { + $query = $qs; + $queryString = $components['query']; + } + } elseif ($query) { + $queryString = http_build_query($query, '', '&'); } - $queryString = http_build_query($query, '', '&'); $server['REQUEST_URI'] = $components['path'] . ('' !== $queryString ? '?' . $queryString : ''); $server['QUERY_STRING'] = $queryString; return new static($query, $request, array(), $cookies, $files, $server, $content); @@ -989,8 +997,11 @@ class Request $dup->basePath = null; $dup->method = null; $dup->format = null; - if (!$dup->get('_format')) { - $dup->setRequestFormat($this->getRequestFormat()); + if (!$dup->get('_format') && $this->get('_format')) { + $dup->attributes->set('_format', $this->get('_format')); + } + if (!$dup->getRequestFormat(null)) { + $dup->setRequestFormat($format = $this->getRequestFormat(null)); } return $dup; } @@ -1176,6 +1187,12 @@ class Request return 443; } } + if ($host = $this->headers->get('HOST')) { + if (false !== ($pos = strrpos($host, ':'))) { + return intval(substr($host, $pos + 1)); + } + return 'https' === $this->getScheme() ? 443 : 80; + } return $this->server->get('SERVER_PORT'); } public function getUser() @@ -1509,14 +1526,14 @@ class Request return rtrim($prefix, '/'); } $truncatedRequestUri = $requestUri; - if (($pos = strpos($requestUri, '?')) !== false) { + if (false !== ($pos = strpos($requestUri, '?'))) { $truncatedRequestUri = substr($requestUri, 0, $pos); } $basename = basename($baseUrl); if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) { return ''; } - if (strlen($requestUri) >= strlen($baseUrl) && (false !== ($pos = strpos($requestUri, $baseUrl)) && $pos !== 0)) { + if (strlen($requestUri) >= strlen($baseUrl) && false !== ($pos = strpos($requestUri, $baseUrl)) && $pos !== 0) { $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); } return rtrim($baseUrl, '/'); @@ -1787,15 +1804,22 @@ class ServerBag extends ParameterBag } elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) { $authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION']; } - if (null !== $authorizationHeader && 0 === stripos($authorizationHeader, 'basic')) { - $exploded = explode(':', base64_decode(substr($authorizationHeader, 6))); - if (count($exploded) == 2) { - list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded; + if (null !== $authorizationHeader) { + if (0 === stripos($authorizationHeader, 'basic')) { + $exploded = explode(':', base64_decode(substr($authorizationHeader, 6))); + if (count($exploded) == 2) { + list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded; + } + } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && 0 === stripos($authorizationHeader, 'digest')) { + $headers['PHP_AUTH_DIGEST'] = $authorizationHeader; + $this->parameters['PHP_AUTH_DIGEST'] = $authorizationHeader; } } } if (isset($headers['PHP_AUTH_USER'])) { $headers['AUTHORIZATION'] = 'Basic ' . base64_encode($headers['PHP_AUTH_USER'] . ':' . $headers['PHP_AUTH_PW']); + } elseif (isset($headers['PHP_AUTH_DIGEST'])) { + $headers['AUTHORIZATION'] = $headers['PHP_AUTH_DIGEST']; } return $headers; } @@ -2225,6 +2249,7 @@ class NativeSessionStorage implements SessionStorageInterface } else { session_start(); } + $this->loadSession(); } return $ret; } @@ -3257,8 +3282,7 @@ class ExceptionServiceProvider extends ServiceProvider } protected function getResourcePath() { - $base = $this->app['path.base']; - return $base . '/vendor/laravel/framework/src/Illuminate/Exception/resources'; + return 'F:\\Nelson\\My Documents - Personal\\Visual Studio 2010\\Projects\\Poniverse\\spa.pony.fm\\vendor\\laravel\\framework\\src\\Illuminate\\Exception' . '/resources'; } } namespace Illuminate\Routing; @@ -3611,7 +3635,7 @@ class ErrorHandler if (null === ($error = error_get_last())) { return; } - unset($this->reservedMemory); + $this->reservedMemory = ''; $type = $error['type']; if (0 === $this->level || !in_array($type, array(E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE))) { return; @@ -4218,10 +4242,6 @@ class ProviderRepository $this->files->put($path, json_encode($manifest)); return $manifest; } - protected function getManifestPath($app) - { - return $this->manifestPath; - } protected function freshManifest(array $providers) { list($eager, $deferred) = array(array(), array()); @@ -5381,6 +5401,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa protected $appends = array(); protected $fillable = array(); protected $guarded = array('*'); + protected $dates = array(); protected $touches = array(); protected $with = array(); public $exists = false; @@ -5853,7 +5874,7 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } public function freshTimestamp() { - return new DateTime(); + return new Carbon(); } public function freshTimestampString() { @@ -6153,7 +6174,8 @@ abstract class Model implements ArrayAccess, ArrayableInterface, JsonableInterfa } public function getDates() { - return array(static::CREATED_AT, static::UPDATED_AT, static::DELETED_AT); + $defaults = array(static::CREATED_AT, static::UPDATED_AT, static::DELETED_AT); + return array_merge($this->dates, $defaults); } public function fromDateTime($value) { @@ -6590,7 +6612,7 @@ class Store extends SymfonySession } protected function mergeNewFlashes(array $keys) { - $values = array_unique(array_merge($this->get('flash.new'), $keys)); + $values = array_unique(array_merge($this->get('flash.new', array()), $keys)); $this->put('flash.new', $values); } protected function removeFromOldFlashData(array $keys) From a91d8cb2595812a7a7fc80d985f2a74ad046dcbc Mon Sep 17 00:00:00 2001 From: nelsonlaquet Date: Sun, 22 Sep 2013 23:05:26 -0500 Subject: [PATCH 2/7] added POST handler for radio details --- app/routes.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/routes.php b/app/routes.php index be0dc69c..5fcfdb4d 100644 --- a/app/routes.php +++ b/app/routes.php @@ -51,6 +51,7 @@ Route::group(['prefix' => 'api/v1'], function() { Route::get('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails'); + Route::post('/tracks/radio-details/{hash}', 'Api\V1\TracksController@getTrackRadioDetails'); }); Route::group(['prefix' => 'api/web'], function() { From 010836e69db35d03a27956695511901f8371202c Mon Sep 17 00:00:00 2001 From: nelsonlaquet Date: Sun, 22 Sep 2013 23:24:40 -0500 Subject: [PATCH 3/7] Added description and lyrics to radio API --- app/controllers/Api/V1/TracksController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/Api/V1/TracksController.php b/app/controllers/Api/V1/TracksController.php index ae989272..5461656d 100644 --- a/app/controllers/Api/V1/TracksController.php +++ b/app/controllers/Api/V1/TracksController.php @@ -48,6 +48,8 @@ return Response::json([ 'id' => $track->id, 'title' => $track->title, + 'description' => $track->description, + 'lyrics' => $track->lyrics, 'user' => [ 'id' => $track->user->id, 'name' => $track->user->display_name, From 675ba179015b589c4a8622d5bf6a6b0ff7d5b0fd Mon Sep 17 00:00:00 2001 From: nelsonlaquet Date: Tue, 24 Sep 2013 00:47:00 -0500 Subject: [PATCH 4/7] Fixed dropdown layout issue Fixed show songs playing wrong track --- app/controllers/Api/Web/TracksController.php | 4 +--- app/views/shared/_app_layout.blade.php | 2 +- public/scripts/shared/layout.coffee | 6 ++++++ public/styles/components.less | 1 + public/styles/layout.less | 12 +++++++++++- 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/app/controllers/Api/Web/TracksController.php b/app/controllers/Api/Web/TracksController.php index 226b2587..61b3180b 100644 --- a/app/controllers/Api/Web/TracksController.php +++ b/app/controllers/Api/Web/TracksController.php @@ -64,7 +64,7 @@ $tracks = []; $ids = []; - foreach ($query->get() as $track) { + foreach ($query->get(['tracks.*']) as $track) { $tracks[] = Track::mapPublicTrackSummary($track); $ids[] = $track->id; } @@ -93,7 +93,6 @@ return Response::json(Track::mapPrivateTrackShow($track), 200); } - private function applyFilters($query) { if (Input::has('order')) { $order = \Input::get('order'); @@ -127,7 +126,6 @@ $join->on('tracks.id', '=', 'show_song_track.track_id'); }); $query->whereIn('show_song_track.show_song_id', Input::get('songs')); - $query->select('tracks.*'); } return $query; diff --git a/app/views/shared/_app_layout.blade.php b/app/views/shared/_app_layout.blade.php index 05689c54..60aeed37 100644 --- a/app/views/shared/_app_layout.blade.php +++ b/app/views/shared/_app_layout.blade.php @@ -24,7 +24,7 @@
- pony.fm + pony.fm (beta)
@if (Auth::check())
-
+
-
+
+
+ +
From 14ef6c72993e4d00db56a22771bcb4c2b7d9c206 Mon Sep 17 00:00:00 2001 From: nelsonlaquet Date: Fri, 27 Sep 2013 15:49:22 -0500 Subject: [PATCH 6/7] Fixed permission issue --- app/models/Entities/Image.php | 1 + app/models/Entities/Track.php | 1 + spa.pony.fm.iml | 3 +++ 3 files changed, 5 insertions(+) diff --git a/app/models/Entities/Image.php b/app/models/Entities/Image.php index 2ffb3adc..60cb483b 100644 --- a/app/models/Entities/Image.php +++ b/app/models/Entities/Image.php @@ -92,6 +92,7 @@ public function ensureDirectoryExists() { $destination = $this->getDirectory(); + umask(0); if (!is_dir($destination)) mkdir($destination, 777, true); diff --git a/app/models/Entities/Track.php b/app/models/Entities/Track.php index c2e3aca7..d0eeb4ec 100644 --- a/app/models/Entities/Track.php +++ b/app/models/Entities/Track.php @@ -349,6 +349,7 @@ public function ensureDirectoryExists() { $destination = $this->getDirectory(); + umask(0); if (!is_dir($destination)) mkdir($destination, 777); diff --git a/spa.pony.fm.iml b/spa.pony.fm.iml index 6ff7b7ed..a1427afa 100644 --- a/spa.pony.fm.iml +++ b/spa.pony.fm.iml @@ -27,6 +27,7 @@ + @@ -75,6 +76,7 @@ + @@ -115,6 +117,7 @@ + From 2c19d4fcc06b96cd0b2ec5f70094317dae71f3d3 Mon Sep 17 00:00:00 2001 From: nelsonlaquet Date: Sun, 6 Oct 2013 21:53:09 -0500 Subject: [PATCH 7/7] trying something --- app/controllers/TracksController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/TracksController.php b/app/controllers/TracksController.php index d1c1d661..b0c204c2 100644 --- a/app/controllers/TracksController.php +++ b/app/controllers/TracksController.php @@ -138,7 +138,7 @@ $response->header('Content-Disposition', 'attachment; filename="' . $track->getDownloadFilenameFor($formatName) . '"'); } else { $response->header('X-Accel-Redirect', $filename); - $response->header('Content-Disposition', 'attachment; filename=' . $track->getDownloadFilenameFor($formatName)); + $response->header('Content-Disposition', 'attachment; filename="' . $track->getDownloadFilenameFor($formatName) . '"'); } $time = gmdate(filemtime($filename));