Comparing version 0.2.2 to 1.0.0-alpha1
@@ -14,2 +14,3 @@ $(function() { | ||
"/mode", | ||
"/msg", | ||
"/nick", | ||
@@ -27,5 +28,12 @@ "/op", | ||
var socket = io.connect(""); | ||
$.each(["network", "channel", "user", "message"], function(i, event) { | ||
socket.on(event, function(json) { | ||
handleEvent(event, json); | ||
var events = [ | ||
"join", | ||
"msg", | ||
"networks", | ||
"nick", | ||
"part", | ||
"users", | ||
].forEach(function(e) { | ||
socket.on(e, function(data) { | ||
event(e, data); | ||
}); | ||
@@ -35,183 +43,74 @@ }); | ||
var tpl = []; | ||
function render(id, json, partials) { | ||
tpl[id] = tpl[id] || $(id).html(); | ||
if (!json) { | ||
// If no data is supplied, return the template instead. | ||
// Handy when fetching partials. | ||
return tpl[id]; | ||
} | ||
return Mustache.render( | ||
tpl[id], | ||
json, | ||
partials || {} | ||
); | ||
function render(id, data) { | ||
tpl[id] = tpl[id] || Handlebars.compile($(id).remove().html()); | ||
return tpl[id](data); | ||
} | ||
function handleEvent(event, json) { | ||
var data = json.data; | ||
switch (event) { | ||
case "network": | ||
var html = ""; | ||
var partials = { | ||
users: render("#users"), | ||
messages: render("#messages"), | ||
}; | ||
data.forEach(function(n) { | ||
html += render( | ||
"#windows", {windows: n.channels}, partials | ||
); | ||
}); | ||
chat[0].innerHTML = html; | ||
sidebar.find("#list").html( | ||
render("#networks", {networks: data}, {channels: render("#channels")}) | ||
).find(".channel") | ||
.first() | ||
.addClass("active") | ||
.end(); | ||
chat.find(".messages") | ||
.scrollGlue({animate: 400}) | ||
.scrollToBottom() | ||
.end(); | ||
chat.find(".window") | ||
.find("input") | ||
function event(e, data) { | ||
switch (e) { | ||
case "join": | ||
chat.append(render("#windows", { | ||
windows: [data.chan], | ||
})).find(".window") | ||
.last() | ||
.find(".input") | ||
.tabComplete({after: " ", list: commands}) | ||
.inputHistory({submit: true}) | ||
.end() | ||
.first() | ||
.bringToTop() | ||
.find(".messages") | ||
.scrollGlue({speed: 400}) | ||
.end(); | ||
$("#network-" + data.id).append(render("#channels", { | ||
channels: [data.chan], | ||
})).find(".channel") | ||
.last() | ||
.uniqueClass("active") | ||
.end(); | ||
break; | ||
case "channel": | ||
var id = data.id; | ||
if (json.action == "remove") { | ||
$("#channel-" + id + ", #window-" + id).remove(); | ||
var highest = 0; | ||
var next = null; | ||
$(".window").each(function() { | ||
var z = $(this).css("z-index"); | ||
if (z > highest) { | ||
highest = z; | ||
next = $(this); | ||
} | ||
}); | ||
if (next != null) { | ||
next.addClass("active"); | ||
} | ||
return; | ||
} | ||
sidebar.find(".channel").removeClass("active"); | ||
$("#network-" + json.target).append( | ||
render("#channels", {channels: data}) | ||
).find(".channel") | ||
.last() | ||
.addClass("active"); | ||
chat.append( | ||
render("#windows", {windows: data}) | ||
).find(".window") | ||
.last() | ||
.find("input") | ||
case "msg": | ||
$("#window-" + data.id).find(".messages").append(render("#messages", { | ||
messages: [data.msg], | ||
})); | ||
break; | ||
case "networks": | ||
chat.html(render("#windows", { | ||
windows: $.map(data.networks, function(n) { return n.channels; }), | ||
})).find(".window") | ||
.find(".input") | ||
.tabComplete({after: " ", list: commands}) | ||
.inputHistory({submit: true}) | ||
.end() | ||
.find(".messages") | ||
.scrollGlue({speed: 400}) | ||
.end() | ||
.last() | ||
.bringToTop() | ||
.find(".messages") | ||
.scrollGlue({animate: 400}) | ||
.end(); | ||
sidebar.html(render("#networks", { | ||
networks: data.networks, | ||
})).find(".channel") | ||
.last() | ||
.addClass("active") | ||
.end(); | ||
break; | ||
case "user": | ||
var target = chat.find("#window-" + json.target).find(".users"); | ||
target.html(render("#users", {users: data})); | ||
case "nick": | ||
// Not yet implemented. | ||
break; | ||
case "message": | ||
var target = $("#window-" + json.target); | ||
if (target.size() == 0) { | ||
return; | ||
} | ||
if (data.type == "error") { | ||
target = target.parent().find(".active"); | ||
} | ||
var msg = $(render("#messages", {messages: data})) | ||
target = target.find(".messages"); | ||
target.append(msg); | ||
case "part": | ||
$("#channel-" + data.id + ", #window-" + data.id).remove(); | ||
break; | ||
case "users": | ||
$("#window-" + data.id).find(".users").html(render("#users", { | ||
users: data.users, | ||
})); | ||
break; | ||
} | ||
} | ||
sidebar.on("click", ".channel", function(e) { | ||
e.preventDefault(); | ||
sidebar.find("#list .active").removeClass("active"); | ||
$("#viewport").removeClass(); | ||
var item = $(this) | ||
.addClass("active") | ||
.find(".badge") | ||
.html("") | ||
.end(); | ||
$("#window-" + item.attr("id").replace("channel-", "")) | ||
.bringToTop(); | ||
}); | ||
sidebar.find("input[type=checkbox]").each(function() { | ||
var input = $(this); | ||
var value = input.val(); | ||
var checked = true; | ||
if (($.cookie("hidden") || []).indexOf(value) !== -1) { | ||
checked = false; | ||
} | ||
input.prop("checked", checked) | ||
.wrap("<label>") | ||
.parent() | ||
.append(value); | ||
if (checked) { | ||
chat.addClass("show-" + value); | ||
} | ||
input.on("change", function() { | ||
var hidden = $.cookie("hidden") || ""; | ||
if (input.prop("checked")) { | ||
hidden = hidden.replace(value, ""); | ||
} else { | ||
hidden += value; | ||
} | ||
$.cookie("hidden", hidden); | ||
chat.toggleClass( | ||
"show-" + value, | ||
input.prop("checked") | ||
); | ||
}); | ||
}); | ||
chat.on("append", ".messages", function(e) { | ||
var item = $(this); | ||
var last = item.find(".message:last"); | ||
var type = last[0].classList[1]; | ||
if (type && !chat.hasClass("show-" + type)) { | ||
return; | ||
} | ||
var id = item.parent() | ||
.attr("id") | ||
.replace("window-", ""); | ||
var badge = sidebar | ||
.find("#channel-" + id + ":not(.active)") | ||
.find(".badge"); | ||
var num = (parseInt(badge.html()) + 1) || "1"; | ||
badge.html(num); | ||
}); | ||
chat.on("click touchstart", ".toggle a", function(e) { | ||
$("#viewport").toggleClass($(this).attr("class")); | ||
return false; | ||
}); | ||
chat.on("submit", "form", function() { | ||
@@ -229,19 +128,11 @@ var input = $(this).find(".input"); | ||
}); | ||
chat.on("click", ".close", function() { | ||
var id = parseInt($(this).closest(".window").attr("id").replace("window-", "")); | ||
socket.emit("input", { | ||
id: id, | ||
text: "/part", | ||
}); | ||
chat.on("focus", ".input", function() { | ||
var input = $(this).parents().eq(1).find(".messages").scrollToBottom(); | ||
}); | ||
chat.on("mousedown", ".user", function(e) { | ||
return false; | ||
}); | ||
chat.on("dblclick", ".user", function() { | ||
var link = $(this); | ||
var id = parseInt(link.closest(".window").attr("id").replace("window-", "")); | ||
var name = link.text().trim(); | ||
chat.on("click", ".user", function() { | ||
var user = $(this); | ||
var id = user.closest(".window").find(".input").data("target"); | ||
var name = user.text().trim(); | ||
if (name == "-!-" || name.indexOf(".") != -1) { | ||
@@ -252,34 +143,53 @@ return; | ||
id: id, | ||
text: "/whois " + link.text().trim(), | ||
text: "/whois " + name, | ||
}); | ||
}); | ||
chat.on("click", ".close", function() { | ||
var id = $(this).closest(".window").find(".input").data("target"); | ||
socket.emit("input", { | ||
id: id, | ||
text: "/part", | ||
}); | ||
}); | ||
chat.on("focus", "input[type=text]", function() { | ||
$(this).closest(".window").find(".messages").scrollToBottom(); | ||
sidebar.on("click", ".channel", function(e) { | ||
e.preventDefault(); | ||
$("#window-" + $(this).attr("id").replace("channel-", "")) | ||
.bringToTop(); | ||
}); | ||
chat.on("mouseover", ".text", function() { | ||
var self = $(this); | ||
if (!self.hasClass("parsed")) { | ||
self.addClass("parsed").html(uri(self.html())); | ||
} | ||
}); | ||
// Utils | ||
function uri(text) { | ||
return URI.withinString(text, function(url) { | ||
return "<a href='" + url + "' target='_blank'>" + url + "</a>"; | ||
return "<a href='" + url.replace(/^www/, "//www") + "' target='_blank'>" + url + "</a>"; | ||
}); | ||
} | ||
var highest = 1; | ||
$.fn.bringToTop = function() { | ||
return this.css('z-index', highest++) | ||
.addClass("active") | ||
.find(".input") | ||
.focus() | ||
.end() | ||
.siblings() | ||
.removeClass("active") | ||
.end(); | ||
}; | ||
function escape(string) { | ||
var e = { | ||
"<": "<", | ||
">": ">", | ||
}; | ||
return string.replace(/[<>]/g, function (s) { | ||
return e[s]; | ||
}); | ||
} | ||
// Helpers | ||
Handlebars.registerHelper( | ||
"uri", | ||
function(text) { | ||
return uri(escape(text)); | ||
} | ||
); | ||
Handlebars.registerHelper( | ||
"partial", | ||
function(id) { | ||
return new Handlebars.SafeString(render(id, this)); | ||
} | ||
); | ||
}); |
module.exports = { | ||
port: 9000, | ||
defaults: { | ||
nick: "t_user", | ||
realname: "Temp User", | ||
nick: "shout_user", | ||
realname: "http://github.com/erming/shout", | ||
}, | ||
servers: [{ | ||
networks: [{ | ||
host: "irc.freenode.org", | ||
channels: ["#t_chan"], | ||
port: 6667, | ||
channels: [ | ||
"#shout-irc", | ||
], | ||
}] | ||
}; |
@@ -1,12 +0,20 @@ | ||
var models = require(__dirname + "/models.js"); | ||
var config = require(__dirname + "/../config.js"); | ||
var http = require("connect"); | ||
var io = require("socket.io"); | ||
var irc = require("slate-irc"); | ||
var net = require("net"); | ||
var _ = require("lodash"); | ||
var config = require("../config"); | ||
var http = require("connect"); | ||
var io = require("socket.io"); | ||
var irc = require("slate-irc"); | ||
var net = require("net"); | ||
var _ = require("lodash"); | ||
var sockets = null; | ||
var networks = new models.Networks; | ||
// Models | ||
var Chan = require("./models/chan"); | ||
var Msg = require("./models/msg"); | ||
var Network = require("./models/network"); | ||
var User = require("./models/user"); | ||
var sockets = null; | ||
var networks = [ | ||
new Network({host: "Status"}) | ||
]; | ||
var events = [ | ||
@@ -28,3 +36,5 @@ "join", | ||
module.exports = function listen() { | ||
module.exports = listen; | ||
function listen() { | ||
var app = http() | ||
@@ -34,17 +44,14 @@ .use(http.static("client")) | ||
var self = this; | ||
sockets = io.listen(app, {log: 0}).sockets.on("connection", function(s) { | ||
s.on("input", input); | ||
sockets.emit("network", { | ||
data: networks, | ||
s.emit("networks", { | ||
networks: networks | ||
}); | ||
}); | ||
networks.on("all", function() { | ||
sockets.emit.apply(sockets, arguments); | ||
config.networks.forEach(function(n) { | ||
connect(n); | ||
}); | ||
config.servers.forEach(function(s) { | ||
connect(s); | ||
}); | ||
}; | ||
} | ||
@@ -58,3 +65,3 @@ function connect(params) { | ||
var host = params.host; | ||
var port = params.port || 6667; | ||
var port = params.port; | ||
@@ -71,14 +78,16 @@ var stream = net.connect({ | ||
var client = irc(stream); | ||
var network = networks.add({ | ||
var network = new Network({ | ||
host: host, | ||
client: client, | ||
}, {silent: true}); | ||
}); | ||
networks.trigger("network", networks); | ||
networks.push(network); | ||
sockets.emit("networks", { | ||
networks: networks | ||
}); | ||
client.nick(params.nick); | ||
client.user(params.nick, params.realname); | ||
client.once("welcome", function() { | ||
params.channels.forEach(function(c) { | ||
(params.channels || []).forEach(function(c) { | ||
client.join(c); | ||
@@ -95,37 +104,44 @@ }); | ||
function input(json) { | ||
var target = networks.find(json.id); | ||
function input(data) { | ||
var target = find(data.id); | ||
if (!target) { | ||
return; | ||
} | ||
var network = target.network; | ||
var channel = target.channel; | ||
var chan = target.chan; | ||
var client = network.get("client"); | ||
var client = network.client; | ||
var id = data.id; | ||
var text = data.text; | ||
var id = json.id; | ||
var text = json.text; | ||
var args = text.replace(/^\//, '').split(" "); | ||
var cmd = text.charAt(0) == "/" ? args[0].toLowerCase() : ""; | ||
var cmd = text.charAt(0) == "/" ? args[0].toLowerCase() : ""; | ||
switch (cmd) { | ||
case "": | ||
args.unshift( | ||
"msg", | ||
channel.get("name") | ||
chan.name | ||
); | ||
case "msg": | ||
var user; | ||
var message = _.tail(args, 2).join(" "); | ||
var text = _.tail(args, 2).join(" "); | ||
if (client) { | ||
user = client.me; | ||
client.send(args[1], message); | ||
client.send(args[1], text); | ||
} | ||
channel.get("messages").add({ | ||
from: user, | ||
message: message, | ||
}); | ||
var chan = _.findWhere(network.channels, {name: args[1]}); | ||
if (typeof chan !== "undefined") { | ||
var msg = new Msg({ | ||
from: user, | ||
text: text, | ||
}); | ||
chan.messages.push(msg) | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
} | ||
break; | ||
@@ -149,6 +165,10 @@ | ||
case "part": | ||
if (channel.get("type") == "query") { | ||
network.get("channels").remove(channel); | ||
var id = chan.id; | ||
if (chan.type == "query" || !chan.users.length) { | ||
remove(id); | ||
sockets.emit("part", { | ||
id: id, | ||
}); | ||
} else if (client) { | ||
client.part(channel.get("name")); | ||
client.part(chan.name); | ||
} | ||
@@ -158,9 +178,7 @@ break; | ||
case "topic": | ||
var chan = channel.get("name"); | ||
if (client) { | ||
var str = "TOPIC " + chan; | ||
if (args[1]) { | ||
str += " :" + args.slice(1).join(" "); | ||
} | ||
client.write(str); | ||
var msg = "TOPIC"; | ||
msg += " " + chan.name; | ||
msg += args[1] ? " :" + args.slice(1).join(" ") : ""; | ||
client.write(msg); | ||
} | ||
@@ -178,3 +196,3 @@ break; | ||
if (client && args[1]) { | ||
client.kick(channel.get("name"), args[1]); | ||
client.kick(chan.name, args[1]); | ||
} | ||
@@ -191,3 +209,2 @@ break; | ||
} | ||
var mode; | ||
@@ -209,5 +226,4 @@ var user; | ||
} | ||
client.mode( | ||
channel.get("name"), | ||
chan.name, | ||
mode, | ||
@@ -220,52 +236,83 @@ user | ||
case "disconnect": | ||
networks.remove(network); | ||
networks.trigger("network", networks); | ||
if (client) { | ||
client.quit(); | ||
networks = _.without(networks, network); | ||
sockets.emit("networks", { | ||
networks: networks | ||
}); | ||
} | ||
break; | ||
} | ||
} | ||
function event(event, data) { | ||
var channels = this.get("channels"); | ||
function event(e, data) { | ||
var data = _.last(data); | ||
var channels = this.channels; | ||
switch (event) { | ||
switch (e) { | ||
case "join": | ||
var chan = channels.findWhere({name: data[0].channel}) || channels.add({name: data[0].channel}); | ||
var users = chan.get("users"); | ||
users.add({name: data[0].nick}, {silent: true}); | ||
if (data[0].nick != this.get("client").me) { | ||
users.sort(); | ||
var chan = _.findWhere(channels, {name: data.channel}); | ||
if (typeof chan === "undefined") { | ||
chan = new Chan({ | ||
name: data.channel, | ||
}); | ||
channels.push(chan); | ||
sockets.emit("join", { | ||
id: this.id, | ||
chan: chan, | ||
}); | ||
} | ||
chan.get("messages").add({ | ||
from: data[0].nick, | ||
var users = chan.users; | ||
users.push(new User({name: data.nick})); | ||
sockets.emit("users", { | ||
id: chan.id, | ||
users: users, | ||
}); | ||
var msg = new Msg({ | ||
from: data.nick, | ||
type: "join", | ||
}); | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
break; | ||
case "kick": | ||
var chan = channels.findWhere({name: data[0].channel}); | ||
var users = chan.get("users"); | ||
if (data[0].client != this.get("client").me) { | ||
users.remove(users.findWhere({name: data[0].client})); | ||
var chan = _.findWhere(channels, {name: data.channel}); | ||
if (data.client == this.client.me) { | ||
chan.users = []; | ||
} else { | ||
users.reset(); | ||
chan.users = _.without(chan.users, _.findWhere(chan.users, {name: data.client})); | ||
} | ||
chan.get("messages").add({ | ||
from: data[0].nick, | ||
message: data[0].client, | ||
sockets.emit("users", { | ||
id: chan.id, | ||
users: chan.users, | ||
}); | ||
var msg = new Msg({ | ||
type: "kick", | ||
from: data.nick, | ||
text: data.client, | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
break; | ||
case "mode": | ||
var chan = channels.findWhere({name: data[0].target}); | ||
var chan = _.findWhere(channels, {name: data.target}); | ||
if (typeof chan !== "undefined") { | ||
chan.get("messages").add({ | ||
from: data[0].nick, | ||
message: data[0].mode + " " + data[0].client, | ||
var msg = new Msg({ | ||
type: "mode", | ||
from: data.nick, | ||
text: data.mode + " " + data.client, | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
} | ||
@@ -275,5 +322,14 @@ break; | ||
case "motd": | ||
var messages = data[0].motd; | ||
messages.forEach(function(msg) { | ||
channels.first().get("messages").add({message: msg}); | ||
var chan = channels[0]; | ||
data.motd.forEach(function(m) { | ||
var msg = new Msg({ | ||
type: "motd", | ||
from: "-!-", | ||
text: m, | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
}); | ||
@@ -283,40 +339,77 @@ break; | ||
case "message": | ||
var chan = channels.findWhere({name: data[0].to}) || channels.add({type: "query", name: data[0].from}); | ||
chan.get("messages").add({ | ||
from: data[0].from, | ||
message: data[0].message | ||
var chan = _.findWhere(channels, {name: data.to}); | ||
if (typeof chan === "undefined") { | ||
chan = new Chan({ | ||
name: data.from, | ||
type: "query", | ||
}); | ||
channels.push(chan); | ||
sockets.emit("join", { | ||
id: this.id, | ||
chan: chan, | ||
}); | ||
} | ||
var type = ""; | ||
var text = data.message; | ||
var network = this; | ||
text.split(" ").forEach(function(w) { | ||
if (w == network.client.me) type = "highlight"; | ||
}); | ||
var msg = new Msg({ | ||
type: type, | ||
from: data.from, | ||
text: text, | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
break; | ||
case "names": | ||
var chan = channels.findWhere({name: data[0].channel}); | ||
var users = chan.get("users"); | ||
users.reset( | ||
_.map(data[0].names, function(n) { return {name: n}; }), | ||
{silent: true} | ||
); | ||
users.sort(); | ||
var chan = _.findWhere(channels, {name: data.channel}); | ||
chan.users = []; | ||
data.names.forEach(function(n) { | ||
chan.users.push(new User({name: n})); | ||
}); | ||
sockets.emit("users", { | ||
id: chan.id, | ||
users: chan.users, | ||
}); | ||
break; | ||
case "nick": | ||
if (data[0].new == this.get("client").me) { | ||
channels.first().get("messages").add({ | ||
message: "You're now known as " + data[0]["new"], | ||
if (data["new"] == this.client.me) { | ||
var chan = channels[0]; | ||
var msg = new Msg({ | ||
from: "-!-", | ||
text: "You're now known as " + data["new"], | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
} | ||
channels.each(function(chan) { | ||
var users = chan.get("users"); | ||
var user = users.findWhere({name: data[0].nick}); | ||
channels.forEach(function(chan) { | ||
var user = _.findWhere(chan.users, {name: data.nick}); | ||
if (!user) { | ||
return; | ||
} | ||
user.set("name", data[0]["new"]); | ||
users.sort(); | ||
chan.get("messages").add({ | ||
from: data[0].nick, | ||
message: data[0]["new"], | ||
user.name = data["new"]; | ||
sockets.emit("users", { | ||
id: chan.id, | ||
users: chan.users, | ||
}); | ||
var msg = new Msg({ | ||
type: "nick", | ||
from: data.nick, | ||
text: data["new"], | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
}); | ||
@@ -326,35 +419,60 @@ break; | ||
case "notice": | ||
if (data[0].to = "*") { | ||
data[0].from = "-!-"; | ||
} | ||
channels.first().get("messages").add(data[0]); | ||
var chan = channels[0]; | ||
var msg = new Msg({ | ||
type: "notice", | ||
from: data.to == "*" ? "-!-" : data.from, | ||
text: data.message, | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
break; | ||
case "part": | ||
var chan = channels.findWhere({name: data[0].channels[0]}); | ||
if (data[0].nick == this.get("client").me) { | ||
channels.remove(chan); | ||
return; | ||
var chan = _.findWhere(channels, {name: data.channels[0]}); | ||
if (data.nick == this.client.me) { | ||
remove(chan.id); | ||
sockets.emit("part", { | ||
id: chan.id, | ||
}); | ||
} else { | ||
chan.users = _.without(chan.users, _.findWhere(chan.users, {name: data.nick})); | ||
sockets.emit("users", { | ||
id: chan.id, | ||
users: chan.users, | ||
}); | ||
var msg = new Msg({ | ||
type: "part", | ||
from: data.nick, | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
} | ||
var users = chan.get("users"); | ||
users.remove(users.findWhere({name: data[0].nick})); | ||
users.sort(); | ||
chan.get("messages").add({ | ||
from: data[0].nick, | ||
type: "part", | ||
}); | ||
break; | ||
case "quit": | ||
channels.each(function(chan) { | ||
var users = chan.get("users"); | ||
var user = users.findWhere({name: data[0].nick}); | ||
if (user) { | ||
users.remove(user); | ||
users.sort(); | ||
chan.get("messages").add({ | ||
from: data[0].nick, | ||
type: "quit", | ||
}); | ||
channels.forEach(function(chan) { | ||
var user = _.findWhere(chan.users, {name: data.nick}); | ||
if (!user) { | ||
return; | ||
} | ||
chan.users = _.without(chan.users, user); | ||
sockets.emit("users", { | ||
id: chan.id, | ||
users: chan.users, | ||
}); | ||
var msg = new Msg({ | ||
type: "quit", | ||
from: data.nick, | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
}); | ||
@@ -364,40 +482,84 @@ break; | ||
case "topic": | ||
var chan = channels.findWhere({name: data[0].channel}); | ||
var from = data[0].nick || chan.get("name"); | ||
chan.get("messages").add({ | ||
var chan = _.findWhere(channels, {name: data.channel}); | ||
var from = data.nick || chan.name; | ||
var msg = new Msg({ | ||
type: "topic", | ||
from: from, | ||
message: data[0].topic, | ||
type: "topic", | ||
text: data.topic, | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
break; | ||
case "welcome": | ||
channels.first().get("messages").add([ | ||
{message: "You're now connected to " + this.get("host")}, | ||
{message: "You're now known as " + data[0]} | ||
]); | ||
// Leaving this empty for now. | ||
break; | ||
case "whois": | ||
if (data[1] == null) { | ||
channels.first().get("messages").add({ | ||
if (!data) { | ||
var chan = channels[0]; | ||
var msg = new Msg({ | ||
type: "error", | ||
message: data[0] | ||
text: "No such nick/channel.", | ||
}); | ||
break; | ||
} | ||
var name = data[1].nickname; | ||
var chan = channels.findWhere({name: name}) || channels.add({type: "query", name: name}); | ||
var i = 0; | ||
for (var k in data[1]) { | ||
if (i++ == 5) break; | ||
chan.get("messages").add({ | ||
message: k + ": " + data[1][k] | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
} else { | ||
var chan = _.findWhere(channels, {name: data.nickname}); | ||
if (typeof chan === "undefined") { | ||
chan = new Chan({ | ||
type: "query", | ||
name: data.nickname, | ||
}); | ||
channels.push(chan); | ||
sockets.emit("join", { | ||
id: this.id, | ||
chan: chan, | ||
}); | ||
} | ||
var i = 0; | ||
for (var k in data) { | ||
if (i++ == 5) break; | ||
var msg = new Msg({ | ||
type: "whois", | ||
from: "-!-", | ||
text: k + ": " + data[k], | ||
}); | ||
chan.messages.push(msg); | ||
sockets.emit("msg", { | ||
id: chan.id, | ||
msg: msg, | ||
}); | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
// Utils | ||
function find(id) { | ||
var result = false; | ||
networks.forEach(function(n) { | ||
result = { | ||
network: n, | ||
chan: _.findWhere(n.channels, {id: id}), | ||
}; | ||
if (!result.chan) { | ||
result = false; | ||
} | ||
}); | ||
return result; | ||
} | ||
function remove(id) { | ||
networks.forEach(function(n) { | ||
n.channels = _.without(n.channels, _.findWhere(n.channels, {id: id})); | ||
}); | ||
} |
{ | ||
"name": "shout", | ||
"description": "The modern IRC client", | ||
"version": "0.2.2", | ||
"version": "1.0.0-alpha1", | ||
"author": { | ||
@@ -11,3 +11,2 @@ "name": "Mattias Erming", | ||
"lodash": "~2.4.1", | ||
"backbone": "~1.1.2", | ||
"slate-irc": "~0.5.0", | ||
@@ -21,3 +20,3 @@ "moment": "~2.5.1", | ||
"chat", | ||
"client", | ||
"client", | ||
"irc", | ||
@@ -24,0 +23,0 @@ "server", |
@@ -1,2 +0,2 @@ | ||
## Chat | ||
## shout | ||
Run your IRC client on a server and access it from the web browser. This gives you a persistent connection and allows you to chat from multiple devices at the same time. | ||
@@ -14,2 +14,3 @@ | ||
- `/mode` | ||
- `/msg` | ||
- `/nick` | ||
@@ -31,6 +32,6 @@ - `/op` | ||
2. Clone the project from GitHub | ||
`git clone --recursive http://github.com/erming/chat` | ||
`git clone http://github.com/erming/shout` | ||
3. Open folder | ||
`cd chat/` | ||
`cd shout/` | ||
@@ -37,0 +38,0 @@ 4. Install Node packages |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
211982
5
3455
44
0
17
2
- Removedbackbone@~1.1.2
- Removedbackbone@1.1.2(transitive)
- Removedunderscore@1.13.7(transitive)