diff --git a/client/css/style.css b/client/css/style.css index 88501852..6a14aaac 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -1248,15 +1248,18 @@ kbd { } #chat table.channel-list, -#chat table.ban-list { +#chat table.ban-list, +#chat table.ignore-list { margin: 5px 10px; width: calc(100% - 30px); } #chat table.channel-list th, #chat table.ban-list th, +#chat table.ignore-list th, #chat table.channel-list td, -#chat table.ban-list td { +#chat table.ban-list td, +#chat.table.ignore-list td { padding: 5px; vertical-align: top; border-bottom: #eee 1px solid; @@ -1270,7 +1273,9 @@ kbd { #chat table.channel-list .topic, #chat table.ban-list .hostmask, #chat table.ban-list .banned_by, -#chat table.ban-list .banned_at { +#chat table.ban-list .banned_at, +#chat table.ignore-list .hostmask, +#chat table.ignore-list .when { text-align: left; } diff --git a/client/js/constants.js b/client/js/constants.js index 05ff6b3d..e7e1ae84 100644 --- a/client/js/constants.js +++ b/client/js/constants.js @@ -38,6 +38,8 @@ const commands = [ "/expand", "/ho", "/hs", + "/ignore", + "/ignorelist", "/invite", "/join", "/kick", @@ -64,6 +66,7 @@ const commands = [ "/slap", "/topic", "/unban", + "/unignore", "/voice", "/whois", ]; diff --git a/client/js/contextMenuFactory.js b/client/js/contextMenuFactory.js index 526e470a..4ee5fa16 100644 --- a/client/js/contextMenuFactory.js +++ b/client/js/contextMenuFactory.js @@ -293,6 +293,23 @@ function addJoinItem() { }); } +function addIgnoreListItem() { + function ignorelist(itemData) { + socket.emit("input", { + target: parseInt(itemData, 10), + text: "/ignorelist", + }); + } + + addContextMenuItem({ + check: (target) => target.hasClass("lobby"), + className: "list", + displayName: "List ignored users", + data: (target) => target.data("id"), + callback: ignorelist, + }); +} + function addDefaultItems() { addWhoisItem(); addQueryItem(); @@ -306,4 +323,5 @@ function addDefaultItems() { addChannelListItem(); addBanListItem(); addJoinItem(); + addIgnoreListItem(); } diff --git a/client/js/socket-events/msg.js b/client/js/socket-events/msg.js index d24c068d..f96e139d 100644 --- a/client/js/socket-events/msg.js +++ b/client/js/socket-events/msg.js @@ -52,7 +52,7 @@ function processReceivedMessage(data) { const container = channel.find(".messages"); const activeChannelId = chat.find(".chan.active").data("id"); - if (data.msg.type === "channel_list" || data.msg.type === "ban_list") { + if (data.msg.type === "channel_list" || data.msg.type === "ban_list" || data.msg.type === "ignore_list") { $(container).empty(); } diff --git a/client/views/actions/ignore_list.tpl b/client/views/actions/ignore_list.tpl new file mode 100644 index 00000000..88e0e70b --- /dev/null +++ b/client/views/actions/ignore_list.tpl @@ -0,0 +1,16 @@ +
Hostmask | +Ignored At | +
---|---|
{{hostmask}} | +{{{localetime when}}} | +
/ignore nick
+ + Block any messages from the specified user on the current network. + This can be a nickname or a hostmask.
+/ignorelist
+ Load the list of ignored users for the current network.
+/join channel
@@ -537,6 +557,17 @@
/unignore nick
+ + Unblock messages from the specified user on the current network. + This can be a nickname or a hostmask.
+/voice nick [...nick]
diff --git a/src/client.js b/src/client.js
index 0aa1355b..e1b5c456 100644
--- a/src/client.js
+++ b/src/client.js
@@ -48,6 +48,7 @@ const inputs = [
"away",
"connect",
"disconnect",
+ "ignore",
"invite",
"kick",
"mode",
diff --git a/src/helper.js b/src/helper.js
index 2fe864aa..a06267a4 100644
--- a/src/helper.js
+++ b/src/helper.js
@@ -33,6 +33,8 @@ const Helper = {
ip2hex,
mergeConfig,
getDefaultNick,
+ parseHostmask,
+ compareHostmask,
password: {
hash: passwordHash,
@@ -226,3 +228,43 @@ function mergeConfig(oldConfig, newConfig) {
}
});
}
+
+function parseHostmask(hostmask) {
+ let nick = "";
+ let ident = "*";
+ let hostname = "*";
+ let parts = [];
+
+ // Parse hostname first, then parse the rest
+ parts = hostmask.split("@");
+
+ if (parts.length >= 2) {
+ hostname = parts[1] || "*";
+ hostmask = parts[0];
+ }
+
+ hostname = hostname.toLowerCase();
+
+ parts = hostmask.split("!");
+
+ if (parts.length >= 2) {
+ ident = parts[1] || "*";
+ hostmask = parts[0];
+ }
+
+ ident = ident.toLowerCase();
+
+ nick = hostmask.toLowerCase() || "*";
+
+ const result = {
+ nick: nick,
+ ident: ident,
+ hostname: hostname,
+ };
+
+ return result;
+}
+
+function compareHostmask(a, b) {
+ return (a.nick.toLowerCase() === b.nick.toLowerCase() || a.nick === "*") && (a.ident.toLowerCase() === b.ident.toLowerCase() || a.ident === "*") && (a.hostname.toLowerCase() === b.hostname.toLowerCase() || a.hostname === "*");
+}
diff --git a/src/models/msg.js b/src/models/msg.js
index 2d292add..ed87240b 100644
--- a/src/models/msg.js
+++ b/src/models/msg.js
@@ -67,6 +67,7 @@ Msg.Type = {
TOPIC_SET_BY: "topic_set_by",
WHOIS: "whois",
BANLIST: "ban_list",
+ IGNORELIST: "ignore_list",
};
module.exports = Msg;
diff --git a/src/models/network.js b/src/models/network.js
index 22574885..0698c113 100644
--- a/src/models/network.js
+++ b/src/models/network.js
@@ -18,6 +18,7 @@ const filteredFromClient = {
highlightRegex: true,
irc: true,
password: true,
+ ignoreList: true,
};
function Network(attr) {
@@ -41,6 +42,7 @@ function Network(attr) {
NETWORK: "",
},
chanCache: [],
+ ignoreList: [],
});
if (!this.uuid) {
@@ -325,6 +327,7 @@ Network.prototype.export = function() {
"commands",
"ip",
"hostname",
+ "ignoreList",
]);
network.channels = this.channels
diff --git a/src/plugins/inputs/ignore.js b/src/plugins/inputs/ignore.js
new file mode 100644
index 00000000..4b999570
--- /dev/null
+++ b/src/plugins/inputs/ignore.js
@@ -0,0 +1,120 @@
+"use strict";
+
+const Chan = require("../../models/chan");
+const Msg = require("../../models/msg");
+const Helper = require("../../helper");
+
+exports.commands = [
+ "ignore",
+ "unignore",
+ "ignorelist",
+];
+
+exports.input = function(network, chan, cmd, args) {
+ const client = this;
+ let target;
+ let hostmask;
+
+ if (cmd !== "ignorelist" && (args.length === 0 || args[0].trim().length === 0)) {
+ chan.pushMessage(client, new Msg({
+ type: Msg.Type.ERROR,
+ text: `Usage: /${cmd}