Create websockets module
This commit is contained in:
parent
4f6d8d12e0
commit
d4a4f1bd7f
4 changed files with 193 additions and 96 deletions
|
@ -23,6 +23,7 @@
|
||||||
<script type="text/javascript" src="js/weechat.js"></script>
|
<script type="text/javascript" src="js/weechat.js"></script>
|
||||||
<script type="text/javascript" src="js/irc-utils.js"></script>
|
<script type="text/javascript" src="js/irc-utils.js"></script>
|
||||||
<script type="text/javascript" src="js/glowingbear.js"></script>
|
<script type="text/javascript" src="js/glowingbear.js"></script>
|
||||||
|
<script type="text/javascript" src="js/websockets.js"></script>
|
||||||
<script type="text/javascript" src="js/models.js"></script>
|
<script type="text/javascript" src="js/models.js"></script>
|
||||||
<script type="text/javascript" src="js/plugins.js"></script>
|
<script type="text/javascript" src="js/plugins.js"></script>
|
||||||
<script type="text/javascript" src="3rdparty/bindonce.min.js"></script>
|
<script type="text/javascript" src="3rdparty/bindonce.min.js"></script>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
var weechat = angular.module('weechat', ['ngRoute', 'localStorage', 'weechatModels', 'plugins', 'ngSanitize', 'pasvaz.bindonce']);
|
var weechat = angular.module('weechat', ['ngRoute', 'localStorage', 'weechatModels', 'plugins', 'ngSanitize', 'ngWebsockets', 'pasvaz.bindonce']);
|
||||||
|
|
||||||
weechat.filter('toArray', function () {
|
weechat.filter('toArray', function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -176,6 +176,14 @@ weechat.factory('handlers', ['$rootScope', 'models', 'plugins', function($rootSc
|
||||||
_nicklist_diff: handleNicklistDiff
|
_nicklist_diff: handleNicklistDiff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$rootScope.$on('onMessage', function(event, message) {
|
||||||
|
|
||||||
|
if (_.has(eventHandlers, message.id)) {
|
||||||
|
|
||||||
|
eventHandlers[message.id](message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var handleEvent = function(event) {
|
var handleEvent = function(event) {
|
||||||
if (_.has(eventHandlers, event.id)) {
|
if (_.has(eventHandlers, event.id)) {
|
||||||
eventHandlers[event.id](event);
|
eventHandlers[event.id](event);
|
||||||
|
@ -191,101 +199,25 @@ weechat.factory('handlers', ['$rootScope', 'models', 'plugins', function($rootSc
|
||||||
|
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers', 'models', function($q, $rootScope, $log, storage, handlers, models) {
|
weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers', 'models', 'conn', function($q, $rootScope, $log, storage, handlers, models, conn) {
|
||||||
protocol = new weeChat.Protocol();
|
protocol = new weeChat.Protocol();
|
||||||
var websocket = null;
|
|
||||||
|
|
||||||
var callbacks = {};
|
|
||||||
var currentCallBackId = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the current callback id
|
|
||||||
*/
|
|
||||||
var getCurrentCallBackId = function() {
|
|
||||||
|
|
||||||
currentCallBackId += 1;
|
|
||||||
|
|
||||||
if (currentCallBackId > 1000) {
|
|
||||||
currentCallBackId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentCallBackId;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a callback, adds it to the callback list
|
|
||||||
* and return it.
|
|
||||||
*/
|
|
||||||
var createCallback = function() {
|
|
||||||
var defer = $q.defer();
|
|
||||||
var cbId = getCurrentCallBackId();
|
|
||||||
|
|
||||||
callbacks[cbId] = {
|
|
||||||
time: new Date(),
|
|
||||||
cb: defer
|
|
||||||
};
|
|
||||||
|
|
||||||
defer.id = cbId;
|
|
||||||
|
|
||||||
return defer;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Fails every currently subscribed callback for the
|
|
||||||
* given reason
|
|
||||||
*
|
|
||||||
* @param reason reason for failure
|
|
||||||
*/
|
|
||||||
failCallbacks = function(reason) {
|
|
||||||
for (var i in callbacks) {
|
|
||||||
callbacks[i].cb.reject(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Send a message to the websocket and returns a promise.
|
|
||||||
* See: http://docs.angularjs.org/api/ng.$q
|
|
||||||
*
|
|
||||||
* @param message message to send
|
|
||||||
* @returns a promise
|
|
||||||
*/
|
|
||||||
var send = function(message) {
|
|
||||||
message.replace(/[\r\n]+$/g, "").split("\n");
|
|
||||||
var cb = createCallback(message);
|
|
||||||
websocket.send("(" + cb.id + ") " + message);
|
|
||||||
return cb.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send all messages to the websocket and returns a promise that is resolved
|
|
||||||
* when all message are resolved.
|
|
||||||
*
|
|
||||||
* @param messages list of messages
|
|
||||||
* @returns a promise
|
|
||||||
*/
|
|
||||||
var sendAll = function(messages) {
|
|
||||||
var promises = [];
|
|
||||||
for (var i in messages) {
|
|
||||||
var promise = send(messages[i]);
|
|
||||||
promises.push(promise);
|
|
||||||
}
|
|
||||||
return $q.all(promises);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Takes care of the connection and websocket hooks
|
// Takes care of the connection and websocket hooks
|
||||||
var connect = function (host, port, passwd, ssl, noCompression) {
|
var connect = function (host, port, passwd, ssl, noCompression) {
|
||||||
var proto = ssl ? 'wss' : 'ws';
|
var proto = ssl ? 'wss' : 'ws';
|
||||||
websocket = new WebSocket(proto + "://" + host + ':' + port + "/weechat");
|
var url = proto + "://" + host + ":" + port + "/weechat";
|
||||||
websocket.binaryType = "arraybuffer";
|
var binaryType = "arraybuffer";
|
||||||
|
|
||||||
websocket.onopen = function () {
|
var onopen = function () {
|
||||||
|
|
||||||
$log.info("Connected to relay");
|
$log.info("Connected to relay");
|
||||||
|
|
||||||
// First command asks for the password and issues
|
// First command asks for the password and issues
|
||||||
// a version command. If it fails, it means the we
|
// a version command. If it fails, it means the we
|
||||||
// did not provide the proper password.
|
// did not provide the proper password.
|
||||||
sendAll([
|
conn.sendAll([
|
||||||
weeChat.Protocol.formatInit({
|
weeChat.Protocol.formatInit({
|
||||||
password: passwd,
|
password: passwd,
|
||||||
compression: noCompression ? 'off' : 'zlib'
|
compression: noCompression ? 'off' : 'zlib'
|
||||||
|
@ -301,7 +233,7 @@ weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
send(
|
conn.send(
|
||||||
weeChat.Protocol.formatHdata({
|
weeChat.Protocol.formatHdata({
|
||||||
path: 'buffer:gui_buffers(*)',
|
path: 'buffer:gui_buffers(*)',
|
||||||
keys: ['local_variables,notify,number,full_name,short_name,title']
|
keys: ['local_variables,notify,number,full_name,short_name,title']
|
||||||
|
@ -321,7 +253,7 @@ weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers',
|
||||||
|
|
||||||
|
|
||||||
// Send all the other commands required for initialization
|
// Send all the other commands required for initialization
|
||||||
send(
|
conn.send(
|
||||||
weeChat.Protocol.formatHdata({
|
weeChat.Protocol.formatHdata({
|
||||||
path: "buffer:gui_buffers(*)/own_lines/last_line(-"+storage.get('lines')+")/data",
|
path: "buffer:gui_buffers(*)/own_lines/last_line(-"+storage.get('lines')+")/data",
|
||||||
keys: []
|
keys: []
|
||||||
|
@ -330,7 +262,7 @@ weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers',
|
||||||
handlers.handleLineInfo(lineinfo);
|
handlers.handleLineInfo(lineinfo);
|
||||||
});
|
});
|
||||||
|
|
||||||
send(
|
conn.send(
|
||||||
weeChat.Protocol.formatHdata({
|
weeChat.Protocol.formatHdata({
|
||||||
path: "hotlist:gui_hotlist(*)",
|
path: "hotlist:gui_hotlist(*)",
|
||||||
keys: []
|
keys: []
|
||||||
|
@ -340,14 +272,14 @@ weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
send(
|
conn.send(
|
||||||
weeChat.Protocol.formatNicklist({
|
weeChat.Protocol.formatNicklist({
|
||||||
})
|
})
|
||||||
).then(function(nicklist) {
|
).then(function(nicklist) {
|
||||||
handlers.handleNicklist(nicklist);
|
handlers.handleNicklist(nicklist);
|
||||||
});
|
});
|
||||||
|
|
||||||
send(
|
conn.send(
|
||||||
weeChat.Protocol.formatSync({})
|
weeChat.Protocol.formatSync({})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -355,14 +287,16 @@ weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers',
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
websocket.onclose = function () {
|
|
||||||
|
|
||||||
|
var onclose = function () {
|
||||||
$log.info("Disconnected from relay");
|
$log.info("Disconnected from relay");
|
||||||
$rootScope.connected = false;
|
$rootScope.connected = false;
|
||||||
failCallbacks('disconnection');
|
failCallbacks('disconnection');
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
};
|
};
|
||||||
|
|
||||||
websocket.onmessage = function (evt) {
|
var onmessage = function (evt) {
|
||||||
message = protocol.parse(evt.data);
|
message = protocol.parse(evt.data);
|
||||||
if (_.has(callbacks, message.id)) {
|
if (_.has(callbacks, message.id)) {
|
||||||
var promise = callbacks[message.id];
|
var promise = callbacks[message.id];
|
||||||
|
@ -375,23 +309,36 @@ weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers',
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
};
|
};
|
||||||
|
|
||||||
websocket.onerror = function (evt) {
|
var onerror = function (evt) {
|
||||||
// on error it means the connection problem
|
// on error it means the connection problem
|
||||||
// come from the relay not from the password.
|
// come from the relay not from the password.
|
||||||
|
|
||||||
if (evt.type === "error" && websocket.readyState !== 1) {
|
if (evt.type === "error" && this.readyState !== 1) {
|
||||||
failCallbacks('error');
|
failCallbacks('error');
|
||||||
$rootScope.errorMessage = true;
|
$rootScope.errorMessage = true;
|
||||||
}
|
}
|
||||||
$log.error("Relay error " + evt.data);
|
$log.error("Relay error " + evt.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.websocket = websocket;
|
protocol.setId = function(id, message) {
|
||||||
|
return '(' + id + ') ' + message;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.connect(url,
|
||||||
|
protocol,
|
||||||
|
{
|
||||||
|
'binaryType': "arraybuffer",
|
||||||
|
'onopen': onopen,
|
||||||
|
'onclose': onclose,
|
||||||
|
'onmessage': onmessage,
|
||||||
|
'onerror': onerror,
|
||||||
|
})
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var disconnect = function() {
|
var disconnect = function() {
|
||||||
/* TODO: Send protocol disconnect */
|
/* TODO: Send protocol disconnect */
|
||||||
this.websocket.close();
|
conn.disconnect();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -400,14 +347,14 @@ weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers',
|
||||||
* @returns the angular promise
|
* @returns the angular promise
|
||||||
*/
|
*/
|
||||||
var sendMessage = function(message) {
|
var sendMessage = function(message) {
|
||||||
return send(weeChat.Protocol.formatInput({
|
conn.send(weeChat.Protocol.formatInput({
|
||||||
buffer: models.getActiveBuffer().fullName,
|
buffer: models.getActiveBuffer().fullName,
|
||||||
data: message
|
data: message
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
var sendCoreCommand = function(command) {
|
var sendCoreCommand = function(command) {
|
||||||
send(weeChat.Protocol.formatInput({
|
conn.send(weeChat.Protocol.formatInput({
|
||||||
buffer: 'core.weechat',
|
buffer: 'core.weechat',
|
||||||
data: command
|
data: command
|
||||||
}));
|
}));
|
||||||
|
@ -415,7 +362,7 @@ weechat.factory('connection', ['$q', '$rootScope', '$log', '$store', 'handlers',
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
send: send,
|
// send: send,
|
||||||
connect: connect,
|
connect: connect,
|
||||||
disconnect: disconnect,
|
disconnect: disconnect,
|
||||||
sendMessage: sendMessage,
|
sendMessage: sendMessage,
|
||||||
|
|
137
js/websockets.js
Normal file
137
js/websockets.js
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
var websockets = angular.module('ngWebsockets', []);
|
||||||
|
|
||||||
|
websockets.factory('conn',
|
||||||
|
['$rootScope','$q',
|
||||||
|
function($rootScope, $q) {
|
||||||
|
|
||||||
|
|
||||||
|
var ws = null;
|
||||||
|
this.protocol = null;
|
||||||
|
var callbacks = {};
|
||||||
|
var currentCallBackId = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fails every currently subscribed callback for the
|
||||||
|
* given reason
|
||||||
|
*
|
||||||
|
* @param reason reason for failure
|
||||||
|
*/
|
||||||
|
failCallbacks = function(reason) {
|
||||||
|
for (var i in callbacks) {
|
||||||
|
callbacks[i].cb.reject(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the current callback id
|
||||||
|
*/
|
||||||
|
var getCurrentCallBackId = function() {
|
||||||
|
|
||||||
|
currentCallBackId += 1;
|
||||||
|
|
||||||
|
if (currentCallBackId > 1000) {
|
||||||
|
currentCallBackId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentCallBackId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Send a message to the websocket and returns a promise.
|
||||||
|
* See: http://docs.angularjs.org/api/ng.$q
|
||||||
|
*
|
||||||
|
* @param message message to send
|
||||||
|
* @returns a promise
|
||||||
|
*/
|
||||||
|
var send = function(message) {
|
||||||
|
|
||||||
|
var cb = createCallback(message);
|
||||||
|
|
||||||
|
message = protocol.setId(cb.id,
|
||||||
|
message);
|
||||||
|
|
||||||
|
ws.send(message);
|
||||||
|
return cb.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a callback, adds it to the callback list
|
||||||
|
* and return it.
|
||||||
|
*/
|
||||||
|
var createCallback = function() {
|
||||||
|
var defer = $q.defer();
|
||||||
|
var cbId = getCurrentCallBackId();
|
||||||
|
|
||||||
|
callbacks[cbId] = {
|
||||||
|
time: new Date(),
|
||||||
|
cb: defer
|
||||||
|
};
|
||||||
|
|
||||||
|
defer.id = cbId;
|
||||||
|
|
||||||
|
return defer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send all messages to the websocket and returns a promise that is resolved
|
||||||
|
* when all message are resolved.
|
||||||
|
*
|
||||||
|
* @param messages list of messages
|
||||||
|
* @returns a promise
|
||||||
|
*/
|
||||||
|
var sendAll = function(messages) {
|
||||||
|
var promises = [];
|
||||||
|
for (var i in messages) {
|
||||||
|
var promise = send(messages[i]);
|
||||||
|
promises.push(promise);
|
||||||
|
}
|
||||||
|
return $q.all(promises);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
var onmessage = function (evt) {
|
||||||
|
/*
|
||||||
|
* Receives a message on the websocket
|
||||||
|
*/
|
||||||
|
var message = protocol.parse(evt.data)
|
||||||
|
if (_.has(callbacks, message.id)) {
|
||||||
|
// see if it's bound to one of the callbacks
|
||||||
|
var promise = callbacks[message.id];
|
||||||
|
promise.cb.resolve(message)
|
||||||
|
delete(callbacks[message.id]);
|
||||||
|
} else {
|
||||||
|
// otherwise emit it
|
||||||
|
$rootScope.$emit('onMessage', message)
|
||||||
|
//handlers.handleEvent(message);
|
||||||
|
}
|
||||||
|
$rootScope.commands.push("RECV: " + evt.data + " TYPE:" + evt.type);
|
||||||
|
$rootScope.$apply();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var connect = function(url,
|
||||||
|
protocol,
|
||||||
|
properties) {
|
||||||
|
|
||||||
|
ws = new WebSocket(url);
|
||||||
|
protocol = protocol;
|
||||||
|
for (var property in properties) {
|
||||||
|
ws[property] = properties[property];
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.onmessage = onmessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
var disconnect = function() {
|
||||||
|
ws.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
send: send,
|
||||||
|
sendAll: sendAll,
|
||||||
|
connect: connect,
|
||||||
|
disconnect: disconnect
|
||||||
|
}
|
||||||
|
}]);
|
|
@ -596,6 +596,16 @@
|
||||||
return defaults;
|
return defaults;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the ID to the previously formatted command
|
||||||
|
*
|
||||||
|
* @param id Command ID
|
||||||
|
* @param command previously formatted command
|
||||||
|
*/
|
||||||
|
WeeChatProtocol.setId = function(id, command) {
|
||||||
|
return '(' + id + ') ' + command;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a command.
|
* Formats a command.
|
||||||
*
|
*
|
||||||
|
@ -614,6 +624,8 @@
|
||||||
cmd = parts.join(' ');
|
cmd = parts.join(' ');
|
||||||
cmd += '\n';
|
cmd += '\n';
|
||||||
|
|
||||||
|
cmd.replace(/[\r\n]+$/g, "").split("\n");
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue