Merge pull request #167 from thelounge/irc-framework
Drop slate-irc, switch to irc-framework
This commit is contained in:
commit
116dbc07be
@ -789,7 +789,8 @@ button,
|
||||
#chat .nick .text,
|
||||
#chat .part .text,
|
||||
#chat .quit .text,
|
||||
#chat .topic .text {
|
||||
#chat .topic .text,
|
||||
#chat .topic_set_by .text {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
@ -826,6 +827,11 @@ button,
|
||||
color: #2ecc40;
|
||||
}
|
||||
|
||||
#chat .ctcp .from:before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f0f6";
|
||||
}
|
||||
|
||||
#chat .whois .from:before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f007";
|
||||
@ -867,6 +873,10 @@ button,
|
||||
color: #f00;
|
||||
}
|
||||
|
||||
#chat .msg.toggle .time {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#chat .toggle-button {
|
||||
background: #f5f5f5;
|
||||
border-radius: 2px;
|
||||
|
7
client/js/libs/handlebars/date.js
Normal file
7
client/js/libs/handlebars/date.js
Normal file
@ -0,0 +1,7 @@
|
||||
Handlebars.registerHelper(
|
||||
"localeDate", function(date) {
|
||||
date = new Date(date);
|
||||
|
||||
return date.toLocaleString();
|
||||
}
|
||||
);
|
7
client/js/libs/handlebars/tojson.js
Normal file
7
client/js/libs/handlebars/tojson.js
Normal file
@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
Handlebars.registerHelper(
|
||||
"toJSON", function(context) {
|
||||
return JSON.stringify(context);
|
||||
}
|
||||
);
|
@ -221,8 +221,10 @@ $(function() {
|
||||
"part",
|
||||
"quit",
|
||||
"topic",
|
||||
"topic_set_by",
|
||||
"action",
|
||||
"whois",
|
||||
"ctcp",
|
||||
].indexOf(type) !== -1) {
|
||||
data.msg.template = "actions/" + type;
|
||||
msg = $(render("msg_action", data.msg));
|
||||
@ -309,6 +311,10 @@ $(function() {
|
||||
sortable();
|
||||
});
|
||||
|
||||
socket.on("network_changed", function(data) {
|
||||
sidebar.find("#network-" + data.network).data("options", data.serverOptions);
|
||||
});
|
||||
|
||||
socket.on("nick", function(data) {
|
||||
var id = data.network;
|
||||
var nick = data.nick;
|
||||
@ -769,7 +775,7 @@ $(function() {
|
||||
|
||||
if (msg.type === "invite") {
|
||||
title = "New channel invite:";
|
||||
body = msg.from + " invited you to " + msg.text;
|
||||
body = msg.from + " invited you to " + msg.channel;
|
||||
} else {
|
||||
title = msg.from;
|
||||
if (!isQuery) {
|
||||
|
2
client/views/actions/ctcp.tpl
Normal file
2
client/views/actions/ctcp.tpl
Normal file
@ -0,0 +1,2 @@
|
||||
<a href="#" class="user" data-name="{{from}}">{{from}}</a>
|
||||
<b>{{ctcpType}}</b> {{ctcpMessage}}
|
@ -3,7 +3,7 @@ invited
|
||||
{{#if invitedYou}}
|
||||
you
|
||||
{{else}}
|
||||
<a href="#" class="user" data-name="{{target}}">{{target}}</a>
|
||||
<a href="#" class="user" data-name="{{invited}}">{{invited}}</a>
|
||||
{{/if}}
|
||||
to
|
||||
{{{parse text}}}
|
||||
{{{parse channel}}}
|
||||
|
@ -1,3 +1,3 @@
|
||||
<a href="#" class="user" data-name="{{from}}">{{mode}}{{from}}</a>
|
||||
<a href="#" class="user" data-name="{{nick}}">{{mode}}{{nick}}</a>
|
||||
is now known as
|
||||
<a href="#" class="user" data-name="{{text}}">{{mode}}{{text}}</a>
|
||||
<a href="#" class="user" data-name="{{new_nick}}">{{mode}}{{new_nick}}</a>
|
||||
|
@ -1,8 +1,8 @@
|
||||
{{#if isSetByChan}}
|
||||
The topic is:
|
||||
{{else}}
|
||||
{{#if from}}
|
||||
<a href="#" class="user" data-name="{{from}}">{{mode}}{{from}}</a>
|
||||
has changed the topic to:
|
||||
{{else}}
|
||||
The topic is:
|
||||
{{/if}}
|
||||
|
||||
<span class="new-topic">{{{parse text}}}</span>
|
||||
|
1
client/views/actions/topic_set_by.tpl
Normal file
1
client/views/actions/topic_set_by.tpl
Normal file
@ -0,0 +1 @@
|
||||
Topic set by <a href="#" class="user" data-name="{{nick}}">{{mode}}{{nick}}</a> on {{localeDate when}}
|
@ -1,26 +1,35 @@
|
||||
<div>
|
||||
<a href="#" class="user" data-name="{{whois.nickname}}">{{whois.nickname}}</a>
|
||||
<i class="hostmask">({{whois.username}}@{{whois.hostname}})</i>:
|
||||
<b>{{whois.realname}}</b>
|
||||
<a href="#" class="user" data-name="{{whois.nick}}">{{whois.nick}}</a>
|
||||
<i class="hostmask">({{whois.user}}@{{whois.host}})</i>:
|
||||
<b>{{whois.real_name}}</b>
|
||||
</div>
|
||||
{{#if whois.account}}
|
||||
<div>
|
||||
<a href="#" class="user" data-name="{{whois.nick}}">{{whois.nick}}</a>
|
||||
is logged in as <b>{{whois.account}}</b>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if whois.channels}}
|
||||
<div>
|
||||
<a href="#" class="user" data-name="{{whois.nickname}}">{{whois.nickname}}</a>
|
||||
is on the following channels:
|
||||
{{#each whois.channels}}
|
||||
{{{parse this}}}
|
||||
{{/each}}
|
||||
<a href="#" class="user" data-name="{{whois.nick}}">{{whois.nick}}</a>
|
||||
is on the following channels: {{{parse whois.channels}}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if whois.server}}
|
||||
<div>
|
||||
<a href="#" class="user" data-name="{{whois.nickname}}">{{whois.nickname}}</a>
|
||||
is connected to {{whois.server}}
|
||||
<a href="#" class="user" data-name="{{whois.nick}}">{{whois.nick}}</a>
|
||||
is connected to {{whois.server}} <i>({{whois.server_info}})</i>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if whois.secure}}
|
||||
<div>
|
||||
<a href="#" class="user" data-name="{{whois.nick}}">{{whois.nick}}</a>
|
||||
is using a secure connection
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if whois.away}}
|
||||
<div>
|
||||
<a href="#" class="user" data-name="{{whois.nickname}}">{{whois.nickname}}</a>
|
||||
<a href="#" class="user" data-name="{{whois.nick}}">{{whois.nick}}</a>
|
||||
is away <i>({{whois.away}})</i>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{{#each networks}}
|
||||
<section id="network-{{id}}" class="network" data-id="{{id}}" data-nick="{{nick}}">
|
||||
<section id="network-{{id}}" class="network" data-id="{{id}}" data-nick="{{nick}}" data-options="{{toJSON serverOptions}}">
|
||||
{{partial "chan"}}
|
||||
</section>
|
||||
{{/each}}
|
||||
|
@ -33,6 +33,7 @@
|
||||
"event-stream": "3.3.2",
|
||||
"express": "4.13.4",
|
||||
"lodash": "4.6.1",
|
||||
"irc-framework": "1.0.10",
|
||||
"mkdirp": "0.5.1",
|
||||
"moment": "2.12.0",
|
||||
"read": "1.0.7",
|
||||
|
190
src/client.js
190
src/client.js
@ -1,19 +1,17 @@
|
||||
var _ = require("lodash");
|
||||
var Chan = require("./models/chan");
|
||||
var crypto = require("crypto");
|
||||
var identd = require("./identd");
|
||||
var log = require("./log");
|
||||
var net = require("net");
|
||||
var Msg = require("./models/msg");
|
||||
var Network = require("./models/network");
|
||||
var slate = require("slate-irc");
|
||||
var tls = require("tls");
|
||||
var ircFramework = require("irc-framework");
|
||||
var Helper = require("./helper");
|
||||
|
||||
module.exports = Client;
|
||||
|
||||
var id = 0;
|
||||
var events = [
|
||||
"connection",
|
||||
"ctcp",
|
||||
"error",
|
||||
"invite",
|
||||
@ -25,7 +23,6 @@ var events = [
|
||||
"link",
|
||||
"names",
|
||||
"nick",
|
||||
"notice",
|
||||
"part",
|
||||
"quit",
|
||||
"topic",
|
||||
@ -33,7 +30,7 @@ var events = [
|
||||
"whois"
|
||||
];
|
||||
var inputs = [
|
||||
// These inputs are sorted in order that is most likely to be used
|
||||
"ctcp",
|
||||
"msg",
|
||||
"part",
|
||||
"action",
|
||||
@ -50,7 +47,7 @@ var inputs = [
|
||||
var path = "./plugins/inputs/" + name;
|
||||
var plugin = require(path);
|
||||
plugin.commands.forEach(function(command) {
|
||||
plugins[command] = plugin.input;
|
||||
plugins[command] = plugin;
|
||||
});
|
||||
return plugins;
|
||||
}, {});
|
||||
@ -129,106 +126,68 @@ Client.prototype.connect = function(args) {
|
||||
var config = Helper.getConfig();
|
||||
var client = this;
|
||||
|
||||
if (config.lockNetwork) {
|
||||
// This check is needed to prevent invalid user configurations
|
||||
if (args.host && args.host.length > 0 && args.host !== config.defaults.host) {
|
||||
var invalidHostnameMsg = new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "Hostname you specified is not allowed."
|
||||
});
|
||||
client.emit("msg", {
|
||||
msg: invalidHostnameMsg
|
||||
});
|
||||
return;
|
||||
}
|
||||
var nick = args.nick || "lounge-user";
|
||||
|
||||
args.host = config.defaults.host;
|
||||
args.port = config.defaults.port;
|
||||
args.tls = config.defaults.tls;
|
||||
}
|
||||
|
||||
var server = {
|
||||
var network = new Network({
|
||||
name: args.name || "",
|
||||
host: args.host || "",
|
||||
port: parseInt(args.port, 10) || (args.tls ? 6697 : 6667),
|
||||
rejectUnauthorized: false
|
||||
};
|
||||
|
||||
if (server.host.length === 0) {
|
||||
var emptyHostnameMsg = new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "You must specify a hostname to connect."
|
||||
});
|
||||
client.emit("msg", {
|
||||
msg: emptyHostnameMsg
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.bind) {
|
||||
server.localAddress = config.bind;
|
||||
if (args.tls) {
|
||||
var socket = net.connect(server);
|
||||
server.socket = socket;
|
||||
}
|
||||
}
|
||||
|
||||
var stream = args.tls ? tls.connect(server) : net.connect(server);
|
||||
|
||||
stream.on("error", function(e) {
|
||||
console.log("Client#connect():\n" + e);
|
||||
stream.end();
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "Connection error."
|
||||
});
|
||||
client.emit("msg", {
|
||||
msg: msg
|
||||
});
|
||||
});
|
||||
|
||||
var nick = args.nick || "lounge-user";
|
||||
var username = args.username || nick.replace(/[^a-zA-Z0-9]/g, "");
|
||||
var realname = args.realname || "The Lounge User";
|
||||
|
||||
var irc = slate(stream);
|
||||
identd.hook(stream, username);
|
||||
|
||||
if (args.password) {
|
||||
irc.pass(args.password);
|
||||
}
|
||||
|
||||
irc.me = nick;
|
||||
irc.nick(nick);
|
||||
irc.user(username, realname);
|
||||
|
||||
var network = new Network({
|
||||
name: server.name,
|
||||
host: server.host,
|
||||
port: server.port,
|
||||
tls: !!args.tls,
|
||||
password: args.password,
|
||||
username: username,
|
||||
realname: realname,
|
||||
username: args.username || nick.replace(/[^a-zA-Z0-9]/g, ""),
|
||||
realname: args.realname || "The Lounge User",
|
||||
commands: args.commands
|
||||
});
|
||||
|
||||
network.irc = irc;
|
||||
|
||||
client.networks.push(network);
|
||||
client.emit("network", {
|
||||
network: network
|
||||
});
|
||||
|
||||
events.forEach(function(plugin) {
|
||||
var path = "./plugins/irc-events/" + plugin;
|
||||
require(path).apply(client, [
|
||||
irc,
|
||||
network
|
||||
]);
|
||||
if (config.lockNetwork) {
|
||||
// This check is needed to prevent invalid user configurations
|
||||
if (args.host && args.host.length > 0 && args.host !== config.defaults.host) {
|
||||
client.emit("msg", {
|
||||
chan: network.channels[0].id,
|
||||
msg: new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "Hostname you specified is not allowed."
|
||||
})
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
network.host = config.defaults.host;
|
||||
network.port = config.defaults.port;
|
||||
network.tls = config.defaults.tls;
|
||||
}
|
||||
|
||||
if (network.host.length === 0) {
|
||||
client.emit("msg", {
|
||||
chan: network.channels[0].id,
|
||||
msg: new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "You must specify a hostname to connect."
|
||||
})
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
network.irc = new ircFramework.Client();
|
||||
network.irc.connect({
|
||||
host: network.host,
|
||||
port: network.port,
|
||||
nick: nick,
|
||||
username: network.username,
|
||||
gecos: network.realname,
|
||||
password: network.password,
|
||||
tls: network.tls,
|
||||
localAddress: config.bind,
|
||||
rejectUnauthorized: false,
|
||||
auto_reconnect: false, // TODO: Enable auto reconnection
|
||||
});
|
||||
|
||||
irc.once("welcome", function() {
|
||||
network.irc.on("registered", function() {
|
||||
var delay = 1000;
|
||||
var commands = args.commands;
|
||||
if (Array.isArray(commands)) {
|
||||
@ -242,18 +201,23 @@ Client.prototype.connect = function(args) {
|
||||
delay += 1000;
|
||||
});
|
||||
}
|
||||
setTimeout(function() {
|
||||
irc.write("PING " + network.host);
|
||||
}, delay);
|
||||
});
|
||||
|
||||
irc.once("pong", function() {
|
||||
var join = (args.join || "");
|
||||
if (join) {
|
||||
join = join.replace(/\,/g, " ").split(/\s+/g);
|
||||
irc.join(join);
|
||||
setTimeout(function() {
|
||||
join = join.split(/\s+/);
|
||||
network.irc.join(join[0], join[1]);
|
||||
}, delay);
|
||||
}
|
||||
});
|
||||
|
||||
events.forEach(function(plugin) {
|
||||
var path = "./plugins/irc-events/" + plugin;
|
||||
require(path).apply(client, [
|
||||
network.irc,
|
||||
network
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
Client.prototype.setPassword = function(hash) {
|
||||
@ -286,10 +250,27 @@ Client.prototype.input = function(data) {
|
||||
var args = text.split(" ");
|
||||
var cmd = args.shift().toLowerCase();
|
||||
|
||||
var irc = target.network.irc;
|
||||
var connected = irc && irc.connection && irc.connection.connected;
|
||||
|
||||
if (cmd in inputs) {
|
||||
inputs[cmd].apply(client, [target.network, target.chan, cmd, args]);
|
||||
} else {
|
||||
target.network.irc.write(text);
|
||||
var plugin = inputs[cmd];
|
||||
if (connected || plugin.allowDisconnected) {
|
||||
connected = true;
|
||||
plugin.input.apply(client, [target.network, target.chan, cmd, args]);
|
||||
}
|
||||
} else if (connected) {
|
||||
irc.raw(text);
|
||||
}
|
||||
|
||||
if (!connected) {
|
||||
this.emit("msg", {
|
||||
chan: target.chan.id,
|
||||
msg: new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "You are not connected to the IRC network, unable to send your command."
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -375,11 +356,8 @@ Client.prototype.quit = function() {
|
||||
}
|
||||
}
|
||||
this.networks.forEach(function(network) {
|
||||
var irc = network.irc;
|
||||
if (network.connected) {
|
||||
irc.quit();
|
||||
} else {
|
||||
irc.stream.end();
|
||||
if (network.irc) {
|
||||
network.irc.quit("Page closed");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -23,18 +23,21 @@ function Chan(attr) {
|
||||
}, attr));
|
||||
}
|
||||
|
||||
Chan.prototype.sortUsers = function() {
|
||||
this.users = _.sortBy(
|
||||
this.users,
|
||||
function(u) { return u.name.toLowerCase(); }
|
||||
);
|
||||
Chan.prototype.sortUsers = function(irc) {
|
||||
var userModeSortPriority = {};
|
||||
irc.network.options.PREFIX.forEach(function(prefix, index) {
|
||||
userModeSortPriority[prefix.symbol] = index;
|
||||
});
|
||||
|
||||
["+", "%", "@", "&", "~"].forEach(function(mode) {
|
||||
this.users = _.remove(
|
||||
this.users,
|
||||
function(u) { return u.mode === mode; }
|
||||
).concat(this.users);
|
||||
}, this);
|
||||
userModeSortPriority[""] = 99; // No mode is lowest
|
||||
|
||||
this.users = this.users.sort(function(a, b) {
|
||||
if (a.mode === b.mode) {
|
||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||
}
|
||||
|
||||
return userModeSortPriority[a.mode] - userModeSortPriority[b.mode];
|
||||
});
|
||||
};
|
||||
|
||||
Chan.prototype.getMode = function(name) {
|
||||
|
@ -14,7 +14,9 @@ Msg.Type = {
|
||||
PART: "part",
|
||||
QUIT: "quit",
|
||||
TOGGLE: "toggle",
|
||||
CTCP: "ctcp",
|
||||
TOPIC: "topic",
|
||||
TOPIC_SET_BY: "topic_set_by",
|
||||
WHOIS: "whois"
|
||||
};
|
||||
|
||||
@ -27,8 +29,13 @@ function Msg(attr) {
|
||||
from: "",
|
||||
id: id++,
|
||||
text: "",
|
||||
time: new Date(),
|
||||
type: Msg.Type.MESSAGE,
|
||||
self: false
|
||||
}, attr));
|
||||
|
||||
if (this.time > 0) {
|
||||
this.time = new Date(this.time);
|
||||
} else {
|
||||
this.time = new Date();
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,11 @@ function Network(attr) {
|
||||
username: "",
|
||||
realname: "",
|
||||
channels: [],
|
||||
connected: false,
|
||||
id: id++,
|
||||
irc: null,
|
||||
serverOptions: {
|
||||
PREFIX: [],
|
||||
},
|
||||
}, attr));
|
||||
this.name = attr.name || prettify(attr.host);
|
||||
this.channels.unshift(
|
||||
@ -30,7 +32,7 @@ function Network(attr) {
|
||||
}
|
||||
|
||||
Network.prototype.toJSON = function() {
|
||||
var json = _.extend(this, {nick: (this.irc || {}).me || ""});
|
||||
var json = _.extend(this, {nick: (this.irc && this.irc.user.nick) || ""});
|
||||
return _.omit(json, "irc", "password");
|
||||
};
|
||||
|
||||
@ -45,7 +47,7 @@ Network.prototype.export = function() {
|
||||
"realname",
|
||||
"commands"
|
||||
]);
|
||||
network.nick = (this.irc || {}).me;
|
||||
network.nick = (this.irc && this.irc.user.nick) || "";
|
||||
network.join = _.map(
|
||||
_.filter(this.channels, {type: "channel"}),
|
||||
"name"
|
||||
@ -53,6 +55,14 @@ Network.prototype.export = function() {
|
||||
return network;
|
||||
};
|
||||
|
||||
Network.prototype.getChannel = function(name) {
|
||||
name = name.toLowerCase();
|
||||
|
||||
return _.find(this.channels, function(that) {
|
||||
return that.name.toLowerCase() === name;
|
||||
});
|
||||
};
|
||||
|
||||
function prettify(host) {
|
||||
var name = capitalize(host.split(".")[1]);
|
||||
if (!name) {
|
||||
|
@ -3,6 +3,10 @@ var _ = require("lodash");
|
||||
module.exports = User;
|
||||
|
||||
function User(attr) {
|
||||
// TODO: Remove this
|
||||
attr.name = attr.name || attr.nick;
|
||||
attr.mode = attr.mode || (attr.modes && attr.modes[0]) || "";
|
||||
|
||||
_.merge(this, _.extend({
|
||||
mode: "",
|
||||
name: ""
|
||||
|
@ -2,25 +2,24 @@ exports.commands = ["slap", "me"];
|
||||
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
var irc = network.irc;
|
||||
var text;
|
||||
|
||||
switch (cmd) {
|
||||
case "slap":
|
||||
var slap = "slaps " + args[0] + " around a bit with a large trout";
|
||||
text = "slaps " + args[0] + " around a bit with a large trout";
|
||||
/* fall through */
|
||||
case "me":
|
||||
if (args.length === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
var text = slap || args.join(" ");
|
||||
irc.action(
|
||||
chan.name,
|
||||
text
|
||||
);
|
||||
irc.emit("message", {
|
||||
from: irc.me,
|
||||
to: chan.name,
|
||||
message: "\u0001ACTION " + text
|
||||
text = text || args.join(" ");
|
||||
|
||||
irc.say(chan.name, "\u0001ACTION " + text + "\u0001");
|
||||
irc.emit("action", {
|
||||
nick: irc.user.nick,
|
||||
target: chan.name,
|
||||
message: text
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
exports.commands = ["connect", "server"];
|
||||
exports.allowDisconnected = true;
|
||||
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
if (args.length === 0) {
|
||||
|
8
src/plugins/inputs/ctcp.js
Normal file
8
src/plugins/inputs/ctcp.js
Normal file
@ -0,0 +1,8 @@
|
||||
exports.commands = ["ctcp"];
|
||||
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
if (args.length > 1) {
|
||||
var irc = network.irc;
|
||||
irc.ctcpRequest(args[0], args.slice(1).join(" "));
|
||||
}
|
||||
};
|
@ -4,9 +4,9 @@ exports.input = function(network, chan, cmd, args) {
|
||||
var irc = network.irc;
|
||||
|
||||
if (args.length === 2) {
|
||||
irc.invite(args[0], args[1]); // Channel provided in the command
|
||||
irc.raw("INVITE", args[0], args[1]); // Channel provided in the command
|
||||
} else if (args.length === 1 && chan.type === "channel") {
|
||||
irc.invite(args[0], chan.name); // Current channel
|
||||
irc.raw("INVITE", args[0], chan.name); // Current channel
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -3,7 +3,7 @@ exports.commands = ["kick"];
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
if (args.length !== 0) {
|
||||
var irc = network.irc;
|
||||
irc.kick(chan.name, args[0]);
|
||||
irc.raw("KICK", chan.name, args[0], args.slice(1).join(" "));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -21,12 +21,9 @@ exports.input = function(network, chan, cmd, args) {
|
||||
mode = args[0];
|
||||
user = args[1];
|
||||
}
|
||||
|
||||
var irc = network.irc;
|
||||
irc.mode(
|
||||
chan.name,
|
||||
mode,
|
||||
user
|
||||
);
|
||||
irc.raw("MODE", chan.name, mode, user);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
@ -1,11 +1,10 @@
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.commands = ["msg", "say"];
|
||||
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
if (args.length === 0 || args[0] === "") {
|
||||
return true;
|
||||
}
|
||||
|
||||
var irc = network.irc;
|
||||
var target = "";
|
||||
if (cmd === "msg") {
|
||||
@ -16,13 +15,15 @@ exports.input = function(network, chan, cmd, args) {
|
||||
} else {
|
||||
target = chan.name;
|
||||
}
|
||||
|
||||
var msg = args.join(" ");
|
||||
irc.send(target, msg);
|
||||
var channel = _.find(network.channels, {name: target});
|
||||
irc.say(target, msg);
|
||||
|
||||
var channel = network.getChannel(target);
|
||||
if (typeof channel !== "undefined") {
|
||||
irc.emit("message", {
|
||||
from: irc.me,
|
||||
to: channel.name,
|
||||
irc.emit("privmsg", {
|
||||
nick: irc.user.nick,
|
||||
target: channel.name,
|
||||
message: msg
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
var _ = require("lodash");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
exports.commands = ["notice"];
|
||||
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
@ -12,22 +9,16 @@ exports.input = function(network, chan, cmd, args) {
|
||||
var irc = network.irc;
|
||||
irc.notice(args[0], message);
|
||||
|
||||
var targetChan = _.find(network.channels, {name: args[0]});
|
||||
var targetChan = network.getChannel(args[0]);
|
||||
if (typeof targetChan === "undefined") {
|
||||
message = "{to " + args[0] + "} " + message;
|
||||
targetChan = chan;
|
||||
}
|
||||
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.NOTICE,
|
||||
mode: targetChan.getMode(irc.me),
|
||||
from: irc.me,
|
||||
text: message
|
||||
});
|
||||
targetChan.messages.push(msg);
|
||||
this.emit("msg", {
|
||||
chan: targetChan.id,
|
||||
msg: msg
|
||||
irc.emit("notice", {
|
||||
nick: irc.user.nick,
|
||||
target: targetChan.name,
|
||||
message: message
|
||||
});
|
||||
|
||||
return true;
|
||||
|
@ -2,6 +2,7 @@ var _ = require("lodash");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
exports.commands = ["close", "leave", "part"];
|
||||
exports.allowDisconnected = true;
|
||||
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
if (chan.type === "lobby") {
|
||||
@ -15,8 +16,8 @@ exports.input = function(network, chan, cmd, args) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (chan.type === "channel") {
|
||||
var irc = network.irc;
|
||||
var irc = network.irc;
|
||||
if (irc && chan.type === "channel") {
|
||||
irc.part(chan.name, args.join(" "));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
var _ = require("lodash");
|
||||
var Chan = require("../../models/chan");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
exports.commands = ["query"];
|
||||
|
||||
@ -14,11 +15,31 @@ exports.input = function(network, chan, cmd, args) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If target doesn't start with an allowed character, ignore
|
||||
if (!/^[a-zA-Z_\\\[\]{}^`|]/.test(target)) {
|
||||
var char = target[0];
|
||||
if (network.irc.network.options.CHANTYPES && network.irc.network.options.CHANTYPES.indexOf(char) !== -1) {
|
||||
this.emit("msg", {
|
||||
chan: chan.id,
|
||||
msg: new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "You can not open query windows for channels, use /join instead."
|
||||
})
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < network.irc.network.options.PREFIX.length; i++) {
|
||||
if (network.irc.network.options.PREFIX[i].symbol === char) {
|
||||
this.emit("msg", {
|
||||
chan: chan.id,
|
||||
msg: new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "You can not open query windows for names starting with a user prefix."
|
||||
})
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var newChan = new Chan({
|
||||
type: Chan.Type.QUERY,
|
||||
name: target
|
||||
|
@ -1,6 +1,7 @@
|
||||
var _ = require("lodash");
|
||||
|
||||
exports.commands = ["quit", "disconnect"];
|
||||
exports.allowDisconnected = true;
|
||||
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
var client = this;
|
||||
@ -13,7 +14,9 @@ exports.input = function(network, chan, cmd, args) {
|
||||
network: network.id
|
||||
});
|
||||
|
||||
irc.quit(quitMessage);
|
||||
if (irc) {
|
||||
irc.quit(quitMessage);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ exports.commands = ["raw", "send", "quote"];
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
if (args.length !== 0) {
|
||||
var irc = network.irc;
|
||||
irc.write(args.join(" "));
|
||||
irc.raw(args);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1,12 +1,8 @@
|
||||
exports.commands = ["topic"];
|
||||
|
||||
exports.input = function(network, chan, cmd, args) {
|
||||
var msg = "TOPIC";
|
||||
msg += " " + chan.name;
|
||||
msg += args[0] ? (" :" + args.join(" ")) : "";
|
||||
|
||||
var irc = network.irc;
|
||||
irc.write(msg);
|
||||
irc.raw("TOPIC", chan.name, args.join(" "));
|
||||
|
||||
return true;
|
||||
};
|
||||
|
75
src/plugins/irc-events/connection.js
Normal file
75
src/plugins/irc-events/connection.js
Normal file
@ -0,0 +1,75 @@
|
||||
var _ = require("lodash");
|
||||
var identd = require("../../identd");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
|
||||
client.emit("msg", {
|
||||
chan: network.channels[0].id,
|
||||
msg: new Msg({
|
||||
text: "Network created, connecting to " + network.host + ":" + network.port + "..."
|
||||
})
|
||||
});
|
||||
|
||||
irc.on("raw socket connected", function() {
|
||||
identd.hook(irc.connection.socket, network.username);
|
||||
});
|
||||
|
||||
irc.on("socket connected", function() {
|
||||
client.emit("msg", {
|
||||
chan: network.channels[0].id,
|
||||
msg: new Msg({
|
||||
text: "Connected to the network."
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
irc.on("socket close", function() {
|
||||
client.emit("msg", {
|
||||
chan: network.channels[0].id,
|
||||
msg: new Msg({
|
||||
text: "Disconnected from the network."
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
irc.on("socket error", function(err) {
|
||||
console.log(err);
|
||||
client.emit("msg", {
|
||||
chan: network.channels[0].id,
|
||||
msg: new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "Socket error: " + err
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
irc.on("reconnecting", function() {
|
||||
client.emit("msg", {
|
||||
chan: network.channels[0].id,
|
||||
msg: new Msg({
|
||||
text: "Reconnecting..."
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
irc.on("server options", function(data) {
|
||||
if (network.serverOptions.PREFIX === data.options.PREFIX) {
|
||||
return;
|
||||
}
|
||||
|
||||
network.prefixLookup = {};
|
||||
|
||||
_.each(data.options.PREFIX, function(mode) {
|
||||
network.prefixLookup[mode.mode] = mode.symbol;
|
||||
});
|
||||
|
||||
network.serverOptions.PREFIX = data.options.PREFIX;
|
||||
|
||||
client.emit("network_changed", {
|
||||
network: network.id,
|
||||
serverOptions: network.serverOptions
|
||||
});
|
||||
});
|
||||
};
|
@ -1,22 +1,38 @@
|
||||
var pkg = require(process.cwd() + "/package.json");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc/* , network */) {
|
||||
irc.on("message", function(data) {
|
||||
if (data.message.indexOf("\001") !== 0) {
|
||||
return;
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
|
||||
irc.on("ctcp response", function(data) {
|
||||
var chan = network.getChannel(data.nick);
|
||||
if (typeof chan === "undefined") {
|
||||
chan = network.channels[0];
|
||||
}
|
||||
var msg = data.message.replace(/\001/g, "");
|
||||
var split = msg.split(" ");
|
||||
switch (split[0]) {
|
||||
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.CTCP,
|
||||
time: data.time,
|
||||
from: data.nick,
|
||||
ctcpType: data.type,
|
||||
ctcpMessage: data.message
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
chan: chan.id,
|
||||
msg: msg
|
||||
});
|
||||
});
|
||||
|
||||
irc.on("ctcp request", function(data) {
|
||||
switch (data.type) {
|
||||
case "VERSION":
|
||||
irc.ctcp(
|
||||
data.from,
|
||||
"VERSION " + pkg.name + " " + pkg.version
|
||||
);
|
||||
irc.ctcpResponse(data.nick, "VERSION", pkg.name + " " + pkg.version);
|
||||
break;
|
||||
case "PING":
|
||||
var split = data.message.split(" ");
|
||||
if (split.length === 2) {
|
||||
irc.ctcp(data.from, "PING " + split[1]);
|
||||
irc.ctcpResponse(data.nick, "PING", split[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2,21 +2,61 @@ var Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("errors", function(data) {
|
||||
|
||||
// TODO: remove later
|
||||
irc.on("irc_error", function(data) {
|
||||
console.log("Got an irc_error");
|
||||
irc.emit("error", data);
|
||||
});
|
||||
|
||||
irc.on("error", function(data) {
|
||||
console.log("error", data);
|
||||
var text = data.error;
|
||||
if (data.reason) {
|
||||
text = data.reason + " (" + text + ")";
|
||||
}
|
||||
var lobby = network.channels[0];
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: data.message,
|
||||
text: text,
|
||||
});
|
||||
client.emit("msg", {
|
||||
chan: lobby.id,
|
||||
msg: msg
|
||||
});
|
||||
if (!network.connected) {
|
||||
if (data.cmd === "ERR_NICKNAMEINUSE") {
|
||||
var random = irc.me + Math.floor(10 + (Math.random() * 89));
|
||||
irc.nick(random);
|
||||
}
|
||||
});
|
||||
|
||||
irc.on("nick in use", function(data) {
|
||||
var lobby = network.channels[0];
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: data.nick + ": " + (data.reason || "Nickname is already in use."),
|
||||
});
|
||||
client.emit("msg", {
|
||||
chan: lobby.id,
|
||||
msg: msg
|
||||
});
|
||||
|
||||
if (irc.connection.registered === false) {
|
||||
var random = (data.nick || irc.user.nick) + Math.floor(10 + (Math.random() * 89));
|
||||
irc.changeNick(random);
|
||||
}
|
||||
});
|
||||
|
||||
irc.on("nick invalid", function(data) {
|
||||
var lobby = network.channels[0];
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: data.nick + ": " + (data.reason || "Nickname is invalid."),
|
||||
});
|
||||
client.emit("msg", {
|
||||
chan: lobby.id,
|
||||
msg: msg
|
||||
});
|
||||
|
||||
if (irc.connection.registered === false) {
|
||||
var random = "i" + Math.random().toString(36).substr(2, 10); // 'i' so it never begins with a number
|
||||
irc.changeNick(random);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -1,22 +1,20 @@
|
||||
var _ = require("lodash");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("invite", function(data) {
|
||||
var target = data.to;
|
||||
|
||||
var chan = _.find(network.channels, {name: data.channel});
|
||||
var chan = network.getChannel(data.channel);
|
||||
if (typeof chan === "undefined") {
|
||||
chan = network.channels[0];
|
||||
}
|
||||
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.INVITE,
|
||||
from: data.from,
|
||||
target: target,
|
||||
text: data.channel,
|
||||
invitedYou: target.toLowerCase() === irc.me.toLowerCase()
|
||||
time: data.time,
|
||||
from: data.nick,
|
||||
invited: data.invited,
|
||||
channel: data.channel,
|
||||
invitedYou: data.invited === irc.user.nick
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
|
@ -1,4 +1,3 @@
|
||||
var _ = require("lodash");
|
||||
var Chan = require("../../models/chan");
|
||||
var Msg = require("../../models/msg");
|
||||
var User = require("../../models/user");
|
||||
@ -6,7 +5,7 @@ var User = require("../../models/user");
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("join", function(data) {
|
||||
var chan = _.find(network.channels, {name: data.channel});
|
||||
var chan = network.getChannel(data.channel);
|
||||
if (typeof chan === "undefined") {
|
||||
chan = new Chan({
|
||||
name: data.channel
|
||||
@ -18,20 +17,17 @@ module.exports = function(irc, network) {
|
||||
chan: chan
|
||||
});
|
||||
}
|
||||
chan.users.push(new User({name: data.nick}));
|
||||
chan.sortUsers();
|
||||
chan.users.push(new User({nick: data.nick, modes: ""}));
|
||||
chan.sortUsers(irc);
|
||||
client.emit("users", {
|
||||
chan: chan.id
|
||||
});
|
||||
var self = false;
|
||||
if (data.nick.toLowerCase() === irc.me.toLowerCase()) {
|
||||
self = true;
|
||||
}
|
||||
var msg = new Msg({
|
||||
time: data.time,
|
||||
from: data.nick,
|
||||
hostmask: data.hostmask.username + "@" + data.hostmask.hostname,
|
||||
hostmask: data.ident + "@" + data.hostname,
|
||||
type: Msg.Type.JOIN,
|
||||
self: self
|
||||
self: data.nick === irc.user.nick
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
|
@ -4,35 +4,30 @@ var Msg = require("../../models/msg");
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("kick", function(data) {
|
||||
var from = data.nick;
|
||||
var chan = _.find(network.channels, {name: data.channel});
|
||||
var mode = chan.getMode(from);
|
||||
|
||||
var chan = network.getChannel(data.channel);
|
||||
if (typeof chan === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.client === irc.me) {
|
||||
if (data.kicked === irc.user.nick) {
|
||||
chan.users = [];
|
||||
} else {
|
||||
chan.users = _.without(chan.users, _.find(chan.users, {name: data.client}));
|
||||
chan.users = _.without(chan.users, _.find(chan.users, {name: data.kicked}));
|
||||
}
|
||||
|
||||
client.emit("users", {
|
||||
chan: chan.id
|
||||
});
|
||||
|
||||
var self = false;
|
||||
if (data.nick.toLowerCase() === irc.me.toLowerCase()) {
|
||||
self = true;
|
||||
}
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.KICK,
|
||||
mode: mode,
|
||||
from: from,
|
||||
target: data.client,
|
||||
time: data.time,
|
||||
mode: chan.getMode(data.nick),
|
||||
from: data.nick,
|
||||
target: data.kicked,
|
||||
text: data.message || "",
|
||||
self: self
|
||||
highlight: data.kicked === irc.user.nick,
|
||||
self: data.nick === irc.user.nick
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
|
@ -9,7 +9,7 @@ process.setMaxListeners(0);
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("message", function(data) {
|
||||
irc.on("privmsg", function(data) {
|
||||
var config = Helper.getConfig();
|
||||
if (!config.prefetch) {
|
||||
return;
|
||||
@ -27,15 +27,13 @@ module.exports = function(irc, network) {
|
||||
return;
|
||||
}
|
||||
|
||||
var self = data.to.toLowerCase() === irc.me.toLowerCase();
|
||||
var chan = _.find(network.channels, {name: self ? data.from : data.to});
|
||||
var chan = network.getChannel(data.target);
|
||||
if (typeof chan === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.TOGGLE,
|
||||
time: ""
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
|
@ -1,4 +1,3 @@
|
||||
var _ = require("lodash");
|
||||
var Chan = require("../../models/chan");
|
||||
var Msg = require("../../models/msg");
|
||||
var Helper = require("../../helper");
|
||||
@ -7,44 +6,64 @@ module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
var config = Helper.getConfig();
|
||||
|
||||
irc.on("message", function(data) {
|
||||
if (data.message.indexOf("\u0001") === 0 && data.message.substring(0, 7) !== "\u0001ACTION") {
|
||||
// Hide ctcp messages.
|
||||
return;
|
||||
irc.on("notice", function(data) {
|
||||
// Some servers send notices without any nickname
|
||||
if (!data.nick) {
|
||||
data.from_server = true;
|
||||
data.nick = network.host;
|
||||
}
|
||||
|
||||
var target = data.to;
|
||||
if (target.toLowerCase() === irc.me.toLowerCase()) {
|
||||
target = data.from;
|
||||
data.type = Msg.Type.NOTICE;
|
||||
handleMessage(data);
|
||||
});
|
||||
|
||||
irc.on("action", function(data) {
|
||||
data.type = Msg.Type.ACTION;
|
||||
handleMessage(data);
|
||||
});
|
||||
|
||||
irc.on("privmsg", function(data) {
|
||||
data.type = Msg.Type.MESSAGE;
|
||||
handleMessage(data);
|
||||
});
|
||||
|
||||
function handleMessage(data) {
|
||||
// Server messages go to server window, no questions asked
|
||||
if (data.from_server) {
|
||||
chan = network.channels[0];
|
||||
} else {
|
||||
var target = data.target;
|
||||
|
||||
// If the message is targeted at us, use sender as target instead
|
||||
if (target.toLowerCase() === irc.user.nick.toLowerCase()) {
|
||||
target = data.nick;
|
||||
}
|
||||
|
||||
var chan = network.getChannel(target);
|
||||
if (typeof chan === "undefined") {
|
||||
// Send notices that are not targeted at us into the server window
|
||||
if (data.type === Msg.Type.NOTICE) {
|
||||
chan = network.channels[0];
|
||||
} else {
|
||||
chan = new Chan({
|
||||
type: Chan.Type.QUERY,
|
||||
name: target
|
||||
});
|
||||
network.channels.push(chan);
|
||||
client.emit("join", {
|
||||
network: network.id,
|
||||
chan: chan
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var chan = _.find(network.channels, {name: target});
|
||||
if (typeof chan === "undefined") {
|
||||
chan = new Chan({
|
||||
type: Chan.Type.QUERY,
|
||||
name: data.from
|
||||
});
|
||||
network.channels.push(chan);
|
||||
client.emit("join", {
|
||||
network: network.id,
|
||||
chan: chan
|
||||
});
|
||||
}
|
||||
|
||||
var type = Msg.Type.MESSAGE;
|
||||
var text = data.message;
|
||||
var textSplit = text.split(" ");
|
||||
if (textSplit[0] === "\u0001ACTION") {
|
||||
type = Msg.Type.ACTION;
|
||||
text = text.replace(/^\u0001ACTION|\u0001$/g, "");
|
||||
}
|
||||
|
||||
var self = (data.from.toLowerCase() === irc.me.toLowerCase());
|
||||
var self = data.nick === irc.user.nick;
|
||||
|
||||
// Self messages are never highlighted
|
||||
// Non-self messages are highlighted as soon as the nick is detected
|
||||
var highlight = !self && textSplit.some(function(w) {
|
||||
return (w.replace(/^@/, "").toLowerCase().indexOf(irc.me.toLowerCase()) === 0);
|
||||
var highlight = !self && data.message.split(" ").some(function(w) {
|
||||
return (w.replace(/^@/, "").toLowerCase().indexOf(irc.user.nick.toLowerCase()) === 0);
|
||||
});
|
||||
|
||||
if (chan.id !== client.activeChannel) {
|
||||
@ -55,12 +74,12 @@ module.exports = function(irc, network) {
|
||||
}
|
||||
}
|
||||
|
||||
var name = data.from;
|
||||
var msg = new Msg({
|
||||
type: type,
|
||||
mode: chan.getMode(name),
|
||||
from: name,
|
||||
text: text,
|
||||
type: data.type,
|
||||
time: data.time,
|
||||
mode: chan.getMode(data.nick),
|
||||
from: data.nick,
|
||||
text: data.message,
|
||||
self: self,
|
||||
highlight: highlight
|
||||
});
|
||||
@ -74,5 +93,5 @@ module.exports = function(irc, network) {
|
||||
chan: chan.id,
|
||||
msg: msg
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,34 +1,53 @@
|
||||
var _ = require("lodash");
|
||||
var Chan = require("../../models/chan");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("mode", function(data) {
|
||||
var chan = _.find(network.channels, {name: data.target});
|
||||
if (typeof chan !== "undefined") {
|
||||
setTimeout(function() {
|
||||
irc.write("NAMES " + data.target);
|
||||
}, 200);
|
||||
var from = data.nick;
|
||||
if (from.indexOf(".") !== -1) {
|
||||
from = data.target;
|
||||
var targetChan;
|
||||
|
||||
if (data.target === irc.user.nick) {
|
||||
targetChan = network.channels[0];
|
||||
} else {
|
||||
targetChan = network.getChannel(data.target);
|
||||
if (typeof targetChan === "undefined") {
|
||||
return;
|
||||
}
|
||||
var self = false;
|
||||
if (from.toLowerCase() === irc.me.toLowerCase()) {
|
||||
self = true;
|
||||
}
|
||||
|
||||
var usersUpdated;
|
||||
|
||||
for (var i = 0; i < data.modes.length; i++) {
|
||||
var mode = data.modes[i];
|
||||
var text = mode.mode;
|
||||
if (mode.param) {
|
||||
text += " " + mode.param;
|
||||
|
||||
var user = _.find(targetChan.users, {name: mode.param});
|
||||
if (typeof user !== "undefined") {
|
||||
usersUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
var msg = new Msg({
|
||||
time: data.time,
|
||||
type: Msg.Type.MODE,
|
||||
mode: chan.getMode(from),
|
||||
from: from,
|
||||
text: data.mode + " " + (data.client || ""),
|
||||
self: self
|
||||
mode: (targetChan.type !== Chan.Type.LOBBY && targetChan.getMode(data.nick)) || "",
|
||||
from: data.nick,
|
||||
text: text,
|
||||
self: data.nick === irc.user.nick
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
targetChan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
chan: chan.id,
|
||||
chan: targetChan.id,
|
||||
msg: msg,
|
||||
});
|
||||
}
|
||||
|
||||
if (usersUpdated) {
|
||||
// TODO: This is horrible
|
||||
irc.raw("NAMES", data.target);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -4,16 +4,31 @@ module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("motd", function(data) {
|
||||
var lobby = network.channels[0];
|
||||
data.motd.forEach(function(text) {
|
||||
|
||||
if (data.motd) {
|
||||
data.motd.split("\n").forEach(function(text) {
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.MOTD,
|
||||
text: text
|
||||
});
|
||||
lobby.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
chan: lobby.id,
|
||||
msg: msg
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (data.error) {
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.MOTD,
|
||||
text: text
|
||||
text: data.error
|
||||
});
|
||||
lobby.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
chan: lobby.id,
|
||||
msg: msg
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -3,16 +3,23 @@ var User = require("../../models/user");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("names", function(data) {
|
||||
var chan = _.find(network.channels, {name: data.channel});
|
||||
irc.on("userlist", function(data) {
|
||||
var chan = network.getChannel(data.channel);
|
||||
if (typeof chan === "undefined") {
|
||||
return;
|
||||
}
|
||||
chan.users = [];
|
||||
_.each(data.names, function(u) {
|
||||
chan.users.push(new User(u));
|
||||
_.each(data.users, function(u) {
|
||||
var user = new User(u);
|
||||
|
||||
// irc-framework sets characater mode, but lounge works with symbols
|
||||
if (user.mode) {
|
||||
user.mode = network.prefixLookup[user.mode];
|
||||
}
|
||||
|
||||
chan.users.push(user);
|
||||
});
|
||||
chan.sortUsers();
|
||||
chan.sortUsers(irc);
|
||||
client.emit("users", {
|
||||
chan: chan.id
|
||||
});
|
||||
|
@ -5,11 +5,10 @@ module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("nick", function(data) {
|
||||
var self = false;
|
||||
var nick = data["new"];
|
||||
if (nick === irc.me) {
|
||||
if (data.nick === irc.user.nick) {
|
||||
var lobby = network.channels[0];
|
||||
var msg = new Msg({
|
||||
text: "You're now known as " + nick,
|
||||
text: "You're now known as " + data.new_nick,
|
||||
});
|
||||
lobby.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
@ -20,23 +19,26 @@ module.exports = function(irc, network) {
|
||||
client.save();
|
||||
client.emit("nick", {
|
||||
network: network.id,
|
||||
nick: nick
|
||||
nick: data.new_nick
|
||||
});
|
||||
}
|
||||
|
||||
network.channels.forEach(function(chan) {
|
||||
var user = _.find(chan.users, {name: data.nick});
|
||||
if (typeof user === "undefined") {
|
||||
return;
|
||||
}
|
||||
user.name = nick;
|
||||
chan.sortUsers();
|
||||
user.name = data.new_nick;
|
||||
chan.sortUsers(irc);
|
||||
client.emit("users", {
|
||||
chan: chan.id
|
||||
});
|
||||
var msg = new Msg({
|
||||
time: data.time,
|
||||
type: Msg.Type.NICK,
|
||||
from: data.nick,
|
||||
text: nick,
|
||||
mode: chan.getMode(data.new_nick),
|
||||
nick: data.nick,
|
||||
new_nick: data.new_nick,
|
||||
self: self
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
|
@ -1,33 +0,0 @@
|
||||
var _ = require("lodash");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("notice", function(data) {
|
||||
var target = data.to;
|
||||
if (target.toLowerCase() === irc.me.toLowerCase()) {
|
||||
target = data.from;
|
||||
}
|
||||
|
||||
var chan = _.find(network.channels, {name: target});
|
||||
if (typeof chan === "undefined") {
|
||||
chan = network.channels[0];
|
||||
}
|
||||
|
||||
var from = data.from || "";
|
||||
if (data.to === "*" || data.from.indexOf(".") !== -1) {
|
||||
from = "";
|
||||
}
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.NOTICE,
|
||||
mode: chan.getMode(from),
|
||||
from: from,
|
||||
text: data.message
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
chan: chan.id,
|
||||
msg: msg
|
||||
});
|
||||
});
|
||||
};
|
@ -4,12 +4,12 @@ var Msg = require("../../models/msg");
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("part", function(data) {
|
||||
var chan = _.find(network.channels, {name: data.channels[0]});
|
||||
var chan = network.getChannel(data.channel);
|
||||
if (typeof chan === "undefined") {
|
||||
return;
|
||||
}
|
||||
var from = data.nick;
|
||||
if (from === irc.me) {
|
||||
if (from === irc.user.nick) {
|
||||
network.channels = _.without(network.channels, chan);
|
||||
client.save();
|
||||
client.emit("part", {
|
||||
@ -23,9 +23,10 @@ module.exports = function(irc, network) {
|
||||
});
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.PART,
|
||||
mode: chan.getMode(from),
|
||||
time: data.time,
|
||||
mode: (user && user.mode) || "",
|
||||
text: data.message || "",
|
||||
hostmask:data.hostmask.username + "@" + data.hostmask.hostname,
|
||||
hostmask: data.ident + "@" + data.hostname,
|
||||
from: from
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
|
@ -15,10 +15,11 @@ module.exports = function(irc, network) {
|
||||
chan: chan.id
|
||||
});
|
||||
var msg = new Msg({
|
||||
time: data.time,
|
||||
type: Msg.Type.QUIT,
|
||||
mode: chan.getMode(from),
|
||||
mode: user.mode || "",
|
||||
text: data.message || "",
|
||||
hostmask: data.hostmask.username + "@" + data.hostmask.hostname,
|
||||
hostmask: data.ident + "@" + data.hostname,
|
||||
from: from
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
|
@ -1,33 +1,51 @@
|
||||
var _ = require("lodash");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("topic", function(data) {
|
||||
var chan = _.find(network.channels, {name: data.channel});
|
||||
var chan = network.getChannel(data.channel);
|
||||
if (typeof chan === "undefined") {
|
||||
return;
|
||||
}
|
||||
var from = data.nick || chan.name;
|
||||
var topic = data.topic;
|
||||
|
||||
var msg = new Msg({
|
||||
time: data.time,
|
||||
type: Msg.Type.TOPIC,
|
||||
mode: chan.getMode(from),
|
||||
from: from,
|
||||
text: topic,
|
||||
isSetByChan: from === chan.name,
|
||||
self: (from.toLowerCase() === irc.me.toLowerCase())
|
||||
mode: (data.nick && chan.getMode(data.nick)) || "",
|
||||
from: data.nick,
|
||||
text: data.topic,
|
||||
self: data.nick === irc.user.nick
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
chan: chan.id,
|
||||
msg: msg
|
||||
});
|
||||
chan.topic = topic;
|
||||
|
||||
chan.topic = data.topic;
|
||||
client.emit("topic", {
|
||||
chan: chan.id,
|
||||
topic: chan.topic
|
||||
});
|
||||
});
|
||||
|
||||
irc.on("topicsetby", function(data) {
|
||||
var chan = network.getChannel(data.channel);
|
||||
if (typeof chan === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.TOPIC_SET_BY,
|
||||
mode: chan.getMode(data.nick),
|
||||
nick: data.nick,
|
||||
when: new Date(data.when * 1000),
|
||||
self: data.nick === irc.user.nick
|
||||
});
|
||||
chan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
chan: chan.id,
|
||||
msg: msg
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -2,13 +2,11 @@ var Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("welcome", function(data) {
|
||||
network.connected = true;
|
||||
irc.write("PING " + network.host);
|
||||
irc.on("registered", function(data) {
|
||||
network.nick = data.nick;
|
||||
var lobby = network.channels[0];
|
||||
var nick = data;
|
||||
var msg = new Msg({
|
||||
text: "You're now known as " + nick
|
||||
text: "You're now known as " + data.nick
|
||||
});
|
||||
lobby.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
@ -18,7 +16,7 @@ module.exports = function(irc, network) {
|
||||
client.save();
|
||||
client.emit("nick", {
|
||||
network: network.id,
|
||||
nick: nick
|
||||
nick: data.nick
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -1,18 +1,14 @@
|
||||
var _ = require("lodash");
|
||||
var Chan = require("../../models/chan");
|
||||
var Msg = require("../../models/msg");
|
||||
|
||||
module.exports = function(irc, network) {
|
||||
var client = this;
|
||||
irc.on("whois", function(err, data) {
|
||||
if (data === null) {
|
||||
return;
|
||||
}
|
||||
var chan = _.find(network.channels, {name: data.nickname});
|
||||
irc.on("whois", function(data) {
|
||||
var chan = network.getChannel(data.nick);
|
||||
if (typeof chan === "undefined") {
|
||||
chan = new Chan({
|
||||
type: Chan.Type.QUERY,
|
||||
name: data.nickname
|
||||
name: data.nick
|
||||
});
|
||||
network.channels.push(chan);
|
||||
client.emit("join", {
|
||||
@ -20,10 +16,20 @@ module.exports = function(irc, network) {
|
||||
chan: chan
|
||||
});
|
||||
}
|
||||
var msg = new Msg({
|
||||
type: Msg.Type.WHOIS,
|
||||
whois: data
|
||||
});
|
||||
|
||||
var msg;
|
||||
if (data.error) {
|
||||
msg = new Msg({
|
||||
type: Msg.Type.ERROR,
|
||||
text: "No such nick: " + data.nick
|
||||
});
|
||||
} else {
|
||||
msg = new Msg({
|
||||
type: Msg.Type.WHOIS,
|
||||
whois: data
|
||||
});
|
||||
}
|
||||
|
||||
chan.messages.push(msg);
|
||||
client.emit("msg", {
|
||||
chan: chan.id,
|
||||
|
@ -5,8 +5,9 @@ var expect = require("chai").expect;
|
||||
var Chan = require("../../src/models/chan");
|
||||
var User = require("../../src/models/user");
|
||||
|
||||
function makeUser(name, mode) {
|
||||
return new User({name: name, mode: mode});
|
||||
function makeUser(name) {
|
||||
// TODO Update/Fix this when User constructor gets reworked (see its TODO)
|
||||
return new User({nick: name, mode: ""});
|
||||
}
|
||||
|
||||
function getUserNames(chan) {
|
||||
@ -14,13 +15,20 @@ function getUserNames(chan) {
|
||||
}
|
||||
|
||||
describe("Chan", function() {
|
||||
describe("#sortUsers()", function() {
|
||||
describe("#sortUsers(irc)", function() {
|
||||
var fullNetworkPrefix = [
|
||||
{symbol: "~", mode: "q"},
|
||||
{symbol: "&", mode: "a"},
|
||||
{symbol: "@", mode: "o"},
|
||||
{symbol: "%", mode: "h"},
|
||||
{symbol: "+", mode: "v"}
|
||||
];
|
||||
|
||||
it("should sort a simple user list", function() {
|
||||
var chan = new Chan({users: [
|
||||
"JocelynD", "YaManicKill", "astorije", "xPaw", "Max-P"
|
||||
].map(makeUser)});
|
||||
chan.sortUsers();
|
||||
chan.sortUsers({network: {options: {PREFIX: fullNetworkPrefix}}});
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal([
|
||||
"astorije", "JocelynD", "Max-P", "xPaw", "YaManicKill"
|
||||
@ -35,7 +43,7 @@ describe("Chan", function() {
|
||||
new User({name: "xPaw", mode: "~"}),
|
||||
new User({name: "Max-P", mode: "@"}),
|
||||
]});
|
||||
chan.sortUsers();
|
||||
chan.sortUsers({network: {options: {PREFIX: fullNetworkPrefix}}});
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal([
|
||||
"xPaw", "JocelynD", "Max-P", "astorije", "YaManicKill"
|
||||
@ -50,7 +58,7 @@ describe("Chan", function() {
|
||||
new User({name: "xPaw"}),
|
||||
new User({name: "Max-P", mode: "@"}),
|
||||
]});
|
||||
chan.sortUsers();
|
||||
chan.sortUsers({network: {options: {PREFIX: fullNetworkPrefix}}});
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal(
|
||||
["Max-P", "YaManicKill", "astorije", "JocelynD", "xPaw"]
|
||||
@ -59,7 +67,7 @@ describe("Chan", function() {
|
||||
|
||||
it("should be case-insensitive", function() {
|
||||
var chan = new Chan({users: ["aB", "Ad", "AA", "ac"].map(makeUser)});
|
||||
chan.sortUsers();
|
||||
chan.sortUsers({network: {options: {PREFIX: fullNetworkPrefix}}});
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal(["AA", "aB", "ac", "Ad"]);
|
||||
});
|
||||
@ -69,7 +77,7 @@ describe("Chan", function() {
|
||||
"[foo", "]foo", "(foo)", "{foo}", "<foo>", "_foo", "@foo", "^foo",
|
||||
"&foo", "!foo", "+foo", "Foo"
|
||||
].map(makeUser)});
|
||||
chan.sortUsers();
|
||||
chan.sortUsers({network: {options: {PREFIX: fullNetworkPrefix}}});
|
||||
|
||||
expect(getUserNames(chan)).to.deep.equal([
|
||||
"!foo", "&foo", "(foo)", "+foo", "<foo>", "@foo", "[foo", "]foo",
|
||||
|
@ -22,7 +22,7 @@ describe("Network", function() {
|
||||
username: "",
|
||||
realname: "",
|
||||
commands: [],
|
||||
nick: undefined,
|
||||
nick: "",
|
||||
join: "#thelounge,&foobar",
|
||||
});
|
||||
});
|
||||
|
17
test/util.js
17
test/util.js
@ -2,9 +2,10 @@ var EventEmitter = require("events").EventEmitter;
|
||||
var util = require("util");
|
||||
var _ = require("lodash");
|
||||
var express = require("express");
|
||||
var Network = require("../src/models/network");
|
||||
|
||||
function MockClient(opts) {
|
||||
this.me = "test-user";
|
||||
this.user = {nick: "test-user"};
|
||||
|
||||
for (var k in opts) {
|
||||
this[k] = opts[k];
|
||||
@ -13,14 +14,13 @@ function MockClient(opts) {
|
||||
util.inherits(MockClient, EventEmitter);
|
||||
|
||||
MockClient.prototype.createMessage = function(opts) {
|
||||
|
||||
var message = _.extend({
|
||||
message: "dummy message",
|
||||
from: "test-user",
|
||||
to: "test-channel"
|
||||
nick: "test-user",
|
||||
target: "#test-channel"
|
||||
}, opts);
|
||||
|
||||
this.emit("message", message);
|
||||
this.emit("privmsg", message);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
@ -28,12 +28,13 @@ module.exports = {
|
||||
return new MockClient();
|
||||
},
|
||||
createNetwork: function() {
|
||||
return {
|
||||
return new Network({
|
||||
host: "example.com",
|
||||
channels: [{
|
||||
name: "test-channel",
|
||||
name: "#test-channel",
|
||||
messages: []
|
||||
}]
|
||||
};
|
||||
});
|
||||
},
|
||||
createWebserver: function() {
|
||||
return express();
|
||||
|
Loading…
Reference in New Issue
Block a user