Removing pusher port in favor of /ws endpoint
This commit is contained in:
@ -1,11 +1,13 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging, os, json
|
||||
import tornado.web
|
||||
import tornado.websocket
|
||||
from mopidy import config, ext
|
||||
from frontend import IrisFrontend
|
||||
from http import RequestHandler
|
||||
from frontend import IrisFrontend, make_iris_factory
|
||||
from http import HttpHandler
|
||||
from websocket import WebsocketHandler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
__version__ = '2.12.1'
|
||||
@ -38,26 +40,8 @@ class Extension( ext.Extension ):
|
||||
# Add web extension
|
||||
registry.add('http:app', {
|
||||
'name': self.ext_name,
|
||||
'factory': factory
|
||||
'factory': make_iris_factory(
|
||||
registry['http:app'],
|
||||
registry['http:static']
|
||||
)
|
||||
})
|
||||
|
||||
# add our frontend
|
||||
registry.add('frontend', IrisFrontend)
|
||||
|
||||
def factory(config, core):
|
||||
|
||||
path = os.path.join( os.path.dirname(__file__), 'static')
|
||||
|
||||
return [
|
||||
(r"/images/(.*)", tornado.web.StaticFileHandler, {
|
||||
"path": config['local-images']['image_dir']
|
||||
}),
|
||||
(r'/http/([^/]*)', RequestHandler, {
|
||||
'core': core,
|
||||
'config': config
|
||||
}),
|
||||
(r'/(.*)', tornado.web.StaticFileHandler, {
|
||||
"path": path,
|
||||
"default_filename": "index.html"
|
||||
}),
|
||||
]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging, json, pykka, pylast, pusher, urllib, urllib2, os, sys, mopidy_iris, subprocess
|
||||
import logging, json, pykka, pylast, urllib, urllib2, os, sys, mopidy_iris, subprocess
|
||||
import tornado.web
|
||||
import tornado.websocket
|
||||
import tornado.ioloop
|
||||
@ -9,8 +10,39 @@ from mopidy.core import CoreListener
|
||||
from pkg_resources import parse_version
|
||||
from spotipy import Spotify
|
||||
|
||||
from websocket import WebsocketHandler
|
||||
from http import HttpHandler
|
||||
|
||||
# import logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
###
|
||||
# Create our factory
|
||||
#
|
||||
# This hooks all our components into the Mopidy registry. Called from __init__.py
|
||||
##
|
||||
def make_iris_factory(apps, statics):
|
||||
def iris_factory(config, core):
|
||||
|
||||
path = os.path.join( os.path.dirname(__file__), 'static')
|
||||
frontend = IrisFrontend(config, core)
|
||||
|
||||
return [
|
||||
(r"/images/(.*)", tornado.web.StaticFileHandler, {
|
||||
"path": config['local-images']['image_dir']
|
||||
}),
|
||||
(r'/http/([^/]*)', HttpHandler, {
|
||||
"frontend": frontend
|
||||
}),
|
||||
(r'/ws/?', WebsocketHandler, {
|
||||
"frontend": frontend
|
||||
}),
|
||||
(r'/(.*)', tornado.web.StaticFileHandler, {
|
||||
"path": path,
|
||||
"default_filename": "index.html"
|
||||
}),
|
||||
]
|
||||
return iris_factory
|
||||
|
||||
###
|
||||
# Spotmop supporting frontend
|
||||
@ -20,7 +52,6 @@ logger = logging.getLogger(__name__)
|
||||
class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
|
||||
def __init__(self, config, core):
|
||||
global spotmop
|
||||
super(IrisFrontend, self).__init__()
|
||||
self.config = config
|
||||
self.core = core
|
||||
@ -28,6 +59,7 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
self.is_root = ( os.geteuid() == 0 )
|
||||
self.spotify_token = False
|
||||
self.queue_metadata = {}
|
||||
self.connections = {}
|
||||
self.radio = {
|
||||
"enabled": 0,
|
||||
"seed_artists": [],
|
||||
@ -35,23 +67,8 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
"seed_tracks": []
|
||||
}
|
||||
|
||||
def on_start(self):
|
||||
|
||||
def on_start(self):
|
||||
logger.info('Starting Iris '+self.version)
|
||||
|
||||
# try and start a pusher server
|
||||
port = str(self.config['iris']['pusherport'])
|
||||
try:
|
||||
self.pusher = tornado.web.Application([( '/pusher', pusher.PusherWebsocketHandler, { 'frontend': self } )])
|
||||
self.pusher.listen(port)
|
||||
logger.info('Pusher server running at [0.0.0.0]:'+port)
|
||||
|
||||
except( pylast.NetworkError, pylast.MalformedResponseError, pylast.WSError ) as e:
|
||||
logger.error('Error starting Pusher: %s', e)
|
||||
self.stop()
|
||||
|
||||
# get a fresh spotify authentication token and store for future use
|
||||
# self.refresh_spotify_token()
|
||||
|
||||
|
||||
##
|
||||
@ -102,7 +119,7 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
self.load_more_tracks()
|
||||
|
||||
except RuntimeError:
|
||||
pusher.broadcast('error', {'source': 'check_for_radio_update', 'message': 'Could not fetch tracklist length'})
|
||||
self.websocket.broadcast('error', {'source': 'check_for_radio_update', 'message': 'Could not fetch tracklist length'})
|
||||
logger.warning('IrisFrontend: Could not fetch tracklist length')
|
||||
pass
|
||||
|
||||
@ -123,7 +140,7 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
token = token['access_token']
|
||||
except:
|
||||
logger.error('IrisFrontend: access_token missing or invalid')
|
||||
pusher.broadcast('error', {'source': 'load_more_tracks', 'message': 'access_token missing or invalid'})
|
||||
self.websocket.broadcast('error', {'source': 'load_more_tracks', 'message': 'access_token missing or invalid'})
|
||||
|
||||
try:
|
||||
spotify = Spotify( auth = token )
|
||||
@ -135,7 +152,7 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
|
||||
self.core.tracklist.add( uris = uris )
|
||||
except:
|
||||
pusher.broadcast('error', {'source': 'load_more_tracks', 'message': 'Failed to fetch Spotify recommendations'})
|
||||
self.websocket.broadcast('error', {'source': 'load_more_tracks', 'message': 'Failed to fetch Spotify recommendations'})
|
||||
logger.error('IrisFrontend: Failed to fetch Spotify recommendations')
|
||||
|
||||
|
||||
@ -161,7 +178,7 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
self.core.playback.play()
|
||||
|
||||
# notify clients
|
||||
pusher.broadcast('radio', { 'radio': self.radio })
|
||||
self.websocket.broadcast('radio', { 'radio': self.radio })
|
||||
|
||||
# return new radio state to initial call
|
||||
return self.radio
|
||||
@ -183,7 +200,7 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
self.core.playback.stop()
|
||||
|
||||
# notify clients
|
||||
pusher.broadcast( 'radio', { 'radio': self.radio })
|
||||
self.websocket.broadcast( 'radio', { 'radio': self.radio })
|
||||
|
||||
# return new radio state to initial call
|
||||
return self.radio
|
||||
@ -212,7 +229,7 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
self.queue_metadata['tlid_'+str(tlid)] = item
|
||||
|
||||
# broadcast to all clients
|
||||
pusher.broadcast('queue_metadata', {'queue_metadata': self.queue_metadata})
|
||||
self.websocket.broadcast('queue_metadata', {'queue_metadata': self.queue_metadata})
|
||||
|
||||
return self.queue_metadata
|
||||
|
||||
@ -232,7 +249,7 @@ class IrisFrontend(pykka.ThreadingActor, CoreListener):
|
||||
self.queue_metadata = cleaned_queue_metadata
|
||||
|
||||
# broadcast to all clients
|
||||
pusher.broadcast('queue_metadata', {'queue_metadata': self.queue_metadata})
|
||||
self.websocket.broadcast('queue_metadata', {'queue_metadata': self.queue_metadata})
|
||||
|
||||
|
||||
##
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging, json, urllib, urllib2
|
||||
@ -7,14 +8,13 @@ from spotipy import Spotify
|
||||
# import logger
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class RequestHandler(tornado.web.RequestHandler):
|
||||
class HttpHandler(tornado.web.RequestHandler):
|
||||
|
||||
def set_default_headers(self):
|
||||
self.set_header("Access-Control-Allow-Origin", "*")
|
||||
|
||||
def initialize(self, core, config):
|
||||
self.core = core
|
||||
self.config = config
|
||||
def initialize(self, frontend):
|
||||
self.frontend = frontend
|
||||
|
||||
def get(self, slug=None):
|
||||
|
||||
|
||||
@ -1,46 +1,14 @@
|
||||
|
||||
import tornado.ioloop, tornado.web, tornado.websocket, tornado.template
|
||||
import logging, uuid, subprocess, pykka
|
||||
import random, string, logging, uuid, subprocess, pykka
|
||||
from datetime import datetime
|
||||
from tornado.escape import json_encode, json_decode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# container for all current pusher connections
|
||||
connections = {}
|
||||
frontend = {}
|
||||
|
||||
|
||||
##
|
||||
# Send a message to an individual connection
|
||||
#
|
||||
# @param recipient_connection_ids = array
|
||||
# @param action = string (action method of this message)
|
||||
# @param request_id = string (used for callbacks)
|
||||
# @param data = array (any data required to include in our message)
|
||||
##
|
||||
def send_message( recipient_connection_id, action, request_id, data ):
|
||||
message = {
|
||||
'action': action,
|
||||
'request_id': request_id,
|
||||
'data': data
|
||||
}
|
||||
connections[recipient_connection_id]['connection'].write_message( json_encode(message) )
|
||||
|
||||
##
|
||||
# Broadcast a message to all recipients
|
||||
#
|
||||
# @param action = string
|
||||
# @param data = array (the body of our message to send)
|
||||
##
|
||||
def broadcast( type, data ):
|
||||
for connection in connections.itervalues():
|
||||
message = {
|
||||
'action': 'broadcast',
|
||||
'type': type,
|
||||
'data': data
|
||||
}
|
||||
connection['connection'].write_message( json_encode(message) )
|
||||
|
||||
# generate random string
|
||||
def generateGuid(length):
|
||||
return ''.join(random.choice(string.lowercase) for i in range(length))
|
||||
|
||||
# digest a protocol header into it's id/name parts
|
||||
def digest_protocol( protocol ):
|
||||
@ -61,9 +29,9 @@ def digest_protocol( protocol ):
|
||||
|
||||
# invalid, so just create a default connection, and auto-generate an ID
|
||||
except:
|
||||
clientid = str(uuid.uuid4().hex)
|
||||
connectionid = str(uuid.uuid4().hex)
|
||||
username = str(uuid.uuid4().hex)
|
||||
clientid = generateGuid(12)
|
||||
connectionid = generateGuid(12)
|
||||
username = 'Anonymous'
|
||||
generated = True
|
||||
|
||||
# construct our protocol object, and return
|
||||
@ -76,14 +44,17 @@ def digest_protocol( protocol ):
|
||||
# This is the actual websocket thread that accepts, digests and emits messages.
|
||||
# TODO: Figure out how to merge this into the main Mopidy websocket to avoid needing two websocket servers
|
||||
##
|
||||
class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
class WebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
|
||||
def initialize(self, frontend):
|
||||
self.frontend = frontend
|
||||
|
||||
def check_origin(self, origin):
|
||||
return True
|
||||
# initiate (not the actual object __init__, but run shortly after)
|
||||
def initialize(self, frontend):
|
||||
|
||||
# add this websocket instance to our Frontend
|
||||
frontend.websocket = self
|
||||
self.frontend = frontend
|
||||
|
||||
|
||||
# when a new connection is opened
|
||||
def open(self):
|
||||
|
||||
@ -104,7 +75,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
'ip': self.request.remote_ip,
|
||||
'created': created
|
||||
}
|
||||
connections[connectionid] = {
|
||||
self.frontend.connections[connectionid] = {
|
||||
'client': client,
|
||||
'connection': self
|
||||
}
|
||||
@ -112,8 +83,13 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
logger.info( 'Pusher connection established: '+ connectionid +' ('+ clientid +'/'+ username +')' )
|
||||
|
||||
# broadcast to all connections that a new user has connected
|
||||
broadcast( 'new_connection', client )
|
||||
self.broadcast( 'new_connection', client )
|
||||
|
||||
|
||||
def check_origin(self, origin):
|
||||
return True
|
||||
|
||||
|
||||
def select_subprotocol(self, subprotocols):
|
||||
# select one of our subprotocol elements and return it. This confirms the connection has been accepted.
|
||||
protocols = digest_protocol( subprotocols )
|
||||
@ -127,6 +103,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
else:
|
||||
return protocols['clientid']
|
||||
|
||||
|
||||
# server received a message
|
||||
def on_message(self, message):
|
||||
messageJson = json_decode(message)
|
||||
@ -134,9 +111,9 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
# construct the origin client info
|
||||
messageJson['origin'] = {
|
||||
'connectionid' : self.connectionid,
|
||||
'clientid': connections[self.connectionid]['client']['clientid'],
|
||||
'clientid': self.frontend.connections[self.connectionid]['client']['clientid'],
|
||||
'ip': self.request.remote_ip,
|
||||
'username': connections[self.connectionid]['client']['username']
|
||||
'username': self.frontend.connections[self.connectionid]['client']['username']
|
||||
}
|
||||
|
||||
logger.debug('Pusher message received: '+message)
|
||||
@ -145,14 +122,14 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
if messageJson['action'] == 'broadcast':
|
||||
|
||||
# respond to request with status update
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
{ 'status': 'Ok' }
|
||||
)
|
||||
|
||||
for connection in connections.itervalues():
|
||||
for connection in self.frontend.connections.itervalues():
|
||||
if connection['client']['connectionid'] != self.connectionid:
|
||||
connection['connection'].write_message(messageJson)
|
||||
|
||||
@ -160,7 +137,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
elif messageJson['action'] == 'send_authorization':
|
||||
|
||||
# make sure we actually have a connection matching the provided connectionid
|
||||
if messageJson['recipient_connectionid'] in connections:
|
||||
if messageJson['recipient_connectionid'] in self.frontend.connections:
|
||||
|
||||
# send payload to recipient
|
||||
authorization_message = {
|
||||
@ -170,10 +147,10 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
'me': messageJson['me'],
|
||||
'origin': messageJson['origin']
|
||||
}
|
||||
connections[messageJson['recipient_connectionid']]['connection'].write_message(authorization_message)
|
||||
self.frontend.connections[messageJson['recipient_connectionid']]['connection'].write_message(authorization_message)
|
||||
|
||||
# respond to request with status update
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -181,7 +158,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
)
|
||||
else:
|
||||
# respond to request with status update
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -190,7 +167,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
|
||||
# fetch our pusher connections
|
||||
elif messageJson['action'] == 'get_config':
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -201,10 +178,10 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
elif messageJson['action'] == 'get_connections':
|
||||
|
||||
connectionsDetailsList = []
|
||||
for connection in connections.itervalues():
|
||||
for connection in self.frontend.connections.itervalues():
|
||||
connectionsDetailsList.append(connection['client'])
|
||||
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -216,10 +193,10 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
queue_metadata = self.frontend.add_queue_metadata(
|
||||
messageJson['tlids'],
|
||||
messageJson['added_from'],
|
||||
connections[self.connectionid]['client']['username']
|
||||
self.frontend.connections[self.connectionid]['client']['username']
|
||||
)
|
||||
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -230,10 +207,10 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
elif messageJson['action'] == 'get_queue_metadata':
|
||||
|
||||
connectionsDetailsList = []
|
||||
for connection in connections.itervalues():
|
||||
for connection in self.frontend.connections.itervalues():
|
||||
connectionsDetailsList.append(connection['client'])
|
||||
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -244,10 +221,10 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
elif messageJson['action'] == 'set_username':
|
||||
|
||||
# username is the only value we allow clients to change
|
||||
connections[messageJson['origin']['connectionid']]['client']['username'] = messageJson['username']
|
||||
self.frontend.connections[messageJson['origin']['connectionid']]['client']['username'] = messageJson['username']
|
||||
|
||||
# respond to request
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -255,7 +232,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
)
|
||||
|
||||
# notify all clients of this change
|
||||
broadcast( 'connection_updated', { 'connection': connections[messageJson['origin']['connectionid']]['client'] })
|
||||
self.broadcast( 'connection_updated', { 'connection': self.frontend.connections[messageJson['origin']['connectionid']]['client'] })
|
||||
|
||||
# start radio
|
||||
elif messageJson['action'] == 'start_radio':
|
||||
@ -268,7 +245,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
'seed_tracks': messageJson['seed_tracks']
|
||||
}
|
||||
radio = self.frontend.start_radio( radio )
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -278,7 +255,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
# stop radio
|
||||
elif messageJson['action'] == 'stop_radio':
|
||||
radio = self.frontend.stop_radio()
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -287,7 +264,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
|
||||
# fetch our current radio state
|
||||
elif messageJson['action'] == 'get_radio':
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -297,7 +274,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
# get system version and check for upgrade
|
||||
elif messageJson['action'] == 'get_version':
|
||||
version = self.frontend.get_version()
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -308,7 +285,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
elif messageJson['action'] == 'upgrade':
|
||||
version = self.frontend.get_version()
|
||||
upgrade_successful = self.frontend.perform_upgrade()
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -321,7 +298,7 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
|
||||
# not an action we recognise!
|
||||
else:
|
||||
send_message(
|
||||
self.send_message(
|
||||
self.connectionid,
|
||||
'response',
|
||||
messageJson['request_id'],
|
||||
@ -330,20 +307,52 @@ class PusherWebsocketHandler(tornado.websocket.WebSocketHandler):
|
||||
|
||||
logger.debug( 'Pusher: Unhandled message received from '+ self.connectionid )
|
||||
|
||||
|
||||
# connection closed
|
||||
def on_close(self):
|
||||
if self.connectionid in connections:
|
||||
if self.connectionid in self.frontend.connections:
|
||||
|
||||
clientRemoved = connections[self.connectionid]['client']
|
||||
clientRemoved = self.frontend.connections[self.connectionid]['client']
|
||||
logger.debug( 'Spotmop Pusher connection to '+ self.connectionid +' closed' )
|
||||
|
||||
# now actually remove it
|
||||
try:
|
||||
del connections[self.connectionid]
|
||||
del self.frontend.connections[self.connectionid]
|
||||
except:
|
||||
logger.info( 'Failed to close connection to '+ self.connectionid )
|
||||
|
||||
broadcast( 'client_disconnected', clientRemoved )
|
||||
self.broadcast( 'client_disconnected', clientRemoved )
|
||||
|
||||
##
|
||||
# Send a message to an individual connection
|
||||
#
|
||||
# @param recipient_connection_ids = array
|
||||
# @param action = string (action method of this message)
|
||||
# @param request_id = string (used for callbacks)
|
||||
# @param data = array (any data required to include in our message)
|
||||
##
|
||||
def send_message( self, recipient_connection_id, action, request_id, data ):
|
||||
message = {
|
||||
'action': action,
|
||||
'request_id': request_id,
|
||||
'data': data
|
||||
}
|
||||
self.frontend.connections[recipient_connection_id]['connection'].write_message( json_encode(message) )
|
||||
|
||||
##
|
||||
# Broadcast a message to all recipients
|
||||
#
|
||||
# @param action = string
|
||||
# @param data = array (the body of our message to send)
|
||||
##
|
||||
def broadcast( self, type, data ):
|
||||
for connection in self.frontend.connections.itervalues():
|
||||
message = {
|
||||
'action': 'broadcast',
|
||||
'type': type,
|
||||
'data': data
|
||||
}
|
||||
connection['connection'].write_message( json_encode(message) )
|
||||
|
||||
|
||||
|
||||
@ -68,8 +68,8 @@ export let sizedImages = function( images ){
|
||||
return sizes;
|
||||
}
|
||||
|
||||
export let generateGuid = function(){
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
export let generateGuid = function(format = 'xxxxxxxxxxxx'){
|
||||
return format.replace(/[xy]/g, function(c) {
|
||||
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
|
||||
@ -90,14 +90,15 @@ const PusherMiddleware = (function(){
|
||||
|
||||
var state = store.getState();
|
||||
var connection = {
|
||||
clientid: Math.random().toString(36).substr(2, 9),
|
||||
clientid: helpers.generateGuid(),
|
||||
connectionid: helpers.generateGuid(),
|
||||
username: Math.random().toString(36).substr(2, 9)
|
||||
username: 'Anonymous'
|
||||
}
|
||||
if( state.pusher.username ) connection.username = state.pusher.username;
|
||||
|
||||
connection.username = connection.username.replace(/\W/g, '')
|
||||
|
||||
socket = new WebSocket(
|
||||
'ws://'+state.mopidy.host+':'+state.pusher.port+'/pusher',
|
||||
'ws://'+state.mopidy.host+':'+state.mopidy.port+'/iris/ws',
|
||||
[ connection.clientid, connection.connectionid, connection.username ]
|
||||
);
|
||||
|
||||
|
||||
@ -26,7 +26,6 @@ class Settings extends React.Component{
|
||||
mopidy_host: this.props.mopidy.host,
|
||||
mopidy_port: this.props.mopidy.port,
|
||||
pusher_username: this.props.pusher.username,
|
||||
pusher_port: this.props.pusher.port,
|
||||
spotify_country: this.props.spotify.country,
|
||||
spotify_locale: this.props.spotify.locale
|
||||
};
|
||||
@ -52,6 +51,10 @@ class Settings extends React.Component{
|
||||
return false;
|
||||
}
|
||||
|
||||
handleUsernameChange(username){
|
||||
this.setState({pusher_username: username.replace(/\W/g, '')})
|
||||
}
|
||||
|
||||
renderConnectionStatus(service){
|
||||
if( this.props[service].connected ){
|
||||
return (
|
||||
@ -147,6 +150,16 @@ class Settings extends React.Component{
|
||||
{ this.renderConnectionStatus('mopidy') }
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name">Username</div>
|
||||
<div className="input">
|
||||
<input
|
||||
type="text"
|
||||
onChange={e => this.handleUsernameChange(e.target.value)}
|
||||
onBlur={ e => this.props.pusherActions.setUsername(this.state.pusher_username) }
|
||||
value={ this.state.pusher_username } />
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name">Host</div>
|
||||
<div className="input">
|
||||
@ -173,36 +186,6 @@ class Settings extends React.Component{
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h4 className="underline">Pusher</h4>
|
||||
<form>
|
||||
<div className="field">
|
||||
<div className="name">Status</div>
|
||||
<div className="input">
|
||||
{ this.renderConnectionStatus('pusher') }
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name">Username</div>
|
||||
<div className="input">
|
||||
<input
|
||||
type="text"
|
||||
onChange={ e => this.setState({ pusher_username: e.target.value }) }
|
||||
onBlur={ e => this.props.pusherActions.setUsername(this.state.pusher_username) }
|
||||
value={ this.state.pusher_username } />
|
||||
</div>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="name">Port</div>
|
||||
<div className="input">
|
||||
<input
|
||||
type="text"
|
||||
onChange={ e => this.setState({ pusher_port: e.target.value })}
|
||||
onBlur={ e => this.props.pusherActions.setPort(this.state.pusher_port) }
|
||||
value={ this.state.pusher_port } />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h4 className="underline">Spotify</h4>
|
||||
<div className="field">
|
||||
<div className="name">Status</div>
|
||||
|
||||
Reference in New Issue
Block a user