From 4b0b31471bfa2bdf44dc14f7613bb33ffe9f9f1d Mon Sep 17 00:00:00 2001 From: Janis Hutz Date: Mon, 6 Nov 2023 09:03:01 +0100 Subject: [PATCH] more progress (still broken) --- frontend/src/app.js | 15 ++- frontend/src/components/mediaPool.vue | 3 +- frontend/src/imageFetcher.js | 4 +- frontend/src/indexer.js | 161 ++++++++++++++++---------- 4 files changed, 112 insertions(+), 71 deletions(-) diff --git a/frontend/src/app.js b/frontend/src/app.js index 892a8b5..8d4e841 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -6,6 +6,7 @@ const fs = require( 'fs' ); const bodyParser = require( 'body-parser' ); const dialog = require( 'electron' ).dialog; const session = require( 'express-session' ); +const indexer = require( './indexer.js' ); app.use( bodyParser.urlencoded( { extended: false } ) ); @@ -121,11 +122,15 @@ app.get( '/openSongs', ( req, res ) => { app.get( '/indexDirs', ( req, res ) => { if ( req.query.dir ) { // TODO: Load from json file - if ( indexedData[ req.query.dir ] ) { - res.send( indexedData[ req.query.dir ] ); - } else { - res.send( files ); - } + indexer.index( req ).then( dirIndex => { + res.send( dirIndex ); + } ).catch( err => { + if ( err === 'ERR_DIR_NOT_FOUND' ) { + res.status( 404 ).send( 'ERR_DIR_NOT_FOUND' ); + } else { + res.status( 500 ).send( 'unable to process' ); + } + } ); } else { res.status( 400 ).send( 'ERR_REQ_INCOMPLETE' ); } diff --git a/frontend/src/components/mediaPool.vue b/frontend/src/components/mediaPool.vue index 02de89c..691769f 100644 --- a/frontend/src/components/mediaPool.vue +++ b/frontend/src/components/mediaPool.vue @@ -206,6 +206,7 @@ repeat: false, isShowingFancyView: false, errorOccurredLoading: false, + coverArtSetting: 'api' } }, methods: { @@ -291,7 +292,7 @@ }, indexFiles () { for ( let dir in this.loadedDirs ) { - fetch( 'http://localhost:8081/indexDirs?dir=' + this.loadedDirs[ dir ] + ( this.loadCoverArtPreview ? '&coverart=true' : '' ) ).then( res => { + fetch( 'http://localhost:8081/indexDirs?dir=' + this.loadedDirs[ dir ] + ( this.loadCoverArtPreview ? '&coverart=' + this.coverArtSetting : '' ) ).then( res => { if ( res.status === 200 ) { this.errorOccurredLoading = false; res.json().then( json => { diff --git a/frontend/src/imageFetcher.js b/frontend/src/imageFetcher.js index 981e3ad..212893f 100644 --- a/frontend/src/imageFetcher.js +++ b/frontend/src/imageFetcher.js @@ -16,8 +16,8 @@ const settings = JSON.parse( fs.readFileSync( path.join( __dirname + '/config/ap const music = new MusicKit( { key: fs.readFileSync( path.join( __dirname + '/config/apple_private_key.p8' ) ).toString(), - teamId: settings.teamID, // This is your developer account's team ID - keyId: settings.keyID // This is the keys ID + teamId: settings.teamID, + keyId: settings.keyID } ); module.exports.fetch = ( type, searchQuery, callback ) => { diff --git a/frontend/src/indexer.js b/frontend/src/indexer.js index 2bc5ba3..9d339a6 100644 --- a/frontend/src/indexer.js +++ b/frontend/src/indexer.js @@ -21,7 +21,7 @@ module.exports.index = ( req ) => { return new Promise( ( resolve, reject ) => { fs.readdir( req.query.dir, { encoding: 'utf-8' }, ( err, dat ) => { if ( err ) { - res.status( 404 ).send( 'ERR_DIR_NOT_FOUND' ); + reject( 'ERR_DIR_NOT_FOUND' ); return; }; ( async() => { @@ -29,9 +29,17 @@ module.exports.index = ( req ) => { // what was found automatically. If no song title was found in songlist or metadata, use filename // TODO: Also save found information to those files and don't rerun checks if data is present if ( dat.includes( 'songlist.csv' ) || dat.includes( 'songlist.json' ) ) { - + parseExistingData( dat, req.query.dir ).then( data => { + parseDir( dat, req, data ); + } ); + } else if ( dat.includes( 'songs.json' ) ) { + parseExistingData( dat, req.query.dir ).then( data => { + resolve( data ); + } ).catch( err => { + reject( err ); + } ); } else { - + resolve( await parseDir( dat, req ) ); } } )(); } ); @@ -40,11 +48,20 @@ module.exports.index = ( req ) => { const parseExistingData = ( dat, dir ) => { return new Promise( ( resolve, reject ) => { - if ( dat.includes( 'songlist.csv' ) ) { + if ( dat.includes( 'songs.json' ) ) { + resolve( JSON.parse( fs.readFileSync( path.join( dir + '/songs.json' ) ) ) ); + } else if ( dat.includes( 'songlist.csv' ) ) { + // This will assume that line #1 will be song #1 in the file list + // (when sorted by name) let results = {}; - fs.createReadStream( path.join( dir + '/songlist.csv' ) ).pipe( csv( [ 'name', 'artist', 'dancingStyle', 'tempo' ] ) ).on( 'data', ( data ) => { - results[ req.query.dir + '/' + dat[ file ] ] = data; + let pos = 0; + fs.createReadStream( path.join( dir + '/songlist.csv' ) ) + .pipe( csv( [ 'name', 'artist', 'dancingStyle', 'tempo' ] ) ) + .on( 'data', ( data ) => { + results[ dir + '/' + dat[ pos ] ] = data; + pos += 1; } ).on( 'end', () => { + console.log( results ); resolve( results ); } ); } else if ( dat.includes( 'songlist.json' ) ) { @@ -53,69 +70,87 @@ const parseExistingData = ( dat, dir ) => { } ); } -const parseDir = async ( dat, req ) => { - let files = {}; - for ( let file in dat ) { - if ( allowedFileTypes.includes( dat[ file ].slice( dat[ file ].indexOf( '.' ), dat[ file ].length ) ) ) { - try { - let metadata = await musicMetadata.parseFile( req.query.dir + '/' + dat[ file ] ); - files[ req.query.dir + '/' + dat[ file ] ] = { - 'artist': metadata[ 'common' ][ 'artist' ], - 'title': metadata[ 'common' ][ 'title' ], - 'year': metadata[ 'common' ][ 'year' ], - 'bpm': metadata[ 'common' ][ 'bpm' ], - 'genre': metadata[ 'common' ][ 'genre' ], - 'duration': Math.round( metadata[ 'format' ][ 'duration' ] ), - 'isLossless': metadata[ 'format' ][ 'lossless' ], - 'sampleRate': metadata[ 'format' ][ 'sampleRate' ], - 'bitrate': metadata[ 'format' ][ 'bitrate' ], - 'numberOfChannels': metadata[ 'format' ][ 'numberOfChannels' ], - 'container': metadata[ 'format' ][ 'container' ], - 'filename': req.query.dir + '/' + dat[ file ], - } - if ( metadata[ 'common' ][ 'picture' ] ) { - files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = true; - if ( req.query.coverart == 'true' ) { - coverArtIndex[ req.query.dir + '/' + dat[ file ] ] = metadata[ 'common' ][ 'picture' ] ? metadata[ 'common' ][ 'picture' ][ 0 ][ 'data' ] : undefined; - } - } else { - if ( req.query.coverart == 'true' ) { - imageFetcher.fetch( 'songs', metadata[ 'common' ][ 'artist' ] + ' ' + metadata[ 'common' ][ 'title' ], ( err, data ) => { - if ( err ) { - indexedData[ req.query.dir ][ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; +hasCompletedFetching = {}; + +const parseDir = ( dat, req, existingData ) => { + console.log( existingData ); + return new Promise( ( resolve, reject ) => { + ( async() => { + let files = {}; + for ( let file in dat ) { + if ( allowedFileTypes.includes( dat[ file ].slice( dat[ file ].indexOf( '.' ), dat[ file ].length ) ) ) { + try { + let metadata = await musicMetadata.parseFile( req.query.dir + '/' + dat[ file ] ); + files[ req.query.dir + '/' + dat[ file ] ] = { + 'artist': metadata[ 'common' ][ 'artist' ], + 'title': metadata[ 'common' ][ 'title' ], + 'year': metadata[ 'common' ][ 'year' ], + 'bpm': metadata[ 'common' ][ 'bpm' ], + 'genre': metadata[ 'common' ][ 'genre' ], + 'duration': Math.round( metadata[ 'format' ][ 'duration' ] ), + 'isLossless': metadata[ 'format' ][ 'lossless' ], + 'sampleRate': metadata[ 'format' ][ 'sampleRate' ], + 'bitrate': metadata[ 'format' ][ 'bitrate' ], + 'numberOfChannels': metadata[ 'format' ][ 'numberOfChannels' ], + 'container': metadata[ 'format' ][ 'container' ], + 'filename': req.query.dir + '/' + dat[ file ], + } + if ( req.query.coverart == 'meta' ) { + if ( metadata[ 'common' ][ 'picture' ] ) { + files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = true; + coverArtIndex[ req.query.dir + '/' + dat[ file ] ] = metadata[ 'common' ][ 'picture' ] ? metadata[ 'common' ][ 'picture' ][ 0 ][ 'data' ] : undefined; + } else { files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; - return; } - if ( data.results.songs ) { - if ( data.results.songs.data ) { - let url = data.results.songs.data[ 0 ].attributes.artwork.url; - url = url.replace( '{w}', data.results.songs.data[ 0 ].attributes.artwork.width ); - url = url.replace( '{h}', data.results.songs.data[ 0 ].attributes.artwork.height ); - console.log( url ); + } else if ( req.query.coverart == 'api' ) { + hasCompletedFetching[ req.query.dir + '/' + dat[ file ] ] = false; + imageFetcher.fetch( 'songs', metadata[ 'common' ][ 'artist' ] + ' ' + metadata[ 'common' ][ 'title' ], ( err, data ) => { + if ( err ) { + files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; + return; + } + if ( data.results.songs ) { + if ( data.results.songs.data ) { + let url = data.results.songs.data[ 0 ].attributes.artwork.url; + url = url.replace( '{w}', data.results.songs.data[ 0 ].attributes.artwork.width ); + url = url.replace( '{h}', data.results.songs.data[ 0 ].attributes.artwork.height ); + console.log( url ); + } else { + files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; + } } else { - indexedData[ req.query.dir ][ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; } - } else { - indexedData[ req.query.dir ][ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; - files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; - } - } ); - files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = true; - } else { - files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; + hasCompletedFetching[ req.query.dir + '/' + dat[ file ] ] = true; + } ); + files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = true; + } else { + files[ req.query.dir + '/' + dat[ file ] ][ 'hasCoverArt' ] = false; + } + } catch ( err ) { + console.error( err ); + files[ req.query.dir + '/' + dat[ file ] ] = 'ERROR'; } } - } catch ( err ) { - console.error( err ); - files[ req.query.dir + '/' + dat[ file ] ] = 'ERROR'; } - } else if ( dat[ file ].slice( dat[ file ].indexOf( '.' ), dat[ file ].length ) === '.csv' ) { + let ok = false; + setInterval( () => { + for ( let song in hasCompletedFetching ) { + if ( !hasCompletedFetching[ song ] ) { + ok = false; + } + } + if ( ok ) { + indexedData[ req.query.dir ] = files; + resolve( files ); + } + ok = true; + }, 250 ); + } )(); + } ) +}; - } else if ( dat[ file ].slice( dat[ file ].indexOf( '.' ), dat[ file ].length ) === '.json' ) { - - } - } - indexedData[ req.query.dir ] = files; - return files; -} \ No newline at end of file + +const saveToDisk = () => { + +}; \ No newline at end of file