mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2025-03-29 14:27:46 +01:00
Biggus Upgradus
- !! NEW DOCKER FILES :D !! - getid3 is now vendored from composer! :D - fix elasticsearch for use with newer versions - fix some migration issues by yeeting a migration that has had its day - fix our asset pipeline (webpack / gulp)
This commit is contained in:
parent
7de9c6c7e7
commit
ff57ce54dd
41 changed files with 2864 additions and 1507 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -13,3 +13,4 @@ resources/views/emails/html
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
/composer.phar
|
/composer.phar
|
||||||
|
.phpstorm.meta.php
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
|
|
||||||
namespace App\Commands;
|
namespace App\Commands;
|
||||||
|
|
||||||
|
use App\Facades\Notification;
|
||||||
use App\Models\Album;
|
use App\Models\Album;
|
||||||
use App\Models\Comment;
|
use App\Models\Comment;
|
||||||
use App\Models\Playlist;
|
use App\Models\Playlist;
|
||||||
use App\Models\Track;
|
use App\Models\Track;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Notification;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
class CreateCommentCommand extends CommandBase
|
class CreateCommentCommand extends CommandBase
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
|
|
||||||
namespace App\Commands;
|
namespace App\Commands;
|
||||||
|
|
||||||
|
use App\Facades\Notification;
|
||||||
use App\Models\Playlist;
|
use App\Models\Playlist;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Notification;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
class CreatePlaylistCommand extends CommandBase
|
class CreatePlaylistCommand extends CommandBase
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
namespace App\Commands;
|
namespace App\Commands;
|
||||||
|
|
||||||
|
use App\Facades\Notification;
|
||||||
use App\Models\Album;
|
use App\Models\Album;
|
||||||
use App\Models\Image;
|
use App\Models\Image;
|
||||||
use App\Models\Playlist;
|
use App\Models\Playlist;
|
||||||
|
@ -28,7 +29,6 @@ use App\Models\TrackType;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Support\Facades\Notification;
|
|
||||||
|
|
||||||
class EditTrackCommand extends CommandBase
|
class EditTrackCommand extends CommandBase
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
namespace App\Commands;
|
namespace App\Commands;
|
||||||
|
|
||||||
use App\Contracts\Favouritable;
|
use App\Contracts\Favouritable;
|
||||||
|
use App\Facades\Notification;
|
||||||
use App\Models\Album;
|
use App\Models\Album;
|
||||||
use App\Models\Favourite;
|
use App\Models\Favourite;
|
||||||
use App\Models\Playlist;
|
use App\Models\Playlist;
|
||||||
|
@ -28,7 +29,6 @@ use App\Models\ResourceUser;
|
||||||
use App\Models\Track;
|
use App\Models\Track;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Notification;
|
|
||||||
|
|
||||||
class ToggleFavouriteCommand extends CommandBase
|
class ToggleFavouriteCommand extends CommandBase
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
|
|
||||||
namespace App\Commands;
|
namespace App\Commands;
|
||||||
|
|
||||||
|
use App\Facades\Notification;
|
||||||
use App\Models\Follower;
|
use App\Models\Follower;
|
||||||
use App\Models\ResourceUser;
|
use App\Models\ResourceUser;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Notification;
|
|
||||||
|
|
||||||
class ToggleFollowingCommand extends CommandBase
|
class ToggleFollowingCommand extends CommandBase
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,13 +22,11 @@ namespace App\Commands;
|
||||||
|
|
||||||
use App\Models\Track;
|
use App\Models\Track;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Carbon\Carbon;
|
use Carbon\CarbonInterface;
|
||||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Config;
|
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Support\Facades\Request;
|
use Illuminate\Support\Facades\Request;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
|
|
||||||
class UploadTrackCommand extends CommandBase
|
class UploadTrackCommand extends CommandBase
|
||||||
{
|
{
|
||||||
|
@ -161,7 +159,7 @@ class UploadTrackCommand extends CommandBase
|
||||||
.'audio_channels:1,2',
|
.'audio_channels:1,2',
|
||||||
];
|
];
|
||||||
if (! $this->_isReplacingTrack) {
|
if (! $this->_isReplacingTrack) {
|
||||||
array_merge($rules, [
|
$rules = array_merge($rules, [
|
||||||
'cover' => 'image|mimes:png,jpeg|min_width:350|min_height:350',
|
'cover' => 'image|mimes:png,jpeg|min_width:350|min_height:350',
|
||||||
'auto_publish' => 'boolean',
|
'auto_publish' => 'boolean',
|
||||||
'title' => 'string',
|
'title' => 'string',
|
||||||
|
@ -169,7 +167,7 @@ class UploadTrackCommand extends CommandBase
|
||||||
'genre' => 'string',
|
'genre' => 'string',
|
||||||
'album' => 'string',
|
'album' => 'string',
|
||||||
'track_number' => 'integer',
|
'track_number' => 'integer',
|
||||||
'released_at' => 'date_format:'.Carbon::ISO8601,
|
'released_at' => 'date_format:'.CarbonInterface::ISO8601,
|
||||||
'description' => 'string',
|
'description' => 'string',
|
||||||
'lyrics' => 'string',
|
'lyrics' => 'string',
|
||||||
'is_vocal' => 'boolean',
|
'is_vocal' => 'boolean',
|
||||||
|
|
|
@ -28,14 +28,12 @@ interface Searchable
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function toElasticsearch():array;
|
public function toElasticsearch(): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool whether this particular object should be indexed or not
|
* @return bool whether this particular object should be indexed or not
|
||||||
*/
|
*/
|
||||||
public function shouldBeIndexed():bool;
|
public function shouldBeIndexed(): bool;
|
||||||
|
|
||||||
public function updateElasticsearchEntry();
|
public function updateElasticsearchEntry(bool $removeFromIndex = false);
|
||||||
|
|
||||||
public function updateElasticsearchEntrySynchronously();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ class AlbumsController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($album->slug != $slug) {
|
if ($album->slug != $slug) {
|
||||||
return Redirect::action('AlbumsController@getAlbum', [$id, $album->slug]);
|
return Redirect::action([AlbumsController::class, 'getAlbum'], [$id, $album->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('albums.show');
|
return view('albums.show');
|
||||||
|
@ -56,7 +56,7 @@ class AlbumsController extends Controller
|
||||||
abort(404);
|
abort(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::action('AlbumsController@getShow', [$id, $album->slug]);
|
return Redirect::action([AlbumsController::class, 'getShow'], [$id, $album->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDownload($id, $extension)
|
public function getDownload($id, $extension)
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace App\Http\Controllers\Api\V1;
|
||||||
|
|
||||||
use App\Commands\UploadTrackCommand;
|
use App\Commands\UploadTrackCommand;
|
||||||
use App\Http\Controllers\ApiControllerBase;
|
use App\Http\Controllers\ApiControllerBase;
|
||||||
|
use App\Http\Controllers\ContentController;
|
||||||
use App\Models\Image;
|
use App\Models\Image;
|
||||||
use App\Models\Track;
|
use App\Models\Track;
|
||||||
use Illuminate\Support\Facades\Response;
|
use Illuminate\Support\Facades\Response;
|
||||||
|
@ -41,8 +42,8 @@ class TracksController extends ApiControllerBase
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'id' => (string) $commandData['id'],
|
'id' => (string) $commandData['id'],
|
||||||
'status_url' => action('Api\V1\TracksController@getUploadStatus', ['id' => $commandData['id']]),
|
'status_url' => action([static::class, 'getUploadStatus'], ['id' => $commandData['id']]),
|
||||||
'track_url' => action('TracksController@getTrack', ['id' => $commandData['id'], 'slug' => $commandData['slug']]),
|
'track_url' => action([\App\Http\Controllers\TracksController::class, 'getTrack'], ['id' => $commandData['id'], 'slug' => $commandData['slug']]),
|
||||||
'message' => $commandData['autoPublish']
|
'message' => $commandData['autoPublish']
|
||||||
? 'This track has been accepted for processing! Poll the status_url to know when it has been published. It will be published at the track_url.'
|
? 'This track has been accepted for processing! Poll the status_url to know when it has been published. It will be published at the track_url.'
|
||||||
: "This track has been accepted for processing! Poll the status_url to know when it's ready to publish. It will be published at the track_url.",
|
: "This track has been accepted for processing! Poll the status_url to know when it's ready to publish. It will be published at the track_url.",
|
||||||
|
@ -66,7 +67,7 @@ class TracksController extends ApiControllerBase
|
||||||
'message' => $track->published_at
|
'message' => $track->published_at
|
||||||
? 'Processing complete! The track is live at the track_url. The artist can edit the track by visiting its edit_url.'
|
? 'Processing complete! The track is live at the track_url. The artist can edit the track by visiting its edit_url.'
|
||||||
: 'Processing complete! The artist must publish the track by visiting its edit_url.',
|
: 'Processing complete! The artist must publish the track by visiting its edit_url.',
|
||||||
'edit_url' => action('ContentController@getTracks', ['id' => $trackId]),
|
'edit_url' => action([ContentController::class, 'getTracks'], ['id' => $trackId]),
|
||||||
'track_url' => $track->url,
|
'track_url' => $track->url,
|
||||||
], 201);
|
], 201);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -33,8 +33,7 @@ use App\Models\Track;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Request as RequestF;
|
||||||
use Illuminate\Support\Facades\Response;
|
|
||||||
|
|
||||||
class PlaylistsController extends ApiControllerBase
|
class PlaylistsController extends ApiControllerBase
|
||||||
{
|
{
|
||||||
|
@ -222,8 +221,8 @@ class PlaylistsController extends ApiControllerBase
|
||||||
*/
|
*/
|
||||||
private function applyOrdering($query)
|
private function applyOrdering($query)
|
||||||
{
|
{
|
||||||
if (Request::has('order')) {
|
if (RequestF::has('order')) {
|
||||||
$order = \Request::get('order');
|
$order = RequestF::get('order');
|
||||||
$parts = explode(',', $order);
|
$parts = explode(',', $order);
|
||||||
$query->orderBy($parts[0], $parts[1]);
|
$query->orderBy($parts[0], $parts[1]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ use App\Models\TrackType;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Request as RequestF;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\File;
|
use Illuminate\Support\Facades\File;
|
||||||
use Illuminate\Support\Facades\Response;
|
use Illuminate\Support\Facades\Response;
|
||||||
|
@ -295,8 +296,8 @@ class TracksController extends ApiControllerBase
|
||||||
*/
|
*/
|
||||||
private function applyOrdering($query)
|
private function applyOrdering($query)
|
||||||
{
|
{
|
||||||
if (Request::has('order')) {
|
if (RequestF::has('order')) {
|
||||||
$order = \Request::get('order');
|
$order = RequestF::get('order');
|
||||||
$parts = explode(',', $order);
|
$parts = explode(',', $order);
|
||||||
$query->orderBy($parts[0], $parts[1]);
|
$query->orderBy($parts[0], $parts[1]);
|
||||||
}
|
}
|
||||||
|
@ -312,8 +313,8 @@ class TracksController extends ApiControllerBase
|
||||||
*/
|
*/
|
||||||
private function applyFilters($query, $unknown = false)
|
private function applyFilters($query, $unknown = false)
|
||||||
{
|
{
|
||||||
if (Request::has('is_vocal')) {
|
if (RequestF::has('is_vocal')) {
|
||||||
$isVocal = \Request::get('is_vocal');
|
$isVocal = RequestF::get('is_vocal');
|
||||||
if ($isVocal == 'true') {
|
if ($isVocal == 'true') {
|
||||||
$query->whereIsVocal(true);
|
$query->whereIsVocal(true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -321,27 +322,27 @@ class TracksController extends ApiControllerBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Request::has('in_album')) {
|
if (RequestF::has('in_album')) {
|
||||||
if (Request::get('in_album') == 'true') {
|
if (RequestF::get('in_album') == 'true') {
|
||||||
$query->whereNotNull('album_id');
|
$query->whereNotNull('album_id');
|
||||||
} else {
|
} else {
|
||||||
$query->whereNull('album_id');
|
$query->whereNull('album_id');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Request::has('genres')) {
|
if (RequestF::has('genres')) {
|
||||||
$query->whereIn('genre_id', Request::get('genres'));
|
$query->whereIn('genre_id', RequestF::get('genres'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Request::has('types') && ! $unknown) {
|
if (RequestF::has('types') && ! $unknown) {
|
||||||
$query->whereIn('track_type_id', Request::get('types'));
|
$query->whereIn('track_type_id', RequestF::get('types'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$archive = null;
|
$archive = null;
|
||||||
|
|
||||||
if (Request::has('archive')) {
|
if (RequestF::has('archive')) {
|
||||||
// Select which archive to view
|
// Select which archive to view
|
||||||
$archive = Request::get('archive');
|
$archive = RequestF::get('archive');
|
||||||
$query->where('source', $archive);
|
$query->where('source', $archive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,14 +365,14 @@ class TracksController extends ApiControllerBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Request::has('songs')) {
|
if (RequestF::has('songs')) {
|
||||||
// DISTINCT is needed here to avoid duplicate results
|
// DISTINCT is needed here to avoid duplicate results
|
||||||
// when a track is associated with multiple show songs.
|
// when a track is associated with multiple show songs.
|
||||||
$query->distinct();
|
$query->distinct();
|
||||||
$query->join('show_song_track', function ($join) {
|
$query->join('show_song_track', function ($join) {
|
||||||
$join->on('tracks.id', '=', 'show_song_track.track_id');
|
$join->on('tracks.id', '=', 'show_song_track.track_id');
|
||||||
});
|
});
|
||||||
$query->whereIn('show_song_track.show_song_id', Request::get('songs'));
|
$query->whereIn('show_song_track.show_song_id', RequestF::get('songs'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
|
|
|
@ -51,7 +51,7 @@ class ArtistsController extends Controller
|
||||||
$newUser = User::find($user->redirect_to);
|
$newUser = User::find($user->redirect_to);
|
||||||
|
|
||||||
if ($newUser) {
|
if ($newUser) {
|
||||||
return Redirect::action('ArtistsController@getProfile', [$newUser->slug]);
|
return Redirect::action([static::class, 'getProfile'], [$newUser->slug]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,6 @@ class ArtistsController extends Controller
|
||||||
abort('404');
|
abort('404');
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::action('ArtistsController@getProfile', [$user->slug]);
|
return Redirect::action([static::class, 'getProfile'], [$user->slug]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ class AuthController extends Controller
|
||||||
if (Auth::guest()) {
|
if (Auth::guest()) {
|
||||||
return redirect(
|
return redirect(
|
||||||
$this->poniverse
|
$this->poniverse
|
||||||
->getOAuthProvider(['redirectUri' => action('AuthController@getOAuth')])
|
->getOAuthProvider(['redirectUri' => action([static::class, 'getOAuth'])])
|
||||||
->getAuthorizationUrl());
|
->getAuthorizationUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class AuthController extends Controller
|
||||||
try {
|
try {
|
||||||
$accessToken = $oauthProvider->getAccessToken('authorization_code', [
|
$accessToken = $oauthProvider->getAccessToken('authorization_code', [
|
||||||
'code' => $request->query('code'),
|
'code' => $request->query('code'),
|
||||||
'redirect_uri' => action('AuthController@getOAuth'),
|
'redirect_uri' => action([static::class, 'getOAuth']),
|
||||||
]);
|
]);
|
||||||
$this->poniverse->setAccessToken($accessToken);
|
$this->poniverse->setAccessToken($accessToken);
|
||||||
$resourceOwner = $oauthProvider->getResourceOwner($accessToken);
|
$resourceOwner = $oauthProvider->getResourceOwner($accessToken);
|
||||||
|
|
|
@ -45,7 +45,7 @@ class PlaylistsController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($playlist->slug != $slug) {
|
if ($playlist->slug != $slug) {
|
||||||
return Redirect::action('PlaylistsController@getPlaylist', [$id, $playlist->slug]);
|
return Redirect::action([static::class, 'getPlaylist'], [$id, $playlist->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('playlists.show');
|
return view('playlists.show');
|
||||||
|
@ -58,7 +58,7 @@ class PlaylistsController extends Controller
|
||||||
abort(404);
|
abort(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::action('PlaylistsController@getPlaylist', [$id, $playlist->slug]);
|
return Redirect::action([static::class, 'getPlaylist'], [$id, $playlist->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDownload(Request $request, $id, $extension)
|
public function getDownload(Request $request, $id, $extension)
|
||||||
|
|
|
@ -107,7 +107,7 @@ class TracksController extends Controller
|
||||||
'title' => $track->title,
|
'title' => $track->title,
|
||||||
'author_name' => $track->user->display_name,
|
'author_name' => $track->user->display_name,
|
||||||
'author_url' => $track->user->url,
|
'author_url' => $track->user->url,
|
||||||
'html' => '<iframe src="'.action('TracksController@getEmbed', ['id' => $track->id]).'" width="100%" height="150" allowTransparency="true" frameborder="0" seamless allowfullscreen></iframe>',
|
'html' => '<iframe src="'.action([static::class, 'getEmbed'], ['id' => $track->id]).'" width="100%" height="150" allowTransparency="true" frameborder="0" seamless allowfullscreen></iframe>',
|
||||||
];
|
];
|
||||||
|
|
||||||
return response()->json($output);
|
return response()->json($output);
|
||||||
|
@ -121,7 +121,7 @@ class TracksController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($track->slug != $slug) {
|
if ($track->slug != $slug) {
|
||||||
return Redirect::action('TracksController@getTrack', [$id, $track->slug]);
|
return Redirect::action([static::class, 'getTrack'], [$id, $track->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('tracks.show', ['track' => $track]);
|
return view('tracks.show', ['track' => $track]);
|
||||||
|
@ -139,7 +139,7 @@ class TracksController extends Controller
|
||||||
abort(404);
|
abort(404);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Redirect::action('TracksController@getTrack', [$id, $track->slug]);
|
return Redirect::action([static::class, 'getTrack'], [$id, $track->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStream(Request $request, $id, $extension)
|
public function getStream(Request $request, $id, $extension)
|
||||||
|
|
|
@ -31,7 +31,6 @@ class Kernel extends HttpKernel
|
||||||
*/
|
*/
|
||||||
protected $middleware = [
|
protected $middleware = [
|
||||||
\App\Http\Middleware\TrustProxies::class,
|
\App\Http\Middleware\TrustProxies::class,
|
||||||
\Fruitcake\Cors\HandleCors::class,
|
|
||||||
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||||
\App\Http\Middleware\TrimStrings::class,
|
\App\Http\Middleware\TrimStrings::class,
|
||||||
|
@ -60,6 +59,7 @@ class Kernel extends HttpKernel
|
||||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||||
|
'cors' => \Fruitcake\Cors\HandleCors::class,
|
||||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||||
|
|
|
@ -130,7 +130,7 @@ class EncodeTrackFile extends Job implements ShouldQueue
|
||||||
Log::info('Encoding track file '.$this->trackFile->id.' into '.$target);
|
Log::info('Encoding track file '.$this->trackFile->id.' into '.$target);
|
||||||
|
|
||||||
// Start a synchronous process to encode the file
|
// Start a synchronous process to encode the file
|
||||||
$process = new Process($command);
|
$process = Process::fromShellCommandline($command);
|
||||||
try {
|
try {
|
||||||
$process->mustRun();
|
$process->mustRun();
|
||||||
} catch (ProcessFailedException $e) {
|
} catch (ProcessFailedException $e) {
|
||||||
|
|
|
@ -20,28 +20,28 @@
|
||||||
|
|
||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
use App\Contracts\Searchable;
|
use Elasticsearch;
|
||||||
use App\Jobs\Job;
|
use Elasticsearch\Common\Exceptions\Missing404Exception;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
class UpdateSearchIndexForEntity extends Job implements ShouldQueue
|
class UpdateSearchIndexForEntity extends Job implements ShouldQueue
|
||||||
{
|
{
|
||||||
use InteractsWithQueue, SerializesModels;
|
use InteractsWithQueue;
|
||||||
|
|
||||||
protected $entity;
|
protected array $elasticsearchBody;
|
||||||
|
protected bool $removeFromIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
*
|
*
|
||||||
* @param Model $entity
|
* @param array $elasticsearchBody
|
||||||
|
* @param bool $removeFromIndex
|
||||||
*/
|
*/
|
||||||
public function __construct(Searchable $entity)
|
public function __construct(array $elasticsearchBody, bool $removeFromIndex = true)
|
||||||
{
|
{
|
||||||
$this->entity = $entity;
|
$this->elasticsearchBody = $elasticsearchBody;
|
||||||
|
$this->removeFromIndex = $removeFromIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,6 +52,26 @@ class UpdateSearchIndexForEntity extends Job implements ShouldQueue
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->beforeHandle();
|
$this->beforeHandle();
|
||||||
$this->entity->updateElasticsearchEntrySynchronously();
|
|
||||||
|
match($this->removeFromIndex) {
|
||||||
|
true => $this->deleteElasticsearchEntry(),
|
||||||
|
false => $this->createOrUpdateElasticsearchEntry(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function createOrUpdateElasticsearchEntry()
|
||||||
|
{
|
||||||
|
Elasticsearch::connection()->index($this->elasticsearchBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function deleteElasticsearchEntry()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Elasticsearch::connection()->delete($this->elasticsearchBody);
|
||||||
|
} catch (Missing404Exception $e) {
|
||||||
|
// If the entity we're trying to delete isn't indexed in Elasticsearch,
|
||||||
|
// that's fine.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ class Assets
|
||||||
|
|
||||||
foreach ($styles as $style) {
|
foreach ($styles as $style) {
|
||||||
$filename = self::replaceExtensionWith($style, '.less', '.css');
|
$filename = self::replaceExtensionWith($style, '.less', '.css');
|
||||||
$retVal .= "<link rel='stylesheet' href='/build/$filename?".filemtime(public_path("/build/${filename}"))."' />";
|
$retVal .= "<link rel='stylesheet' href='/build/styles/$filename?".filemtime(public_path("/build/styles/${filename}"))."' />";
|
||||||
}
|
}
|
||||||
|
|
||||||
return $retVal;
|
return $retVal;
|
||||||
|
@ -81,7 +81,7 @@ class Assets
|
||||||
$files = [];
|
$files = [];
|
||||||
$filesFound = [];
|
$filesFound = [];
|
||||||
foreach ($globs as $glob) {
|
foreach ($globs as $glob) {
|
||||||
foreach (glob('../resources/assets/'.$glob, GLOB_BRACE) as $file) {
|
foreach (glob('../resources/'.$glob) as $file) {
|
||||||
if (isset($filesFound[$file])) {
|
if (isset($filesFound[$file])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ class External
|
||||||
{
|
{
|
||||||
public static function execute($command)
|
public static function execute($command)
|
||||||
{
|
{
|
||||||
$process = new Process($command);
|
$process = Process::fromShellCommandline($command);
|
||||||
$process->run();
|
$process->run();
|
||||||
|
|
||||||
if (! $process->isSuccessful()) {
|
if (! $process->isSuccessful()) {
|
||||||
|
|
|
@ -48,10 +48,15 @@ class Search
|
||||||
public function searchAllContent(string $query)
|
public function searchAllContent(string $query)
|
||||||
{
|
{
|
||||||
$results = $this->elasticsearch->msearch([
|
$results = $this->elasticsearch->msearch([
|
||||||
'index' => $this->index,
|
'index' => [
|
||||||
|
$this->index.'-album',
|
||||||
|
$this->index.'-playlist',
|
||||||
|
$this->index.'-tracks',
|
||||||
|
$this->index.'-user',
|
||||||
|
],
|
||||||
'body' => [
|
'body' => [
|
||||||
//===== Tracks=====//
|
//===== Tracks=====//
|
||||||
['type' => 'track'],
|
['index' => $this->index.'-track'],
|
||||||
[
|
[
|
||||||
'query' => [
|
'query' => [
|
||||||
'multi_match' => [
|
'multi_match' => [
|
||||||
|
@ -70,7 +75,7 @@ class Search
|
||||||
],
|
],
|
||||||
|
|
||||||
//===== Albums =====//
|
//===== Albums =====//
|
||||||
['type' => 'album'],
|
['index' => $this->index.'-album'],
|
||||||
[
|
[
|
||||||
'query' => [
|
'query' => [
|
||||||
'multi_match' => [
|
'multi_match' => [
|
||||||
|
@ -87,7 +92,7 @@ class Search
|
||||||
],
|
],
|
||||||
|
|
||||||
//===== Playlists =====//
|
//===== Playlists =====//
|
||||||
['type' => 'playlist'],
|
['index' => $this->index.'-playlist'],
|
||||||
[
|
[
|
||||||
'query' => [
|
'query' => [
|
||||||
'multi_match' => [
|
'multi_match' => [
|
||||||
|
@ -104,7 +109,7 @@ class Search
|
||||||
],
|
],
|
||||||
|
|
||||||
//===== Users =====//
|
//===== Users =====//
|
||||||
['type' => 'user'],
|
['index' => $this->index.'-user'],
|
||||||
[
|
[
|
||||||
'query' => [
|
'query' => [
|
||||||
'multi_match' => [
|
'multi_match' => [
|
||||||
|
|
|
@ -24,6 +24,7 @@ use App\Contracts\Commentable;
|
||||||
use App\Contracts\Favouritable;
|
use App\Contracts\Favouritable;
|
||||||
use App\Contracts\Searchable;
|
use App\Contracts\Searchable;
|
||||||
use App\Exceptions\TrackFileNotFoundException;
|
use App\Exceptions\TrackFileNotFoundException;
|
||||||
|
use App\Http\Controllers\AlbumsController;
|
||||||
use App\Traits\IndexedInElasticsearchTrait;
|
use App\Traits\IndexedInElasticsearchTrait;
|
||||||
use App\Traits\SlugTrait;
|
use App\Traits\SlugTrait;
|
||||||
use App\Traits\TrackCollection;
|
use App\Traits\TrackCollection;
|
||||||
|
@ -211,7 +212,7 @@ class Album extends Model implements Searchable, Commentable, Favouritable
|
||||||
$data['description'] = $album->description;
|
$data['description'] = $album->description;
|
||||||
$data['is_downloadable'] = $is_downloadable;
|
$data['is_downloadable'] = $is_downloadable;
|
||||||
$data['share'] = [
|
$data['share'] = [
|
||||||
'url' => action('AlbumsController@getShortlink', ['id' => $album->id]),
|
'url' => action([AlbumsController::class, 'getShortlink'], ['id' => $album->id]),
|
||||||
'tumblrUrl' => 'http://www.tumblr.com/share/link?url='.urlencode($album->url).'&name='.urlencode($album->title).'&description='.urlencode($album->description),
|
'tumblrUrl' => 'http://www.tumblr.com/share/link?url='.urlencode($album->url).'&name='.urlencode($album->title).'&description='.urlencode($album->description),
|
||||||
'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text='.$album->title.' by '.$album->user->display_name.' on Pony.fm',
|
'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text='.$album->title.' by '.$album->user->display_name.' on Pony.fm',
|
||||||
];
|
];
|
||||||
|
@ -279,12 +280,12 @@ class Album extends Model implements Searchable, Commentable, Favouritable
|
||||||
|
|
||||||
public function getUrlAttribute()
|
public function getUrlAttribute()
|
||||||
{
|
{
|
||||||
return action('AlbumsController@getShow', ['id' => $this->id, 'slug' => $this->slug]);
|
return action([AlbumsController::class, 'getShow'], ['id' => $this->id, 'slug' => $this->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDownloadUrl($format)
|
public function getDownloadUrl($format)
|
||||||
{
|
{
|
||||||
return action('AlbumsController@getDownload', ['id' => $this->id, 'extension' => Track::$Formats[$format]['extension']]);
|
return action([AlbumsController::class, 'getDownload'], ['id' => $this->id, 'extension' => Track::$Formats[$format]['extension']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCoverUrl($type = Image::NORMAL)
|
public function getCoverUrl($type = Image::NORMAL)
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Http\Controllers\ImagesController;
|
||||||
use External;
|
use External;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Facades\Config;
|
use Illuminate\Support\Facades\Config;
|
||||||
|
@ -169,7 +170,7 @@ class Image extends Model
|
||||||
{
|
{
|
||||||
$type = self::$ImageTypes[$type];
|
$type = self::$ImageTypes[$type];
|
||||||
|
|
||||||
return action('ImagesController@getImage', ['id' => $this->id, 'type' => $type['name'], 'extension' => $this->extension]);
|
return action([ImagesController::class, 'getImage'], ['id' => $this->id, 'type' => $type['name'], 'extension' => $this->extension]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFile($type = self::NORMAL)
|
public function getFile($type = self::NORMAL)
|
||||||
|
|
|
@ -24,6 +24,7 @@ use App\Contracts\Commentable;
|
||||||
use App\Contracts\Favouritable;
|
use App\Contracts\Favouritable;
|
||||||
use App\Contracts\Searchable;
|
use App\Contracts\Searchable;
|
||||||
use App\Exceptions\TrackFileNotFoundException;
|
use App\Exceptions\TrackFileNotFoundException;
|
||||||
|
use App\Http\Controllers\PlaylistsController;
|
||||||
use App\Traits\IndexedInElasticsearchTrait;
|
use App\Traits\IndexedInElasticsearchTrait;
|
||||||
use App\Traits\SlugTrait;
|
use App\Traits\SlugTrait;
|
||||||
use App\Traits\TrackCollection;
|
use App\Traits\TrackCollection;
|
||||||
|
@ -173,7 +174,7 @@ class Playlist extends Model implements Searchable, Commentable, Favouritable
|
||||||
$data['comments'] = $comments;
|
$data['comments'] = $comments;
|
||||||
$data['formats'] = $formats;
|
$data['formats'] = $formats;
|
||||||
$data['share'] = [
|
$data['share'] = [
|
||||||
'url' => action('PlaylistsController@getShortlink', ['id' => $playlist->id]),
|
'url' => action([PlaylistsController::class, 'getShortlink'], ['id' => $playlist->id]),
|
||||||
'tumblrUrl' => 'http://www.tumblr.com/share/link?url='.urlencode($playlist->url).'&name='.urlencode($playlist->title).'&description='.urlencode($playlist->description),
|
'tumblrUrl' => 'http://www.tumblr.com/share/link?url='.urlencode($playlist->url).'&name='.urlencode($playlist->title).'&description='.urlencode($playlist->description),
|
||||||
'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text='.$playlist->title.' by '.$playlist->user->display_name.' on Pony.fm',
|
'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text='.$playlist->title.' by '.$playlist->user->display_name.' on Pony.fm',
|
||||||
];
|
];
|
||||||
|
@ -308,12 +309,12 @@ class Playlist extends Model implements Searchable, Commentable, Favouritable
|
||||||
|
|
||||||
public function getUrlAttribute()
|
public function getUrlAttribute()
|
||||||
{
|
{
|
||||||
return action('PlaylistsController@getPlaylist', ['id' => $this->id, 'slug' => $this->slug]);
|
return action([PlaylistsController::class, 'getPlaylist'], ['id' => $this->id, 'slug' => $this->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDownloadUrl($format)
|
public function getDownloadUrl($format)
|
||||||
{
|
{
|
||||||
return action('PlaylistsController@getDownload', ['id' => $this->id, 'format' => Track::$Formats[$format]['extension']]);
|
return action([PlaylistsController::class, 'getDownload'], ['id' => $this->id, 'format' => Track::$Formats[$format]['extension']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCoverUrl($type = Image::NORMAL)
|
public function getCoverUrl($type = Image::NORMAL)
|
||||||
|
|
|
@ -24,6 +24,7 @@ use App\Contracts\Commentable;
|
||||||
use App\Contracts\Favouritable;
|
use App\Contracts\Favouritable;
|
||||||
use App\Contracts\Searchable;
|
use App\Contracts\Searchable;
|
||||||
use App\Exceptions\TrackFileNotFoundException;
|
use App\Exceptions\TrackFileNotFoundException;
|
||||||
|
use App\Http\Controllers\TracksController;
|
||||||
use App\Models\ResourceLogItem;
|
use App\Models\ResourceLogItem;
|
||||||
use App\Traits\IndexedInElasticsearchTrait;
|
use App\Traits\IndexedInElasticsearchTrait;
|
||||||
use App\Traits\SlugTrait;
|
use App\Traits\SlugTrait;
|
||||||
|
@ -226,7 +227,7 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
'tag_format' => 'AtomicParsley',
|
'tag_format' => 'AtomicParsley',
|
||||||
'tag_method' => 'updateTagsWithAtomicParsley',
|
'tag_method' => 'updateTagsWithAtomicParsley',
|
||||||
'mime_type' => 'audio/mp4',
|
'mime_type' => 'audio/mp4',
|
||||||
'command' => 'ffmpeg 2>&1 -y -i {$source} -map 0:a -map_metadata -1 -codec:a libfaac -ab 256k -f mp4 {$target}',
|
'command' => 'ffmpeg 2>&1 -y -i {$source} -map 0:a -map_metadata -1 -codec:a aac -ab 256k -f mp4 {$target}',
|
||||||
],
|
],
|
||||||
'ALAC' => [
|
'ALAC' => [
|
||||||
'index' => 4,
|
'index' => 4,
|
||||||
|
@ -523,8 +524,8 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
}
|
}
|
||||||
|
|
||||||
$returnValue['share'] = [
|
$returnValue['share'] = [
|
||||||
'url' => action('TracksController@getShortlink', ['id' => $track->id]),
|
'url' => action([TracksController::class, 'getShortlink'], ['id' => $track->id]),
|
||||||
'html' => '<iframe src="'.action('TracksController@getEmbed', ['id' => $track->id]).'" width="100%" height="150" allowTransparency="true" frameborder="0" seamless allowfullscreen></iframe>',
|
'html' => '<iframe src="'.action([TracksController::class, 'getEmbed'], ['id' => $track->id]).'" width="100%" height="150" allowTransparency="true" frameborder="0" seamless allowfullscreen></iframe>',
|
||||||
'bbcode' => '[url='.$track->url.'][img]'.$track->getCoverUrl().'[/img][/url]',
|
'bbcode' => '[url='.$track->url.'][img]'.$track->getCoverUrl().'[/img][/url]',
|
||||||
'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text='.$track->title.' by '.$track->user->display_name.' on Pony.fm',
|
'twitterUrl' => 'https://platform.twitter.com/widgets/tweet_button.html?text='.$track->title.' by '.$track->user->display_name.' on Pony.fm',
|
||||||
];
|
];
|
||||||
|
@ -813,7 +814,7 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
*/
|
*/
|
||||||
public function getUrlAttribute()
|
public function getUrlAttribute()
|
||||||
{
|
{
|
||||||
return action('TracksController@getTrack', ['id' => $this->id, 'slug' => $this->slug]);
|
return action([TracksController::class, 'getTrack'], ['id' => $this->id, 'slug' => $this->slug]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -942,7 +943,7 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
*/
|
*/
|
||||||
public function getStreamUrl(string $format = 'MP3', string $apiClientId = null)
|
public function getStreamUrl(string $format = 'MP3', string $apiClientId = null)
|
||||||
{
|
{
|
||||||
return action('TracksController@getStream',
|
return action([TracksController::class, 'getStream'],
|
||||||
[
|
[
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'extension' => self::$Formats[$format]['extension'],
|
'extension' => self::$Formats[$format]['extension'],
|
||||||
|
@ -1052,7 +1053,7 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
|
|
||||||
$format = self::$Formats[$format];
|
$format = self::$Formats[$format];
|
||||||
|
|
||||||
return action('TracksController@getDownload', ['id' => $this->id, 'extension' => $format['extension']]);
|
return action([TracksController::class, 'getDownload'], ['id' => $this->id, 'extension' => $format['extension']]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1160,9 +1161,7 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
*/
|
*/
|
||||||
private function updateTagsWithGetId3(string $format)
|
private function updateTagsWithGetId3(string $format)
|
||||||
{
|
{
|
||||||
require_once app_path().'/Library/getid3/getid3/getid3.php';
|
$tagWriter = new \getid3_writetags;
|
||||||
require_once app_path().'/Library/getid3/getid3/write.php';
|
|
||||||
$tagWriter = new getid3_writetags;
|
|
||||||
|
|
||||||
$tagWriter->overwrite_tags = true;
|
$tagWriter->overwrite_tags = true;
|
||||||
$tagWriter->tag_encoding = 'UTF-8';
|
$tagWriter->tag_encoding = 'UTF-8';
|
||||||
|
@ -1171,7 +1170,7 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
$tagWriter->tag_data = [
|
$tagWriter->tag_data = [
|
||||||
'title' => [$this->title],
|
'title' => [$this->title],
|
||||||
'artist' => [$this->user->display_name],
|
'artist' => [$this->user->display_name],
|
||||||
'year' => [''.$this->year],
|
'year' => [(string) $this->year],
|
||||||
'genre' => [$this->genre != null ? $this->genre->name : ''],
|
'genre' => [$this->genre != null ? $this->genre->name : ''],
|
||||||
'comment' => ['Downloaded from: https://pony.fm/'],
|
'comment' => ['Downloaded from: https://pony.fm/'],
|
||||||
'copyright' => ['© '.$this->year.' '.$this->user->display_name],
|
'copyright' => ['© '.$this->year.' '.$this->user->display_name],
|
||||||
|
@ -1185,7 +1184,7 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
|
|
||||||
if ($this->album_id !== null) {
|
if ($this->album_id !== null) {
|
||||||
$tagWriter->tag_data['album'] = [$this->album->title];
|
$tagWriter->tag_data['album'] = [$this->album->title];
|
||||||
$tagWriter->tag_data['track'] = [$this->track_number];
|
$tagWriter->tag_data['track'] = [(string) $this->track_number];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($format == 'MP3' && $this->cover_id != null && is_file($this->cover->getFile())) {
|
if ($format == 'MP3' && $this->cover_id != null && is_file($this->cover->getFile())) {
|
||||||
|
@ -1250,8 +1249,8 @@ class Track extends Model implements Searchable, Commentable, Favouritable
|
||||||
'title' => $this->title,
|
'title' => $this->title,
|
||||||
'artist' => $this->user->display_name,
|
'artist' => $this->user->display_name,
|
||||||
'published_at' => $this->published_at ? $this->published_at->toIso8601String() : null,
|
'published_at' => $this->published_at ? $this->published_at->toIso8601String() : null,
|
||||||
'genre' => $this->genre->name,
|
'genre' => $this->genre?->name,
|
||||||
'track_type' => $this->trackType->title,
|
'track_type' => $this->trackType?->title,
|
||||||
'show_songs' => $this->showSongs->pluck('title'),
|
'show_songs' => $this->showSongs->pluck('title'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Http\Controllers\TracksController;
|
||||||
use Helpers;
|
use Helpers;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
|
@ -144,7 +145,7 @@ class TrackFile extends Model
|
||||||
|
|
||||||
public function getUrlAttribute()
|
public function getUrlAttribute()
|
||||||
{
|
{
|
||||||
return action('TracksController@getDownload', ['id' => $this->track_id, 'extension' => $this->extension]);
|
return action([TracksController::class, 'getDownload'], ['id' => $this->track_id, 'extension' => $this->extension]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizeAttribute()
|
public function getSizeAttribute()
|
||||||
|
|
|
@ -22,6 +22,7 @@ namespace App\Models;
|
||||||
|
|
||||||
use App\Contracts\Commentable;
|
use App\Contracts\Commentable;
|
||||||
use App\Contracts\Searchable;
|
use App\Contracts\Searchable;
|
||||||
|
use App\Http\Controllers\ArtistsController;
|
||||||
use App\Traits\IndexedInElasticsearchTrait;
|
use App\Traits\IndexedInElasticsearchTrait;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Gravatar;
|
use Gravatar;
|
||||||
|
@ -346,7 +347,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
||||||
|
|
||||||
public function getUrlAttribute()
|
public function getUrlAttribute()
|
||||||
{
|
{
|
||||||
return action('ArtistsController@getProfile', $this->slug);
|
return action([ArtistsController::class, 'getProfile'], $this->slug);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMessageUrlAttribute()
|
public function getMessageUrlAttribute()
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Library\Search;
|
||||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
use Illuminate\Foundation\Application;
|
use Illuminate\Foundation\Application;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
@ -48,12 +49,12 @@ class AppServiceProvider extends ServiceProvider
|
||||||
*/
|
*/
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
$this->app->bind(Poniverse::class, function (Application $app) {
|
$this->app->bind(\Poniverse::class, function (Application $app) {
|
||||||
return new Poniverse($app['config']->get('poniverse.client_id'), $app['config']->get('poniverse.secret'));
|
return new \Poniverse($app['config']->get('poniverse.client_id'), $app['config']->get('poniverse.secret'));
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->app->bind(App\Library\Search::class, function (Application $app) {
|
$this->app->bind(Search::class, function (Application $app) {
|
||||||
return new App\Library\Search(
|
return new Search(
|
||||||
\Elasticsearch::connection(),
|
\Elasticsearch::connection(),
|
||||||
$app['config']->get('ponyfm.elasticsearch_index')
|
$app['config']->get('ponyfm.elasticsearch_index')
|
||||||
);
|
);
|
||||||
|
|
|
@ -51,7 +51,7 @@ trait IndexedInElasticsearchTrait
|
||||||
});
|
});
|
||||||
|
|
||||||
static::deleted(function (Searchable $entity) {
|
static::deleted(function (Searchable $entity) {
|
||||||
$entity->updateElasticsearchEntry();
|
$entity->updateElasticsearchEntry(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ trait IndexedInElasticsearchTrait
|
||||||
private function getElasticsearchParameters(bool $includeBody = true)
|
private function getElasticsearchParameters(bool $includeBody = true)
|
||||||
{
|
{
|
||||||
$parameters = [
|
$parameters = [
|
||||||
'index' => config('ponyfm.elasticsearch_index'),
|
'index' => config('ponyfm.elasticsearch_index')."-".$this->elasticsearchType,
|
||||||
'type' => $this->elasticsearchType,
|
'type' => $this->elasticsearchType,
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
];
|
];
|
||||||
|
@ -74,41 +74,15 @@ trait IndexedInElasticsearchTrait
|
||||||
return $parameters;
|
return $parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createOrUpdateElasticsearchEntry()
|
|
||||||
{
|
|
||||||
Elasticsearch::connection()->index($this->getElasticsearchParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
private function deleteElasticsearchEntry()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
Elasticsearch::connection()->delete($this->getElasticsearchParameters(false));
|
|
||||||
} catch (Missing404Exception $e) {
|
|
||||||
// If the entity we're trying to delete isn't indexed in Elasticsearch,
|
|
||||||
// that's fine.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously updates the Elasticsearch entry.
|
* Asynchronously updates the Elasticsearch entry.
|
||||||
* When in doubt, this is the method to use.
|
* When in doubt, this is the method to use.
|
||||||
|
*
|
||||||
|
* @param bool $removeFromIndex
|
||||||
*/
|
*/
|
||||||
public function updateElasticsearchEntry()
|
public function updateElasticsearchEntry(bool $removeFromIndex = false)
|
||||||
{
|
{
|
||||||
$job = (new UpdateSearchIndexForEntity($this))->onQueue(config('ponyfm.indexing_queue'));
|
$job = (new UpdateSearchIndexForEntity($this->getElasticsearchParameters(!$removeFromIndex), $removeFromIndex))->onQueue(config('ponyfm.indexing_queue'));
|
||||||
$this->dispatch($job);
|
$this->dispatch($job);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronously updates the Elasticsearch entry. This should only be
|
|
||||||
* called from the UpdateSearchIndexForEntity job.
|
|
||||||
*/
|
|
||||||
public function updateElasticsearchEntrySynchronously()
|
|
||||||
{
|
|
||||||
if ($this->shouldBeIndexed()) {
|
|
||||||
$this->createOrUpdateElasticsearchEntry();
|
|
||||||
} else {
|
|
||||||
$this->deleteElasticsearchEntry();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"license": "AGPL",
|
"license": "AGPL",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.4|^8.0",
|
"php": "^8.0",
|
||||||
"laravel/framework": "^8.27",
|
"laravel/framework": "^8.27",
|
||||||
"codescale/ffmpeg-php": "2.7.0",
|
"codescale/ffmpeg-php": "2.7.0",
|
||||||
"guzzlehttp/guzzle": "^7.0.1",
|
"guzzlehttp/guzzle": "^7.0.1",
|
||||||
|
@ -20,9 +20,9 @@
|
||||||
"cviebrock/laravel-elasticsearch": "^8.0",
|
"cviebrock/laravel-elasticsearch": "^8.0",
|
||||||
"barryvdh/laravel-debugbar": "^3.5",
|
"barryvdh/laravel-debugbar": "^3.5",
|
||||||
"predis/predis": "^1.1",
|
"predis/predis": "^1.1",
|
||||||
"ksubileau/color-thief-php": "^1.3",
|
"ksubileau/color-thief-php": "v2.0.x-dev",
|
||||||
"graham-campbell/exceptions": "^14.0",
|
"graham-campbell/exceptions": "^14.0",
|
||||||
"minishlink/web-push": "^1.0",
|
"minishlink/web-push": "^6.0",
|
||||||
"alsofronie/eloquent-uuid": "^1.0",
|
"alsofronie/eloquent-uuid": "^1.0",
|
||||||
"poniverse/api": "dev-rewrite",
|
"poniverse/api": "dev-rewrite",
|
||||||
"fruitcake/laravel-cors": "2.0.1",
|
"fruitcake/laravel-cors": "2.0.1",
|
||||||
|
@ -31,7 +31,8 @@
|
||||||
"doctrine/annotations": "^1.11",
|
"doctrine/annotations": "^1.11",
|
||||||
"doctrine/cache": "^1.8",
|
"doctrine/cache": "^1.8",
|
||||||
"doctrine/instantiator": "^1.4",
|
"doctrine/instantiator": "^1.4",
|
||||||
"fideloper/proxy": "^4.4"
|
"fideloper/proxy": "^4.4",
|
||||||
|
"james-heinrich/getid3": "^1.9"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"mockery/mockery": "^1.4.2",
|
"mockery/mockery": "^1.4.2",
|
||||||
|
@ -46,6 +47,9 @@
|
||||||
"barryvdh/laravel-ide-helper": "^2.9"
|
"barryvdh/laravel-ide-helper": "^2.9"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"vendor/james-heinrich/getid3/getid3/getid3.php"
|
||||||
|
],
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"database/migrations",
|
"database/migrations",
|
||||||
"app/Library"
|
"app/Library"
|
||||||
|
|
1850
composer.lock
generated
1850
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -35,7 +35,10 @@ class AddDeletedAtColumnToActivities extends Migration
|
||||||
$table->softDeletes()->index();
|
$table->softDeletes()->index();
|
||||||
});
|
});
|
||||||
|
|
||||||
if ('sqlite' !== DB::getDriverName()) {
|
// this has issues now, but considering it's about 5 years old and already ran in production
|
||||||
|
// i don't think we need to worry about making this work :)
|
||||||
|
|
||||||
|
/*if ('sqlite' !== DB::getDriverName()) {
|
||||||
// Retroactively fix activities that should be marked as deleted.
|
// Retroactively fix activities that should be marked as deleted.
|
||||||
// Tracks
|
// Tracks
|
||||||
DB::table('activities')
|
DB::table('activities')
|
||||||
|
@ -64,7 +67,7 @@ class AddDeletedAtColumnToActivities extends Migration
|
||||||
->join('comments', 'activities.resource_id', '=', 'comments.id')
|
->join('comments', 'activities.resource_id', '=', 'comments.id')
|
||||||
->whereNotNull('comments.deleted_at')
|
->whereNotNull('comments.deleted_at')
|
||||||
->update(['deleted_at' => DB::raw('comments.deleted_at')]);
|
->update(['deleted_at' => DB::raw('comments.deleted_at')]);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
docker/composer8.0/Dockerfile
Normal file
7
docker/composer8.0/Dockerfile
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
FROM php:8.0-fpm-alpine
|
||||||
|
|
||||||
|
RUN docker-php-ext-install mysqli pdo pdo_mysql
|
||||||
|
|
||||||
|
COPY --from=composer /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
ENTRYPOINT ["composer"]
|
20
docker/entrypoint.sh
Executable file
20
docker/entrypoint.sh
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
MODE=$1
|
||||||
|
|
||||||
|
case $MODE in
|
||||||
|
web)
|
||||||
|
php-fpm -D
|
||||||
|
nginx -g 'pid /tmp/nginx.pid; daemon off;'
|
||||||
|
;;
|
||||||
|
|
||||||
|
worker)
|
||||||
|
sudo -Esu www-data php artisan queue:listen --queue=default,notifications,indexing --sleep=5 --tries=3
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown mode given"
|
||||||
|
;;
|
||||||
|
esac
|
26
docker/nginx/site.conf
Normal file
26
docker/nginx/site.conf
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
server {
|
||||||
|
root /app/public;
|
||||||
|
|
||||||
|
index index.php index.html index.htm;
|
||||||
|
|
||||||
|
client_max_body_size 600m;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.php$is_args$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /app/storage/app/datastore {
|
||||||
|
internal;
|
||||||
|
alias /app/storage/app/datastore/;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
location ~ [^/]\.php(/|$) {
|
||||||
|
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
||||||
|
# Mitigate https://httpoxy.org/ vulnerabilities
|
||||||
|
fastcgi_param HTTP_PROXY "";
|
||||||
|
fastcgi_pass 127.0.0.1:9000;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
include fastcgi.conf;
|
||||||
|
}
|
||||||
|
}
|
3
docker/php/php.ini
Normal file
3
docker/php/php.ini
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[php]
|
||||||
|
post_max_size = 600M
|
||||||
|
upload_max_filesize = 600M
|
18
gulpfile.js
18
gulpfile.js
|
@ -94,9 +94,9 @@ gulp.task("webpack-dev-server", function () {
|
||||||
|
|
||||||
gulp.task("styles-app", function () {
|
gulp.task("styles-app", function () {
|
||||||
var includedStyles = [
|
var includedStyles = [
|
||||||
"resources/assets/styles/base/jquery-ui.css",
|
"resources/styles/base/jquery-ui.css",
|
||||||
"resources/assets/styles/base/colorbox.css",
|
"resources/styles/base/colorbox.css",
|
||||||
"resources/assets/styles/app.less"
|
"resources/styles/app.less"
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!argv.production) {
|
if (!argv.production) {
|
||||||
|
@ -104,7 +104,7 @@ gulp.task("styles-app", function () {
|
||||||
// we want to watch embed files and re-compile them. However, we want
|
// we want to watch embed files and re-compile them. However, we want
|
||||||
// to leave this path out in production so that embed files are not bloating
|
// to leave this path out in production so that embed files are not bloating
|
||||||
// the css file
|
// the css file
|
||||||
includedStyles.push("resources/assets/styles/embed.less");
|
includedStyles.push("resources/styles/embed.less");
|
||||||
|
|
||||||
// Remove app.less from the cache so that it gets recompiled
|
// Remove app.less from the cache so that it gets recompiled
|
||||||
var styleCache = plug.cached.caches.styles;
|
var styleCache = plug.cached.caches.styles;
|
||||||
|
@ -124,7 +124,7 @@ gulp.task("styles-app", function () {
|
||||||
|
|
||||||
return argv.production
|
return argv.production
|
||||||
// Production pipeline
|
// Production pipeline
|
||||||
? gulp.src(includedStyles, {base: "resources/assets/styles"})
|
? gulp.src(includedStyles, {base: "resources/styles"})
|
||||||
.pipe(plug.plumber(plumberOptions))
|
.pipe(plug.plumber(plumberOptions))
|
||||||
.pipe(plug.if(/\.less/, plug.less()))
|
.pipe(plug.if(/\.less/, plug.less()))
|
||||||
.pipe(plug.autoprefixer({
|
.pipe(plug.autoprefixer({
|
||||||
|
@ -137,7 +137,7 @@ gulp.task("styles-app", function () {
|
||||||
.pipe(gulp.dest("public/build/styles"))
|
.pipe(gulp.dest("public/build/styles"))
|
||||||
|
|
||||||
// Development pipeline
|
// Development pipeline
|
||||||
: gulp.src(includedStyles, {base: "resources/assets/styles"})
|
: gulp.src(includedStyles, {base: "resources/styles"})
|
||||||
.pipe(plug.plumber(plumberOptions))
|
.pipe(plug.plumber(plumberOptions))
|
||||||
.pipe(plug.cached("styles"))
|
.pipe(plug.cached("styles"))
|
||||||
.pipe(plug.sourcemaps.init())
|
.pipe(plug.sourcemaps.init())
|
||||||
|
@ -153,7 +153,7 @@ gulp.task("styles-embed", function () {
|
||||||
// since development-mode watches and builds include the embed styles
|
// since development-mode watches and builds include the embed styles
|
||||||
// already
|
// already
|
||||||
|
|
||||||
return gulp.src(["resources/assets/styles/embed.less"], {base: "resources/assets/styles"})
|
return gulp.src(["resources/styles/embed.less"], {base: "resources/styles"})
|
||||||
.pipe(plug.less())
|
.pipe(plug.less())
|
||||||
.pipe(plug.autoprefixer({
|
.pipe(plug.autoprefixer({
|
||||||
browsers: ["last 2 versions"],
|
browsers: ["last 2 versions"],
|
||||||
|
@ -166,7 +166,7 @@ gulp.task("styles-embed", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('copy:templates', function () {
|
gulp.task('copy:templates', function () {
|
||||||
gulp.src([
|
return gulp.src([
|
||||||
'public/templates/**/*.html'
|
'public/templates/**/*.html'
|
||||||
])
|
])
|
||||||
.pipe(plug.angularTemplatecache({
|
.pipe(plug.angularTemplatecache({
|
||||||
|
@ -312,7 +312,7 @@ gulp.task('build', gulp.parallel('webpack-build',
|
||||||
|
|
||||||
|
|
||||||
gulp.task("watch-legacy", gulp.series(gulp.parallel("build"), function () {
|
gulp.task("watch-legacy", gulp.series(gulp.parallel("build"), function () {
|
||||||
gulp.watch("resources/assets/styles/**/*.{css,less}", gulp.parallel("styles-app"));
|
gulp.watch("resources/styles/**/*.{css,less}", gulp.parallel("styles-app"));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
gulp.task("watch", gulp.parallel("webpack-dev-server", "email-default", "watch-legacy"));
|
gulp.task("watch", gulp.parallel("webpack-dev-server", "email-default", "watch-legacy"));
|
||||||
|
|
|
@ -43,8 +43,7 @@ require 'script!../base/moment'
|
||||||
require '../base/soundmanager2-nodebug'
|
require '../base/soundmanager2-nodebug'
|
||||||
require 'script!../base/tumblr'
|
require 'script!../base/tumblr'
|
||||||
require 'angular-strap'
|
require 'angular-strap'
|
||||||
# Just ignore this, blame webpack
|
require 'angular-strap/dist/angular-strap.tpl.js'
|
||||||
require '../../../../node_modules/angular-strap/dist/angular-strap.tpl'
|
|
||||||
require 'chart.js';
|
require 'chart.js';
|
||||||
require 'angular-chart.js';
|
require 'angular-chart.js';
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ module.exports = {
|
||||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
|
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
|
||||||
],
|
],
|
||||||
entry: {
|
entry: {
|
||||||
app: './resources/assets/scripts/app/app.coffee',
|
app: './resources/scripts/app/app.coffee',
|
||||||
embed: './resources/assets/scripts/embed/embed.coffee'
|
embed: './resources/scripts/embed/embed.coffee'
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: __dirname + '/public',
|
path: __dirname + '/public',
|
||||||
|
|
Loading…
Add table
Reference in a new issue