2016-10-27 16:58:11 +13:00
|
|
|
|
2016-10-27 21:20:05 +13:00
|
|
|
var helpers = require('../../helpers.js')
|
2017-02-06 17:02:43 +13:00
|
|
|
var uiActions = require('../ui/actions.js')
|
|
|
|
|
var pusherActions = require('./actions.js')
|
|
|
|
|
var spotifyActions = require('../spotify/actions.js')
|
2016-10-27 16:58:11 +13:00
|
|
|
|
|
|
|
|
const PusherMiddleware = (function(){
|
|
|
|
|
|
|
|
|
|
// container for the actual Mopidy socket
|
|
|
|
|
var socket = null;
|
2017-01-09 09:29:56 +13:00
|
|
|
var deferredRequests = [];
|
|
|
|
|
|
|
|
|
|
const resolveRequest = (requestId, message ) => {
|
|
|
|
|
var response = JSON.parse( message );
|
|
|
|
|
deferredRequests[request_id].resolve( response );
|
|
|
|
|
delete deferredRequests[request_id];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const rejectRequest = (requestId, message) => {
|
|
|
|
|
deferredRequests[requestId].reject( message );
|
|
|
|
|
}
|
2016-10-27 16:58:11 +13:00
|
|
|
|
|
|
|
|
// handle all manner of socket messages
|
|
|
|
|
const handleMessage = (ws, store, message) => {
|
2017-02-19 21:27:43 +13:00
|
|
|
|
2017-02-18 22:04:05 +13:00
|
|
|
// response to a request [we] made
|
|
|
|
|
if (typeof(message.request_id) !== 'undefined' && message.request_id){
|
|
|
|
|
if (typeof( deferredRequests[ message.request_id ]) !== 'undefined' ){
|
|
|
|
|
deferredRequests[ message.request_id ].resolve( message )
|
|
|
|
|
} else {
|
|
|
|
|
console.error('Pusher: Response with no matching request', message);
|
|
|
|
|
}
|
2016-10-27 16:58:11 +13:00
|
|
|
|
2017-02-18 22:04:05 +13:00
|
|
|
// general message
|
|
|
|
|
// this can be client-client, server-client or a broadcast to many clients
|
|
|
|
|
} else {
|
2017-02-19 21:27:43 +13:00
|
|
|
message.type = 'PUSHER_'+message.type.toUpperCase()
|
2017-02-18 22:04:05 +13:00
|
|
|
store.dispatch(message)
|
2017-01-09 09:29:56 +13:00
|
|
|
}
|
2016-10-27 21:20:05 +13:00
|
|
|
}
|
|
|
|
|
|
2017-02-18 22:04:05 +13:00
|
|
|
const request = (method, data = {}) => {
|
2017-01-09 09:29:56 +13:00
|
|
|
return new Promise( (resolve, reject) => {
|
2017-02-18 22:04:05 +13:00
|
|
|
var request_id = helpers.generateGuid()
|
|
|
|
|
var message = {
|
|
|
|
|
method: method,
|
|
|
|
|
data: data,
|
|
|
|
|
request_id: request_id
|
|
|
|
|
}
|
|
|
|
|
socket.send( JSON.stringify(message) )
|
2017-01-09 09:29:56 +13:00
|
|
|
|
|
|
|
|
// add query to our deferred responses
|
2017-02-18 22:04:05 +13:00
|
|
|
deferredRequests[request_id] = {
|
2017-01-09 09:29:56 +13:00
|
|
|
resolve: resolve,
|
|
|
|
|
reject: reject
|
|
|
|
|
}
|
|
|
|
|
})
|
2016-11-29 15:36:01 +13:00
|
|
|
}
|
|
|
|
|
|
2016-10-27 16:58:11 +13:00
|
|
|
return store => next => action => {
|
|
|
|
|
switch(action.type) {
|
|
|
|
|
|
2017-01-09 09:29:56 +13:00
|
|
|
case 'PUSHER_INSTRUCT':
|
2017-02-18 22:04:05 +13:00
|
|
|
request( action )
|
2017-01-09 09:29:56 +13:00
|
|
|
.then(
|
|
|
|
|
response => {
|
|
|
|
|
store.dispatch({ type: 'PUSHER_INSTRUCT', data: response.data })
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
break
|
|
|
|
|
|
2016-10-27 16:58:11 +13:00
|
|
|
case 'PUSHER_CONNECT':
|
|
|
|
|
|
|
|
|
|
if(socket != null) socket.close();
|
|
|
|
|
store.dispatch({ type: 'PUSHER_CONNECTING' });
|
|
|
|
|
|
|
|
|
|
var state = store.getState();
|
2016-10-28 09:14:29 +13:00
|
|
|
var connection = {
|
2017-02-17 21:36:31 +13:00
|
|
|
clientid: helpers.generateGuid(),
|
2017-02-18 22:04:05 +13:00
|
|
|
connection_id: helpers.generateGuid(),
|
2017-02-17 21:36:31 +13:00
|
|
|
username: 'Anonymous'
|
2016-10-28 09:14:29 +13:00
|
|
|
}
|
2016-10-28 15:58:07 +13:00
|
|
|
if( state.pusher.username ) connection.username = state.pusher.username;
|
2017-02-17 21:36:31 +13:00
|
|
|
connection.username = connection.username.replace(/\W/g, '')
|
2017-02-16 19:51:49 +13:00
|
|
|
|
2016-10-27 16:58:11 +13:00
|
|
|
socket = new WebSocket(
|
2017-02-16 19:51:49 +13:00
|
|
|
'ws://'+state.mopidy.host+':'+state.mopidy.port+'/iris/ws',
|
2017-02-18 22:04:05 +13:00
|
|
|
[ connection.clientid, connection.connection_id, connection.username ]
|
2016-10-27 16:58:11 +13:00
|
|
|
);
|
|
|
|
|
|
2016-10-28 09:14:29 +13:00
|
|
|
socket.onmessage = (message) => {
|
2016-10-27 16:58:11 +13:00
|
|
|
var message = JSON.parse(message.data);
|
|
|
|
|
handleMessage( socket, store, message )
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
2016-10-27 21:20:05 +13:00
|
|
|
case 'PUSHER_CONNECTED':
|
2017-02-18 22:04:05 +13:00
|
|
|
request('get_config')
|
2017-02-06 10:07:32 +13:00
|
|
|
.then(
|
|
|
|
|
response => {
|
2017-02-18 22:04:05 +13:00
|
|
|
if (response.error){
|
|
|
|
|
console.error(response.error)
|
2017-02-07 10:21:20 +13:00
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-21 05:46:28 +13:00
|
|
|
response.type = 'PUSHER_CONFIG'
|
2017-02-18 22:04:05 +13:00
|
|
|
store.dispatch(response)
|
|
|
|
|
if (response.config.spotify_username){
|
|
|
|
|
store.dispatch(spotifyActions.getUser('spotify:user:'+response.config.spotify_username))
|
2017-02-06 17:02:43 +13:00
|
|
|
}
|
2017-02-06 13:00:21 +13:00
|
|
|
var spotify = store.getState().spotify
|
|
|
|
|
if (!spotify.country || !spotify.locale){
|
2017-02-18 22:04:05 +13:00
|
|
|
store.dispatch({ type: 'SPOTIFY_SET_CONFIG', config: response.config })
|
2017-02-06 13:00:21 +13:00
|
|
|
}
|
2017-02-06 10:07:32 +13:00
|
|
|
}
|
|
|
|
|
)
|
2017-02-18 22:04:05 +13:00
|
|
|
request('get_version')
|
2017-01-09 09:29:56 +13:00
|
|
|
.then(
|
|
|
|
|
response => {
|
2017-02-18 22:04:05 +13:00
|
|
|
if (response.error){
|
|
|
|
|
console.error(response.error)
|
2017-02-07 10:21:20 +13:00
|
|
|
return false
|
|
|
|
|
}
|
2017-02-21 05:46:28 +13:00
|
|
|
response.type = 'PUSHER_VERSION'
|
2017-02-18 22:04:05 +13:00
|
|
|
store.dispatch(response)
|
2017-01-09 09:29:56 +13:00
|
|
|
}
|
|
|
|
|
)
|
2017-02-18 22:04:05 +13:00
|
|
|
request('get_radio')
|
2017-02-06 10:07:32 +13:00
|
|
|
.then(
|
|
|
|
|
response => {
|
2017-02-18 22:04:05 +13:00
|
|
|
if (response.error){
|
|
|
|
|
console.error(response.error)
|
2017-02-07 10:21:20 +13:00
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-21 05:46:28 +13:00
|
|
|
response.type = 'PUSHER_RADIO'
|
2017-02-18 22:04:05 +13:00
|
|
|
store.dispatch(response)
|
2017-02-06 10:07:32 +13:00
|
|
|
}
|
|
|
|
|
)
|
2017-02-14 21:41:13 +13:00
|
|
|
|
|
|
|
|
store.dispatch(pusherActions.getQueueMetadata())
|
|
|
|
|
|
2016-10-29 22:40:02 +13:00
|
|
|
return next(action);
|
|
|
|
|
break;
|
|
|
|
|
|
2017-02-14 12:13:07 +13:00
|
|
|
case 'PUSHER_GET_QUEUE_METADATA':
|
2017-02-18 22:04:05 +13:00
|
|
|
request('get_queue_metadata')
|
2017-02-14 12:13:07 +13:00
|
|
|
.then(
|
|
|
|
|
response => {
|
2017-02-18 22:04:05 +13:00
|
|
|
response.type = 'QUEUE_METADATA'
|
|
|
|
|
store.dispatch(response)
|
2017-02-14 12:13:07 +13:00
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'PUSHER_ADD_QUEUE_METADATA':
|
2017-02-18 22:04:05 +13:00
|
|
|
request('add_queue_metadata', {
|
|
|
|
|
tlids: action.tlids,
|
|
|
|
|
added_from: action.from_uri,
|
|
|
|
|
added_by: store.getState().pusher.username
|
|
|
|
|
})
|
2017-02-14 12:13:07 +13:00
|
|
|
break;
|
|
|
|
|
|
2017-02-19 21:27:43 +13:00
|
|
|
case 'PUSHER_START_UPGRADE':
|
2017-02-18 22:04:05 +13:00
|
|
|
request('upgrade')
|
|
|
|
|
.then(
|
|
|
|
|
response => {
|
|
|
|
|
if (response.error){
|
|
|
|
|
console.error(response.error)
|
|
|
|
|
return false
|
|
|
|
|
}
|
2017-02-07 10:21:20 +13:00
|
|
|
|
2017-02-18 22:04:05 +13:00
|
|
|
if (response.upgrade_successful){
|
|
|
|
|
store.dispatch( uiActions.createNotification('Upgrade complete') )
|
|
|
|
|
}else{
|
|
|
|
|
store.dispatch( uiActions.createNotification('Upgrade failed, please upgrade manually','bad') )
|
2017-01-09 09:29:56 +13:00
|
|
|
}
|
2017-02-18 22:04:05 +13:00
|
|
|
|
2017-02-21 05:46:28 +13:00
|
|
|
response.type = 'PUSHER_VERSION'
|
2017-02-18 22:04:05 +13:00
|
|
|
store.dispatch(response)
|
|
|
|
|
}
|
|
|
|
|
)
|
2016-10-28 09:14:29 +13:00
|
|
|
return next(action);
|
|
|
|
|
break;
|
|
|
|
|
|
2017-01-09 09:29:56 +13:00
|
|
|
case 'PUSHER_SET_USERNAME':
|
2017-02-18 22:04:05 +13:00
|
|
|
request('set_username', {
|
|
|
|
|
username: action.username
|
|
|
|
|
})
|
|
|
|
|
.then(
|
|
|
|
|
response => {
|
|
|
|
|
if (response.error){
|
|
|
|
|
console.error(response.error)
|
|
|
|
|
return false
|
2017-01-09 09:29:56 +13:00
|
|
|
}
|
2017-02-19 21:27:43 +13:00
|
|
|
response.type = 'PUSHER_USERNAME_CHANGED'
|
|
|
|
|
store.dispatch(response)
|
2017-02-18 22:04:05 +13:00
|
|
|
}
|
|
|
|
|
)
|
2016-10-28 10:48:55 +13:00
|
|
|
return next(action);
|
|
|
|
|
break;
|
|
|
|
|
|
2017-02-19 21:27:43 +13:00
|
|
|
case 'PUSHER_GET_CONNECTIONS':
|
2017-02-18 22:04:05 +13:00
|
|
|
request('get_connections')
|
|
|
|
|
.then(
|
|
|
|
|
response => {
|
|
|
|
|
if (response.error){
|
|
|
|
|
console.error(response.error)
|
|
|
|
|
return false
|
2017-01-09 09:29:56 +13:00
|
|
|
}
|
2017-02-19 21:27:43 +13:00
|
|
|
response.type = 'PUSHER_CONNECTIONS'
|
2017-02-18 22:04:05 +13:00
|
|
|
store.dispatch(response)
|
|
|
|
|
}
|
|
|
|
|
)
|
2017-01-09 09:29:56 +13:00
|
|
|
return next(action);
|
|
|
|
|
break
|
2016-12-05 10:20:01 +13:00
|
|
|
|
|
|
|
|
case 'PUSHER_DEBUG':
|
2017-02-21 05:46:28 +13:00
|
|
|
request( action.message.method, action.message.data )
|
2017-02-18 22:04:05 +13:00
|
|
|
.then(
|
2017-02-21 05:46:28 +13:00
|
|
|
response => {
|
|
|
|
|
store.dispatch({type: 'DEBUG', response: response})
|
2017-02-18 22:04:05 +13:00
|
|
|
}
|
|
|
|
|
)
|
2016-10-27 21:20:05 +13:00
|
|
|
break;
|
|
|
|
|
|
2017-01-09 09:29:56 +13:00
|
|
|
case 'PUSHER_SEND_AUTHORIZATION':
|
2017-02-18 22:04:05 +13:00
|
|
|
request('send_authorization', {
|
|
|
|
|
recipient_connection_id: action.recipient_connection_id,
|
2017-01-09 09:29:56 +13:00
|
|
|
authorization: action.authorization,
|
|
|
|
|
me: action.me
|
|
|
|
|
})
|
|
|
|
|
.then(
|
|
|
|
|
response => {
|
2017-02-18 22:04:05 +13:00
|
|
|
if (response.error){
|
|
|
|
|
console.error(response.error)
|
2017-02-07 10:21:20 +13:00
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-10 16:51:08 +13:00
|
|
|
store.dispatch( uiActions.createNotification('Authorization sent') )
|
2017-01-09 09:29:56 +13:00
|
|
|
}
|
|
|
|
|
)
|
2016-11-29 15:36:01 +13:00
|
|
|
break;
|
|
|
|
|
|
2016-12-12 09:07:47 +13:00
|
|
|
case 'PUSHER_SEND_AUTHORIZATION':
|
2017-02-18 22:04:05 +13:00
|
|
|
if( window.confirm('Spotify authorization for user '+action.me.id+' received. Do you want to import?') ){
|
2016-12-12 09:07:47 +13:00
|
|
|
|
|
|
|
|
// remove any existing authentication
|
|
|
|
|
store.dispatch({ type: 'SPOTIFY_AUTHORIZATION_REVOKED' })
|
|
|
|
|
|
|
|
|
|
// import our new authentication
|
2017-02-18 22:04:05 +13:00
|
|
|
store.dispatch({ type: 'SPOTIFY_ME_LOADED', data: action.me })
|
|
|
|
|
store.dispatch({ type: 'SPOTIFY_AUTHORIZATION_GRANTED', data: action.authorization })
|
2016-12-12 09:07:47 +13:00
|
|
|
}else{
|
|
|
|
|
console.log('Authorization ignored')
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
|
2017-02-21 05:46:28 +13:00
|
|
|
case 'PUSHER_START_RADIO':
|
|
|
|
|
store.dispatch(uiActions.createNotification('Starting radio...'))
|
2017-01-05 13:49:38 +13:00
|
|
|
|
2016-12-20 16:58:20 +13:00
|
|
|
var data = {
|
|
|
|
|
seed_artists: [],
|
|
|
|
|
seed_genres: [],
|
|
|
|
|
seed_tracks: []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for( var i = 0; i < action.uris.length; i++){
|
|
|
|
|
switch( helpers.uriType( action.uris[i] ) ){
|
|
|
|
|
case 'artist':
|
|
|
|
|
data.seed_artists.push( action.uris[i] );
|
|
|
|
|
break;
|
|
|
|
|
case 'track':
|
|
|
|
|
data.seed_tracks.push( action.uris[i] );
|
|
|
|
|
break;
|
2017-01-31 08:44:12 +13:00
|
|
|
case 'genre':
|
|
|
|
|
data.seed_genres.push( action.uris[i] );
|
|
|
|
|
break;
|
2016-12-20 16:58:20 +13:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-21 05:46:28 +13:00
|
|
|
request( 'start_radio', data )
|
|
|
|
|
.then(response => {
|
|
|
|
|
console.log(response)
|
|
|
|
|
})
|
2016-12-20 16:58:20 +13:00
|
|
|
break
|
|
|
|
|
|
2017-02-21 05:46:28 +13:00
|
|
|
case 'PUSHER_STOP_RADIO':
|
|
|
|
|
store.dispatch(uiActions.createNotification('Stopping radio'))
|
2017-01-05 13:49:38 +13:00
|
|
|
|
2016-12-20 19:54:19 +13:00
|
|
|
var data = {
|
|
|
|
|
seed_artists: [],
|
|
|
|
|
seed_genres: [],
|
|
|
|
|
seed_tracks: []
|
|
|
|
|
}
|
2017-02-21 05:46:28 +13:00
|
|
|
|
|
|
|
|
// we don't need to wait for request, as change will be broadcast
|
|
|
|
|
request( 'stop_radio', data )
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
case 'PUSHER_BROWSER_NOTIFICATION':
|
|
|
|
|
store.dispatch(uiActions.createBrowserNotification(action))
|
2016-12-20 19:54:19 +13:00
|
|
|
break
|
|
|
|
|
|
2016-10-27 16:58:11 +13:00
|
|
|
// This action is irrelevant to us, pass it on to the next middleware
|
|
|
|
|
default:
|
|
|
|
|
return next(action);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
export default PusherMiddleware
|