2022-01-04 18:19:03 +00:00
|
|
|
const NodeID3 = require('node-id3');
|
2022-01-04 16:51:22 +00:00
|
|
|
const fs = require('fs').promises;
|
|
|
|
const path = require('path');
|
2022-01-04 18:19:03 +00:00
|
|
|
const { setupSpotify, spotifyApi } = require(path.join(__dirname, 'bits', 'spotify'));
|
2022-01-04 16:51:22 +00:00
|
|
|
|
|
|
|
const audPath = process.argv[2];
|
|
|
|
|
|
|
|
if (!audPath) {
|
|
|
|
throw new Error('No directory specified');
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readTags(file) {
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
NodeID3.read(file, {noRaw: true, exclude: ['image']}, function(err, tags) {
|
|
|
|
if (err) return resolve(null)
|
|
|
|
if (tags.image) tags.image = null;
|
|
|
|
if (tags.private) tags.private = null;
|
|
|
|
resolve(tags);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readAudioFiles() {
|
|
|
|
let fileAndMeta = [];
|
|
|
|
const contents = await fs.readdir(audPath);
|
|
|
|
for (const file of contents) {
|
|
|
|
const fullp = path.join(audPath, file);
|
|
|
|
const tags = await readTags(fullp);
|
|
|
|
fileAndMeta.push({
|
|
|
|
path: fullp,
|
|
|
|
tags: tags,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
fileAndMeta = fileAndMeta.filter((item) => item.tags && item.tags.artist && item.tags.title);
|
|
|
|
await fs.writeFile('file-meta-cache.json', JSON.stringify(fileAndMeta, undefined, 2));
|
|
|
|
return fileAndMeta;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function delay(time) {
|
|
|
|
return new Promise((resolve) => setTimeout(resolve, time));
|
|
|
|
}
|
|
|
|
|
|
|
|
let requestDelay = 100;
|
|
|
|
|
|
|
|
async function searchTrack(query) {
|
|
|
|
console.log('Searching for', query);
|
|
|
|
let returned
|
|
|
|
|
|
|
|
try {
|
|
|
|
returned = await spotifyApi.searchTracks(query, { limit: 5, market: 'EE' });
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
console.log('We may have hit a rate limit');
|
|
|
|
console.log('Waiting 30 seconds for the rate limit window');
|
|
|
|
requestDelay = 1000;
|
|
|
|
await delay(30000);
|
|
|
|
return searchTrack(query);
|
|
|
|
}
|
|
|
|
|
|
|
|
await delay(requestDelay);
|
|
|
|
console.log('Got', returned.body.tracks.total, 'results');
|
|
|
|
return returned.body.tracks.items;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function searchAllOfSpotify() {
|
|
|
|
await setupSpotify();
|
|
|
|
|
|
|
|
const audioFiles = await readAudioFiles();
|
|
|
|
let tracks = [];
|
|
|
|
let progress = 0;
|
|
|
|
let hits = 0;
|
|
|
|
|
|
|
|
for (const file of audioFiles) {
|
|
|
|
console.log('=> item %d of %d', (progress++), audioFiles.length);
|
|
|
|
const results = await searchTrack(`${file.tags.title} artist:${file.tags.artist}`);
|
|
|
|
if (results.length) {
|
|
|
|
hits++;
|
|
|
|
tracks.push({
|
|
|
|
file: file.path,
|
|
|
|
title: file.tags.title,
|
|
|
|
artist: file.tags.artist,
|
|
|
|
spotify: results,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
console.log('Traversed %d audio files, of which %d had potential results from Spotify', audioFiles.length, hits);
|
|
|
|
await fs.writeFile('spotify.json', JSON.stringify(tracks, undefined, 2));
|
|
|
|
}
|
|
|
|
|
2022-01-04 18:19:03 +00:00
|
|
|
searchAllOfSpotify().catch(console.error);
|