571 lines
24 KiB
JavaScript
571 lines
24 KiB
JavaScript
"use strict";
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var hosts_exports = {};
|
|
__export(hosts_exports, {
|
|
commands: () => commands,
|
|
pages: () => pages,
|
|
visualizeRangeList: () => visualizeRangeList
|
|
});
|
|
module.exports = __toCommonJS(hosts_exports);
|
|
var import_lib = require("../../lib");
|
|
const HOST_SUFFIXES = ["res", "proxy", "mobile"];
|
|
const SUFFIX_ALIASES = {
|
|
residential: "res"
|
|
};
|
|
const WHITELISTED_USERIDS = [];
|
|
function checkCanPerform(context, user, permission = "lockdown") {
|
|
if (!WHITELISTED_USERIDS.includes(user.id))
|
|
context.checkCan(permission);
|
|
}
|
|
function getHostType(type) {
|
|
type = toID(type);
|
|
if (HOST_SUFFIXES.includes(type))
|
|
return type;
|
|
if (SUFFIX_ALIASES[type])
|
|
return SUFFIX_ALIASES[type];
|
|
throw new Chat.ErrorMessage(`'${type}' is not a valid host type. Please specify one of ${HOST_SUFFIXES.join(", ")}.`);
|
|
}
|
|
function visualizeRangeList(ranges) {
|
|
let html = `<tr><th>Lowest IP address</th><th>Highest IP address</th><th>Host</th></tr>`;
|
|
for (const range of ranges) {
|
|
html += `<tr>`;
|
|
html += `<td>${IPTools.numberToIP(range.minIP)}</td>`;
|
|
html += `<td>${IPTools.numberToIP(range.maxIP)}</td>`;
|
|
html += import_lib.Utils.html`<td>${range.host}</td>`;
|
|
html += `</tr>`;
|
|
}
|
|
return html;
|
|
}
|
|
function formatRange(range, includeModlogBrackets) {
|
|
const startBracket = includeModlogBrackets ? "[" : "";
|
|
const endBracket = includeModlogBrackets ? "]" : "";
|
|
let result = `${startBracket}${IPTools.numberToIP(range.minIP)}${endBracket}`;
|
|
result += `-${startBracket}${IPTools.numberToIP(range.maxIP)}${endBracket}`;
|
|
if (range.host)
|
|
result += ` (${range.host})`;
|
|
return result;
|
|
}
|
|
const pages = {
|
|
proxies(query, user) {
|
|
this.title = "[Proxies]";
|
|
checkCanPerform(this, user, "globalban");
|
|
const openProxies = [...IPTools.singleIPOpenProxies];
|
|
const proxyHosts = [...IPTools.proxyHosts];
|
|
import_lib.Utils.sortBy(openProxies, (ip) => {
|
|
const number = IPTools.ipToNumber(ip);
|
|
if (number === null) {
|
|
Rooms.get("upperstaff")?.add(`|error|Invalid IP address in IPTools.singleIPOpenProxies: '${ip}'`);
|
|
return -1;
|
|
}
|
|
return number;
|
|
});
|
|
proxyHosts.sort();
|
|
IPTools.sortRanges();
|
|
let html = `<div class="ladder pad"><h2>Single IP proxies:</h2><table><tr><th>IP</th><th>Type</th></tr>`;
|
|
for (const proxyIP of openProxies) {
|
|
html += `<tr><td>${proxyIP}</td><td>Single IP open proxy</td></tr>`;
|
|
}
|
|
html += `</table></div>`;
|
|
html += `<div class="ladder pad"><h2>Proxy hosts:</h2><table><tr><th>Host</th><th>Type</th></tr>`;
|
|
for (const proxyHost of proxyHosts) {
|
|
html += `<tr><td>${proxyHost}</td><td>Proxy host</td></tr>`;
|
|
}
|
|
html += `</table></div>`;
|
|
html += `<div class="ladder pad"><h2>Proxy IP Ranges:</h2><table>`;
|
|
html += visualizeRangeList(IPTools.ranges.filter((r) => r.host?.endsWith("/proxy")));
|
|
html += `</table></div>`;
|
|
return html;
|
|
},
|
|
hosts(query, user) {
|
|
this.title = "[Hosts]";
|
|
checkCanPerform(this, user, "globalban");
|
|
const type = toID(query[0]) || "all";
|
|
IPTools.sortRanges();
|
|
const mobileHosts = ["all", "mobile"].includes(type) ? [...IPTools.mobileHosts] : [];
|
|
const residentialHosts = ["all", "residential", "res"].includes(type) ? [...IPTools.residentialHosts] : [];
|
|
const hostRanges = ["all", "ranges", "isps"].includes(type) ? IPTools.ranges.filter((r) => r.host && !r.host.endsWith("/proxy")) : [];
|
|
mobileHosts.sort();
|
|
residentialHosts.sort();
|
|
let html = `<div class="ladder pad"><h2>Mobile hosts:</h2><table><tr><th>Host</th><th>Type</th></tr>`;
|
|
for (const mobileHost of mobileHosts) {
|
|
html += `<tr><td>${mobileHost}</td><td>Mobile host</td></tr>`;
|
|
}
|
|
html += `</table></div>`;
|
|
html += `<div class="ladder pad"><h2>Residential hosts:</h2><table><tr><th>Host</th><th>Type</th></tr>`;
|
|
for (const resHost of residentialHosts) {
|
|
html += `<tr><td>${resHost}</td><td>Residential host</td></tr>`;
|
|
}
|
|
html += `</table></div>`;
|
|
html += `<div class="ladder pad"><h2>ISP IP Ranges:</h2><table>`;
|
|
html += visualizeRangeList(hostRanges);
|
|
html += `</table></div>`;
|
|
return html;
|
|
},
|
|
ranges(query, user) {
|
|
this.title = "[IP Ranges]";
|
|
checkCanPerform(this, user, "globalban");
|
|
const type = toID(query[0]) || "all";
|
|
IPTools.sortRanges();
|
|
let html = ``;
|
|
if (["all", "mobile"].includes(type)) {
|
|
html += `<div class="ladder pad"><h2>Mobile IP Ranges:</h2><table>`;
|
|
html += visualizeRangeList(IPTools.ranges.filter((range) => range.host?.endsWith("/mobile")));
|
|
html += `</table></div>`;
|
|
}
|
|
if (["all", "res", "residential"].includes(type)) {
|
|
html += `<div class="ladder pad"><h2>Residential IP Ranges:</h2><table>`;
|
|
html += visualizeRangeList(IPTools.ranges.filter((range) => range.host?.endsWith("/res")));
|
|
html += `</table></div>`;
|
|
}
|
|
if (["all", "proxy", "proxies"].includes(type)) {
|
|
html += `<div class="ladder pad"><h2>Proxy IP Ranges:</h2><table>`;
|
|
html += visualizeRangeList(IPTools.ranges.filter((range) => range.host?.endsWith("/proxy")));
|
|
html += `</table></div>`;
|
|
}
|
|
if (["all", "openproxy"].includes(type)) {
|
|
html += `<div class="ladder pad"><h2>Single-IP Open Proxies:</h2><table>`;
|
|
for (const ip of IPTools.singleIPOpenProxies) {
|
|
html += `<tr><td>${ip}</td></tr>`;
|
|
}
|
|
html += `</table></div>`;
|
|
}
|
|
return html;
|
|
},
|
|
sharedipblacklist(args, user, connection) {
|
|
this.title = `[Shared IP Blacklist]`;
|
|
checkCanPerform(this, user, "lock");
|
|
let buf = `<div class="pad"><h2>IPs blocked from being marked as shared</h2>`;
|
|
if (!Punishments.sharedIpBlacklist.size) {
|
|
buf += `<p>None currently.</p>`;
|
|
} else {
|
|
buf += `<div class="ladder"><table><tr><th>IP</th><th>Reason</th></tr>`;
|
|
const sortedSharedIPBlacklist = [...Punishments.sharedIpBlacklist];
|
|
import_lib.Utils.sortBy(sortedSharedIPBlacklist, ([ipOrRange]) => {
|
|
if (IPTools.ipRegex.test(ipOrRange)) {
|
|
const number = IPTools.ipToNumber(ipOrRange);
|
|
if (number === null) {
|
|
Monitor.error(`Invalid blacklisted-from-markshared IP: '${ipOrRange}`);
|
|
return -1;
|
|
}
|
|
return number;
|
|
}
|
|
return IPTools.stringToRange(ipOrRange).minIP;
|
|
});
|
|
for (const [ip, reason] of sortedSharedIPBlacklist) {
|
|
buf += `<tr><td>${ip}</td><td>${reason}</td></tr>`;
|
|
}
|
|
buf += `</table></div>`;
|
|
}
|
|
buf += `</div>`;
|
|
return buf;
|
|
},
|
|
sharedips(args, user, connection) {
|
|
this.title = `[Shared IPs]`;
|
|
checkCanPerform(this, user, "globalban");
|
|
let buf = `<div class="pad"><h2>IPs marked as shared</h2>`;
|
|
if (!Punishments.sharedIps.size) {
|
|
buf += `<p>None currently.</p>`;
|
|
} else {
|
|
buf += `<div class="ladder"><table><tr><th>IP</th><th>Location</th></tr>`;
|
|
const sortedSharedIPs = [...Punishments.sharedIps];
|
|
import_lib.Utils.sortBy(sortedSharedIPs, ([ip]) => {
|
|
const number = IPTools.ipToNumber(ip);
|
|
if (number === null) {
|
|
Monitor.error(`Invalid shared IP address: '${ip}'`);
|
|
return -1;
|
|
}
|
|
return number;
|
|
});
|
|
for (const [ip, location] of sortedSharedIPs) {
|
|
buf += `<tr><td>${ip}</td><td>${location}</td></tr>`;
|
|
}
|
|
buf += `</table></div>`;
|
|
}
|
|
buf += `</div>`;
|
|
return buf;
|
|
}
|
|
};
|
|
const commands = {
|
|
dc: "ipranges",
|
|
datacenter: "ipranges",
|
|
datacenters: "ipranges",
|
|
iprange: "ipranges",
|
|
ipranges: {
|
|
"": "help",
|
|
help() {
|
|
return this.parse("/help ipranges");
|
|
},
|
|
show: "view",
|
|
view(target, room, user) {
|
|
checkCanPerform(this, user, "globalban");
|
|
const types = ["all", "residential", "res", "mobile", "proxy", "openproxy"];
|
|
const type = target ? toID(target) : "all";
|
|
if (!types.includes(type)) {
|
|
return this.errorReply(`'${type}' isn't a valid host type. Specify one of ${types.join(", ")}.`);
|
|
}
|
|
return this.parse(`/join view-ranges-${type}`);
|
|
},
|
|
viewhelp: [
|
|
`/ipranges view - View the list of all IP ranges. Requires: hosts manager @ &`,
|
|
`/ipranges view [type] - View the list of a particular type of IP range ('residential', 'mobile', or 'proxy'). Requires: hosts manager @ &`
|
|
],
|
|
// Originally by Zarel
|
|
widen: "add",
|
|
add(target, room, user, connection, cmd) {
|
|
checkCanPerform(this, user, "globalban");
|
|
if (!target)
|
|
return this.parse("/help ipranges add");
|
|
const widen = cmd.includes("widen");
|
|
const [typeString, stringRange, host] = target.split(",").map((part) => part.trim());
|
|
if (!host || !IPTools.hostRegex.test(host)) {
|
|
return this.errorReply(`Invalid data: ${target}`);
|
|
}
|
|
const type = getHostType(typeString);
|
|
const range = IPTools.stringToRange(stringRange);
|
|
if (!range)
|
|
return this.errorReply(`Couldn't parse IP range '${stringRange}'.`);
|
|
range.host = `${IPTools.urlToHost(host)}?/${type}`;
|
|
IPTools.sortRanges();
|
|
let result;
|
|
try {
|
|
result = IPTools.checkRangeConflicts(range, IPTools.ranges, widen);
|
|
} catch (e) {
|
|
return this.errorReply(e.message);
|
|
}
|
|
if (typeof result === "number") {
|
|
IPTools.removeRange(IPTools.ranges[result].minIP, IPTools.ranges[result].maxIP);
|
|
}
|
|
IPTools.addRange(range);
|
|
this.privateGlobalModAction(`${user.name} added the IP range ${formatRange(range)} to the list of ${type} ranges.`);
|
|
this.globalModlog("IPRANGE ADD", null, formatRange(range, true));
|
|
},
|
|
addhelp: [
|
|
`/ipranges add [type], [low]-[high], [host] - Adds an IP range. Requires: hosts manager &`,
|
|
`/ipranges widen [type], [low]-[high], [host] - Adds an IP range, allowing a new range to completely cover an old range. Requires: hosts manager &`,
|
|
`For example: /ipranges add proxy, 5.152.192.0 - 5.152.223.255, redstation.com`,
|
|
`Get datacenter info from whois; [low], [high] are the range in the last inetnum; [type] is one of res, proxy, or mobile.`
|
|
],
|
|
remove(target, room, user) {
|
|
checkCanPerform(this, user);
|
|
if (!target)
|
|
return this.parse("/help ipranges remove");
|
|
const range = IPTools.stringToRange(target);
|
|
if (!range)
|
|
return this.errorReply(`Couldn't parse the IP range '${target}'.`);
|
|
if (!IPTools.getRange(range.minIP, range.maxIP))
|
|
return this.errorReply(`No IP range found at '${target}'.`);
|
|
void IPTools.removeRange(range.minIP, range.maxIP);
|
|
this.privateGlobalModAction(`${user.name} removed the IP range ${formatRange(range)}.`);
|
|
this.globalModlog("IPRANGE REMOVE", null, formatRange(range, true));
|
|
},
|
|
removehelp: [
|
|
`/ipranges remove [low IP]-[high IP] - Removes an IP range. Requires: hosts manager &`,
|
|
`Example: /ipranges remove 5.152.192.0-5.152.223.255`
|
|
],
|
|
rename(target, room, user) {
|
|
checkCanPerform(this, user);
|
|
if (!target)
|
|
return this.parse("/help ipranges rename");
|
|
const [type, rangeString, url] = target.split(",").map((part) => part.trim());
|
|
if (!url) {
|
|
return this.parse("/help ipranges rename");
|
|
}
|
|
const toRename = IPTools.stringToRange(rangeString);
|
|
if (!toRename)
|
|
return this.errorReply(`Couldn't parse IP range '${rangeString}'.`);
|
|
const exists = IPTools.getRange(toRename.minIP, toRename.maxIP);
|
|
if (!exists)
|
|
return this.errorReply(`No IP range found at '${rangeString}'.`);
|
|
const range = {
|
|
minIP: toRename.minIP,
|
|
maxIP: toRename.maxIP,
|
|
host: `${IPTools.urlToHost(url)}?/${type}`
|
|
};
|
|
void IPTools.addRange(range);
|
|
this.privateGlobalModAction(`${user.name} renamed the IP range ${formatRange(toRename)} to ${range.host}.`);
|
|
this.globalModlog("IPRANGE RENAME", null, `IP range ${formatRange(toRename, true)} to ${range.host}`);
|
|
},
|
|
renamehelp: [
|
|
`/ipranges rename [type], [low IP]-[high IP], [host] - Changes the host an IP range resolves to. Requires: hosts manager &`
|
|
]
|
|
},
|
|
iprangeshelp() {
|
|
const help = [
|
|
`<code>/ipranges view [type]</code>: view the list of a particular type of IP range (<code>residential</code>, <code>mobile</code>, or <code>proxy</code>). Requires: hosts manager @ &`,
|
|
`<code>/ipranges add [type], [low IP]-[high IP], [host]</code>: add IP ranges (can be multiline). Requires: hosts manager &</summary><code>/ipranges view</code>: view the list of all IP ranges. Requires: hosts manager @ &`,
|
|
`<code>/ipranges widen [type], [low IP]-[high IP], [host]</code>: add IP ranges, allowing a new range to completely cover an old range. Requires: hosts manager &`,
|
|
`For example: <code>/ipranges add proxy, 5.152.192.0-5.152.223.255, redstation.com</code>.`,
|
|
`Get datacenter info from <code>/whois</code>; <code>[low IP]</code>, <code>[high IP]</code> are the range in the last inetnum.`,
|
|
`<code>/ipranges remove [low IP]-[high IP]</code>: remove IP range(s). Can be multiline. Requires: hosts manager &`,
|
|
`For example: <code>/ipranges remove 5.152.192.0, 5.152.223.255</code>.`,
|
|
`<code>/ipranges rename [type], [low IP]-[high IP], [host]</code>: changes the host an IP range resolves to. Requires: hosts manager &`
|
|
];
|
|
return this.sendReply(`|html|<details class="readmore"><summary>${help.join("<br />")}`);
|
|
},
|
|
viewhosts(target, room, user) {
|
|
checkCanPerform(this, user, "globalban");
|
|
const types = ["all", "residential", "mobile", "ranges"];
|
|
const type = target ? toID(target) : "all";
|
|
if (!types.includes(type)) {
|
|
return this.errorReply(`'${type}' isn't a valid host type. Specify one of ${types.join(", ")}.`);
|
|
}
|
|
return this.parse(`/join view-hosts-${type}`);
|
|
},
|
|
viewhostshelp: [
|
|
`/viewhosts - View the list of hosts. Requires: hosts manager @ &`,
|
|
`/viewhosts [type] - View the list of a particular type of host. Requires: hosts manager @ &`,
|
|
`Host types are: 'all', 'residential', 'mobile', and 'ranges'.`
|
|
],
|
|
removehost: "addhosts",
|
|
removehosts: "addhosts",
|
|
addhost: "addhosts",
|
|
addhosts(target, room, user, connection, cmd) {
|
|
checkCanPerform(this, user);
|
|
const removing = cmd.includes("remove");
|
|
let [type, ...hosts] = target.split(",");
|
|
type = toID(type);
|
|
hosts = hosts.map((host) => host.trim());
|
|
if (!hosts.length)
|
|
return this.parse("/help addhosts");
|
|
switch (type) {
|
|
case "openproxy":
|
|
for (const host of hosts) {
|
|
if (!IPTools.ipRegex.test(host))
|
|
return this.errorReply(`'${host}' is not a valid IP address.`);
|
|
if (removing !== IPTools.singleIPOpenProxies.has(host)) {
|
|
return this.errorReply(`'${host}' is ${removing ? "not" : "already"} in the list of proxy IPs.`);
|
|
}
|
|
}
|
|
if (removing) {
|
|
void IPTools.removeOpenProxies(hosts);
|
|
} else {
|
|
void IPTools.addOpenProxies(hosts);
|
|
}
|
|
break;
|
|
case "proxy":
|
|
for (const host of hosts) {
|
|
if (!IPTools.hostRegex.test(host))
|
|
return this.errorReply(`'${host}' is not a valid host.`);
|
|
if (removing !== IPTools.proxyHosts.has(host)) {
|
|
return this.errorReply(`'${host}' is ${removing ? "not" : "already"} in the list of proxy hosts.`);
|
|
}
|
|
}
|
|
if (removing) {
|
|
void IPTools.removeProxyHosts(hosts);
|
|
} else {
|
|
void IPTools.addProxyHosts(hosts);
|
|
}
|
|
break;
|
|
case "residential":
|
|
for (const host of hosts) {
|
|
if (!IPTools.hostRegex.test(host))
|
|
return this.errorReply(`'${host}' is not a valid host.`);
|
|
if (removing !== IPTools.residentialHosts.has(host)) {
|
|
return this.errorReply(`'${host}' is ${removing ? "not" : "already"} in the list of residential hosts.`);
|
|
}
|
|
}
|
|
if (removing) {
|
|
void IPTools.removeResidentialHosts(hosts);
|
|
} else {
|
|
void IPTools.addResidentialHosts(hosts);
|
|
}
|
|
break;
|
|
case "mobile":
|
|
for (const host of hosts) {
|
|
if (!IPTools.hostRegex.test(host))
|
|
return this.errorReply(`'${host}' is not a valid host.`);
|
|
if (removing !== IPTools.mobileHosts.has(host)) {
|
|
return this.errorReply(`'${host}' is ${removing ? "not" : "already"} in the list of mobile hosts.`);
|
|
}
|
|
}
|
|
if (removing) {
|
|
void IPTools.removeMobileHosts(hosts);
|
|
} else {
|
|
void IPTools.addMobileHosts(hosts);
|
|
}
|
|
break;
|
|
default:
|
|
return this.errorReply(`'${type}' isn't one of 'openproxy', 'proxy', 'residential', or 'mobile'.`);
|
|
}
|
|
this.privateGlobalModAction(
|
|
`${user.name} ${removing ? "removed" : "added"} ${hosts.length} hosts (${hosts.join(", ")}) ${removing ? "from" : "to"} the ${type} category`
|
|
);
|
|
this.globalModlog(removing ? "REMOVEHOSTS" : "ADDHOSTS", null, `${type}: ${hosts.join(", ")}`);
|
|
},
|
|
addhostshelp: [
|
|
`/addhosts [category], host1, host2, ... - Adds hosts to the given category. Requires: hosts manager &`,
|
|
`/removehosts [category], host1, host2, ... - Removes hosts from the given category. Requires: hosts manager &`,
|
|
`Categories are: 'openproxy' (which takes IP addresses, not hosts), 'proxy', 'residential', and 'mobile'.`
|
|
],
|
|
viewproxies(target, room, user) {
|
|
checkCanPerform(this, user, "globalban");
|
|
return this.parse("/join view-proxies");
|
|
},
|
|
viewproxieshelp: [
|
|
`/viewproxies - View the list of proxies. Requires: hosts manager @ &`
|
|
],
|
|
markshared(target, room, user) {
|
|
if (!target)
|
|
return this.parse("/help markshared");
|
|
checkCanPerform(this, user, "globalban");
|
|
const [ip, note] = this.splitOne(target);
|
|
if (!IPTools.ipRegex.test(ip)) {
|
|
const pattern = IPTools.stringToRange(ip);
|
|
if (!pattern) {
|
|
return this.errorReply("Please enter a valid IP address.");
|
|
}
|
|
if (!user.can("rangeban")) {
|
|
return this.errorReply("Only upper staff can markshare ranges.");
|
|
}
|
|
for (const range of Punishments.sharedRanges.keys()) {
|
|
if (IPTools.rangeIntersects(range, pattern)) {
|
|
return this.errorReply(
|
|
`Range ${IPTools.rangeToString(pattern)} intersects with shared range ${IPTools.rangeToString(range)}`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if (Punishments.isSharedIp(ip))
|
|
return this.errorReply("This IP is already marked as shared.");
|
|
if (Punishments.isBlacklistedSharedIp(ip)) {
|
|
return this.errorReply(`This IP is blacklisted from being marked as shared.`);
|
|
}
|
|
if (!note) {
|
|
this.errorReply(`You must specify who owns this shared IP.`);
|
|
this.parse(`/help markshared`);
|
|
return;
|
|
}
|
|
Punishments.addSharedIp(ip, note);
|
|
this.privateGlobalModAction(`The IP '${ip}' was marked as shared by ${user.name}. (${note})`);
|
|
this.globalModlog("SHAREDIP", null, note, ip);
|
|
},
|
|
marksharedhelp: [
|
|
`/markshared [IP], [owner/organization of IP] - Marks an IP address as shared.`,
|
|
`Note: the owner/organization (i.e., University of Minnesota) of the shared IP is required. Requires @ &`
|
|
],
|
|
unmarkshared(target, room, user) {
|
|
if (!target)
|
|
return this.parse("/help unmarkshared");
|
|
checkCanPerform(this, user, "globalban");
|
|
target = target.trim();
|
|
const pattern = IPTools.stringToRange(target);
|
|
if (!pattern)
|
|
return this.errorReply("Please enter a valid IP address.");
|
|
if (pattern.minIP !== pattern.maxIP && !user.can("rangeban")) {
|
|
return this.errorReply(`Only administrators can unmarkshare ranges.`);
|
|
}
|
|
let shared = false;
|
|
if (pattern.minIP !== pattern.maxIP) {
|
|
for (const range of Punishments.sharedRanges.keys()) {
|
|
shared = range.minIP === pattern.minIP && range.maxIP === pattern.maxIP;
|
|
if (shared)
|
|
break;
|
|
}
|
|
} else {
|
|
shared = Punishments.sharedIps.has(target);
|
|
}
|
|
if (!shared)
|
|
return this.errorReply(`That IP/range isn't marked as shared.`);
|
|
Punishments.removeSharedIp(target);
|
|
this.privateGlobalModAction(`The IP '${target}' was unmarked as shared by ${user.name}.`);
|
|
this.globalModlog("UNSHAREDIP", null, null, target);
|
|
},
|
|
unmarksharedhelp: [`/unmarkshared [IP] - Unmarks a shared IP address. Requires @ &`],
|
|
marksharedblacklist: "nomarkshared",
|
|
marksharedbl: "nomarkshared",
|
|
nomarkshared: {
|
|
add(target, room, user) {
|
|
if (!target)
|
|
return this.parse(`/help nomarkshared`);
|
|
checkCanPerform(this, user, "globalban");
|
|
const [ip, ...reasonArr] = target.split(",");
|
|
if (!IPTools.ipRangeRegex.test(ip))
|
|
return this.errorReply(`Please enter a valid IP address or range.`);
|
|
if (!reasonArr?.length) {
|
|
this.errorReply(`A reason is required.`);
|
|
this.parse(`/help nomarkshared`);
|
|
return;
|
|
}
|
|
if (Punishments.isBlacklistedSharedIp(ip)) {
|
|
return this.errorReply(`This IP is already blacklisted from being marked as shared.`);
|
|
}
|
|
if (!IPTools.ipRegex.test(ip)) {
|
|
if (!ip.endsWith("*")) {
|
|
this.errorReply(`That looks like a range, but it is invalid.`);
|
|
this.errorReply(`Append * to the end of the range and try again.`);
|
|
return;
|
|
}
|
|
if (!user.can("bypassall")) {
|
|
return this.errorReply(`Only Administrators can add ranges.`);
|
|
}
|
|
const range = IPTools.stringToRange(ip);
|
|
if (!range)
|
|
return this.errorReply(`Invalid IP range.`);
|
|
for (const sharedIp of Punishments.sharedIps.keys()) {
|
|
const ipNum = IPTools.ipToNumber(sharedIp);
|
|
if (IPTools.checkPattern([range], ipNum)) {
|
|
this.parse(`/unmarkshared ${sharedIp}`);
|
|
}
|
|
}
|
|
} else {
|
|
if (Punishments.isSharedIp(ip))
|
|
this.parse(`/unmarkshared ${ip}`);
|
|
}
|
|
const reason = reasonArr.join(",");
|
|
Punishments.addBlacklistedSharedIp(ip, reason);
|
|
this.privateGlobalModAction(`The IP '${ip}' was blacklisted from being marked as shared by ${user.name}.`);
|
|
this.globalModlog("SHAREDIP BLACKLIST", null, reason.trim(), ip);
|
|
},
|
|
remove(target, room, user) {
|
|
if (!target)
|
|
return this.parse(`/help nomarkshared`);
|
|
checkCanPerform(this, user);
|
|
if (!IPTools.ipRangeRegex.test(target))
|
|
return this.errorReply(`Please enter a valid IP address or range.`);
|
|
if (!Punishments.sharedIpBlacklist.has(target)) {
|
|
return this.errorReply(`This IP is not blacklisted from being marked as shared.`);
|
|
}
|
|
Punishments.removeBlacklistedSharedIp(target);
|
|
this.privateGlobalModAction(`The IP '${target}' was unblacklisted from being marked as shared by ${user.name}.`);
|
|
this.globalModlog("SHAREDIP UNBLACKLIST", null, null, target);
|
|
},
|
|
view() {
|
|
return this.parse(`/join view-sharedipblacklist`);
|
|
},
|
|
help: "",
|
|
""() {
|
|
return this.parse(`/help nomarkshared`);
|
|
}
|
|
},
|
|
nomarksharedhelp: [
|
|
`/nomarkshared add [IP], [reason] - Prevents an IP from being marked as shared until it's removed from this list. Requires &`,
|
|
`Note: Reasons are required.`,
|
|
`/nomarkshared remove [IP] - Removes an IP from the nomarkshared list. Requires &`,
|
|
`/nomarkshared view - Lists all IPs prevented from being marked as shared. Requires @ &`
|
|
],
|
|
sharedips: "viewsharedips",
|
|
viewsharedips() {
|
|
return this.parse("/join view-sharedips");
|
|
},
|
|
viewsharedipshelp: [
|
|
`/viewsharedips \u2014 Lists IP addresses marked as shared. Requires: hosts manager @ &`
|
|
]
|
|
};
|
|
//# sourceMappingURL=hosts.js.map
|