@@ -137,10 +137,10 @@ public function generateData() {
137137 }
138138
139139 foreach ($ seriesEntries as $ seriesChange ) { // log series additions
140- $ folderID = $ seriesChange ['folder_id ' ];
141- $ compositeID = $ seriesChange ['composite_id ' ];
140+ $ folderId = $ seriesChange ['folder_id ' ];
141+ $ compositeId = $ seriesChange ['composite_id ' ];
142142
143- $ dbOut .= "INSERT INTO [series] VALUES ( {$ folderID }, {$ compositeID }); \n\n" ; // insert
143+ $ dbOut .= "INSERT INTO [series] VALUES ( {$ folderId }, {$ compositeId }); \n\n" ; // insert
144144
145145 array_push ($ seriesTransactions , $ seriesChange );
146146 }
@@ -167,15 +167,15 @@ public function generateData() {
167167 }
168168
169169 foreach ($ metaDataEntries as $ metadataChange ) { // log metadata additions
170- $ videoID = $ metadataChange ['video_id ' ];
171- $ compositeID = $ metadataChange ['composite_id ' ];
170+ $ videoId = $ metadataChange ['video_id ' ];
171+ $ compositeId = $ metadataChange ['composite_id ' ];
172172 $ uuid = $ metadataChange ['uuid ' ];
173173 $ file_size = $ metadataChange ['file_size ' ];
174174 $ duration = $ metadataChange ['duration ' ];
175175 $ date_scanned = $ metadataChange ['date_scanned ' ];
176176 $ date_uploaded = $ metadataChange ['date_uploaded ' ];
177177
178- $ dbOut .= "UPSERT INTO [metadata] VALUES ( {$ videoID }, {$ compositeID }, {$ uuid }, {$ file_size }, {$ duration }, {$ date_scanned }, {$ date_uploaded }); \n\n" ; // upsert
178+ $ dbOut .= "UPSERT INTO [metadata] VALUES ( {$ videoId }, {$ compositeId }, {$ uuid }, {$ file_size }, {$ duration }, {$ date_scanned }, {$ date_uploaded }); \n\n" ; // upsert
179179
180180 array_push ($ metadataTransactions , $ metadataChange );
181181 }
@@ -227,7 +227,7 @@ private function generateCategories($path) {
227227 $ data = Storage::json ('categories.json ' ) ?? ['next_ID ' => 1 , 'categoryStructure ' => []]; // array("anime"=>1,"tv"=>2,"yogscast"=>3); // read from json
228228 $ scanned = array_filter (
229229 scandir ($ path ),
230- fn ($ item ) => $ item !== '. ' &&
230+ fn ($ item ) => $ item !== '. ' &&
231231 $ item !== '.. ' &&
232232 is_dir ($ path . DIRECTORY_SEPARATOR . $ item )
233233 ); // read folder structure
@@ -455,18 +455,12 @@ private function generateVideos($path, $folderStructure) {
455455 continue ;
456456 }
457457
458- $ uuid = $ fileMetaData ['tags ' ]['uuid ' ] ?? $ fileMetaData ['tags ' ]['uid ' ] ?? null ;
459- $ embeddingUuid = false ;
460- if (! $ uuid || ! Uuid::isValid ($ uuid )) {
461- $ embeddingUuid = true ;
462- } else {
463- // Check for an existing file (not deleted) with the scanned uuid only if a uuid was found on the video. Usually this means the user copied the previously scanned video to a new folder.
464- $ existingData = Metadata::where ('uuid ' , $ uuid )->first ();
465- $ embeddingUuid = $ existingData && File::exists (public_path ("storage/media/ $ existingData ->composite_id " ));
466- }
458+ $ embeddedUuid = $ fileMetaData ['tags ' ]['uuid ' ] ?? null ;
459+ $ compositeId = "$ folder/ $ name " ;
460+
461+ ['uuid ' => $ uuid , 'willEmbedUuid ' => $ willEmbedUuid ] = $ this ->ResolveExistingUuid ($ embeddedUuid , $ compositeId );
467462
468- if ($ embeddingUuid ) {
469- $ uuid = Str::uuid ()->toString ();
463+ if ($ willEmbedUuid ) {
470464 $ this ->embedChain [] = new EmbedUidInMetadata ($ absolutePath , $ uuid , $ this ->taskId , $ currentID ); // TODO: Make tagging user configurable, probably by library but always use a uuid
471465 }
472466
@@ -478,8 +472,8 @@ private function generateVideos($path, $folderStructure) {
478472 $ rawDuration = $ fileMetaData ['format ' ]['duration ' ] ?? $ fileMetaData ['streams ' ][0 ]['duration ' ] ?? null ;
479473 $ duration = is_numeric ($ rawDuration ) ? floor ($ rawDuration ) : null ;
480474
481- $ generated = ['id ' => $ currentID , 'uuid ' => $ embeddingUuid ? null : $ uuid , 'name ' => $ cleanName , 'path ' => $ key , 'folder_id ' => $ folderStructure [$ folder ]['id ' ], 'date ' => date ('Y-m-d h:i A ' , $ mtime < $ ctime ? $ mtime : $ ctime ), 'action ' => 'INSERT ' ];
482- $ metadata = ['video_id ' => $ currentID , 'composite_id ' => " $ folder / $ name " , 'uuid ' => $ uuid , 'file_size ' => filesize ($ rawFile ), 'duration ' => $ duration , 'mime_type ' => $ mime_type ?? null , 'media_type ' => $ media_type , 'date_scanned ' => date ('Y-m-d h:i:s A ' ), 'date_uploaded ' => date ('Y-m-d h:i A ' , $ mtime < $ ctime ? $ mtime : $ ctime )];
475+ $ generated = ['id ' => $ currentID , 'uuid ' => $ willEmbedUuid ? null : $ uuid , 'name ' => $ cleanName , 'path ' => $ key , 'folder_id ' => $ folderStructure [$ folder ]['id ' ], 'date ' => date ('Y-m-d h:i A ' , $ mtime < $ ctime ? $ mtime : $ ctime ), 'action ' => 'INSERT ' ];
476+ $ metadata = ['video_id ' => $ currentID , 'composite_id ' => $ compositeId , 'uuid ' => $ uuid , 'file_size ' => filesize ($ rawFile ), 'duration ' => $ duration , 'mime_type ' => $ mime_type ?? null , 'media_type ' => $ media_type , 'date_scanned ' => date ('Y-m-d h:i:s A ' ), 'date_uploaded ' => date ('Y-m-d h:i A ' , $ mtime < $ ctime ? $ mtime : $ ctime )];
483477 $ current [$ key ] = $ currentID ; // add to current
484478 array_push ($ changes , $ generated ); // add to new (insert)
485479 array_push ($ metadataChanges , $ metadata ); // create metadata (insert)
@@ -543,5 +537,56 @@ public function upsertMetadata($data) {
543537 private function generatedChangesText ($ count , $ type ) {
544538 return 'Generated ' . $ count . ' ' . $ type . ' Changes ' ;
545539 }
540+
541+ private function ResolveExistingUuid (?string $ embeddedUuid , string $ compositeId ): array {
542+ // sanitise input
543+ $ embeddedUuid = $ embeddedUuid && Uuid::isValid ($ embeddedUuid ) ? $ embeddedUuid : null ;
544+ $ logicalCompositeId = pathinfo ($ compositeId , PATHINFO_DIRNAME ) . '/ ' . pathinfo ($ compositeId , PATHINFO_FILENAME );
545+
546+ /**
547+ * Scenario 1:
548+ * the file has a uuid embedded, and there is an existing metadata with the same uuid without an existing video
549+ * -> dont embed, use the embedded uuid and dont embed but update the metadata composite id
550+ */
551+ if ($ embeddedUuid && $ metadata = Metadata::where ('uuid ' , $ embeddedUuid )->first ()) {
552+ if ($ metadata ->video_id === null ) {
553+ return [
554+ 'uuid ' => $ metadata ->uuid ,
555+ 'willEmbedUuid ' => false ,
556+ ];
557+ } else {
558+ // the file was explicitly duplicated (copied from previously scanned library) -> force new uuid
559+ return [
560+ 'uuid ' => Str::uuid ()->toString (),
561+ 'willEmbedUuid ' => true ,
562+ ];
563+ }
564+ }
565+
566+ /**
567+ * Scenario 2:
568+ * the file has no uuid, but its composite id matches an existing metadata also without an existing video
569+ * -> embed the existing metadata uuid into the file
570+ */
571+ if (! $ embeddedUuid && $ metadata = Metadata::where ('composite_id ' , 'LIKE ' , $ logicalCompositeId . '.% ' )->orderBy ('updated_at ' , 'desc ' )->first ()) {
572+ if ($ metadata ->video_id === null ) {
573+ return [
574+ 'uuid ' => $ metadata ->uuid ,
575+ 'willEmbedUuid ' => true ,
576+ ];
577+ }
578+ }
579+
580+ /**
581+ * Scenario 3:
582+ * the file has no uuid and matches no metadata
583+ * -> generate new uuid and upsert new metadata
584+ */
585+ return [
586+ 'uuid ' => Str::uuid ()->toString (),
587+ 'willEmbedUuid ' => true ,
588+ ];
589+ }
590+ }
591+ class BatchCancelledException extends \Exception {
546592}
547- class BatchCancelledException extends \Exception {}
0 commit comments