add websockets, cassette updates for admin
This commit is contained in:
parent
a123170622
commit
5ed29ee67d
5 changed files with 631 additions and 12 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const EventEmitter = require('events')
|
||||||
|
const qs = require('querystring')
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
@ -13,6 +15,9 @@ const argv = require('minimist')(process.argv.slice(2))
|
||||||
const got = require('got')
|
const got = require('got')
|
||||||
const morgan = require('morgan')
|
const morgan = require('morgan')
|
||||||
const helmet = require('helmet')
|
const helmet = require('helmet')
|
||||||
|
const WebSocket = require('ws')
|
||||||
|
const http = require('http')
|
||||||
|
const SocketIo = require('socket.io')
|
||||||
|
|
||||||
const machineLoader = require('../lib/machine-loader')
|
const machineLoader = require('../lib/machine-loader')
|
||||||
const T = require('../lib/time')
|
const T = require('../lib/time')
|
||||||
|
|
@ -26,6 +31,7 @@ const server = require('../lib/admin/server')
|
||||||
const transactions = require('../lib/admin/transactions')
|
const transactions = require('../lib/admin/transactions')
|
||||||
|
|
||||||
const NEVER = new Date(Date.now() + 100 * T.years)
|
const NEVER = new Date(Date.now() + 100 * T.years)
|
||||||
|
const REAUTHENTICATE_INTERVAL = T.minute
|
||||||
|
|
||||||
const devMode = argv.dev
|
const devMode = argv.dev
|
||||||
|
|
||||||
|
|
@ -200,12 +206,58 @@ process.on('unhandledRejection', err => {
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const socketServer = http.createServer()
|
||||||
|
const io = SocketIo(socketServer)
|
||||||
|
socketServer.listen(3060)
|
||||||
|
const socketEmitter = new EventEmitter()
|
||||||
|
|
||||||
|
io.on('connection', client => {
|
||||||
|
client.on('message', msg => socketEmitter.emit('message', msg))
|
||||||
|
})
|
||||||
|
|
||||||
|
const webServer = https.createServer(options, app)
|
||||||
|
const wss = new WebSocket.Server({server: webServer})
|
||||||
|
|
||||||
|
function establishSocket (ws, token) {
|
||||||
|
return login.authenticate(token)
|
||||||
|
.then(success => {
|
||||||
|
if (!success) return ws.close(1008, 'Authentication error')
|
||||||
|
|
||||||
|
const listener = data => {
|
||||||
|
console.log('DEBUG200: %j', data)
|
||||||
|
ws.send(JSON.stringify(data))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reauthenticate every once in a while, in case token expired
|
||||||
|
setInterval(() => {
|
||||||
|
return login.authenticate(token)
|
||||||
|
.then(success => {
|
||||||
|
if (!success) {
|
||||||
|
socketEmitter.removeListener('message', listener)
|
||||||
|
ws.close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, REAUTHENTICATE_INTERVAL)
|
||||||
|
|
||||||
|
socketEmitter.on('message', listener)
|
||||||
|
|
||||||
|
console.log('DEBUG120: %j', token)
|
||||||
|
ws.send('Testing123')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
wss.on('connection', ws => {
|
||||||
|
const token = qs.parse(ws.upgradeReq.headers.cookie).token
|
||||||
|
|
||||||
|
return establishSocket(ws, token)
|
||||||
|
})
|
||||||
|
|
||||||
if (devMode) {
|
if (devMode) {
|
||||||
https.createServer(options, app).listen(8070, () => {
|
webServer.listen(8070, () => {
|
||||||
console.log('lamassu-admin-server listening on port 8070')
|
console.log('lamassu-admin-server listening on port 8070')
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
https.createServer(options, app).listen(443, () => {
|
webServer.listen(443, () => {
|
||||||
console.log('lamassu-admin-server listening on port 443')
|
console.log('lamassu-admin-server listening on port 443')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ const T = require('./time')
|
||||||
const logger = require('./logger')
|
const logger = require('./logger')
|
||||||
const plugins = require('./plugins')
|
const plugins = require('./plugins')
|
||||||
const helper = require('./cash-out-helper')
|
const helper = require('./cash-out-helper')
|
||||||
|
const socket = require('./socket-client')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
post,
|
post,
|
||||||
|
|
@ -171,7 +172,8 @@ function updateCassettes (tx) {
|
||||||
const sql = `update devices set
|
const sql = `update devices set
|
||||||
cassette1 = cassette1 - $1,
|
cassette1 = cassette1 - $1,
|
||||||
cassette2 = cassette2 - $2
|
cassette2 = cassette2 - $2
|
||||||
where device_id = $3`
|
where device_id = $3
|
||||||
|
returning cassette1, cassette2`
|
||||||
|
|
||||||
const values = [
|
const values = [
|
||||||
tx.bills[0].dispensed + tx.bills[0].rejected,
|
tx.bills[0].dispensed + tx.bills[0].rejected,
|
||||||
|
|
@ -179,7 +181,8 @@ function updateCassettes (tx) {
|
||||||
tx.deviceId
|
tx.deviceId
|
||||||
]
|
]
|
||||||
|
|
||||||
return db.none(sql, values)
|
return db.one(sql, values)
|
||||||
|
.then(r => socket.emit(_.assign(r, {op: 'cassetteUpdate', deviceId: tx.deviceId})))
|
||||||
}
|
}
|
||||||
|
|
||||||
function wasJustAuthorized (oldTx, newTx, isZeroConf) {
|
function wasJustAuthorized (oldTx, newTx, isZeroConf) {
|
||||||
|
|
|
||||||
9
lib/socket-client.js
Normal file
9
lib/socket-client.js
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
const io = require('socket.io-client')
|
||||||
|
|
||||||
|
const socket = io('http://localhost:3060')
|
||||||
|
|
||||||
|
module.exports = {emit}
|
||||||
|
|
||||||
|
function emit (msg) {
|
||||||
|
socket.emit('message', msg)
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
"express": "^4.13.4",
|
"express": "^4.13.4",
|
||||||
"express-limiter": "^1.6.0",
|
"express-limiter": "^1.6.0",
|
||||||
"express-rate-limit": "^2.6.0",
|
"express-rate-limit": "^2.6.0",
|
||||||
|
"express-ws": "^3.0.0",
|
||||||
"got": "^6.6.3",
|
"got": "^6.6.3",
|
||||||
"helmet": "^3.1.0",
|
"helmet": "^3.1.0",
|
||||||
"lodash": "^4.17.2",
|
"lodash": "^4.17.2",
|
||||||
|
|
@ -39,12 +40,13 @@
|
||||||
"promise-sequential": "^1.1.1",
|
"promise-sequential": "^1.1.1",
|
||||||
"ramda": "^0.22.1",
|
"ramda": "^0.22.1",
|
||||||
"serve-static": "^1.11.1",
|
"serve-static": "^1.11.1",
|
||||||
"socket.io": "^1.7.1",
|
"socket.io": "^1.7.4",
|
||||||
"socket.io-client": "^1.7.1",
|
"socket.io-client": "^1.7.1",
|
||||||
"twilio": "^2.11.1",
|
"twilio": "^2.11.1",
|
||||||
"uuid": "^3.0.0",
|
"uuid": "^3.0.0",
|
||||||
"web3": "^0.18.4",
|
"web3": "^0.18.4",
|
||||||
"winston": "^2.3.0"
|
"winston": "^2.3.0",
|
||||||
|
"ws": "^2.3.1"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
565
public/elm.js
565
public/elm.js
|
|
@ -10683,6 +10683,541 @@ var _elm_lang$svg$Svg_Attributes$accumulate = _elm_lang$virtual_dom$VirtualDom$a
|
||||||
var _elm_lang$svg$Svg_Attributes$accelerate = _elm_lang$virtual_dom$VirtualDom$attribute('accelerate');
|
var _elm_lang$svg$Svg_Attributes$accelerate = _elm_lang$virtual_dom$VirtualDom$attribute('accelerate');
|
||||||
var _elm_lang$svg$Svg_Attributes$accentHeight = _elm_lang$virtual_dom$VirtualDom$attribute('accent-height');
|
var _elm_lang$svg$Svg_Attributes$accentHeight = _elm_lang$virtual_dom$VirtualDom$attribute('accent-height');
|
||||||
|
|
||||||
|
var _elm_lang$websocket$Native_WebSocket = function() {
|
||||||
|
|
||||||
|
function open(url, settings)
|
||||||
|
{
|
||||||
|
return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var socket = new WebSocket(url);
|
||||||
|
socket.elm_web_socket = true;
|
||||||
|
}
|
||||||
|
catch(err)
|
||||||
|
{
|
||||||
|
return callback(_elm_lang$core$Native_Scheduler.fail({
|
||||||
|
ctor: err.name === 'SecurityError' ? 'BadSecurity' : 'BadArgs',
|
||||||
|
_0: err.message
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.addEventListener("open", function(event) {
|
||||||
|
callback(_elm_lang$core$Native_Scheduler.succeed(socket));
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.addEventListener("message", function(event) {
|
||||||
|
_elm_lang$core$Native_Scheduler.rawSpawn(A2(settings.onMessage, socket, event.data));
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.addEventListener("close", function(event) {
|
||||||
|
_elm_lang$core$Native_Scheduler.rawSpawn(settings.onClose({
|
||||||
|
code: event.code,
|
||||||
|
reason: event.reason,
|
||||||
|
wasClean: event.wasClean
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
return function()
|
||||||
|
{
|
||||||
|
if (socket && socket.close)
|
||||||
|
{
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function send(socket, string)
|
||||||
|
{
|
||||||
|
return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback)
|
||||||
|
{
|
||||||
|
var result =
|
||||||
|
socket.readyState === WebSocket.OPEN
|
||||||
|
? _elm_lang$core$Maybe$Nothing
|
||||||
|
: _elm_lang$core$Maybe$Just({ ctor: 'NotOpen' });
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
socket.send(string);
|
||||||
|
}
|
||||||
|
catch(err)
|
||||||
|
{
|
||||||
|
result = _elm_lang$core$Maybe$Just({ ctor: 'BadString' });
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(_elm_lang$core$Native_Scheduler.succeed(result));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function close(code, reason, socket)
|
||||||
|
{
|
||||||
|
return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
socket.close(code, reason);
|
||||||
|
}
|
||||||
|
catch(err)
|
||||||
|
{
|
||||||
|
return callback(_elm_lang$core$Native_Scheduler.fail(_elm_lang$core$Maybe$Just({
|
||||||
|
ctor: err.name === 'SyntaxError' ? 'BadReason' : 'BadCode'
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
callback(_elm_lang$core$Native_Scheduler.succeed(_elm_lang$core$Maybe$Nothing));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bytesQueued(socket)
|
||||||
|
{
|
||||||
|
return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) {
|
||||||
|
callback(_elm_lang$core$Native_Scheduler.succeed(socket.bufferedAmount));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
open: F2(open),
|
||||||
|
send: F2(send),
|
||||||
|
close: F3(close),
|
||||||
|
bytesQueued: bytesQueued
|
||||||
|
};
|
||||||
|
|
||||||
|
}();
|
||||||
|
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$bytesQueued = _elm_lang$websocket$Native_WebSocket.bytesQueued;
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$send = _elm_lang$websocket$Native_WebSocket.send;
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$closeWith = _elm_lang$websocket$Native_WebSocket.close;
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$close = function (socket) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Task$map,
|
||||||
|
_elm_lang$core$Basics$always(
|
||||||
|
{ctor: '_Tuple0'}),
|
||||||
|
A3(_elm_lang$websocket$WebSocket_LowLevel$closeWith, 1000, '', socket));
|
||||||
|
};
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$open = _elm_lang$websocket$Native_WebSocket.open;
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$Settings = F2(
|
||||||
|
function (a, b) {
|
||||||
|
return {onMessage: a, onClose: b};
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$WebSocket = {ctor: 'WebSocket'};
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$BadArgs = {ctor: 'BadArgs'};
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$BadSecurity = {ctor: 'BadSecurity'};
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$BadReason = {ctor: 'BadReason'};
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$BadCode = {ctor: 'BadCode'};
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$BadString = {ctor: 'BadString'};
|
||||||
|
var _elm_lang$websocket$WebSocket_LowLevel$NotOpen = {ctor: 'NotOpen'};
|
||||||
|
|
||||||
|
var _elm_lang$websocket$WebSocket$closeConnection = function (connection) {
|
||||||
|
var _p0 = connection;
|
||||||
|
if (_p0.ctor === 'Opening') {
|
||||||
|
return _elm_lang$core$Process$kill(_p0._1);
|
||||||
|
} else {
|
||||||
|
return _elm_lang$websocket$WebSocket_LowLevel$close(_p0._0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var _elm_lang$websocket$WebSocket$after = function (backoff) {
|
||||||
|
return (_elm_lang$core$Native_Utils.cmp(backoff, 1) < 0) ? _elm_lang$core$Task$succeed(
|
||||||
|
{ctor: '_Tuple0'}) : _elm_lang$core$Process$sleep(
|
||||||
|
_elm_lang$core$Basics$toFloat(
|
||||||
|
10 * Math.pow(2, backoff)));
|
||||||
|
};
|
||||||
|
var _elm_lang$websocket$WebSocket$removeQueue = F2(
|
||||||
|
function (name, state) {
|
||||||
|
return _elm_lang$core$Native_Utils.update(
|
||||||
|
state,
|
||||||
|
{
|
||||||
|
queues: A2(_elm_lang$core$Dict$remove, name, state.queues)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$updateSocket = F3(
|
||||||
|
function (name, connection, state) {
|
||||||
|
return _elm_lang$core$Native_Utils.update(
|
||||||
|
state,
|
||||||
|
{
|
||||||
|
sockets: A3(_elm_lang$core$Dict$insert, name, connection, state.sockets)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$add = F2(
|
||||||
|
function (value, maybeList) {
|
||||||
|
var _p1 = maybeList;
|
||||||
|
if (_p1.ctor === 'Nothing') {
|
||||||
|
return _elm_lang$core$Maybe$Just(
|
||||||
|
{
|
||||||
|
ctor: '::',
|
||||||
|
_0: value,
|
||||||
|
_1: {ctor: '[]'}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return _elm_lang$core$Maybe$Just(
|
||||||
|
{ctor: '::', _0: value, _1: _p1._0});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$buildSubDict = F2(
|
||||||
|
function (subs, dict) {
|
||||||
|
buildSubDict:
|
||||||
|
while (true) {
|
||||||
|
var _p2 = subs;
|
||||||
|
if (_p2.ctor === '[]') {
|
||||||
|
return dict;
|
||||||
|
} else {
|
||||||
|
if (_p2._0.ctor === 'Listen') {
|
||||||
|
var _v3 = _p2._1,
|
||||||
|
_v4 = A3(
|
||||||
|
_elm_lang$core$Dict$update,
|
||||||
|
_p2._0._0,
|
||||||
|
_elm_lang$websocket$WebSocket$add(_p2._0._1),
|
||||||
|
dict);
|
||||||
|
subs = _v3;
|
||||||
|
dict = _v4;
|
||||||
|
continue buildSubDict;
|
||||||
|
} else {
|
||||||
|
var _v5 = _p2._1,
|
||||||
|
_v6 = A3(
|
||||||
|
_elm_lang$core$Dict$update,
|
||||||
|
_p2._0._0,
|
||||||
|
function (_p3) {
|
||||||
|
return _elm_lang$core$Maybe$Just(
|
||||||
|
A2(
|
||||||
|
_elm_lang$core$Maybe$withDefault,
|
||||||
|
{ctor: '[]'},
|
||||||
|
_p3));
|
||||||
|
},
|
||||||
|
dict);
|
||||||
|
subs = _v5;
|
||||||
|
dict = _v6;
|
||||||
|
continue buildSubDict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket_ops = _elm_lang$websocket$WebSocket_ops || {};
|
||||||
|
_elm_lang$websocket$WebSocket_ops['&>'] = F2(
|
||||||
|
function (t1, t2) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Task$andThen,
|
||||||
|
function (_p4) {
|
||||||
|
return t2;
|
||||||
|
},
|
||||||
|
t1);
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$sendMessagesHelp = F3(
|
||||||
|
function (cmds, socketsDict, queuesDict) {
|
||||||
|
sendMessagesHelp:
|
||||||
|
while (true) {
|
||||||
|
var _p5 = cmds;
|
||||||
|
if (_p5.ctor === '[]') {
|
||||||
|
return _elm_lang$core$Task$succeed(queuesDict);
|
||||||
|
} else {
|
||||||
|
var _p9 = _p5._1;
|
||||||
|
var _p8 = _p5._0._0;
|
||||||
|
var _p7 = _p5._0._1;
|
||||||
|
var _p6 = A2(_elm_lang$core$Dict$get, _p8, socketsDict);
|
||||||
|
if ((_p6.ctor === 'Just') && (_p6._0.ctor === 'Connected')) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$websocket$WebSocket_ops['&>'],
|
||||||
|
A2(_elm_lang$websocket$WebSocket_LowLevel$send, _p6._0._0, _p7),
|
||||||
|
A3(_elm_lang$websocket$WebSocket$sendMessagesHelp, _p9, socketsDict, queuesDict));
|
||||||
|
} else {
|
||||||
|
var _v9 = _p9,
|
||||||
|
_v10 = socketsDict,
|
||||||
|
_v11 = A3(
|
||||||
|
_elm_lang$core$Dict$update,
|
||||||
|
_p8,
|
||||||
|
_elm_lang$websocket$WebSocket$add(_p7),
|
||||||
|
queuesDict);
|
||||||
|
cmds = _v9;
|
||||||
|
socketsDict = _v10;
|
||||||
|
queuesDict = _v11;
|
||||||
|
continue sendMessagesHelp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$subscription = _elm_lang$core$Native_Platform.leaf('WebSocket');
|
||||||
|
var _elm_lang$websocket$WebSocket$command = _elm_lang$core$Native_Platform.leaf('WebSocket');
|
||||||
|
var _elm_lang$websocket$WebSocket$State = F3(
|
||||||
|
function (a, b, c) {
|
||||||
|
return {sockets: a, queues: b, subs: c};
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$init = _elm_lang$core$Task$succeed(
|
||||||
|
A3(_elm_lang$websocket$WebSocket$State, _elm_lang$core$Dict$empty, _elm_lang$core$Dict$empty, _elm_lang$core$Dict$empty));
|
||||||
|
var _elm_lang$websocket$WebSocket$Send = F2(
|
||||||
|
function (a, b) {
|
||||||
|
return {ctor: 'Send', _0: a, _1: b};
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$send = F2(
|
||||||
|
function (url, message) {
|
||||||
|
return _elm_lang$websocket$WebSocket$command(
|
||||||
|
A2(_elm_lang$websocket$WebSocket$Send, url, message));
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$cmdMap = F2(
|
||||||
|
function (_p11, _p10) {
|
||||||
|
var _p12 = _p10;
|
||||||
|
return A2(_elm_lang$websocket$WebSocket$Send, _p12._0, _p12._1);
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$KeepAlive = function (a) {
|
||||||
|
return {ctor: 'KeepAlive', _0: a};
|
||||||
|
};
|
||||||
|
var _elm_lang$websocket$WebSocket$keepAlive = function (url) {
|
||||||
|
return _elm_lang$websocket$WebSocket$subscription(
|
||||||
|
_elm_lang$websocket$WebSocket$KeepAlive(url));
|
||||||
|
};
|
||||||
|
var _elm_lang$websocket$WebSocket$Listen = F2(
|
||||||
|
function (a, b) {
|
||||||
|
return {ctor: 'Listen', _0: a, _1: b};
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$listen = F2(
|
||||||
|
function (url, tagger) {
|
||||||
|
return _elm_lang$websocket$WebSocket$subscription(
|
||||||
|
A2(_elm_lang$websocket$WebSocket$Listen, url, tagger));
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$subMap = F2(
|
||||||
|
function (func, sub) {
|
||||||
|
var _p13 = sub;
|
||||||
|
if (_p13.ctor === 'Listen') {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$websocket$WebSocket$Listen,
|
||||||
|
_p13._0,
|
||||||
|
function (_p14) {
|
||||||
|
return func(
|
||||||
|
_p13._1(_p14));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return _elm_lang$websocket$WebSocket$KeepAlive(_p13._0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$Connected = function (a) {
|
||||||
|
return {ctor: 'Connected', _0: a};
|
||||||
|
};
|
||||||
|
var _elm_lang$websocket$WebSocket$Opening = F2(
|
||||||
|
function (a, b) {
|
||||||
|
return {ctor: 'Opening', _0: a, _1: b};
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$BadOpen = function (a) {
|
||||||
|
return {ctor: 'BadOpen', _0: a};
|
||||||
|
};
|
||||||
|
var _elm_lang$websocket$WebSocket$GoodOpen = F2(
|
||||||
|
function (a, b) {
|
||||||
|
return {ctor: 'GoodOpen', _0: a, _1: b};
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$Die = function (a) {
|
||||||
|
return {ctor: 'Die', _0: a};
|
||||||
|
};
|
||||||
|
var _elm_lang$websocket$WebSocket$Receive = F2(
|
||||||
|
function (a, b) {
|
||||||
|
return {ctor: 'Receive', _0: a, _1: b};
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$open = F2(
|
||||||
|
function (name, router) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$websocket$WebSocket_LowLevel$open,
|
||||||
|
name,
|
||||||
|
{
|
||||||
|
onMessage: F2(
|
||||||
|
function (_p15, msg) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Platform$sendToSelf,
|
||||||
|
router,
|
||||||
|
A2(_elm_lang$websocket$WebSocket$Receive, name, msg));
|
||||||
|
}),
|
||||||
|
onClose: function (details) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Platform$sendToSelf,
|
||||||
|
router,
|
||||||
|
_elm_lang$websocket$WebSocket$Die(name));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$attemptOpen = F3(
|
||||||
|
function (router, backoff, name) {
|
||||||
|
var badOpen = function (_p16) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Platform$sendToSelf,
|
||||||
|
router,
|
||||||
|
_elm_lang$websocket$WebSocket$BadOpen(name));
|
||||||
|
};
|
||||||
|
var goodOpen = function (ws) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Platform$sendToSelf,
|
||||||
|
router,
|
||||||
|
A2(_elm_lang$websocket$WebSocket$GoodOpen, name, ws));
|
||||||
|
};
|
||||||
|
var actuallyAttemptOpen = A2(
|
||||||
|
_elm_lang$core$Task$onError,
|
||||||
|
badOpen,
|
||||||
|
A2(
|
||||||
|
_elm_lang$core$Task$andThen,
|
||||||
|
goodOpen,
|
||||||
|
A2(_elm_lang$websocket$WebSocket$open, name, router)));
|
||||||
|
return _elm_lang$core$Process$spawn(
|
||||||
|
A2(
|
||||||
|
_elm_lang$websocket$WebSocket_ops['&>'],
|
||||||
|
_elm_lang$websocket$WebSocket$after(backoff),
|
||||||
|
actuallyAttemptOpen));
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$onEffects = F4(
|
||||||
|
function (router, cmds, subs, state) {
|
||||||
|
var newSubs = A2(_elm_lang$websocket$WebSocket$buildSubDict, subs, _elm_lang$core$Dict$empty);
|
||||||
|
var cleanup = function (newQueues) {
|
||||||
|
var rightStep = F3(
|
||||||
|
function (name, connection, getNewSockets) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$websocket$WebSocket_ops['&>'],
|
||||||
|
_elm_lang$websocket$WebSocket$closeConnection(connection),
|
||||||
|
getNewSockets);
|
||||||
|
});
|
||||||
|
var bothStep = F4(
|
||||||
|
function (name, _p17, connection, getNewSockets) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Task$map,
|
||||||
|
A2(_elm_lang$core$Dict$insert, name, connection),
|
||||||
|
getNewSockets);
|
||||||
|
});
|
||||||
|
var leftStep = F3(
|
||||||
|
function (name, _p18, getNewSockets) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Task$andThen,
|
||||||
|
function (newSockets) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Task$andThen,
|
||||||
|
function (pid) {
|
||||||
|
return _elm_lang$core$Task$succeed(
|
||||||
|
A3(
|
||||||
|
_elm_lang$core$Dict$insert,
|
||||||
|
name,
|
||||||
|
A2(_elm_lang$websocket$WebSocket$Opening, 0, pid),
|
||||||
|
newSockets));
|
||||||
|
},
|
||||||
|
A3(_elm_lang$websocket$WebSocket$attemptOpen, router, 0, name));
|
||||||
|
},
|
||||||
|
getNewSockets);
|
||||||
|
});
|
||||||
|
var newEntries = A2(
|
||||||
|
_elm_lang$core$Dict$union,
|
||||||
|
newQueues,
|
||||||
|
A2(
|
||||||
|
_elm_lang$core$Dict$map,
|
||||||
|
F2(
|
||||||
|
function (k, v) {
|
||||||
|
return {ctor: '[]'};
|
||||||
|
}),
|
||||||
|
newSubs));
|
||||||
|
var collectNewSockets = A6(
|
||||||
|
_elm_lang$core$Dict$merge,
|
||||||
|
leftStep,
|
||||||
|
bothStep,
|
||||||
|
rightStep,
|
||||||
|
newEntries,
|
||||||
|
state.sockets,
|
||||||
|
_elm_lang$core$Task$succeed(_elm_lang$core$Dict$empty));
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Task$andThen,
|
||||||
|
function (newSockets) {
|
||||||
|
return _elm_lang$core$Task$succeed(
|
||||||
|
A3(_elm_lang$websocket$WebSocket$State, newSockets, newQueues, newSubs));
|
||||||
|
},
|
||||||
|
collectNewSockets);
|
||||||
|
};
|
||||||
|
var sendMessagesGetNewQueues = A3(_elm_lang$websocket$WebSocket$sendMessagesHelp, cmds, state.sockets, state.queues);
|
||||||
|
return A2(_elm_lang$core$Task$andThen, cleanup, sendMessagesGetNewQueues);
|
||||||
|
});
|
||||||
|
var _elm_lang$websocket$WebSocket$onSelfMsg = F3(
|
||||||
|
function (router, selfMsg, state) {
|
||||||
|
var _p19 = selfMsg;
|
||||||
|
switch (_p19.ctor) {
|
||||||
|
case 'Receive':
|
||||||
|
var sends = A2(
|
||||||
|
_elm_lang$core$List$map,
|
||||||
|
function (tagger) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Platform$sendToApp,
|
||||||
|
router,
|
||||||
|
tagger(_p19._1));
|
||||||
|
},
|
||||||
|
A2(
|
||||||
|
_elm_lang$core$Maybe$withDefault,
|
||||||
|
{ctor: '[]'},
|
||||||
|
A2(_elm_lang$core$Dict$get, _p19._0, state.subs)));
|
||||||
|
return A2(
|
||||||
|
_elm_lang$websocket$WebSocket_ops['&>'],
|
||||||
|
_elm_lang$core$Task$sequence(sends),
|
||||||
|
_elm_lang$core$Task$succeed(state));
|
||||||
|
case 'Die':
|
||||||
|
var _p21 = _p19._0;
|
||||||
|
var _p20 = A2(_elm_lang$core$Dict$get, _p21, state.sockets);
|
||||||
|
if (_p20.ctor === 'Nothing') {
|
||||||
|
return _elm_lang$core$Task$succeed(state);
|
||||||
|
} else {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Task$andThen,
|
||||||
|
function (pid) {
|
||||||
|
return _elm_lang$core$Task$succeed(
|
||||||
|
A3(
|
||||||
|
_elm_lang$websocket$WebSocket$updateSocket,
|
||||||
|
_p21,
|
||||||
|
A2(_elm_lang$websocket$WebSocket$Opening, 0, pid),
|
||||||
|
state));
|
||||||
|
},
|
||||||
|
A3(_elm_lang$websocket$WebSocket$attemptOpen, router, 0, _p21));
|
||||||
|
}
|
||||||
|
case 'GoodOpen':
|
||||||
|
var _p24 = _p19._1;
|
||||||
|
var _p23 = _p19._0;
|
||||||
|
var _p22 = A2(_elm_lang$core$Dict$get, _p23, state.queues);
|
||||||
|
if (_p22.ctor === 'Nothing') {
|
||||||
|
return _elm_lang$core$Task$succeed(
|
||||||
|
A3(
|
||||||
|
_elm_lang$websocket$WebSocket$updateSocket,
|
||||||
|
_p23,
|
||||||
|
_elm_lang$websocket$WebSocket$Connected(_p24),
|
||||||
|
state));
|
||||||
|
} else {
|
||||||
|
return A3(
|
||||||
|
_elm_lang$core$List$foldl,
|
||||||
|
F2(
|
||||||
|
function (msg, task) {
|
||||||
|
return A2(
|
||||||
|
_elm_lang$websocket$WebSocket_ops['&>'],
|
||||||
|
A2(_elm_lang$websocket$WebSocket_LowLevel$send, _p24, msg),
|
||||||
|
task);
|
||||||
|
}),
|
||||||
|
_elm_lang$core$Task$succeed(
|
||||||
|
A2(
|
||||||
|
_elm_lang$websocket$WebSocket$removeQueue,
|
||||||
|
_p23,
|
||||||
|
A3(
|
||||||
|
_elm_lang$websocket$WebSocket$updateSocket,
|
||||||
|
_p23,
|
||||||
|
_elm_lang$websocket$WebSocket$Connected(_p24),
|
||||||
|
state))),
|
||||||
|
_p22._0);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
var _p27 = _p19._0;
|
||||||
|
var _p25 = A2(_elm_lang$core$Dict$get, _p27, state.sockets);
|
||||||
|
if (_p25.ctor === 'Nothing') {
|
||||||
|
return _elm_lang$core$Task$succeed(state);
|
||||||
|
} else {
|
||||||
|
if (_p25._0.ctor === 'Opening') {
|
||||||
|
var _p26 = _p25._0._0;
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Task$andThen,
|
||||||
|
function (pid) {
|
||||||
|
return _elm_lang$core$Task$succeed(
|
||||||
|
A3(
|
||||||
|
_elm_lang$websocket$WebSocket$updateSocket,
|
||||||
|
_p27,
|
||||||
|
A2(_elm_lang$websocket$WebSocket$Opening, _p26 + 1, pid),
|
||||||
|
state));
|
||||||
|
},
|
||||||
|
A3(_elm_lang$websocket$WebSocket$attemptOpen, router, _p26 + 1, _p27));
|
||||||
|
} else {
|
||||||
|
return _elm_lang$core$Task$succeed(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_elm_lang$core$Native_Platform.effectManagers['WebSocket'] = {pkg: 'elm-lang/websocket', init: _elm_lang$websocket$WebSocket$init, onEffects: _elm_lang$websocket$WebSocket$onEffects, onSelfMsg: _elm_lang$websocket$WebSocket$onSelfMsg, tag: 'fx', cmdMap: _elm_lang$websocket$WebSocket$cmdMap, subMap: _elm_lang$websocket$WebSocket$subMap};
|
||||||
|
|
||||||
var _evancz$elm_markdown$Native_Markdown = function() {
|
var _evancz$elm_markdown$Native_Markdown = function() {
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -33008,6 +33543,9 @@ var _user$project$CoreTypes$PairRoute = {ctor: 'PairRoute'};
|
||||||
var _user$project$CoreTypes$AccountRoute = function (a) {
|
var _user$project$CoreTypes$AccountRoute = function (a) {
|
||||||
return {ctor: 'AccountRoute', _0: a};
|
return {ctor: 'AccountRoute', _0: a};
|
||||||
};
|
};
|
||||||
|
var _user$project$CoreTypes$WebSocketMsg = function (a) {
|
||||||
|
return {ctor: 'WebSocketMsg', _0: a};
|
||||||
|
};
|
||||||
var _user$project$CoreTypes$Interval = {ctor: 'Interval'};
|
var _user$project$CoreTypes$Interval = {ctor: 'Interval'};
|
||||||
var _user$project$CoreTypes$UrlChange = function (a) {
|
var _user$project$CoreTypes$UrlChange = function (a) {
|
||||||
return {ctor: 'UrlChange', _0: a};
|
return {ctor: 'UrlChange', _0: a};
|
||||||
|
|
@ -34570,11 +35108,20 @@ var _user$project$Maintenance_View$view = function (model) {
|
||||||
};
|
};
|
||||||
|
|
||||||
var _user$project$Main$subscriptions = function (model) {
|
var _user$project$Main$subscriptions = function (model) {
|
||||||
return A2(
|
return _elm_lang$core$Platform_Sub$batch(
|
||||||
_elm_lang$core$Time$every,
|
{
|
||||||
10 * _elm_lang$core$Time$second,
|
ctor: '::',
|
||||||
function (_p0) {
|
_0: A2(
|
||||||
return _user$project$CoreTypes$Interval;
|
_elm_lang$core$Time$every,
|
||||||
|
5 * _elm_lang$core$Time$second,
|
||||||
|
function (_p0) {
|
||||||
|
return _user$project$CoreTypes$Interval;
|
||||||
|
}),
|
||||||
|
_1: {
|
||||||
|
ctor: '::',
|
||||||
|
_0: A2(_elm_lang$websocket$WebSocket$listen, 'wss://localhost:8070', _user$project$CoreTypes$WebSocketMsg),
|
||||||
|
_1: {ctor: '[]'}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var _user$project$Main$statusBar = function (maybeStatus) {
|
var _user$project$Main$statusBar = function (maybeStatus) {
|
||||||
|
|
@ -35119,7 +35666,7 @@ var _user$project$Main$update = F2(
|
||||||
});
|
});
|
||||||
case 'UrlChange':
|
case 'UrlChange':
|
||||||
return A2(_user$project$Main$urlUpdate, _p12._0, model);
|
return A2(_user$project$Main$urlUpdate, _p12._0, model);
|
||||||
default:
|
case 'Interval':
|
||||||
var route = A2(
|
var route = A2(
|
||||||
_elm_lang$core$Maybe$withDefault,
|
_elm_lang$core$Maybe$withDefault,
|
||||||
_user$project$CoreTypes$NotFoundRoute,
|
_user$project$CoreTypes$NotFoundRoute,
|
||||||
|
|
@ -35140,6 +35687,12 @@ var _user$project$Main$update = F2(
|
||||||
_1: {ctor: '[]'}
|
_1: {ctor: '[]'}
|
||||||
},
|
},
|
||||||
extraCmds));
|
extraCmds));
|
||||||
|
default:
|
||||||
|
var _p20 = A2(_elm_lang$core$Debug$log, 'DEBUG100', _p12._0);
|
||||||
|
return A2(
|
||||||
|
_elm_lang$core$Platform_Cmd_ops['!'],
|
||||||
|
model,
|
||||||
|
{ctor: '[]'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var _user$project$Main$main = A2(
|
var _user$project$Main$main = A2(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue