[#7] Prevent completely lossy albums/playlists from being downloaded as lossless

This commit is contained in:
Kelvin 2016-07-10 15:00:59 +01:00
parent a2f00f8134
commit 05c66ca5dd
5 changed files with 60 additions and 3 deletions

View file

@ -61,7 +61,7 @@ class AlbumsController extends Controller
public function getDownload($id, $extension) public function getDownload($id, $extension)
{ {
$album = Album::with('tracks', 'user')->find($id); $album = Album::with('tracks', 'tracks.trackFiles', 'user')->find($id);
if (!$album) { if (!$album) {
App::abort(404); App::abort(404);
} }
@ -81,6 +81,10 @@ class AlbumsController extends Controller
App::abort(404); App::abort(404);
} }
if (!Album::hasLosslessTracks($album) && in_array($formatName, Track::$LosslessFormats)) {
App::abort(404);
}
ResourceLogItem::logItem('album', $id, ResourceLogItem::DOWNLOAD, $format['index']); ResourceLogItem::logItem('album', $id, ResourceLogItem::DOWNLOAD, $format['index']);
$downloader = new AlbumDownloader($album, $formatName); $downloader = new AlbumDownloader($album, $formatName);
$downloader->download(); $downloader->download();

View file

@ -62,7 +62,7 @@ class PlaylistsController extends Controller
public function getDownload($id, $extension) public function getDownload($id, $extension)
{ {
$playlist = Playlist::with('tracks', 'user', 'tracks.album')->find($id); $playlist = Playlist::with('tracks', 'tracks.trackFiles', 'user', 'tracks.album')->find($id);
if (!$playlist || (!$playlist->is_public && !Auth::check()) || (!$playlist->is_public && ($playlist->user_id !== Auth::user()->id))) { if (!$playlist || (!$playlist->is_public && !Auth::check()) || (!$playlist->is_public && ($playlist->user_id !== Auth::user()->id))) {
App::abort(404); App::abort(404);
} }
@ -82,6 +82,10 @@ class PlaylistsController extends Controller
App::abort(404); App::abort(404);
} }
if (!Playlist::hasLosslessTracks($playlist) && in_array($formatName, Track::$LosslessFormats)) {
App::abort(404);
}
ResourceLogItem::logItem('playlist', $id, ResourceLogItem::DOWNLOAD, $format['index']); ResourceLogItem::logItem('playlist', $id, ResourceLogItem::DOWNLOAD, $format['index']);
$downloader = new PlaylistDownloader($playlist, $formatName); $downloader = new PlaylistDownloader($playlist, $formatName);
$downloader->download(); $downloader->download();

View file

@ -134,6 +134,18 @@ class Album extends Model implements Searchable, Commentable, Favouritable
return $this->morphMany(Activity::class, 'resource'); return $this->morphMany(Activity::class, 'resource');
} }
public static function hasLosslessTracks(Album $album)
{
$hasLosslessTracks = false;
foreach ($album->tracks as $track) {
if (!$track->isMasterLossy()) {
$hasLosslessTracks = true;
break;
}
}
return $hasLosslessTracks;
}
public static function mapPublicAlbumShow(Album $album) public static function mapPublicAlbumShow(Album $album)
{ {
$tracks = []; $tracks = [];
@ -142,7 +154,12 @@ class Album extends Model implements Searchable, Commentable, Favouritable
} }
$formats = []; $formats = [];
$hasLosslessTracks = Album::hasLosslessTracks($album);
foreach (Track::$Formats as $name => $format) { foreach (Track::$Formats as $name => $format) {
if (!$hasLosslessTracks && in_array($name, Track::$LosslessFormats)) {
continue;
}
$formats[] = [ $formats[] = [
'name' => $name, 'name' => $name,
'extension' => $format['extension'], 'extension' => $format['extension'],
@ -151,7 +168,7 @@ class Album extends Model implements Searchable, Commentable, Favouritable
'isCacheable' => (in_array($name, Track::$CacheableFormats) ? true : false) 'isCacheable' => (in_array($name, Track::$CacheableFormats) ? true : false)
]; ];
} }
$comments = []; $comments = [];
foreach ($album->comments as $comment) { foreach ($album->comments as $comment) {
$comments[] = Comment::mapPublic($comment); $comments[] = Comment::mapPublic($comment);

View file

@ -107,6 +107,18 @@ class Playlist extends Model implements Searchable, Commentable, Favouritable
return !$query; return !$query;
} }
public static function hasLosslessTracks(Playlist $playlist)
{
$hasLosslessTracks = false;
foreach ($playlist->tracks as $track) {
if (!$track->isMasterLossy()) {
$hasLosslessTracks = true;
break;
}
}
return $hasLosslessTracks;
}
public static function mapPublicPlaylistShow(Playlist $playlist) public static function mapPublicPlaylistShow(Playlist $playlist)
{ {
$tracks = []; $tracks = [];
@ -117,7 +129,12 @@ class Playlist extends Model implements Searchable, Commentable, Favouritable
} }
$formats = []; $formats = [];
$hasLosslessTracks = Playlist::hasLosslessTracks($playlist);
foreach (Track::$Formats as $name => $format) { foreach (Track::$Formats as $name => $format) {
if (!$hasLosslessTracks && in_array($name, Track::$LosslessFormats)) {
continue;
}
$formats[] = [ $formats[] = [
'name' => $name, 'name' => $name,
'extension' => $format['extension'], 'extension' => $format['extension'],

View file

@ -205,6 +205,11 @@ class Track extends Model implements Searchable, Commentable, Favouritable
'AAC' 'AAC'
]; ];
public static $LosslessFormats = [
'FLAC',
'ALAC'
];
public static function summary() public static function summary()
{ {
return self::select('tracks.id', 'title', 'user_id', 'slug', 'is_vocal', 'is_explicit', 'created_at', return self::select('tracks.id', 'title', 'user_id', 'slug', 'is_vocal', 'is_explicit', 'created_at',
@ -628,6 +633,16 @@ class Track extends Model implements Searchable, Commentable, Favouritable
return $this->published_at != null && $this->deleted_at == null; return $this->published_at != null && $this->deleted_at == null;
} }
public function isMasterLossy()
{
return is_null(
$this->trackFiles->where('is_master', true)
->first(function ($key, $trackFile) {
return in_array($trackFile->format, Track::$LosslessFormats);
})
);
}
public function getCoverUrl($type = Image::NORMAL) public function getCoverUrl($type = Image::NORMAL)
{ {
if (!$this->hasCover()) { if (!$this->hasCover()) {