├── .gitignore ├── readme ├── lyricexp1.png ├── lyricexp2.png └── lyricexp3.png ├── public ├── src │ ├── favicon.png │ ├── lyricexp1.png │ ├── lyricexp2.png │ ├── lyricexp3.png │ ├── Spotify_Logo_RGB_Black.png │ └── Spotify_Logo_RGB_White.png ├── Fonts │ ├── Gotham-Black.otf │ ├── Gotham-Bold.otf │ ├── GothamBold.ttf │ ├── GothamBook.ttf │ ├── GothamMedium.ttf │ ├── GothamMedium_1.ttf │ ├── GothamBoldItalic.ttf │ └── GothamMediumItalic.ttf ├── scripts │ ├── gsearch.js │ ├── search.js │ ├── lyrics.js │ └── home.js └── sheets │ ├── policy.css │ ├── about.css │ ├── search.css │ ├── genius.css │ ├── lyrics.css │ └── home.css ├── modules ├── .npmignore ├── getAlbumArt.js ├── getSong.js ├── utils │ ├── index.js │ └── extractLyrics.js ├── package.json ├── getSongById.js ├── getLyrics.js ├── .gitignore ├── LICENSE.txt ├── searchSong.js └── README.md ├── .vscode └── launch.json ├── package.json ├── views ├── search.ejs ├── gsearch.ejs ├── privacy.ejs ├── home.ejs ├── lyrics.ejs └── about.ejs ├── README.md ├── server.js └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | .vscode -------------------------------------------------------------------------------- /readme/lyricexp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/readme/lyricexp1.png -------------------------------------------------------------------------------- /readme/lyricexp2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/readme/lyricexp2.png -------------------------------------------------------------------------------- /readme/lyricexp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/readme/lyricexp3.png -------------------------------------------------------------------------------- /public/src/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/src/favicon.png -------------------------------------------------------------------------------- /public/src/lyricexp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/src/lyricexp1.png -------------------------------------------------------------------------------- /public/src/lyricexp2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/src/lyricexp2.png -------------------------------------------------------------------------------- /public/src/lyricexp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/src/lyricexp3.png -------------------------------------------------------------------------------- /public/Fonts/Gotham-Black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/Fonts/Gotham-Black.otf -------------------------------------------------------------------------------- /public/Fonts/Gotham-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/Fonts/Gotham-Bold.otf -------------------------------------------------------------------------------- /public/Fonts/GothamBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/Fonts/GothamBold.ttf -------------------------------------------------------------------------------- /public/Fonts/GothamBook.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/Fonts/GothamBook.ttf -------------------------------------------------------------------------------- /public/Fonts/GothamMedium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/Fonts/GothamMedium.ttf -------------------------------------------------------------------------------- /public/Fonts/GothamMedium_1.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/Fonts/GothamMedium_1.ttf -------------------------------------------------------------------------------- /public/Fonts/GothamBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/Fonts/GothamBoldItalic.ttf -------------------------------------------------------------------------------- /public/Fonts/GothamMediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/Fonts/GothamMediumItalic.ttf -------------------------------------------------------------------------------- /public/src/Spotify_Logo_RGB_Black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/src/Spotify_Logo_RGB_Black.png -------------------------------------------------------------------------------- /public/src/Spotify_Logo_RGB_White.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MythicalMayhem/MythicalLyrics/HEAD/public/src/Spotify_Logo_RGB_White.png -------------------------------------------------------------------------------- /modules/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | demo/ 3 | npm-debug.log 4 | yarn-error.log 5 | 6 | # BUCK 7 | buck-out/ 8 | \.buckd/ 9 | *.keystore 10 | yarn.lock -------------------------------------------------------------------------------- /modules/getAlbumArt.js: -------------------------------------------------------------------------------- 1 | const searchSong = require('./searchSong'); 2 | const { checkOptions } = require('./utils'); 3 | 4 | /** 5 | * @param {{apiKey: string, title: string, artist: string, optimizeQuery: boolean}} options 6 | */ 7 | module.exports = async function (options) { 8 | checkOptions(options); 9 | let results = await searchSong(options); 10 | if (!results) return null; 11 | return results[0].albumArt; 12 | }; 13 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "chrome", 9 | "request": "launch", 10 | "name": "Launch Chrome against localhost", 11 | "url": "http://localhost:8080", 12 | "webRoot": "${workspaceFolder}" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spotifyxgenius", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "nodemon server.js" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "dotenv": "^16.3.1", 14 | "ejs": "^3.1.9", 15 | "express": "^4.18.2", 16 | "extract-colors": "^4.0.1", 17 | "genius-lyrics-api": "^3.2.0", 18 | "get-pixels": "^3.3.3", 19 | "html2canvas": "^1.4.1", 20 | "node-fetch": "^2.7.0" 21 | }, 22 | "devDependencies": { 23 | "nodemon": "^3.0.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /modules/getSong.js: -------------------------------------------------------------------------------- 1 | const searchSong = require('./searchSong'); 2 | const extractLyrics = require('./utils/extractLyrics'); 3 | const { checkOptions } = require('./utils'); 4 | 5 | /** 6 | * @param {{apiKey: string, title: string, artist: string, optimizeQuery: boolean}} options 7 | */ 8 | module.exports = async function (options) { 9 | try { 10 | checkOptions(options); 11 | let results = await searchSong(options); 12 | if (!results) return null; 13 | let lyrics = await extractLyrics(results[0].url); 14 | return { 15 | id: results[0].id, 16 | title: results[0].title, 17 | url: results[0].url, 18 | lyrics, 19 | albumArt: results[0].albumArt 20 | }; 21 | } catch (e) { 22 | throw e; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /modules/utils/index.js: -------------------------------------------------------------------------------- 1 | const checkOptions = (options) => { 2 | let { apiKey, title, artist } = options; 3 | if (!apiKey) { 4 | throw '"apiKey" property is missing from options'; 5 | } else if (!title) { 6 | throw '"title" property is missing from options'; 7 | } 8 | }; 9 | const getTitle = (title, artist) => { 10 | let b = `${artist} ${title}` 11 | .toLowerCase() 12 | 13 | .replace(/[ ](ft|feat)\.?[ ].*/g, '').replace(/\([^)]*\)/g, '') 14 | .replace(/ *\[[^\]]*]/g, '') 15 | .replace(/\s+/g, ' ') 16 | .trim() 17 | console.log(b) 18 | if (b.length > 12) { 19 | const lastIndex = b.lastIndexOf('-'); 20 | b = b.slice(0, lastIndex) 21 | } 22 | return b 23 | }; 24 | 25 | module.exports = { checkOptions, getTitle }; 26 | -------------------------------------------------------------------------------- /modules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "genius-lyrics-api", 3 | "version": "3.2.0", 4 | "main": "index.js", 5 | "author": { 6 | "name": "Faisal Arshed", 7 | "url": "https://github.com/farshed" 8 | }, 9 | "contributors": [ 10 | { 11 | "name": "Garlicvideos", 12 | "url": "https://github.com/Garlicvideos" 13 | } 14 | ], 15 | "license": "MIT", 16 | "dependencies": { 17 | "axios": "^0.27.2", 18 | "cheerio-without-node-native": "0.20.2" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/farshed/genius-lyrics-api.git" 23 | }, 24 | "keywords": [ 25 | "genius", 26 | "lyrics", 27 | "album-art", 28 | "scraper", 29 | "genius-lyrics", 30 | "genius-album-art", 31 | "genius-api", 32 | "lyrics-scraper" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /modules/getSongById.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const extractLyrics = require('./utils/extractLyrics'); 3 | 4 | const url = 'https://api.genius.com/songs/'; 5 | 6 | /** 7 | * @param {(number|string)} id 8 | * @param {string} apiKey 9 | */ 10 | module.exports = async function (id, apiKey) { 11 | if (!id) throw 'No id was provided'; 12 | if (!apiKey) throw 'No apiKey was provided'; 13 | try { 14 | let { 15 | data: { 16 | response: { song } 17 | } 18 | } = await axios.get(`${url}${id}?access_token=${apiKey}`); 19 | let lyrics = await extractLyrics(song.url); 20 | return { 21 | id: song.id, 22 | title: song.title, 23 | url: song.url, 24 | lyrics, 25 | albumArt: song.song_art_image_url 26 | }; 27 | } catch (e) { 28 | throw e; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /modules/getLyrics.js: -------------------------------------------------------------------------------- 1 | const searchSong = require('./searchSong'); 2 | const { checkOptions } = require('./utils'); 3 | const extractLyrics = require('./utils/extractLyrics'); 4 | 5 | /** 6 | * @param {({apiKey: string, title: string, artist: string, optimizeQuery: boolean}|string)} arg - options object, or Genius URL 7 | */ 8 | module.exports = async function (arg) { 9 | try { 10 | if (arg && typeof arg === 'string') { 11 | let lyrics = await extractLyrics(arg); 12 | return lyrics; 13 | } else if (typeof arg === 'object') { 14 | checkOptions(arg); 15 | let results = await searchSong(arg); 16 | if (!results) return null; 17 | let lyrics = await extractLyrics(results[0].url); 18 | return lyrics; 19 | } else { 20 | throw 'Invalid argument'; 21 | } 22 | } catch (e) { 23 | throw e; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /modules/utils/extractLyrics.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const cheerio = require('cheerio-without-node-native'); 3 | 4 | /** 5 | * @param {string} url - Genius URL 6 | */ 7 | module.exports = async function (url) { 8 | try { 9 | console.log(url) 10 | let { data } = await axios.get(url); 11 | const $ = cheerio.load(data); 12 | let lyrics = $('div[class="lyrics"]').text().trim(); 13 | if (!lyrics) { 14 | lyrics = ''; 15 | $('div[class^="Lyrics__Container"]').each((i, elem) => { 16 | if ($(elem).text().length !== 0) { 17 | let snippet = $(elem) 18 | .html() 19 | .replace(/
/g, '\n') 20 | .replace(/<(?!\s*br\s*\/?)[^>]+>/gi, ''); 21 | lyrics += $('