diff options
Diffstat (limited to 'lyrics.js')
-rw-r--r-- | lyrics.js | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/lyrics.js b/lyrics.js new file mode 100644 index 0000000..f2edf2c --- /dev/null +++ b/lyrics.js @@ -0,0 +1,136 @@ +/* + * MIT License + * + * Copyright (c) 2022- Minteck + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +(async () => { + const fs = require('fs'); + const child_process = require("child_process"); + const path = require("path"); + const exec = require('child_process').execFileSync; + + let noLyrics = []; + let yesLyrics = []; + + const Genius = require("genius-lyrics"); + const g = new Genius.Client(); + + const artists = fs.readdirSync(process.argv[2]); + const albums = []; + const tracks = {}; + + for (let artist of artists) { + if (fs.lstatSync(process.argv[2] + "/" + artist).isDirectory()) { + const artistAlbums = fs.readdirSync(process.argv[2] + "/" + artist); + + for (let album of artistAlbums) { + if (fs.lstatSync(process.argv[2] + "/" + artist + "/" + album).isDirectory()) { + albums.push(process.argv[2] + "/" + artist + "/" + album); + const albumTracks = fs.readdirSync(process.argv[2] + "/" + artist + "/" + album); + + for (let track of albumTracks) { + if (fs.lstatSync(process.argv[2] + "/" + artist + "/" + album + "/" + track).isFile() && !track.startsWith(".")) { + tracks[process.argv[2] + "/" + artist + "/" + album + "/" + track] = { + artist, + album, + name: track + }; + } + } + } + } + } + } + + for (let id of Object.keys(tracks)) { + const track = tracks[id]; + console.log(id); + + if (JSON.parse(child_process.execFileSync("ffprobe", [ "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", id ]).toString()).format.tags.lyrics === undefined) { + let lyricsComplete = false; + let lyrics = "[Instrumental]"; + try { + let geniusSearchArtist = track.artist; + let geniusSearchTitle = track.name.substring(0, track.name.length - path.extname(track.name).length).replace(/[0-9]+-[0-9]+ (.*)/gm, "$1"); + let geniusSong = (await g.songs.search(geniusSearchArtist + " - " + geniusSearchTitle))[0]; + let geniusSongSec = (await g.songs.search(geniusSearchArtist + " - " + geniusSearchTitle))[1]; + let geniusSongTer = (await g.songs.search(geniusSearchArtist + " - " + geniusSearchTitle))[2]; + let geniusSongQua = (await g.songs.search(geniusSearchArtist + " - " + geniusSearchTitle))[3]; + let geniusTitle = geniusSong.title.replace(/^([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)-( |)(.*)(\[(.*)\]|)/gm, "$3").replace(/(.*)\((feat|ft|with)(\.|:| |)(| |)([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)\)(.*)/gmi, "$1").replace(/(.*)\[(.*)\](.*)/gm, "$1").replace(/(.*)\((from|in|by)(\.|:| |)(| |)([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)\)(.*)/gmi, "$1").replaceAll("’", "'").trim(); + let geniusTitleSec; + let geniusTitleTer; + let geniusTitleQua; + try { + geniusTitleSec = geniusSongSec.title.replace(/^([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)-( |)(.*)(\[(.*)\]|)/gm, "$3").replace(/(.*)\((feat|ft|with)(\.|:| |)(| |)([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)\)(.*)/gmi, "$1").replace(/(.*)\[(.*)\](.*)/gm, "$1").replace(/(.*)\((from|in|by)(\.|:| |)(| |)([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)\)(.*)/gmi, "$1").replaceAll("’", "'").trim(); + } catch (e) { + geniusTitleSec = ""; + } + try { + geniusTitleTer = geniusSongTer.title.replace(/^([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)-( |)(.*)(\[(.*)\]|)/gm, "$3").replace(/(.*)\((feat|ft|with)(\.|:| |)(| |)([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)\)(.*)/gmi, "$1").replace(/(.*)\[(.*)\](.*)/gm, "$1").replace(/(.*)\((from|in|by)(\.|:| |)(| |)([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)\)(.*)/gmi, "$1").replaceAll("’", "'").trim(); + } catch (e) { + geniusTitleTer = ""; + } + try { + geniusTitleQua = geniusSongQua.title.replace(/^([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)-( |)(.*)(\[(.*)\]|)/gm, "$3").replace(/(.*)\((feat|ft|with)(\.|:| |)(| |)([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)\)(.*)/gmi, "$1").replace(/(.*)\[(.*)\](.*)/gm, "$1").replace(/(.*)\((from|in|by)(\.|:| |)(| |)([:\"'a-zA-Z0-9 .\-*\_\/\\,&]*)\)(.*)/gmi, "$1").replaceAll("’", "'").trim(); + } catch (e) { + geniusTitleQua = ""; + } + console.log("1. " + geniusTitle.toLowerCase().trim() + " <-> " + geniusSearchTitle.toLowerCase().trim(), geniusTitle.toLowerCase().trim() === geniusSearchTitle.toLowerCase().trim()); + console.log("2. " + geniusTitleSec.toLowerCase().trim() + " <-> " + geniusSearchTitle.toLowerCase().trim(), geniusTitleSec.toLowerCase().trim() === geniusSearchTitle.toLowerCase().trim()); + console.log("3. " + geniusTitleTer.toLowerCase().trim() + " <-> " + geniusSearchTitle.toLowerCase(), geniusTitleTer.toLowerCase().trim() === geniusSearchTitle.toLowerCase().trim()); + console.log("4. " + geniusTitleQua.toLowerCase().trim() + " <-> " + geniusSearchTitle.toLowerCase().trim(), geniusTitleQua.toLowerCase().trim() === geniusSearchTitle.toLowerCase().trim()); + if (geniusTitle.toLowerCase().trim() === geniusSearchTitle.toLowerCase().trim() && geniusSong.raw.lyrics_state === "complete") { + lyricsComplete = true; + lyrics = (await geniusSong.lyrics()).trim() + } else if (geniusTitleSec.toLowerCase().trim() === geniusSearchTitle.toLowerCase().trim() && geniusSongSec.raw.lyrics_state === "complete") { + lyricsComplete = true; + lyrics = (await geniusSongSec.lyrics()).trim() + } else if (geniusTitleTer.toLowerCase().trim() === geniusSearchTitle.toLowerCase().trim() && geniusSongTer.raw.lyrics_state === "complete") { + lyricsComplete = true; + lyrics = (await geniusSongTer.lyrics()).trim() + } else if (geniusTitleQua.toLowerCase().trim() === geniusSearchTitle.toLowerCase().trim() && geniusSongQua.raw.lyrics_state === "complete") { + lyricsComplete = true; + lyrics = (await geniusSongQua.lyrics()).trim() + } + } catch (e) { + console.error(e); + lyrics = "[Instrumental]"; + lyricsComplete = true; + } + if (lyricsComplete) { + console.log("Found lyrics: yes"); + yesLyrics.push(id); + exec("ffmpeg", [ "-v", "quiet", "-y", "-i", id, "-c", "copy", "-metadata", "lyrics=" + lyrics, id + "-" + path.extname(id) ], { stdio: "inherit" }); + fs.renameSync(id + "-" + path.extname(id), id); + } else { + console.log("Found lyrics: no"); + noLyrics.push(id); + } + } + } + + console.log(noLyrics.length + " song(s) doesn't have lyrics, see 'Missing.txt' for details"); + console.log(yesLyrics.length + " song(s) have lyrics and were affected, see 'Changes.txt' for details"); + fs.writeFileSync("Missing.txt", noLyrics.join("\n")) + fs.writeFileSync("Changes.txt", yesLyrics.join("\n")) +})()
\ No newline at end of file |