From 92c2c43e588ab3b4b7fd44987a22cc6635cae2c2 Mon Sep 17 00:00:00 2001 From: Kelvin Zhang Date: Thu, 10 Sep 2015 12:15:19 +0100 Subject: [PATCH] Merge rPF91611faead64: Merge the MLP Music Archive import scripts. --- .arcconfig | 5 +- app/Commands/UploadTrackCommand.php | 64 ++- app/Console/Commands/ClassifyMLPMA.php | 209 +++++++++ app/Console/Commands/ImportMLPMA.php | 408 ++++++++++++++++++ app/Console/Kernel.php | 2 + app/Track.php | 14 +- app/TrackType.php | 6 + .../2015_09_10_105709_make_email_nullable.php | 27 ++ .../2015_09_10_105950_add_new_indicies.php | 45 ++ .../2015_09_10_105956_create_mlpma_table.php | 38 ++ vagrant/config/app.php | 1 + 11 files changed, 811 insertions(+), 8 deletions(-) create mode 100644 app/Console/Commands/ClassifyMLPMA.php create mode 100644 app/Console/Commands/ImportMLPMA.php create mode 100644 database/migrations/2015_09_10_105709_make_email_nullable.php create mode 100644 database/migrations/2015_09_10_105950_add_new_indicies.php create mode 100644 database/migrations/2015_09_10_105956_create_mlpma_table.php diff --git a/.arcconfig b/.arcconfig index fe223088..f4b1e785 100644 --- a/.arcconfig +++ b/.arcconfig @@ -1,3 +1,4 @@ { - "phabricator.uri" : "https://phabricator.poniverse.net/" -} + "phabricator.uri" : "https://phabricator.poniverse.net/", + "history.immutable" : true +} \ No newline at end of file diff --git a/app/Commands/UploadTrackCommand.php b/app/Commands/UploadTrackCommand.php index d91e9b97..41d8938f 100644 --- a/app/Commands/UploadTrackCommand.php +++ b/app/Commands/UploadTrackCommand.php @@ -4,10 +4,32 @@ namespace App\Commands; use App\Track; use App\TrackFile; +use AudioCache; +use File; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Str; class UploadTrackCommand extends CommandBase { + private $_allowLossy; + private $_allowShortTrack; + private $_losslessFormats = [ + 'flac', + 'pcm_s16le ([1][0][0][0] / 0x0001)', + 'pcm_s16be', + 'adpcm_ms ([2][0][0][0] / 0x0002)', + 'pcm_s24le ([1][0][0][0] / 0x0001)', + 'pcm_s24be', + 'pcm_f32le ([3][0][0][0] / 0x0003)', + 'pcm_f32be (fl32 / 0x32336C66)' + ]; + + public function __construct($allowLossy = false, $allowShortTrack = false) + { + $this->_allowLossy = $allowLossy; + $this->_allowShortTrack = $allowShortTrack; + } + /** * @return bool */ @@ -29,10 +51,10 @@ class UploadTrackCommand extends CommandBase $validator = \Validator::make(['track' => $trackFile], [ 'track' => 'required|' - . 'audio_format:flac,pcm_s16le ([1][0][0][0] / 0x0001),pcm_s16be,adpcm_ms ([2][0][0][0] / 0x0002),pcm_s24le ([1][0][0][0] / 0x0001),pcm_s24be,pcm_f32le ([3][0][0][0] / 0x0003),pcm_f32be (fl32 / 0x32336C66)|' + . ($this->_allowLossy ? '' : 'audio_format:'. implode(',', $this->_losslessFormats).'|') + . ($this->_allowShortTrack ? '' : 'min_duration:30|') . 'audio_channels:1,2|' - . 'sample_rate:44100,48000,88200,96000,176400,192000|' - . 'min_duration:30' + . 'sample_rate:44100,48000,88200,96000,176400,192000' ]); if ($validator->fails()) { @@ -57,7 +79,43 @@ class UploadTrackCommand extends CommandBase $processes = []; + // Lossy uploads need to be identified and set as the master file + // without being re-encoded. + $audioObject = AudioCache::get($source); + $isLossyUpload = !in_array($audioObject->getAudioCodec(), $this->_losslessFormats); + + if ($isLossyUpload) { + if ($audioObject->getAudioCodec() === 'mp3') { + $masterFormat = 'MP3'; + + } else if (Str::startsWith($audioObject->getAudioCodec(), 'aac')) { + $masterFormat = 'AAC'; + + } else if ($audioObject->getAudioCodec() === 'vorbis') { + $masterFormat = 'OGG Vorbis'; + + } else { + $validator->messages()->add('track', 'The track does not contain audio in a known lossy format.'); + return CommandResponse::fail($validator); + } + + $trackFile = new TrackFile(); + $trackFile->is_master = true; + $trackFile->format = $masterFormat; + $trackFile->track_id = $track->id; + $trackFile->save(); + + // Lossy masters are copied into the datastore - no re-encoding involved. + File::copy($source, $trackFile->getFile()); + } + foreach (Track::$Formats as $name => $format) { + // Don't bother with lossless transcodes of lossy uploads, and + // don't re-encode the lossy master. + if ($isLossyUpload && ($format['is_lossless'] || $name === $masterFormat)) { + continue; + } + $trackFile = new TrackFile(); $trackFile->is_master = $name === 'FLAC' ? true : false; $trackFile->format = $name; diff --git a/app/Console/Commands/ClassifyMLPMA.php b/app/Console/Commands/ClassifyMLPMA.php new file mode 100644 index 00000000..a1d28dd0 --- /dev/null +++ b/app/Console/Commands/ClassifyMLPMA.php @@ -0,0 +1,209 @@ +orderBy('id') + ->get(); + + $this->comment('Importing tracks...'); + + $totalTracks = sizeof($tracks); + + $fileToStartAt = (int) $this->option('startAt') - 1; + $this->comment("Skipping $fileToStartAt files..." . PHP_EOL); + + $tracks = array_slice($tracks, $fileToStartAt); + $this->currentTrack = $fileToStartAt; + + foreach ($tracks as $track) { + $this->currentTrack++; + $this->comment('[' . $this->currentTrack . '/' . $totalTracks . '] Classifying track [' . $track->filename . ']...'); + + $parsedTags = json_decode($track->parsed_tags, true); + + + //========================================================================================================== + // Original, show song remix, fan song remix, show audio remix, or ponified song? + //========================================================================================================== + $sanitizedTrackTitle = $parsedTags['title']; + $sanitizedTrackTitle = str_replace([' - ', 'ft.', '*'], ' ', $sanitizedTrackTitle); + + $queriedTitle = DB::connection()->getPdo()->quote($sanitizedTrackTitle); + $officialSongs = ShowSong::select(['id', 'title']) + ->whereRaw(" + MATCH (title) + AGAINST ($queriedTitle IN BOOLEAN MODE) + ") + ->get(); + + + // If it has "Ingram" in the name, it's definitely an official song remix. + if (Str::contains(Str::lower($track->filename), 'ingram')) { + $this->info('This is an official song remix!'); + + list($trackType, $linkedSongIds) = $this->classifyTrack($track->filename, $officialSongs, true); + + + // If it has "remix" in the name, it's definitely a remix. + } else if (Str::contains(Str::lower($sanitizedTrackTitle), 'remix')) { + $this->info('This is some kind of remix!'); + + list($trackType, $linkedSongIds) = $this->classifyTrack($track->filename, $officialSongs); + + // No idea what this is. Have the pony at the terminal figure it out! + } else { + list($trackType, $linkedSongIds) = $this->classifyTrack($track->filename, $officialSongs); + } + + + //========================================================================================================== + // Attach the data and publish the track! + //========================================================================================================== + + $track = Track::find($track->track_id); + + $track->track_type_id = $trackType; + $track->published_at = $parsedTags['released_at']; + $track->save(); + + if (sizeof($linkedSongIds) > 0) { + $track->showSongs()->attach($linkedSongIds); + } + + echo PHP_EOL; + } + + } + + /** + * Determines what type of track the given file is. If unable to guess, the user + * is asked to identify it interactively. + * + * @param string $filename + * @param ShowSong[] $officialSongs + * @param bool|false $isRemixOfOfficialTrack + * @return array + */ + protected function classifyTrack($filename, $officialSongs, $isRemixOfOfficialTrack = false) { + $trackTypeId = null; + $linkedSongIds = []; + + + foreach ($officialSongs as $song) { + $this->comment('=> Matched official song: [' . $song->id . '] ' . $song->title); + } + + + if ($isRemixOfOfficialTrack && sizeof($officialSongs) === 1) { + $linkedSongIds = [$officialSongs[0]->id]; + + } else { + if ($isRemixOfOfficialTrack && sizeof($officialSongs) > 1) { + $this->question('Multiple official songs matched! Please enter the ID of the correct one.'); + + } else if (sizeof($officialSongs) > 0) { + $this->question('This looks like a remix of an official song!'); + $this->question('Press "r" if the match above is right!'); + + } else { + $this->question('Exactly what kind of track is this?'); + + } + $this->question('If this is a medley, multiple song ID\'s can be separated by commas. '); + $this->question(' '); + $this->question(' ' . $filename . ' '); + $this->question(' '); + $this->question(' r = official song remix (accept all "guessed" matches) '); + $this->question(' # = official song remix (enter the ID(s) of the show song(s)) '); + $this->question(' a = show audio remix '); + $this->question(' f = fan track remix '); + $this->question(' p = ponified track '); + $this->question(' o = original track '); + $this->question(' '); + $input = $this->ask('[r/#/a/f/p/o]: '); + + switch ($input) { + case 'r': + $trackTypeId = TrackType::OFFICIAL_TRACK_REMIX; + foreach ($officialSongs as $officialSong) { + $linkedSongIds[] = (int) $officialSong->id; + } + break; + + case 'a': + $trackTypeId = TrackType::OFFICIAL_AUDIO_REMIX; + break; + + case 'f': + $trackTypeId = TrackType::FAN_TRACK_REMIX; + break; + + case 'p': + $trackTypeId = TrackType::PONIFIED_TRACK; + break; + + case 'o': + $trackTypeId = TrackType::ORIGINAL_TRACK; + break; + + default: + $trackTypeId = TrackType::OFFICIAL_TRACK_REMIX; + $linkedSongIds = explode(',', $input); + $linkedSongIds = array_map(function ($item) { + return (int) $item; + }, $linkedSongIds); + } + } + + return [$trackTypeId, $linkedSongIds]; + } +} diff --git a/app/Console/Commands/ImportMLPMA.php b/app/Console/Commands/ImportMLPMA.php new file mode 100644 index 00000000..1bf660ae --- /dev/null +++ b/app/Console/Commands/ImportMLPMA.php @@ -0,0 +1,408 @@ +error('Import aborted!'); + $this->error('Resume it from here using: --startAt=' . $this->currentFile); + $this->isInterrupted = true; + } + + /** + * Execute the console command. + * + * @return void + */ + public function handle() + { + pcntl_signal(SIGINT, [$this, 'handleInterrupt']); + + $mlpmaPath = Config::get('app.files_directory') . 'mlpma'; + $tmpPath = Config::get('app.files_directory') . 'tmp'; + + if (!File::exists($tmpPath)) { + File::makeDirectory($tmpPath); + } + + $this->comment('Enumerating MLP Music Archive source files...'); + $files = File::allFiles($mlpmaPath); + $this->info(sizeof($files) . ' files found!'); + + $this->comment('Enumerating artists...'); + $artists = File::directories($mlpmaPath); + $this->info(sizeof($artists) . ' artists found!'); + + $this->comment('Importing tracks...'); + + $totalFiles = sizeof($files); + + $fileToStartAt = (int)$this->option('startAt') - 1; + $this->comment("Skipping $fileToStartAt files..." . PHP_EOL); + + $files = array_slice($files, $fileToStartAt); + $this->currentFile = $fileToStartAt; + + foreach ($files as $file) { + $this->currentFile++; + + pcntl_signal_dispatch(); + if ($this->isInterrupted) { + break; + } + + $this->comment('[' . $this->currentFile . '/' . $totalFiles . '] Importing track [' . $file->getFilename() . ']...'); + + if (in_array($file->getExtension(), $this->ignoredExtensions)) { + $this->comment('This is not an audio file! Skipping...' . PHP_EOL); + continue; + } + + + // Has this track already been imported? + $importedTrack = DB::table('mlpma_tracks') + ->where('filename', '=', $file->getFilename()) + ->first(); + + if ($importedTrack) { + $this->comment('This track has already been imported! Skipping...' . PHP_EOL); + continue; + } + + + //========================================================================================================== + // Extract the original tags. + //========================================================================================================== + $getId3 = new getID3; + + // all tags read by getID3, including the cover art + $allTags = $getId3->analyze($file->getPathname()); + + // tags specific to a file format (ID3 or Atom), pre-normalization but with cover art removed + $rawTags = []; + + // normalized tags used by Pony.fm + $parsedTags = []; + + if ($file->getExtension() === 'mp3') { + list($parsedTags, $rawTags) = $this->getId3Tags($allTags); + + } else { + if ($file->getExtension() === 'm4a') { + list($parsedTags, $rawTags) = $this->getAtomTags($allTags); + } + } + + + //========================================================================================================== + // Determine the release date. + //========================================================================================================== + $modifiedDate = Carbon::createFromTimeStampUTC(File::lastModified($file->getPathname())); + $taggedYear = $parsedTags['year']; + + $this->info('Modification year: ' . $modifiedDate->year); + $this->info('Tagged year: ' . $taggedYear); + + if ($taggedYear !== null && $modifiedDate->year === $taggedYear) { + $releasedAt = $modifiedDate; + + } else { + if ($taggedYear !== null && $modifiedDate->year !== $taggedYear) { + $this->error('Release years don\'t match! Using the tagged year...'); + $releasedAt = Carbon::create($taggedYear); + + } else { + // $taggedYear is null + $this->error('This track isn\'t tagged with its release year! Using the track\'s last modified date...'); + $releasedAt = $modifiedDate; + } + } + + // This is later used by the classification/publishing script to determine the publication date. + $parsedTags['released_at'] = $releasedAt->toDateTimeString(); + + //========================================================================================================== + // Does this track have vocals? + //========================================================================================================== + $isVocal = $parsedTags['lyrics'] !== null; + + + //========================================================================================================== + // Determine which artist account this file belongs to using the containing directory. + //========================================================================================================== + $this->info('Path to file: ' . $file->getRelativePath()); + $path_components = explode(DIRECTORY_SEPARATOR, $file->getRelativePath()); + $artist_name = $path_components[0]; + $album_name = array_key_exists(1, $path_components) ? $path_components[1] : null; + + $this->info('Artist: ' . $artist_name); + $this->info('Album: ' . $album_name); + + $artist = User::where('display_name', '=', $artist_name)->first(); + + if (!$artist) { + $artist = new User; + $artist->display_name = $artist_name; + $artist->email = null; + $artist->is_archived = true; + + $artist->slug = Str::slug($artist_name); + + $slugExists = User::where('slug', '=', $artist->slug)->first(); + if ($slugExists) { + $this->error('Horsefeathers! The slug ' . $artist->slug . ' is already taken!'); + $artist->slug = $artist->slug . '-' . Str::random(4); + } + + $artist->save(); + } + + //========================================================================================================== + // Extract the cover art, if any exists. + //========================================================================================================== + + $this->comment('Extracting cover art!'); + $coverId = null; + if (array_key_exists('comments', $allTags) && array_key_exists('picture', $allTags['comments'])) { + $image = $allTags['comments']['picture'][0]; + + if ($image['image_mime'] === 'image/png') { + $extension = 'png'; + + } else { + if ($image['image_mime'] === 'image/jpeg') { + $extension = 'jpg'; + + } else { + if ($image['image_mime'] === 'image/gif') { + $extension = 'gif'; + + } else { + $this->error('Unknown cover art format!'); + } + } + } + + // write temporary image file + $imageFilename = $file->getFilename() . ".cover.$extension"; + $imageFilePath = "$tmpPath/" . $imageFilename; + File::put($imageFilePath, $image['data']); + + + $imageFile = new UploadedFile($imageFilePath, $imageFilename, $image['image_mime']); + + $cover = Image::upload($imageFile, $artist); + $coverId = $cover->id; + + } else { + $this->comment('No cover art found!'); + } + + + //========================================================================================================== + // Is this part of an album? + //========================================================================================================== + // Find the album if it exists and create it if it doesn't. + $albumId = null; + $albumName = $parsedTags['album']; + + if ($albumName !== null) { + $album = Album::where('user_id', '=', $artist->id) + ->where('title', '=', $albumName) + ->first(); + + if (!$album) { + $album = new Album; + + $album->title = $albumName; + $album->user_id = $artist->id; + $album->cover_id = $coverId; + + $album->save(); + } + + $albumId = $album->id; + } + + + //========================================================================================================== + // Save this track. + //========================================================================================================== + + // "Upload" the track to Pony.fm + $this->comment('Transcoding the track!'); + Auth::loginUsingId($artist->id); + + $trackFile = new UploadedFile($file->getPathname(), $file->getFilename(), $allTags['mime_type']); + Input::instance()->files->add(['track' => $trackFile]); + + $upload = new UploadTrackCommand(true); + $result = $upload->execute(); + + if ($result->didFail()) { + $this->error(json_encode($result->getValidator()->messages()->getMessages(), JSON_PRETTY_PRINT)); + + } else { + // Save metadata. + $track = Track::find($result->getResponse()['id']); + + $track->title = $parsedTags['title']; + $track->cover_id = $coverId; + $track->album_id = $albumId; + $track->track_number = $parsedTags['track_number']; + $track->released_at = $releasedAt; + $track->description = $parsedTags['comments']; + $track->is_downloadable = true; + $track->lyrics = $parsedTags['lyrics']; + $track->is_vocal = $isVocal; + $track->license_id = 2; + $track->save(); + + // If we made it to here, the track is intact! Log the import. + DB::table('mlpma_tracks') + ->insert([ + 'track_id' => $result->getResponse()['id'], + 'path' => $file->getRelativePath(), + 'filename' => $file->getFilename(), + 'extension' => $file->getExtension(), + 'imported_at' => Carbon::now(), + 'parsed_tags' => json_encode($parsedTags), + 'raw_tags' => json_encode($rawTags), + ]); + } + + echo PHP_EOL . PHP_EOL; + } + } + + /** + * @param array $rawTags + * @return array + */ + protected function getId3Tags($rawTags) + { + $tags = $rawTags['tags']['id3v2']; + $comment = null; + + if (isset($tags['comment'])) { + // The "comment" tag comes in with a badly encoded string index + // so its array key has to be used implicitly. + $key = array_keys($tags['comment'])[0]; + + // The comment may have a null byte at the end. trim() removes it. + $comment = trim($tags['comment'][$key]); + + // Replace the malformed comment with the "fixed" one. + unset($tags['comment'][$key]); + $tags['comment'][0] = $comment; + } + + return [ + [ + 'title' => $tags['title'][0], + 'artist' => $tags['artist'][0], + 'band' => isset($tags['band']) ? $tags['band'][0] : null, + 'genre' => isset($tags['genre']) ? $tags['genre'][0] : null, + 'track_number' => isset($tags['track_number']) ? $tags['track_number'][0] : null, + 'album' => isset($tags['album']) ? $tags['album'][0] : null, + 'year' => isset($tags['year']) ? (int)$tags['year'][0] : null, + 'comments' => $comment, + 'lyrics' => isset($tags['unsynchronised_lyric']) ? $tags['unsynchronised_lyric'][0] : null, + ], + $tags + ]; + } + + /** + * @param array $rawTags + * @return array + */ + protected function getAtomTags($rawTags) + { + $tags = $rawTags['tags']['quicktime']; + + $trackNumber = null; + if (isset($tags['track_number'])) { + $trackNumberComponents = explode('/', $tags['track_number'][0]); + $trackNumber = $trackNumberComponents[0]; + } + + return [ + [ + 'title' => $tags['title'][0], + 'artist' => $tags['artist'][0], + 'band' => isset($tags['band']) ? $tags['band'][0] : null, + 'album_artist' => isset($tags['album_artist']) ? $tags['album_artist'][0] : null, + 'genre' => isset($tags['genre']) ? $tags['genre'][0] : null, + 'track_number' => $trackNumber, + 'album' => isset($tags['album']) ? $tags['album'][0] : null, + 'year' => isset($tags['year']) ? (int)$tags['year'][0] : null, + 'comments' => isset($tags['comments']) ? $tags['comments'][0] : null, + 'lyrics' => isset($tags['lyrics']) ? $tags['lyrics'][0] : null, + ], + $tags + ]; + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 599c8651..d29e84c1 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -15,6 +15,8 @@ class Kernel extends ConsoleKernel protected $commands = [ \App\Console\Commands\MigrateOldData::class, \App\Console\Commands\RefreshCache::class, + \App\Console\Commands\ImportMLPMA::class, + \App\Console\Commands\ClassifyMLPMA::class, ]; /** diff --git a/app/Track.php b/app/Track.php index 56a73dee..7358dc1f 100644 --- a/app/Track.php +++ b/app/Track.php @@ -30,6 +30,7 @@ class Track extends Model public static $Formats = [ 'FLAC' => [ 'index' => 0, + 'is_lossless' => true, 'extension' => 'flac', 'tag_format' => 'metaflac', 'tag_method' => 'updateTagsWithGetId3', @@ -38,6 +39,7 @@ class Track extends Model ], 'MP3' => [ 'index' => 1, + 'is_lossless' => false, 'extension' => 'mp3', 'tag_format' => 'id3v2.3', 'tag_method' => 'updateTagsWithGetId3', @@ -46,6 +48,7 @@ class Track extends Model ], 'OGG Vorbis' => [ 'index' => 2, + 'is_lossless' => false, 'extension' => 'ogg', 'tag_format' => 'vorbiscomment', 'tag_method' => 'updateTagsWithGetId3', @@ -54,6 +57,7 @@ class Track extends Model ], 'AAC' => [ 'index' => 3, + 'is_lossless' => false, 'extension' => 'm4a', 'tag_format' => 'AtomicParsley', 'tag_method' => 'updateTagsWithAtomicParsley', @@ -62,6 +66,7 @@ class Track extends Model ], 'ALAC' => [ 'index' => 4, + 'is_lossless' => true, 'extension' => 'alac.m4a', 'tag_format' => 'AtomicParsley', 'tag_method' => 'updateTagsWithAtomicParsley', @@ -538,7 +543,11 @@ class Track extends Model public function updateTags() { $this->trackFiles()->touch(); - foreach (self::$Formats as $format => $data) { + + foreach ($this->trackFiles as $trackFile) { + $format = $trackFile->format; + $data = self::$Formats[$format]; + $this->{$data['tag_method']}($format); } } @@ -553,8 +562,7 @@ class Track extends Model $command .= '--genre ' . escapeshellarg($this->genre != null ? $this->genre->name : '') . ' '; $command .= '--copyright ' . escapeshellarg('© ' . $this->year . ' ' . $this->user->display_name) . ' '; $command .= '--comment "' . 'Downloaded from: https://pony.fm/' . '" '; - $command .= '--encodingTool "' . 'Pony.fm' . '" '; - $command .= '--encodedBy "' . 'Pony.fm - https://pony.fm/' . '" '; + $command .= '--encodingTool "' . 'Pony.fm - https://pony.fm/' . '" '; if ($this->album_id !== null) { $command .= '--album ' . escapeshellarg($this->album->title) . ' '; diff --git a/app/TrackType.php b/app/TrackType.php index 24b4ef58..fc0437df 100644 --- a/app/TrackType.php +++ b/app/TrackType.php @@ -7,4 +7,10 @@ use Illuminate\Database\Eloquent\Model; class TrackType extends Model { protected $table = 'track_types'; + + const ORIGINAL_TRACK = 1; + const OFFICIAL_TRACK_REMIX = 2; + const FAN_TRACK_REMIX = 3; + const PONIFIED_TRACK = 4; + const OFFICIAL_AUDIO_REMIX = 5; } \ No newline at end of file diff --git a/database/migrations/2015_09_10_105709_make_email_nullable.php b/database/migrations/2015_09_10_105709_make_email_nullable.php new file mode 100644 index 00000000..302611eb --- /dev/null +++ b/database/migrations/2015_09_10_105709_make_email_nullable.php @@ -0,0 +1,27 @@ +index('hash'); + }); + + Schema::table('track_files', function ($table) { + $table->index('is_master'); + $table->index('format'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + DB::statement('ALTER TABLE `show_songs` DROP INDEX show_songs_title_fulltext'); + + Schema::table('images', function ($table) { + $table->dropIndex('images_hash_index'); + }); + + Schema::table('track_files', function ($table) { + $table->dropIndex('track_files_is_master_index'); + $table->dropIndex('track_files_format_index'); + }); + } +} diff --git a/database/migrations/2015_09_10_105956_create_mlpma_table.php b/database/migrations/2015_09_10_105956_create_mlpma_table.php new file mode 100644 index 00000000..806a317a --- /dev/null +++ b/database/migrations/2015_09_10_105956_create_mlpma_table.php @@ -0,0 +1,38 @@ +increments('id'); + $table->integer('track_id')->unsigned()->index(); + $table->string('path')->index(); + $table->string('filename')->index(); + $table->string('extension')->index(); + $table->dateTime('imported_at'); + $table->longText('parsed_tags'); + $table->longText('raw_tags'); + + $table->foreign('track_id')->references('id')->on('tracks'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('mlpma_tracks'); + } +} diff --git a/vagrant/config/app.php b/vagrant/config/app.php index 8170ee19..26c18c64 100644 --- a/vagrant/config/app.php +++ b/vagrant/config/app.php @@ -8,6 +8,7 @@ return array( 'debug' => true, 'url' => 'pony.fm.local', 'files_directory' => '/vagrant-files/', + 'mlpma_directory' => '/vagrant-files/mlpma/', 'node' => null, 'node_paths' => ['/usr/lib/node_modules/'], 'secure' => false,