Commit 313e014f authored by Deac Karns's avatar Deac Karns
Browse files

Merge branch 'master' of git.karnsonline.com:karns-online/spotiko

parents 51d97247 bd24f1b2
node_modules/
package-lock.json
\ No newline at end of file
# EthReal
A command line utility that will display the current market values of the Cryptocurrencies you care most about right in your terminal. EthReal utilizes data from the [coinmarketcap.com](https://coinmarketcap.com) top 100.
# Spotiko
A command line utility for adding your current playing song to a pre-existing playlist. This is primarily a
convenience program so you dont have to keep leaving your development environment to save songs you like.
- [Install](#install)
- [Useage](#useage)
- [Configuration](#configuration)
- [Following a Cryptocurrency](#following-a-cryptocurrency)
- [Colors](#colors)
- [Options](#options)
- [Supported Cryptocurrencies](#supported-cryptocurrencies)
- [Useage](#useage)
### Install
```
npm install ethreal -g
```
### Useage
```
ethreal
```
### Output
```
╔══════════════╤══════════╤════════╤════════╤═══════════╤══════════╗
║ Crypto │ USD │ 24h │ 7d │ Holding │ USD ║
╟──────────────┼──────────┼────────┼────────┼───────────┼──────────╢
║ Bitcoin │ $15477.3 │ 8.5 │ -19.49 │ - │ - ║
╟──────────────┼──────────┼────────┼────────┼───────────┼──────────╢
║ Ethereum │ $759.211 │ 9.31 │ 9.0 │ 2 │ $1518.42 ║
╟──────────────┼──────────┼────────┼────────┼───────────┼──────────╢
║ Bitcoin Cash │ $3448.4 │ 19.08 │ 90.88 │ 1 │ $3448.40 ║
╟──────────────┼──────────┼────────┼────────┼───────────┼──────────╢
║ Litecoin │ $304.587 │ 9.87 │ 0.93 │ 0.1194417 │ $36.38 ║
╚══════════════╧══════════╧════════╧════════╧═══════════╧══════════╝
npm install spotiko -g
```
### Configuration
All the configuration data is stored in a `json` file in your home directory `~/.ethreal`
All the configuration data is stored in a `json` file in your home directory `~/.spotiko`
### Holdings
You can now calculate the value of your holdings automatically with EthReal. Holdings data is stored in the configuration file `~/.ethreal` as a type float. No private data is saved or stored, just a number.
The first time you run spotiko it will prompt you for the following details. obtaining them
can be found at the spotify documentation for developers https://developer.spotify.com/dashboard/
- client id
- client secret
##### Add Holdings
Example adding `0.001234` to your bitcoin holdings
```
ethreal -a 0.001234 -s btc
```
##### Remove Holdings
Example removing `0.001234` from your bitcoin holdings
### Useage
Add current track to a playlist
```
ethreal -r 0.001234 -s btc
spotiko -a
```
### Following a Cryptocurrency
###### Follow
Example, start following Bytecoin. the color option is optional. `red` will be used by default
View the current configuration
```
ethreal -f bcn -c yellow
spotiko -s
```
###### Un-follow
Example, stop following Bytecoin
View details about the current track
```
ethreal -u bcn
spotiko -c
```
### Colors
Changing the color of a cryptocurrency row is easy.
View the tracks in a playlist
```
ethreal -s btc -c blue
spotiko -p
```
##### Available colors
black, red, green, yellow, blue, magenta, cyan, white, gray, grey,
bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite,
reset, bold, dim, italic, underline, inverse, hidden, strikethrough,
rainbow, zebra, america, trap, random
### Additional Options
```
ethreal -h
spotiko -h
```
### Supported Cryptocurrencies
EthReal is currently able to display the current market value in USD for the [coinmarketcap.com](https://coinmarketcap.com) top 100:
This diff is collapsed.
{
"name": "spotiko",
"version": "0.0.4",
"version": "0.1.1",
"description": "a node CLI app for working with the spotify API",
"main": "spotiko",
"bin": {
......
......@@ -7,20 +7,23 @@ const home = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE
const inquirer = require('inquirer');
const request = require('request');
const querystring = require('querystring');
const readlineLib = require('readline');
const opn = require('opn');
const readline = readlineLib.createInterface({
input: process.stdin,
output: process.stdout
table = new Table({
head: ['Title', 'Artist', 'Album'],
chars: { 'top': '' , 'top-mid': '' , 'top-left': '' , 'top-right': ''
, 'bottom': '' , 'bottom-mid': '' , 'bottom-left': '' , 'bottom-right': ''
, 'left': '' , 'left-mid': '' , 'mid': '' , 'mid-mid': ''
, 'right': '' , 'right-mid': '' , 'middle': '' },
colWidths: [40, 20, 20]
});
program
.version('0.0.4')
.version('0.1.1')
.option('-a, --add', 'Add current track to default playlist', 0)
.option('-s, --settings', 'Display the current configuration', 0)
.option('-c, --current', 'Display the current playing track', 0)
.option('-p, --playlist', 'Display the default playlist', 0)
.option('-p, --playlist', 'Display playlist tracks', 0)
.parse(process.argv);
console.reset = function () {
......@@ -54,21 +57,18 @@ if (!fs.existsSync(home+'/.spotiko')) {
var config = loadConfig();
const promptForAuthorizationCode = function() {
return new Promise((resolve) => {
readline.question(colors.cyan('\nPaste the provided authentication code here:\n\n'), (answer) => {
readline.close();
resolve(answer)
})
});
}
var questions = [
{
type: 'input',
name: 'answer',
message: 'Paste the provided authentication code here:'
}
];
const promptForInput = function(prompt) {
return new Promise((resolve) => {
readline.question(colors.cyan('\n'+prompt+'\n\n'), (answer) => {
readline.close();
resolve(answer)
})
});
return inquirer.prompt(questions)
.then( (answers) => {
return answers.answer;
});
}
const refreshAccessToken = function() {
......@@ -149,26 +149,49 @@ const exchangeAuthorizationCodeForTokens = function(code) {
});
}
const addTrackToPlaylist = function(track,playlist) {
trackString = querystring.stringify({
uris: track.track_uri,
});
const addTrackToPlaylist = function(track, playlist) {
trackString = querystring.stringify({
uris: track.track_uri,
});
let options = {
url: ' https://api.spotify.com/v1/playlists/'+playlist.id+'/tracks?'+trackString,
auth: {
'bearer': config.access_token
},
json: true
}
let options = {
url: ' https://api.spotify.com/v1/playlists/'+playlist.id+'/tracks?'+trackString,
auth: {
'bearer': config.access_token
},
json: true
}
return new Promise(function(resolve, reject) {
request.post(options, function(error, response, body) {
if (!error && response.statusCode >= 200 && response.statusCode < 300) {
resolve(true);
}
});
});
return new Promise(function(resolve, reject) {
request.post(options, function(error, response, body) {
if (!error && response.statusCode >= 200 && response.statusCode < 300) {
resolve(playlist);
}else{
reject(error);
}
})
})
}
const selectPlaylist = function(){
console.log('\n');
return getAllPlaylists()
.then( (pl) => {
let playlists = pl.items.map(p => p.name)
return inquirer
.prompt([
{
type: 'list',
name: 'playlist',
message: 'Select a playlist?',
choices: playlists
}
])
.then(answers => {
let list = pl.items.filter( p => p.name == answers.playlist )
return list.shift()
});
})
}
const getCurrentTrack = function() {
......@@ -194,41 +217,54 @@ const getCurrentTrack = function() {
})
}
const getDefinedPlaylist = function() {
const getAllPlaylists = function() {
let options = {
url: 'https://api.spotify.com/v1/me/playlists',
auth: {
'bearer': config.access_token
}
},
json: true
}
return new Promise(function(resolve, reject) {
request(options, function(error, response, body){
let playlists = JSON.parse(body)
let use = playlists.items.filter(function(playlist) {
return (playlist.name == 'Bi Weekly Build')
})
playlist = use.shift()
resolve(playlist);
resolve(body);
})
})
}
const getPlaylistTracks = function(playlist) {
let options = {
url: 'https://api.spotify.com/v1/playlists/'+playlist.id+'/tracks',
auth: {
'bearer': config.access_token
},
json: true
}
return new Promise(function(resolve, reject) {
request(options, function(error, response, body){
resolve(body);
})
})
}
const ensureClientId = function() {
if(!config.client_id){
return new Promise(function(resolve, reject) {
promptForInput('Enter your client id:')
.then((client_id) => {
writeToConfig({
client_id: client_id
});
resolve(client_id)
})
var questions = [
{
type: 'input',
name: 'answer',
message: 'Please enter your client ID:'
}
];
});
}
else{
return inquirer.prompt(questions)
.then( (answers) => {
writeToConfig({
client_id: answers.answer
});
return answers.answer;
});
}else{
return new Promise(function(resolve, reject) {
resolve(config.client_id)
});
......@@ -236,20 +272,27 @@ const ensureClientId = function() {
}
const ensureClientSecret = function() {
return new Promise(function(resolve, reject) {
if(!config.client_id){
console.log("----here 1")
promptForInput('Enter your client secret:')
.then((client_secret) => {
writeToConfig({
client_secret: client_secret
});
resolve(client_secret)
})
}else{
if(!config.client_secret){
var questions = [
{
type: 'input',
name: 'answer',
message: 'Please enter your client Secret:'
}
];
return inquirer.prompt(questions)
.then( (answers) => {
writeToConfig({
client_secret: answers.answer
});
return answers.answer;
});
}else{
return new Promise(function(resolve, reject) {
resolve(config.client_secret)
}
});
});
}
}
......@@ -285,82 +328,78 @@ const ensureTokens = function() {
}
}
const ProgramPlaylist = function(playlist=null) {
if(!playlist){
dynpl = selectPlaylist()
}else{
dynpl = new Promise(resolve => resolve(playlist))
}
ensureClientId()
.then(()=>{
return ensureClientSecret()
})
.then(() => {
return ensureTokens()
})
.finally(()=>{
runProgram();
})
return dynpl
.then( pl => {
return getPlaylistTracks(pl)
})
.then( t => {
t.items.forEach( function(i) {
table.push(
[i.track.name, i.track.artists.map( (artist) => artist.name).toString(), i.track.album.name]
);
})
return table;
})
.then( t => {
console.log(table.toString())
return t
})
}
const runProgram = function(){
if(program.add){
refreshAccessToken()
.then( () => {
getCurrentTrack()
.then( (track) => {
console.log(colors.cyan('\n[Track]'))
console.log(colors.magenta(' Artist: ')+track.album_artist);
console.log(colors.magenta(' Album: ')+track.album_name);
console.log(colors.magenta(' Name: ')+track.track_name);
console.log(colors.magenta(' ID: ')+track.track_id);
console.log(colors.magenta(' URI: ')+track.track_uri);
console.log(colors.magenta(' URL: ')+track.track_url);
return track
})
.then( (track) => {
return getDefinedPlaylist()
.then( (playlist) => {
console.log(colors.cyan('\n[Playlist]'))
console.log(colors.magenta(' Name: ')+playlist.name)
console.log(colors.magenta(' ID: ')+playlist.id)
return playlist
}).then( (playlist) => {
return addTrackToPlaylist(track, playlist)
refreshAccessToken()
.then( () => {
getCurrentTrack()
.then( track => {
console.log(colors.cyan('\n[Track]'))
console.log(colors.magenta(' Artist: ')+track.album_artist);
console.log(colors.magenta(' Album: ')+track.album_name);
console.log(colors.magenta(' Name: ')+track.track_name);
console.log(colors.magenta(' ID: ')+track.track_id);
console.log(colors.magenta(' URI: ')+track.track_uri);
console.log(colors.magenta(' URL: ')+track.track_url);
return track
})
.then( track => {
return selectPlaylist()
.then( playlist => {
return addTrackToPlaylist(track, playlist)
})
})
.finally( () => {
console.log('\nTrack added to playlist\n');
process.exit()
.then( playlist => {
ProgramPlaylist(playlist)
})
})
})
}
else if(program.current){
refreshAccessToken()
.then( () => {
return getCurrentTrack()
.then( (track) => {
console.log(colors.cyan('\n[Track]'))
console.log(colors.magenta(' Artist: ')+track.album_artist);
console.log(colors.magenta(' Album: ')+track.album_name);
console.log(colors.magenta(' Name: ')+track.track_name);
console.log(colors.magenta(' ID: ')+track.track_id);
console.log(colors.magenta(' URI: ')+track.track_uri);
console.log(colors.magenta(' URL: ')+track.track_url);
})
.then( (track) => {
console.log(colors.cyan('\n[Track]'))
console.log(colors.magenta(' Artist: ')+track.album_artist);
console.log(colors.magenta(' Album: ')+track.album_name);
console.log(colors.magenta(' Name: ')+track.track_name);
console.log(colors.magenta(' ID: ')+track.track_id);
console.log(colors.magenta(' URI: ')+track.track_uri);
console.log(colors.magenta(' URL: ')+track.track_url);
})
})
.finally( () => process.exit())
}
else if(program.playlist){
refreshAccessToken()
.then( () => {
return getDefinedPlaylist()
.then( (playlist) => {
console.log(colors.cyan('\n[Playlist]'))
console.log(colors.magenta(' Name: ')+playlist.name)
console.log(colors.magenta(' ID: ')+playlist.id)
})
})
.finally( () => process.exit())
ProgramPlaylist()
}
else if(program.settings){
......@@ -370,4 +409,9 @@ const runProgram = function(){
else {
program.help();
}
}
\ No newline at end of file
}
ensureClientId()
.then(ensureClientSecret)
.then(ensureTokens)
.finally(runProgram)
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment