Skip to content

Commit

Permalink
Got carried away and created simple http interface.
Browse files Browse the repository at this point in the history
  • Loading branch information
SamFleming committed Mar 16, 2016
1 parent bb33624 commit c3d6255
Show file tree
Hide file tree
Showing 28 changed files with 5,492 additions and 21 deletions.
5,044 changes: 5,044 additions & 0 deletions assets/css/app.css

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions assets/css/app.css.map

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions assets/js/angular.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions assets/js/app.js

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions assets/js/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
var foundationRoutes = [
{
"name": "settings",
"url":"/settings",
"animationIn": "fadeIn",
"animationOut": "fadeOut",
"path":"templates/settings.html"
},
{
"name": "home",
"url": "/",
"animationIn": "fadeIn",
"animationOut": "fadeOut",
"path":"templates/home.html"
}
];
4 changes: 4 additions & 0 deletions assets/partials/accordion-item.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div class="accordion-item" ng-class="{'is-active': active}">
<div class="accordion-title" ng-click="activate()">{{ title }}</div>
<div class="accordion-content" ng-transclude></div>
</div>
2 changes: 2 additions & 0 deletions assets/partials/accordion.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<div class="accordion" ng-transclude>
</div>
7 changes: 7 additions & 0 deletions assets/partials/actionsheet-button.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div>
<a href="#"
class="button"
ng-click="toggle()"
ng-if="title.length > 0">{{ title }}</a>
<div ng-transclude></div>
</div>
5 changes: 5 additions & 0 deletions assets/partials/actionsheet-content.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div
class="action-sheet {{ position }}"
ng-class="{'is-active': active}"
ng-transclude>
</div>
2 changes: 2 additions & 0 deletions assets/partials/actionsheet.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<div class="action-sheet-container" ng-transclude>
</div>
9 changes: 9 additions & 0 deletions assets/partials/modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div
ng-class="{'modal-overlay': overlay}"
ng-click="hide()">
<aside
class="modal"
ng-click="$event.stopPropagation();"
ng-transclude>
</aside>
</div>
7 changes: 7 additions & 0 deletions assets/partials/notification-set.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<zf-notification ng-repeat="notification in notifications"
title="notification.title"
img="notification.image"
notif-id = "notification.id"
color="notification.color"
position="notification.position">{{ notification.content }}</zf-notification>

12 changes: 12 additions & 0 deletions assets/partials/notification.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<div class="notification {{ position }} {{ color }}">
<a href="#"
class="close-button"
ng-click="remove(); $event.preventDefault(); $event.stopPropagation()">&times;</a>
<div class="notification-icon" ng-if="image">
<img src="{{ image }}" />
</div>
<div class="notification-content">
<h1>{{ title }}</h1>
<p ng-transclude></p>
</div>
</div>
5 changes: 5 additions & 0 deletions assets/partials/offcanvas.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div
class="off-canvas {{ position }}"
ng-class="{'is-active': active}"
ng-transclude>
</div>
4 changes: 4 additions & 0 deletions assets/partials/panel.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div
class="panel {{ 'panel-' + position }}"
ng-transclude>
</div>
2 changes: 2 additions & 0 deletions assets/partials/popup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<div class="popup" ng-class="{'is-active': active }" ng-transclude>
</div>
8 changes: 8 additions & 0 deletions assets/partials/tab-content.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div class="tab-contents">
<div zf-tab-individual
class="tab-content"
ng-class="{'is-active': tab.active}"
ng-repeat="tab in tabs"
tab="tab">
</div>
</div>
3 changes: 3 additions & 0 deletions assets/partials/tab.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="tab-item"
ng-class="{'is-active': active}"
ng-click="makeActive()">{{ title }}</div>
8 changes: 8 additions & 0 deletions assets/partials/tabs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<div>
<div class="tabs" ng-transclude>
</div>
<div zf-tab-content
target="{{ id }}"
ng-if="showTabContent">
</div>
</div>
56 changes: 56 additions & 0 deletions assets/templates/home.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<div zf-panel position="left" id="sub-nav" class="fast bounceInOut medium-2 medium-grid-block vertical">
<div class="grid-content">
<ul class="icon-left vertical menu-bar">
<li><a href="#"><img zf-iconic="" data-src="/assets/img/iconic/ban.svg"> Songs</a></li>
<li><a href="#"><img zf-iconic="" data-src="/assets/img/iconic/ban.svg"> Albums</a></li>
<li><a href="#"><img zf-iconic="" data-src="/assets/img/iconic/ban.svg"> Artists</a></li>
</ul>
</div>
<div class="grid-content shrink now-playing" ng-controller="NowPlayingCtrl">
<h5>Now Playing</h5>
<img src="http://placehold.it/350x350&text=Album">
<p>Shake it off by Taylor Swift</p>
</div>
</div>

<div class="small-12 medium-7 messages grid-content">

<div ng-controller="SearchCtrl">
<br />
<input type="search" id="search" autocomplete="off" placeholder="keywords..." ng-model="searchQuery" ng-keyup="search()" />

<div class="grid-block small-up-2 medium-up-2 large-up-4">
<div ng-repeat="result in results" class="">
<div class="card">
<img ng-src="{{ result.album.images[1].url }}" />
<div class="card-divider">
{{ result.name }}
</div>
<div class="card-section">
<p>
{{ result.album.name }}<br />
{{ result.artists[0].name }}

<a class="success button" ng-click="queue(result)">Add to Queue</a>
</p>
</div>
</div>
</div>
</div>
</div>
</div>

<div zf-panel id="feed" position="right" class="fast bounceInOut medium-3 medium-grid-content">
<section class="block-list" ng-controller="QueueCtrl">
<header>Queue</header>
<ul>
<li ng-repeat="track in queue">
<div class="grid-content">
<img ng-src="{{ track.album.images[0].url }}" />
{{ track.name }}<br />
{{ track.artists[0].name }}
</div>
</li>
</ul>
</section>
</div>
38 changes: 38 additions & 0 deletions assets/templates/settings.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

<div class="grid-block align-center">
<div class="grid-content medium-6">
<h4><a ui-sref="home">&#10094; Back</a></h4>

<hr />

<section class="block-list">
<header>Account Info</header>
<ul>
<li><input type="text" value="[email protected]"></li>
<li><input type="password" value="password1234"></li>
</ul>
</section>

<section class="block-list">
<header>Filtering</header>
<ul>
<li>
<span>Filter Spam</span>
<div class="switch"><input type="checkbox" id="setting1"><label for="setting1"></label></div>
</li>
<li>
<span>Delete Facebook Emails</span>
<div class="switch"><input type="checkbox" id="setting2"><label for="setting2"></label></div>
</li>
<li>
<span>Bake Pizza</span>
<div class="switch"><input type="checkbox" id="setting3"><label for="setting3"></label></div>
</li>
<li>
<span>Consider Corgis</span>
<div class="switch"><input type="checkbox" id="setting4"><label for="setting4"></label></div>
</li>
</ul>
</section>
</div>
</div>
4 changes: 2 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
var spotiPi = require('./src/client.js');
var spotifyApi = require('./src/spotifyAPI.js')('https://api.spotify.com/v1/');
var slack = require('./src/slackInterface.js');
var http = require('./src/httpInterface.js')(spotiPi);
var http = require('./src/httpInterface.js');

http(spotiPi);
slack(spotiPi);

//TODO: have options for http interface, slack interface, etc, defined in config.
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"description": "A server component to send SpotiPi events over a websocket connection.",
"dependencies": {
"@slack/client": "^2.2.1",
"body-parser": "^1.15.0",
"ejs": "^2.4.1",
"express": "^4.13.4",
"request-promise": "^2.0.1",
"socket.io": "^1.4.5"
Expand Down
63 changes: 47 additions & 16 deletions src/client.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
var io = require('socket.io')(3000);
var request = require('request-promise');
var spotifyAPI = require('./spotifyAPI.js');
var playlist = require('./playlist.js');

var apiClient = new spotifyAPI('https://api.spotify.com/v1/');

io.on('connection', function() {
console.log('Client connected');
});

exports.search = function(searchQuery, callback) {
apiClient.search(searchQuery, callback);
};

exports.getPlaylist = function () {
return playlist.get();
};

exports.add = function (track) {
var queue = playlist.add(track);
io.emit('add track to queue', track.uri);
return queue;
};

exports.searchAndAdd = function(searchQuery, callback) {

console.log("Searching for..." + searchQuery);
var searchURI = encodeURI('https://api.spotify.com/v1/search?q=' + searchQuery + '&type=track&limit=1');

request(searchURI).then(function (response) {

var track = JSON.parse(response).tracks.items[0];
io.emit('add track to queue', track.uri);

callback({
name: track.name,
artist: track.artists[0].name
});
})
.catch(function (err) {
apiClient.search(searchQuery, function (tracks) {
var track = tracks.items[0];

console.log("error with Spotify web API request: " + err);
console.log("tried to search with URI: " + searchURI)
io.emit('add track to queue', track.uri);
console.log('Queued track ' + track.artists[0].name + ': ' + track.name);

callback({
name: track.name,
artist: track.artists[0].name
});

});
};

exports.skip = function(callback) {
Expand All @@ -37,4 +48,24 @@ exports.skip = function(callback) {

callback();

};
};

exports.play = function(callback) {
var callback = callback || function() {};

console.log("playing...");

io.emit('play');

callback();
};

exports.pause = function(callback) {
var callback = callback || function() {};

console.log("pausing...");

io.emit('pause');

callback();
};
48 changes: 46 additions & 2 deletions src/httpInterface.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,51 @@
var express = require('express');
var bodyParser = require('body-parser');

module.exports = function (spotiPiClient) {
module.exports = function (spotiPiClient, playlist) {
var app = express();

app.listen(4000);
app.use(express.static(__dirname + '/../assets'));
app.use(bodyParser.json());
app.set('views', __dirname + '/../views');
app.engine('html', require('ejs').renderFile);

app.get('/', function (req, res) {
res.render('index.html');
});

app.get('/api/play', function (req, res) {
spotiPiClient.play();

res.json({ 'status': 'playing' });
});

app.get('/api/pause', function (req, res) {
spotiPiClient.pause();

res.json({ 'status': 'paused' });
});

app.get('/api/playlist', function (req, res) {
res.json(spotiPiClient.getPlaylist());
});

app.post('/api/queue', function (req, res) {
var queue = spotiPiClient.add(req.body);
res.json({ 'added': true, 'queue': queue });
});

app.get('/api/search', function (req, res) {
if (req.query.hasOwnProperty('q')) {
var searchQuery = req.query.q;

spotiPiClient.search(searchQuery, function (tracks) {
res.json(tracks);
});
} else {
res.json({ 'error': 'Must specify a query' });
}
});

app.get('/play_from_query', function (req, res) {

Expand All @@ -15,8 +57,10 @@ module.exports = function (spotiPiClient) {
spotiPiClient.searchAndAdd(searchQuery, function (track) {
rtm.sendMessage('I\'ve queued up ' + track.name + ' by ' + track.artist, message.channel);
});

res.json({ 'status': 'queued', 'artist': track.artist, 'track': track.name });
} else {
res.send('You must provide a query.');
res.json({ 'error': 'Must specify a query' });
}

});
Expand Down
11 changes: 11 additions & 0 deletions src/playlist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var queue = [];

exports.get = function (err) {
return queue;
};

exports.add = function (track) {
queue.push(track);

return queue;
};
Loading

0 comments on commit c3d6255

Please sign in to comment.