Place to store the code and config used for the next-Iterations live event.
https://iterations.space/live/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
459 lines
17 KiB
459 lines
17 KiB
// Holds anything kiwi client specific (ie. front, gateway, _kiwi.plugs..)
|
|
/**
|
|
* @namespace
|
|
*/
|
|
var _kiwi = {};
|
|
|
|
_kiwi.misc = {};
|
|
_kiwi.model = {};
|
|
_kiwi.view = {};
|
|
_kiwi.applets = {};
|
|
_kiwi.utils = {};
|
|
|
|
|
|
/**
|
|
* A global container for third party access
|
|
* Will be used to access a limited subset of kiwi functionality
|
|
* and data (think: plugins)
|
|
*/
|
|
_kiwi.global = {
|
|
build_version: '', // Kiwi IRC version this is built from (Set from index.html)
|
|
settings: undefined, // Instance of _kiwi.model.DataStore
|
|
plugins: undefined, // Instance of _kiwi.model.PluginManager
|
|
events: undefined, // Instance of PluginInterface
|
|
rpc: undefined, // Instance of WebsocketRpc
|
|
utils: {}, // References to misc. re-usable helpers / functions
|
|
|
|
// Make public some internal utils for plugins to make use of
|
|
initUtils: function() {
|
|
this.utils.randomString = randomString;
|
|
this.utils.secondsToTime = secondsToTime;
|
|
this.utils.parseISO8601 = parseISO8601;
|
|
this.utils.escapeRegex = escapeRegex;
|
|
this.utils.formatIRCMsg = formatIRCMsg;
|
|
this.utils.styleText = styleText;
|
|
this.utils.hsl2rgb = hsl2rgb;
|
|
this.utils.toUserMask = toUserMask;
|
|
|
|
this.utils.notifications = _kiwi.utils.notifications;
|
|
this.utils.formatDate = _kiwi.utils.formatDate;
|
|
},
|
|
|
|
addMediaMessageType: function(match, buildHtml) {
|
|
_kiwi.view.MediaMessage.addType(match, buildHtml);
|
|
},
|
|
|
|
// Event managers for plugins
|
|
components: {
|
|
EventComponent: function(event_source, proxy_event_name) {
|
|
/*
|
|
* proxyEvent() listens for events then re-triggers them on its own
|
|
* event emitter. Why? So we can .off() on this emitter without
|
|
* effecting the source of events. Handy for plugins that we don't
|
|
* trust meddling with the core events.
|
|
*
|
|
* If listening for 'all' events the arguments are as follows:
|
|
* 1. Name of the triggered event
|
|
* 2. The event data
|
|
* For all other events, we only have one argument:
|
|
* 1. The event data
|
|
*
|
|
* When this is used via `new kiwi.components.Network()`, this listens
|
|
* for 'all' events so the first argument is the event name which is
|
|
* the connection ID. We don't want to re-trigger this event name so
|
|
* we need to juggle the arguments to find the real event name we want
|
|
* to emit.
|
|
*/
|
|
function proxyEvent(event_name, event_data) {
|
|
if (proxy_event_name == 'all') {
|
|
} else {
|
|
event_data = event_name.event_data;
|
|
event_name = event_name.event_name;
|
|
}
|
|
|
|
this.trigger(event_name, event_data);
|
|
}
|
|
|
|
// The event we are to proxy
|
|
proxy_event_name = proxy_event_name || 'all';
|
|
|
|
_.extend(this, Backbone.Events);
|
|
this._source = event_source;
|
|
|
|
// Proxy the events to this dispatcher
|
|
event_source.on(proxy_event_name, proxyEvent, this);
|
|
|
|
// Clean up this object
|
|
this.dispose = function () {
|
|
event_source.off(proxy_event_name, proxyEvent);
|
|
this.off();
|
|
delete this.event_source;
|
|
};
|
|
},
|
|
|
|
Network: function(connection_id) {
|
|
var connection_event;
|
|
|
|
// If no connection id given, use all connections
|
|
if (typeof connection_id !== 'undefined') {
|
|
connection_event = 'connection:' + connection_id.toString();
|
|
} else {
|
|
connection_event = 'connection';
|
|
}
|
|
|
|
// Helper to get the network object
|
|
var getNetwork = function() {
|
|
var network = typeof connection_id === 'undefined' ?
|
|
_kiwi.app.connections.active_connection :
|
|
_kiwi.app.connections.getByConnectionId(connection_id);
|
|
|
|
return network ?
|
|
network :
|
|
undefined;
|
|
};
|
|
|
|
// Create the return object (events proxy from the gateway)
|
|
var obj = new this.EventComponent(_kiwi.gateway, connection_event);
|
|
|
|
// Proxy several gateway functions onto the return object
|
|
var funcs = {
|
|
kiwi: 'kiwi', raw: 'raw', kick: 'kick', topic: 'topic',
|
|
part: 'part', join: 'join', action: 'action', ctcp: 'ctcp',
|
|
ctcpRequest: 'ctcpRequest', ctcpResponse: 'ctcpResponse',
|
|
notice: 'notice', msg: 'privmsg', say: 'privmsg',
|
|
changeNick: 'changeNick', channelInfo: 'channelInfo',
|
|
mode: 'mode', quit: 'quit'
|
|
};
|
|
|
|
_.each(funcs, function(gateway_fn, func_name) {
|
|
obj[func_name] = function() {
|
|
var fn_name = gateway_fn;
|
|
|
|
// Add connection_id to the argument list
|
|
var args = Array.prototype.slice.call(arguments, 0);
|
|
args.unshift(connection_id);
|
|
|
|
// Call the gateway function on behalf of this connection
|
|
return _kiwi.gateway[fn_name].apply(_kiwi.gateway, args);
|
|
};
|
|
});
|
|
|
|
// Now for some network related functions...
|
|
obj.createQuery = function(nick) {
|
|
var network, restricted_keys;
|
|
|
|
network = getNetwork();
|
|
if (!network) {
|
|
return;
|
|
}
|
|
|
|
return network.createQuery(nick);
|
|
};
|
|
|
|
obj.ignoreMask = function(mask) {
|
|
var network = getNetwork();
|
|
if (!network) {
|
|
return;
|
|
}
|
|
|
|
return network.ignore_list.addMask(mask);
|
|
};
|
|
|
|
obj.unignoreMask = function(mask) {
|
|
var network = getNetwork();
|
|
if (!network) {
|
|
return;
|
|
}
|
|
|
|
return network.ignore_list.removeMask(mask);
|
|
};
|
|
|
|
// Add the networks getters/setters
|
|
obj.get = function(name) {
|
|
var network, restricted_keys;
|
|
|
|
network = getNetwork();
|
|
if (!network) {
|
|
return;
|
|
}
|
|
|
|
restricted_keys = [
|
|
'password'
|
|
];
|
|
if (restricted_keys.indexOf(name) > -1) {
|
|
return undefined;
|
|
}
|
|
|
|
return network.get(name);
|
|
};
|
|
|
|
obj.set = function() {
|
|
var network = getNetwork();
|
|
if (!network) {
|
|
return;
|
|
}
|
|
|
|
return network.set.apply(network, arguments);
|
|
};
|
|
|
|
return obj;
|
|
},
|
|
|
|
ControlInput: function() {
|
|
var obj = new this.EventComponent(_kiwi.app.controlbox);
|
|
var funcs = {
|
|
run: 'processInput', addPluginIcon: 'addPluginIcon'
|
|
};
|
|
|
|
_.each(funcs, function(controlbox_fn, func_name) {
|
|
obj[func_name] = function() {
|
|
var fn_name = controlbox_fn;
|
|
return _kiwi.app.controlbox[fn_name].apply(_kiwi.app.controlbox, arguments);
|
|
};
|
|
});
|
|
|
|
// Give access to the control input textarea
|
|
obj.input = _kiwi.app.controlbox.$('.inp');
|
|
|
|
return obj;
|
|
}
|
|
},
|
|
|
|
// Entry point to start the kiwi application
|
|
init: function (opts, callback) {
|
|
var locale_promise, theme_promise,
|
|
that = this;
|
|
|
|
opts = opts || {};
|
|
|
|
this.initUtils();
|
|
|
|
// Set up the settings datastore
|
|
_kiwi.global.settings = _kiwi.model.DataStore.instance('kiwi.settings');
|
|
_kiwi.global.settings.load();
|
|
|
|
// Set the window title
|
|
window.document.title = opts.server_settings.client.window_title || 'Kiwi IRC';
|
|
|
|
locale_promise = new Promise(function (resolve) {
|
|
// In order, find a locale from the users saved settings, the URL, default settings on the server, or auto detect
|
|
var locale = _kiwi.global.settings.get('locale') || opts.locale || opts.server_settings.client.settings.locale || 'magic';
|
|
$.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', function (locale) {
|
|
if (locale) {
|
|
that.i18n = new Jed(locale);
|
|
} else {
|
|
that.i18n = new Jed();
|
|
}
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
theme_promise = new Promise(function (resolve) {
|
|
var text_theme = opts.server_settings.client.settings.text_theme || 'default';
|
|
$.getJSON(opts.base_path + '/assets/text_themes/' + text_theme + '.json', function(text_theme) {
|
|
opts.text_theme = text_theme;
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
|
|
Promise.all([locale_promise, theme_promise]).then(function () {
|
|
_kiwi.app = new _kiwi.model.Application(opts);
|
|
|
|
// Start the client up
|
|
_kiwi.app.initializeInterfaces();
|
|
|
|
// Event emitter to let plugins interface with parts of kiwi
|
|
_kiwi.global.events = new PluginInterface();
|
|
|
|
// Now everything has started up, load the plugin manager for third party plugins
|
|
_kiwi.global.plugins = new _kiwi.model.PluginManager();
|
|
|
|
callback();
|
|
|
|
}).then(null, function(err) {
|
|
console.error(err.stack);
|
|
});
|
|
},
|
|
|
|
start: function() {
|
|
_kiwi.app.showStartup();
|
|
},
|
|
|
|
// Allow plugins to change the startup applet
|
|
registerStartupApplet: function(startup_applet_name) {
|
|
_kiwi.app.startup_applet_name = startup_applet_name;
|
|
},
|
|
|
|
/**
|
|
* Open a new IRC connection
|
|
* @param {Object} connection_details {nick, host, port, ssl, password, options}
|
|
* @param {Function} callback function(err, network){}
|
|
*/
|
|
newIrcConnection: function(connection_details, callback) {
|
|
_kiwi.gateway.newConnection(connection_details, callback);
|
|
},
|
|
|
|
|
|
/**
|
|
* Taking settings from the server and URL, extract the default server/channel/nick settings
|
|
*/
|
|
defaultServerSettings: function () {
|
|
var parts;
|
|
var defaults = {
|
|
nick: '',
|
|
server: '',
|
|
port: 6667,
|
|
ssl: false,
|
|
channel: '',
|
|
channel_key: ''
|
|
};
|
|
var uricheck;
|
|
|
|
|
|
/**
|
|
* Get any settings set by the server
|
|
* These settings may be changed in the server selection dialog or via URL parameters
|
|
*/
|
|
if (_kiwi.app.server_settings.client) {
|
|
if (_kiwi.app.server_settings.client.nick)
|
|
defaults.nick = _kiwi.app.server_settings.client.nick;
|
|
|
|
if (_kiwi.app.server_settings.client.server)
|
|
defaults.server = _kiwi.app.server_settings.client.server;
|
|
|
|
if (_kiwi.app.server_settings.client.port)
|
|
defaults.port = _kiwi.app.server_settings.client.port;
|
|
|
|
if (_kiwi.app.server_settings.client.ssl)
|
|
defaults.ssl = _kiwi.app.server_settings.client.ssl;
|
|
|
|
if (_kiwi.app.server_settings.client.channel)
|
|
defaults.channel = _kiwi.app.server_settings.client.channel;
|
|
|
|
if (_kiwi.app.server_settings.client.channel_key)
|
|
defaults.channel_key = _kiwi.app.server_settings.client.channel_key;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Get any settings passed in the URL
|
|
* These settings may be changed in the server selection dialog
|
|
*/
|
|
|
|
// Any query parameters first
|
|
if (getQueryVariable('nick'))
|
|
defaults.nick = getQueryVariable('nick');
|
|
|
|
if (window.location.hash)
|
|
defaults.channel = window.location.hash;
|
|
|
|
|
|
// Process the URL part by part, extracting as we go
|
|
parts = window.location.pathname.toString().replace(_kiwi.app.get('base_path'), '').split('/');
|
|
|
|
if (parts.length > 0) {
|
|
parts.shift();
|
|
|
|
if (parts.length > 0 && parts[0]) {
|
|
// Check to see if we're dealing with an irc: uri, or whether we need to extract the server/channel info from the HTTP URL path.
|
|
uricheck = parts[0].substr(0, 7).toLowerCase();
|
|
if ((uricheck === 'ircs%3a') || (uricheck.substr(0,6) === 'irc%3a')) {
|
|
parts[0] = decodeURIComponent(parts[0]);
|
|
// irc[s]://<host>[:<port>]/[<channel>[?<password>]]
|
|
uricheck = /^irc(s)?:(?:\/\/?)?([^:\/]+)(?::([0-9]+))?(?:(?:\/)([^\?]*)(?:(?:\?)(.*))?)?$/.exec(parts[0]);
|
|
/*
|
|
uricheck[1] = ssl (optional)
|
|
uricheck[2] = host
|
|
uricheck[3] = port (optional)
|
|
uricheck[4] = channel (optional)
|
|
uricheck[5] = channel key (optional, channel must also be set)
|
|
*/
|
|
if (uricheck) {
|
|
if (typeof uricheck[1] !== 'undefined') {
|
|
defaults.ssl = true;
|
|
if (defaults.port === 6667) {
|
|
defaults.port = 6697;
|
|
}
|
|
}
|
|
defaults.server = uricheck[2];
|
|
if (typeof uricheck[3] !== 'undefined') {
|
|
defaults.port = uricheck[3];
|
|
}
|
|
if (typeof uricheck[4] !== 'undefined') {
|
|
// Only prepend # if it doesn't already start with it
|
|
defaults.channel = (uricheck[4][0] === '#') ?
|
|
uricheck[4] :
|
|
'#' + uricheck[4];
|
|
|
|
if (typeof uricheck[5] !== 'undefined') {
|
|
defaults.channel_key = uricheck[5];
|
|
}
|
|
}
|
|
}
|
|
parts = [];
|
|
} else {
|
|
// Extract the port+ssl if we find one
|
|
if (parts[0].search(/:/) > 0) {
|
|
defaults.port = parts[0].substring(parts[0].search(/:/) + 1);
|
|
defaults.server = parts[0].substring(0, parts[0].search(/:/));
|
|
if (defaults.port[0] === '+') {
|
|
defaults.port = parseInt(defaults.port.substring(1), 10);
|
|
defaults.ssl = true;
|
|
} else {
|
|
defaults.ssl = false;
|
|
}
|
|
|
|
} else {
|
|
defaults.server = parts[0];
|
|
}
|
|
|
|
parts.shift();
|
|
}
|
|
}
|
|
|
|
if (parts.length > 0 && parts[0]) {
|
|
defaults.channel = '#' + parts[0];
|
|
parts.shift();
|
|
}
|
|
}
|
|
|
|
// If any settings have been given by the server.. override any auto detected settings
|
|
/**
|
|
* Get any server restrictions as set in the server config
|
|
* These settings can not be changed in the server selection dialog
|
|
*/
|
|
if (_kiwi.app.server_settings && _kiwi.app.server_settings.connection) {
|
|
if (_kiwi.app.server_settings.connection.server) {
|
|
defaults.server = _kiwi.app.server_settings.connection.server;
|
|
}
|
|
|
|
if (_kiwi.app.server_settings.connection.port) {
|
|
defaults.port = _kiwi.app.server_settings.connection.port;
|
|
}
|
|
|
|
if (_kiwi.app.server_settings.connection.ssl) {
|
|
defaults.ssl = _kiwi.app.server_settings.connection.ssl;
|
|
}
|
|
}
|
|
|
|
// Set any random numbers if needed
|
|
defaults.nick = defaults.nick.replace(/\?/g, Math.floor(Math.random() * 100000).toString());
|
|
|
|
if (getQueryVariable('encoding'))
|
|
defaults.encoding = getQueryVariable('encoding');
|
|
|
|
return defaults;
|
|
},
|
|
};
|
|
|
|
|
|
|
|
// If within a closure, expose the kiwi globals
|
|
if (typeof global !== 'undefined') {
|
|
global.kiwi = _kiwi.global;
|
|
} else {
|
|
// Not within a closure so set a var in the current scope
|
|
var kiwi = _kiwi.global;
|
|
}
|
|
|