├── .gitignore ├── Dockerfile ├── package.json ├── README.md ├── index.js ├── test └── api.js └── lib └── api.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | from node:argon 2 | 3 | RUN mkdir -p /install 4 | 5 | WORKDIR /install 6 | 7 | COPY package.json /install/ 8 | 9 | ENV NODE_PATH=/install 10 | 11 | RUN npm install 12 | 13 | ENV NODE_PATH=/install/node_modules 14 | 15 | WORKDIR /app/ 16 | 17 | COPY . /app/ 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsgalume", 3 | "version": "0.0.1", 4 | "description": "download lyrics using vagalume's api", 5 | "main": "index.js", 6 | "repository": "", 7 | "author": "Fellipe Pinheiro", 8 | "dependencies": { 9 | "request": "latest", 10 | "yargs": "latest" 11 | }, 12 | "devDependencies": { 13 | "mocha": "latest" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jsgalume 2 | 3 | 4 | Cópia descarada e mal feita em Javascript do [Pygalume](https://github.com/indacode/pygalume), 5 | feito só para aprendizado e diversão. :] 6 | 7 | 8 | ## Como usar? 9 | 10 | Pra instalar todas as dependências: 11 | 12 | `npm install` 13 | 14 | 15 | Para baixar a letra da música `Last Kiss` do `Pearl Jam`: 16 | 17 | `node index.js -a "Pearl Jam" -m "Last Kiss"` 18 | 19 | Para listar a discografia do `Pearl Jam`: 20 | 21 | `node index.js -a "Pearl Jam" -d` 22 | 23 | Mais informações: 24 | 25 | `node index.js --help` 26 | 27 | 28 | # Desenvolvedor 29 | 30 | Para rodar usando Docker, primeiro crie uma imagem do Dockerfile: 31 | 32 | `docker build -t node-app .` 33 | 34 | Agora execute: 35 | 36 | `docker run -it node-app node index.js -a "Pearl Jam" -m "Last Kiss"` 37 | 38 | 39 | ## Tests 40 | 41 | Para rodar os testes unitários: 42 | 43 | `mocha test/` 44 | 45 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var argv = require('yargs') 4 | .usage('Usage to get lyrics: $0 -a [artist name] -m [music name]\n' + 5 | 'Usage to get songs list: $0 -a [artist name] -b [album name]' + 6 | 'Usage to get discography: $0 -a [artist name] -d') 7 | .demand('a') 8 | .argv; 9 | 10 | const API = require('./lib/api.js'); 11 | 12 | 13 | var api = new API(); 14 | 15 | 16 | if ( argv.a && argv.m ) { 17 | 18 | api.getLyrics(argv.a, argv.m).then( 19 | function (data) { 20 | console.log('\n\n'); 21 | console.log('- Artista: ' + data.artist); 22 | console.log('- Música: ' + data.music); 23 | console.log('- URL: ' + data.music_url); 24 | console.log('\n\n -ORIGINAL:\n' + data.text); 25 | if (data.translate) { 26 | console.log('\n\n -TRANSLATE : ' + data.translate); 27 | } 28 | }, 29 | function (err) { 30 | console.log(err); 31 | } 32 | ); 33 | 34 | } else if ( argv.a && argv.d) { 35 | 36 | api.getDiscography(argv.a).then( 37 | function (data) { 38 | for (var item of data) 39 | console.log(item.desc + ' - ' + item.published); 40 | }, 41 | function (err) { 42 | console.log(err); 43 | } 44 | ); 45 | 46 | } else if ( argv.a && argv.b ) { 47 | 48 | api.getSongs(argv.a, argv.b).then( 49 | function (data) { 50 | // Remove the last char, because is a "/" 51 | const URL = api.MAIN_URL.slice(api.API_URL, -1) 52 | 53 | for (var item of data) { 54 | console.log(item.desc); 55 | console.log(URL + item.url + '\n'); 56 | } 57 | }, 58 | function (err) { 59 | console.log(err); 60 | } 61 | ); 62 | 63 | } else { 64 | console.log('Something went wrong, see --help for more information.'); 65 | } 66 | -------------------------------------------------------------------------------- /test/api.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const chai = require('chai'); 4 | const expect = chai.expect; 5 | const chaiAsPromised = require('chai-as-promised'); 6 | const API = require('./../lib/api') 7 | 8 | chai.use(chaiAsPromised); 9 | 10 | 11 | describe('Test API responses', function () { 12 | 13 | const api = new API(); 14 | 15 | describe('Test getLyrics', function () { 16 | 17 | it('Must return the right artist name', function () { 18 | const expected = 'Pearl Jam'; 19 | 20 | var result = api.getLyrics('Pearl Jam', 'Last Kiss'); 21 | 22 | return expect(result.then( obj => obj.artist )).to.eventually.equal(expected); 23 | }); 24 | 25 | it('Must return a message error: Artist not found!', function () { 26 | const expected = 'Artist not found!'; 27 | 28 | var result = api.getLyrics('Pel Jam', 'Last Kiss'); 29 | 30 | return expect(result).to.be.rejectedWith(expected); 31 | }); 32 | 33 | it('Must return a message error: Song not found!', function () { 34 | const expected = 'Song not found!'; 35 | 36 | var result = api.getLyrics('Pearl Jam', 'blabla'); 37 | 38 | return expect(result).to.be.rejectedWith(expected); 39 | }); 40 | }); 41 | 42 | describe('Test getDiscography', function () { 43 | 44 | it('Must return the right amount of albums', function () { 45 | const expected = 15; 46 | 47 | var result = api.getDiscography('Pearl Jam'); 48 | 49 | return expect(result.then( obj => obj.length )).to.eventually.equal(expected) 50 | }); 51 | 52 | it('Must return a message error: Artist not found!', function () { 53 | const expected = 'Artist not found!'; 54 | 55 | var result = api.getDiscography('Pel Jam'); 56 | 57 | return expect(result).to.be.rejectedWith(expected); 58 | }); 59 | }); 60 | 61 | describe('Test getSongs', function () { 62 | 63 | it('Must return the right amount of songs', function () { 64 | const expected = 11; 65 | 66 | var result = api.getSongs('Pearl Jam', 'Ten'); 67 | 68 | return expect(result.then( obj => obj.length )).to.eventually.equal(expected); 69 | }); 70 | 71 | it('Must return a message error: Artist not found!', function () { 72 | const expected = 'Artist not found!'; 73 | 74 | var result = api.getSongs('Pel Jam', 'Ten'); 75 | 76 | return expect(result).to.be.rejectedWith(expected); 77 | }); 78 | 79 | it('Must return a message error: Album not found!', function () { 80 | const expected = 'Album not found!'; 81 | 82 | var result = api.getSongs('Pearl Jam', 'blabla'); 83 | 84 | return expect(result).to.be.rejectedWith(expected); 85 | }); 86 | }); 87 | 88 | }); 89 | -------------------------------------------------------------------------------- /lib/api.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const request = require('request'); 4 | 5 | 6 | class API{ 7 | constructor(){ 8 | this.API_URL = 'http://api.vagalume.com.br/search.php?'; 9 | this.MAIN_URL = 'http://www.vagalume.com.br/' 10 | } 11 | 12 | getLyrics(artist_name, music_name) { 13 | 14 | return new Promise((resolve, reject) => { 15 | const art = artist_name.replace(' ', '+'); 16 | const mus = music_name.replace(' ', '+'); 17 | const options = { 18 | url: this.API_URL + 'art='+ art +'&mus=' + mus 19 | }; 20 | 21 | request(options, (err, res, body) => { 22 | 23 | if ( err ) { 24 | reject(err); 25 | } else { 26 | 27 | let data = JSON.parse(body); 28 | 29 | if ( data.type === 'song_notfound' ) { 30 | reject(Error('Song not found!')); 31 | 32 | } else if ( data.type === 'notfound' ) { 33 | reject(Error('Artist not found!')); 34 | 35 | } else { 36 | 37 | // If the song is in portuguese, for example, there is no translation. 38 | var translate; 39 | try { 40 | translate = data.mus[0].translate[0].text; 41 | } catch (TypeError) { 42 | translate = ''; 43 | } 44 | const song = { 45 | 'artist': data.art.name 46 | , 'music': data.mus[0].name 47 | , 'music_url': data.mus[0].url 48 | , 'text': data.mus[0].text 49 | , 'translate': translate 50 | }; 51 | 52 | resolve(song); 53 | } 54 | } 55 | 56 | }); 57 | }); 58 | } 59 | 60 | getDiscography(artist_name) { 61 | 62 | return new Promise((resolve, reject) => { 63 | 64 | const art = artist_name.replace(' ', '-'); 65 | 66 | const options = { 67 | url: this.MAIN_URL + art + '/discografia/index.js' 68 | }; 69 | 70 | request(options, (err, res, body) => { 71 | 72 | if ( err ) { 73 | reject(err); 74 | } else { 75 | 76 | try { 77 | 78 | var data = JSON.parse(body); 79 | 80 | } catch (SyntaxError) { 81 | reject(Error('Artist not found!')); 82 | } 83 | 84 | if (typeof(data) === 'undefined') { 85 | 86 | reject(Error('Artist not found!')) 87 | 88 | } else { 89 | 90 | resolve(data.discography.item); 91 | 92 | } 93 | } 94 | 95 | }); 96 | 97 | }); 98 | } 99 | 100 | getSongs(artist_name, album_name) { 101 | 102 | return new Promise((resolve, reject) => { 103 | const art = artist_name.replace(' ', '-'); 104 | 105 | const options = { 106 | url: this.MAIN_URL + art + '/discografia/index.js' 107 | }; 108 | 109 | request(options, (err, res, body) => { 110 | if ( err ) { 111 | reject(err); 112 | } else { 113 | 114 | try { 115 | 116 | var data = JSON.parse(body) 117 | 118 | } catch (SyntaxError) { 119 | reject(Error('Artist not found!')); 120 | } 121 | 122 | if (typeof(data) === 'undefined') { 123 | 124 | reject(Error('Artist not found!')) 125 | 126 | } else { 127 | var songs = []; 128 | 129 | for ( var item of data.discography.item ) { 130 | if ( item.desc === album_name ) { 131 | for ( var song of item.discs[0] ) { 132 | songs.push(song); 133 | } 134 | break; 135 | } 136 | } 137 | 138 | if ( songs.length > 0 ) { 139 | resolve(songs); 140 | } else { 141 | reject(Error('Album not found!')); 142 | } 143 | 144 | } 145 | } 146 | }); 147 | }); 148 | } 149 | 150 | }; 151 | 152 | module.exports = API 153 | --------------------------------------------------------------------------------