diff --git a/client/js/condensed.js b/client/js/condensed.js
index 87d5930e..a7c49668 100644
--- a/client/js/condensed.js
+++ b/client/js/condensed.js
@@ -29,6 +29,9 @@ function updateText(condensed, addedTypes) {
case "back":
strings.push(obj[type] + (obj[type] > 1 ? " users have come back" : " user has come back"));
break;
+ case "chghost":
+ strings.push(obj[type] + (obj[type] > 1 ? " users have changed hostname" : " user has changed hostname"));
+ break;
case "join":
strings.push(obj[type] + (obj[type] > 1 ? " users have joined the channel" : " user has joined the channel"));
break;
diff --git a/client/js/constants.js b/client/js/constants.js
index 6958ace0..754a349b 100644
--- a/client/js/constants.js
+++ b/client/js/constants.js
@@ -84,12 +84,14 @@ const actionTypes = [
"action",
"whois",
"ctcp",
+ "chghost",
"channel_list",
];
const condensedTypes = [
"away",
"back",
+ "chghost",
"join",
"part",
"quit",
diff --git a/client/views/actions/chghost.tpl b/client/views/actions/chghost.tpl
new file mode 100644
index 00000000..0f89c69e
--- /dev/null
+++ b/client/views/actions/chghost.tpl
@@ -0,0 +1,4 @@
+{{> ../user_name nick=from.nick mode=from.mode}}
+has changed
+{{#if new_ident}}username to {{new_ident}}{{#if new_host}}, and{{/if}}{{/if}}
+{{#if new_host}}hostname to {{new_host}}{{/if}}
diff --git a/client/views/index.js b/client/views/index.js
index 267f0691..9f5bf6c0 100644
--- a/client/views/index.js
+++ b/client/views/index.js
@@ -7,6 +7,7 @@ module.exports = {
back: require("./actions/back.tpl"),
ban_list: require("./actions/ban_list.tpl"),
channel_list: require("./actions/channel_list.tpl"),
+ chghost: require("./actions/chghost.tpl"),
ctcp: require("./actions/ctcp.tpl"),
invite: require("./actions/invite.tpl"),
join: require("./actions/join.tpl"),
diff --git a/src/client.js b/src/client.js
index 94a8cc59..65db1235 100644
--- a/src/client.js
+++ b/src/client.js
@@ -20,6 +20,7 @@ var events = [
"unhandled",
"banlist",
"ctcp",
+ "chghost",
"error",
"invite",
"join",
@@ -255,6 +256,7 @@ Client.prototype.connect = function(args) {
tls: network.tls,
localAddress: config.bind,
rejectUnauthorized: false,
+ enable_chghost: true,
enable_echomessage: true,
auto_reconnect: true,
auto_reconnect_wait: 10000 + Math.floor(Math.random() * 1000), // If multiple users are connected to the same network, randomize their reconnections a little
diff --git a/src/models/msg.js b/src/models/msg.js
index 6c53e212..2ea8193a 100644
--- a/src/models/msg.js
+++ b/src/models/msg.js
@@ -56,6 +56,7 @@ Msg.Type = {
PART: "part",
QUIT: "quit",
CTCP: "ctcp",
+ CHGHOST: "chghost",
TOPIC: "topic",
TOPIC_SET_BY: "topic_set_by",
WHOIS: "whois",
diff --git a/src/plugins/irc-events/chghost.js b/src/plugins/irc-events/chghost.js
new file mode 100644
index 00000000..2636bb5f
--- /dev/null
+++ b/src/plugins/irc-events/chghost.js
@@ -0,0 +1,31 @@
+"use strict";
+
+const Msg = require("../../models/msg");
+
+module.exports = function(irc, network) {
+ const client = this;
+
+ // If server supports CHGHOST cap, then changing the hostname does not require
+ // sending PART and JOIN, which means less work for us over all
+ irc.on("user updated", function(data) {
+ const msg = new Msg({
+ time: data.time,
+ type: Msg.Type.CHGHOST,
+ new_ident: data.ident !== data.new_ident ? data.new_ident : "",
+ new_host: data.hostname !== data.new_host ? data.new_host : "",
+ self: data.nick === irc.user.nick,
+ });
+
+ network.channels.forEach((chan) => {
+ const user = chan.findUser(data.nick);
+
+ if (typeof user === "undefined") {
+ return;
+ }
+
+ msg.from = user;
+
+ chan.pushMessage(client, msg);
+ });
+ });
+};