{
"version": 3,
"sources": ["../../../server/chat-plugins/hosts.ts"],
"sourcesContent": ["/**\n * Chat plugin to help manage hosts, proxies, and datacenters\n * Written by Annika\n * Original /adddatacenters command written by Zarel\n */\n\nimport { Utils } from \"../../lib\";\nimport type { AddressRange } from \"../ip-tools\";\nimport type { GlobalPermission } from \"../user-groups\";\n\nconst HOST_SUFFIXES = ['res', 'proxy', 'mobile'];\nconst SUFFIX_ALIASES: { [k: string]: string } = {\n\tresidential: 'res',\n};\nconst WHITELISTED_USERIDS: ID[] = [];\n\nfunction checkCanPerform(\n\tcontext: Chat.PageContext | Chat.CommandContext, user: User, permission: GlobalPermission = 'lockdown'\n) {\n\tif (!WHITELISTED_USERIDS.includes(user.id)) context.checkCan(permission);\n}\n\nfunction getHostType(type: string) {\n\ttype = toID(type);\n\tif (HOST_SUFFIXES.includes(type)) return type;\n\tif (SUFFIX_ALIASES[type]) return SUFFIX_ALIASES[type];\n\tthrow new Chat.ErrorMessage(`'${type}' is not a valid host type. Please specify one of ${HOST_SUFFIXES.join(', ')}.`);\n}\n\nexport function visualizeRangeList(ranges: AddressRange[]) {\n\tlet html = `
Lowest IP address | Highest IP address | Host |
`;\n\tfor (const range of ranges) {\n\t\thtml += ``;\n\t\thtml += `${IPTools.numberToIP(range.minIP)} | `;\n\t\thtml += `${IPTools.numberToIP(range.maxIP)} | `;\n\t\thtml += Utils.html`${range.host} | `;\n\t\thtml += `
`;\n\t}\n\treturn html;\n}\n\nfunction formatRange(range: AddressRange, includeModlogBrackets?: boolean) {\n\tconst startBracket = includeModlogBrackets ? '[' : '';\n\tconst endBracket = includeModlogBrackets ? ']' : '';\n\n\tlet result = `${startBracket}${IPTools.numberToIP(range.minIP)}${endBracket}`;\n\tresult += `-${startBracket}${IPTools.numberToIP(range.maxIP)}${endBracket}`;\n\tif (range.host) result += ` (${range.host})`;\n\n\treturn result;\n}\n\nexport const pages: Chat.PageTable = {\n\tproxies(query, user) {\n\t\tthis.title = \"[Proxies]\";\n\t\tcheckCanPerform(this, user, 'globalban');\n\n\t\tconst openProxies = [...IPTools.singleIPOpenProxies];\n\t\tconst proxyHosts = [...IPTools.proxyHosts];\n\t\tUtils.sortBy(openProxies, ip => {\n\t\t\tconst number = IPTools.ipToNumber(ip);\n\t\t\tif (number === null) {\n\t\t\t\tRooms.get('upperstaff')?.add(`|error|Invalid IP address in IPTools.singleIPOpenProxies: '${ip}'`);\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\treturn number;\n\t\t});\n\t\tproxyHosts.sort();\n\t\tIPTools.sortRanges();\n\n\t\tlet html = `Single IP proxies:
IP | Type |
`;\n\t\tfor (const proxyIP of openProxies) {\n\t\t\thtml += `${proxyIP} | Single IP open proxy |
`;\n\t\t}\n\t\thtml += `
`;\n\n\t\thtml += `Proxy hosts:
Host | Type |
`;\n\t\tfor (const proxyHost of proxyHosts) {\n\t\t\thtml += `${proxyHost} | Proxy host |
`;\n\t\t}\n\t\thtml += `
`;\n\n\t\thtml += `Proxy IP Ranges:
`;\n\t\thtml += visualizeRangeList(IPTools.ranges.filter(r => r.host?.endsWith('/proxy')));\n\t\thtml += `
`;\n\t\treturn html;\n\t},\n\n\thosts(query, user) {\n\t\tthis.title = \"[Hosts]\";\n\t\tcheckCanPerform(this, user, 'globalban');\n\t\tconst type = toID(query[0]) || 'all';\n\n\t\tIPTools.sortRanges();\n\t\tconst mobileHosts = ['all', 'mobile'].includes(type) ? [...IPTools.mobileHosts] : [];\n\t\tconst residentialHosts = ['all', 'residential', 'res'].includes(type) ? [...IPTools.residentialHosts] : [];\n\t\tconst hostRanges = ['all', 'ranges', 'isps'].includes(type) ?\n\t\t\tIPTools.ranges.filter(r => r.host && !r.host.endsWith('/proxy')) :\n\t\t\t[];\n\t\tmobileHosts.sort();\n\t\tresidentialHosts.sort();\n\n\t\tlet html = `Mobile hosts:
Host | Type |
`;\n\t\tfor (const mobileHost of mobileHosts) {\n\t\t\thtml += `${mobileHost} | Mobile host |
`;\n\t\t}\n\t\thtml += `
`;\n\n\t\thtml += `Residential hosts:
Host | Type |
`;\n\t\tfor (const resHost of residentialHosts) {\n\t\t\thtml += `${resHost} | Residential host |
`;\n\t\t}\n\t\thtml += `
`;\n\n\t\thtml += `ISP IP Ranges:
`;\n\t\thtml += visualizeRangeList(hostRanges);\n\t\thtml += `
`;\n\t\treturn html;\n\t},\n\n\tranges(query, user) {\n\t\tthis.title = \"[IP Ranges]\";\n\t\tcheckCanPerform(this, user, 'globalban');\n\t\tconst type = toID(query[0]) || 'all';\n\t\tIPTools.sortRanges();\n\n\t\tlet html = ``;\n\t\tif (['all', 'mobile'].includes(type)) {\n\t\t\thtml += `Mobile IP Ranges:
`;\n\t\t\thtml += visualizeRangeList(IPTools.ranges.filter(range => range.host?.endsWith('/mobile')));\n\t\t\thtml += `
`;\n\t\t}\n\t\tif (['all', 'res', 'residential'].includes(type)) {\n\t\t\thtml += `Residential IP Ranges:
`;\n\t\t\thtml += visualizeRangeList(IPTools.ranges.filter(range => range.host?.endsWith('/res')));\n\t\t\thtml += `
`;\n\t\t}\n\t\tif (['all', 'proxy', 'proxies'].includes(type)) {\n\t\t\thtml += `Proxy IP Ranges:
`;\n\t\t\thtml += visualizeRangeList(IPTools.ranges.filter(range => range.host?.endsWith('/proxy')));\n\t\t\thtml += `
`;\n\t\t}\n\t\tif (['all', 'openproxy'].includes(type)) {\n\t\t\thtml += `Single-IP Open Proxies:
`;\n\t\t\tfor (const ip of IPTools.singleIPOpenProxies) {\n\t\t\t\thtml += `${ip} |
`;\n\t\t\t}\n\t\t\thtml += `
`;\n\t\t}\n\t\treturn html;\n\t},\n\n\tsharedipblacklist(args, user, connection) {\n\t\tthis.title = `[Shared IP Blacklist]`;\n\t\tcheckCanPerform(this, user, 'lock');\n\n\t\tlet buf = `IPs blocked from being marked as shared
`;\n\t\tif (!Punishments.sharedIpBlacklist.size) {\n\t\t\tbuf += `
None currently.
`;\n\t\t} else {\n\t\t\tbuf += `
IP | Reason |
`;\n\t\t\tconst sortedSharedIPBlacklist = [...Punishments.sharedIpBlacklist];\n\t\t\tUtils.sortBy(sortedSharedIPBlacklist, ([ipOrRange]) => {\n\t\t\t\tif (IPTools.ipRegex.test(ipOrRange)) {\n\t\t\t\t\tconst number = IPTools.ipToNumber(ipOrRange);\n\t\t\t\t\tif (number === null) {\n\t\t\t\t\t\tMonitor.error(`Invalid blacklisted-from-markshared IP: '${ipOrRange}`);\n\t\t\t\t\t\treturn -1;\n\t\t\t\t\t}\n\t\t\t\t\treturn number;\n\t\t\t\t}\n\t\t\t\treturn IPTools.stringToRange(ipOrRange)!.minIP;\n\t\t\t});\n\t\t\tfor (const [ip, reason] of sortedSharedIPBlacklist) {\n\t\t\t\tbuf += `${ip} | ${reason} |
`;\n\t\t\t}\n\t\t\tbuf += `
`;\n\t\t}\n\t\tbuf += `
`;\n\t\treturn buf;\n\t},\n\n\tsharedips(args, user, connection) {\n\t\tthis.title = `[Shared IPs]`;\n\t\tcheckCanPerform(this, user, 'globalban');\n\n\t\tlet buf = `IPs marked as shared
`;\n\t\tif (!Punishments.sharedIps.size) {\n\t\t\tbuf += `
None currently.
`;\n\t\t} else {\n\t\t\tbuf += `
IP | Location |
`;\n\t\t\tconst sortedSharedIPs = [...Punishments.sharedIps];\n\t\t\tUtils.sortBy(sortedSharedIPs, ([ip]) => {\n\t\t\t\tconst number = IPTools.ipToNumber(ip);\n\t\t\t\tif (number === null) {\n\t\t\t\t\tMonitor.error(`Invalid shared IP address: '${ip}'`);\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\treturn number;\n\t\t\t});\n\n\t\t\tfor (const [ip, location] of sortedSharedIPs) {\n\t\t\t\tbuf += `${ip} | ${location} |
`;\n\t\t\t}\n\t\t\tbuf += `
`;\n\t\t}\n\t\tbuf += `
`;\n\t\treturn buf;\n\t},\n};\n\nexport const commands: Chat.ChatCommands = {\n\tdc: 'ipranges',\n\tdatacenter: 'ipranges',\n\tdatacenters: 'ipranges',\n\tiprange: 'ipranges',\n\tipranges: {\n\t\t'': 'help',\n\t\thelp() {\n\t\t\treturn this.parse('/help ipranges');\n\t\t},\n\n\t\tshow: 'view',\n\t\tview(target, room, user) {\n\t\t\tcheckCanPerform(this, user, 'globalban');\n\t\t\tconst types = ['all', 'residential', 'res', 'mobile', 'proxy', 'openproxy'];\n\t\t\tconst type = target ? toID(target) : 'all';\n\t\t\tif (!types.includes(type)) {\n\t\t\t\treturn this.errorReply(`'${type}' isn't a valid host type. Specify one of ${types.join(', ')}.`);\n\t\t\t}\n\t\t\treturn this.parse(`/join view-ranges-${type}`);\n\t\t},\n\t\tviewhelp: [\n\t\t\t`/ipranges view - View the list of all IP ranges. Requires: hosts manager @ ~`,\n\t\t\t`/ipranges view [type] - View the list of a particular type of IP range ('residential', 'mobile', or 'proxy'). Requires: hosts manager @ ~`,\n\t\t],\n\n\t\t// Originally by Zarel\n\t\twiden: 'add',\n\t\tadd(target, room, user, connection, cmd) {\n\t\t\tcheckCanPerform(this, user, 'globalban');\n\t\t\tif (!target) return this.parse('/help ipranges add');\n\t\t\t// should be in the format: IP, IP, name, URL\n\t\t\tconst widen = cmd.includes('widen');\n\n\t\t\tconst [typeString, stringRange, host] = target.split(',').map(part => part.trim());\n\t\t\tif (!host || !IPTools.hostRegex.test(host)) {\n\t\t\t\treturn this.errorReply(`Invalid data: ${target}`);\n\t\t\t}\n\t\t\tconst type = getHostType(typeString);\n\t\t\tconst range = IPTools.stringToRange(stringRange);\n\t\t\tif (!range) return this.errorReply(`Couldn't parse IP range '${stringRange}'.`);\n\t\t\trange.host = `${IPTools.urlToHost(host)}?/${type}`;\n\n\t\t\tIPTools.sortRanges();\n\t\t\tlet result;\n\t\t\ttry {\n\t\t\t\tresult = IPTools.checkRangeConflicts(range, IPTools.ranges, widen);\n\t\t\t} catch (e: any) {\n\t\t\t\treturn this.errorReply(e.message);\n\t\t\t}\n\t\t\tif (typeof result === 'number') {\n\t\t\t\t// Remove the range that is being widened\n\t\t\t\tIPTools.removeRange(IPTools.ranges[result].minIP, IPTools.ranges[result].maxIP);\n\t\t\t}\n\t\t\tIPTools.addRange(range as AddressRange & { host: string });\n\n\t\t\tthis.privateGlobalModAction(`${user.name} added the IP range ${formatRange(range)} to the list of ${type} ranges.`);\n\t\t\tthis.globalModlog('IPRANGE ADD', null, formatRange(range, true));\n\t\t},\n\t\taddhelp: [\n\t\t\t`/ipranges add [type], [low]-[high], [host] - Adds an IP range. Requires: hosts manager ~`,\n\t\t\t`/ipranges widen [type], [low]-[high], [host] - Adds an IP range, allowing a new range to completely cover an old range. Requires: hosts manager ~`,\n\t\t\t`For example: /ipranges add proxy, 5.152.192.0 - 5.152.223.255, redstation.com`,\n\t\t\t`Get datacenter info from whois; [low], [high] are the range in the last inetnum; [type] is one of res, proxy, or mobile.`,\n\t\t],\n\n\t\tremove(target, room, user) {\n\t\t\tcheckCanPerform(this, user);\n\t\t\tif (!target) return this.parse('/help ipranges remove');\n\n\t\t\tconst range = IPTools.stringToRange(target);\n\t\t\tif (!range) return this.errorReply(`Couldn't parse the IP range '${target}'.`);\n\t\t\tif (!IPTools.getRange(range.minIP, range.maxIP)) return this.errorReply(`No IP range found at '${target}'.`);\n\n\t\t\tvoid IPTools.removeRange(range.minIP, range.maxIP);\n\n\t\t\tthis.privateGlobalModAction(`${user.name} removed the IP range ${formatRange(range)}.`);\n\t\t\tthis.globalModlog('IPRANGE REMOVE', null, formatRange(range, true));\n\t\t},\n\t\tremovehelp: [\n\t\t\t`/ipranges remove [low IP]-[high IP] - Removes an IP range. Requires: hosts manager ~`,\n\t\t\t`Example: /ipranges remove 5.152.192.0-5.152.223.255`,\n\t\t],\n\n\t\trename(target, room, user) {\n\t\t\tcheckCanPerform(this, user);\n\t\t\tif (!target) return this.parse('/help ipranges rename');\n\t\t\tconst [type, rangeString, url] = target.split(',').map(part => part.trim());\n\t\t\tif (!url) {\n\t\t\t\treturn this.parse('/help ipranges rename');\n\t\t\t}\n\t\t\tconst toRename = IPTools.stringToRange(rangeString);\n\t\t\tif (!toRename) return this.errorReply(`Couldn't parse IP range '${rangeString}'.`);\n\t\t\tconst exists = IPTools.getRange(toRename.minIP, toRename.maxIP);\n\t\t\tif (!exists) return this.errorReply(`No IP range found at '${rangeString}'.`);\n\n\t\t\tconst range = {\n\t\t\t\tminIP: toRename.minIP,\n\t\t\t\tmaxIP: toRename.maxIP,\n\t\t\t\thost: `${IPTools.urlToHost(url)}?/${type}`,\n\t\t\t};\n\t\t\tvoid IPTools.addRange(range);\n\n\t\t\tthis.privateGlobalModAction(`${user.name} renamed the IP range ${formatRange(toRename)} to ${range.host}.`);\n\t\t\tthis.globalModlog('IPRANGE RENAME', null, `IP range ${formatRange(toRename, true)} to ${range.host}`);\n\t\t},\n\t\trenamehelp: [\n\t\t\t`/ipranges rename [type], [low IP]-[high IP], [host] - Changes the host an IP range resolves to. Requires: hosts manager ~`,\n\t\t],\n\t},\n\n\tiprangeshelp() {\n\t\tconst help = [\n\t\t\t`/ipranges view [type]
: view the list of a particular type of IP range (residential
, mobile
, or proxy
). Requires: hosts manager @ ~`,\n\t\t\t`/ipranges add [type], [low IP]-[high IP], [host]
: add IP ranges (can be multiline). Requires: hosts manager ~/ipranges view
: view the list of all IP ranges. Requires: hosts manager @ ~`,\n\t\t\t`/ipranges widen [type], [low IP]-[high IP], [host]
: add IP ranges, allowing a new range to completely cover an old range. Requires: hosts manager ~`,\n\t\t\t`For example: /ipranges add proxy, 5.152.192.0-5.152.223.255, redstation.com
.`,\n\t\t\t`Get datacenter info from /whois
; [low IP]
, [high IP]
are the range in the last inetnum.`,\n\t\t\t`/ipranges remove [low IP]-[high IP]
: remove IP range(s). Can be multiline. Requires: hosts manager ~`,\n\t\t\t`For example: /ipranges remove 5.152.192.0, 5.152.223.255
.`,\n\t\t\t`/ipranges rename [type], [low IP]-[high IP], [host]
: changes the host an IP range resolves to. Requires: hosts manager ~`,\n\t\t];\n\t\treturn this.sendReply(`|html|${help.join('
')}`);\n\t},\n\tviewhosts(target, room, user) {\n\t\tcheckCanPerform(this, user, 'globalban');\n\t\tconst types = ['all', 'residential', 'mobile', 'ranges'];\n\t\tconst type = target ? toID(target) : 'all';\n\t\tif (!types.includes(type)) {\n\t\t\treturn this.errorReply(`'${type}' isn't a valid host type. Specify one of ${types.join(', ')}.`);\n\t\t}\n\t\treturn this.parse(`/join view-hosts-${type}`);\n\t},\n\tviewhostshelp: [\n\t\t`/viewhosts - View the list of hosts. Requires: hosts manager @ ~`,\n\t\t`/viewhosts [type] - View the list of a particular type of host. Requires: hosts manager @ ~`,\n\t\t`Host types are: 'all', 'residential', 'mobile', and 'ranges'.`,\n\t],\n\n\tremovehost: 'addhosts',\n\tremovehosts: 'addhosts',\n\taddhost: 'addhosts',\n\taddhosts(target, room, user, connection, cmd) {\n\t\tcheckCanPerform(this, user);\n\t\tconst removing = cmd.includes('remove');\n\t\tlet [type, ...hosts] = target.split(',');\n\t\ttype = toID(type);\n\t\thosts = hosts.map(host => host.trim());\n\t\tif (!hosts.length) return this.parse('/help addhosts');\n\n\t\tswitch (type) {\n\t\tcase 'openproxy':\n\t\t\tfor (const host of hosts) {\n\t\t\t\tif (!IPTools.ipRegex.test(host)) return this.errorReply(`'${host}' is not a valid IP address.`);\n\t\t\t\tif (removing !== IPTools.singleIPOpenProxies.has(host)) {\n\t\t\t\t\treturn this.errorReply(`'${host}' is ${removing ? 'not' : 'already'} in the list of proxy IPs.`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (removing) {\n\t\t\t\tvoid IPTools.removeOpenProxies(hosts);\n\t\t\t} else {\n\t\t\t\tvoid IPTools.addOpenProxies(hosts);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'proxy':\n\t\t\tfor (const host of hosts) {\n\t\t\t\tif (!IPTools.hostRegex.test(host)) return this.errorReply(`'${host}' is not a valid host.`);\n\t\t\t\tif (removing !== IPTools.proxyHosts.has(host)) {\n\t\t\t\t\treturn this.errorReply(`'${host}' is ${removing ? 'not' : 'already'} in the list of proxy hosts.`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (removing) {\n\t\t\t\tvoid IPTools.removeProxyHosts(hosts);\n\t\t\t} else {\n\t\t\t\tvoid IPTools.addProxyHosts(hosts);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'residential':\n\t\t\tfor (const host of hosts) {\n\t\t\t\tif (!IPTools.hostRegex.test(host)) return this.errorReply(`'${host}' is not a valid host.`);\n\t\t\t\tif (removing !== IPTools.residentialHosts.has(host)) {\n\t\t\t\t\treturn this.errorReply(`'${host}' is ${removing ? 'not' : 'already'} in the list of residential hosts.`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (removing) {\n\t\t\t\tvoid IPTools.removeResidentialHosts(hosts);\n\t\t\t} else {\n\t\t\t\tvoid IPTools.addResidentialHosts(hosts);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase 'mobile':\n\t\t\tfor (const host of hosts) {\n\t\t\t\tif (!IPTools.hostRegex.test(host)) return this.errorReply(`'${host}' is not a valid host.`);\n\t\t\t\tif (removing !== IPTools.mobileHosts.has(host)) {\n\t\t\t\t\treturn this.errorReply(`'${host}' is ${removing ? 'not' : 'already'} in the list of mobile hosts.`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (removing) {\n\t\t\t\tvoid IPTools.removeMobileHosts(hosts);\n\t\t\t} else {\n\t\t\t\tvoid IPTools.addMobileHosts(hosts);\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn this.errorReply(`'${type}' isn't one of 'openproxy', 'proxy', 'residential', or 'mobile'.`);\n\t\t}\n\t\tthis.privateGlobalModAction(\n\t\t\t`${user.name} ${removing ? 'removed' : 'added'} ${hosts.length} hosts (${hosts.join(', ')}) ${removing ? 'from' : 'to'} the ${type} category`\n\t\t);\n\t\tthis.globalModlog(removing ? 'REMOVEHOSTS' : 'ADDHOSTS', null, `${type}: ${hosts.join(', ')}`);\n\t},\n\taddhostshelp: [\n\t\t`/addhosts [category], host1, host2, ... - Adds hosts to the given category. Requires: hosts manager ~`,\n\t\t`/removehosts [category], host1, host2, ... - Removes hosts from the given category. Requires: hosts manager ~`,\n\t\t`Categories are: 'openproxy' (which takes IP addresses, not hosts), 'proxy', 'residential', and 'mobile'.`,\n\t],\n\n\tviewproxies(target, room, user) {\n\t\tcheckCanPerform(this, user, 'globalban');\n\t\treturn this.parse('/join view-proxies');\n\t},\n\tviewproxieshelp: [\n\t\t`/viewproxies - View the list of proxies. Requires: hosts manager @ ~`,\n\t],\n\n\tmarkshared(target, room, user) {\n\t\tif (!target) return this.parse('/help markshared');\n\t\tcheckCanPerform(this, user, 'globalban');\n\t\tconst [ip, note] = this.splitOne(target);\n\t\tif (!IPTools.ipRegex.test(ip)) {\n\t\t\tconst pattern = IPTools.stringToRange(ip);\n\t\t\tif (!pattern) {\n\t\t\t\treturn this.errorReply(\"Please enter a valid IP address.\");\n\t\t\t}\n\t\t\tif (!user.can('rangeban')) {\n\t\t\t\treturn this.errorReply('Only upper staff can markshare ranges.');\n\t\t\t}\n\t\t\tfor (const range of Punishments.sharedRanges.keys()) {\n\t\t\t\tif (IPTools.rangeIntersects(range, pattern)) {\n\t\t\t\t\treturn this.errorReply(\n\t\t\t\t\t\t`Range ${IPTools.rangeToString(pattern)} intersects with shared range ${IPTools.rangeToString(range)}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Punishments.isSharedIp(ip)) return this.errorReply(\"This IP is already marked as shared.\");\n\t\tif (Punishments.isBlacklistedSharedIp(ip)) {\n\t\t\treturn this.errorReply(`This IP is blacklisted from being marked as shared.`);\n\t\t}\n\t\tif (!note) {\n\t\t\tthis.errorReply(`You must specify who owns this shared IP.`);\n\t\t\tthis.parse(`/help markshared`);\n\t\t\treturn;\n\t\t}\n\n\t\tPunishments.addSharedIp(ip, note);\n\t\tthis.privateGlobalModAction(`The IP '${ip}' was marked as shared by ${user.name}. (${note})`);\n\t\tthis.globalModlog('SHAREDIP', null, note, ip);\n\t},\n\tmarksharedhelp: [\n\t\t`/markshared [IP], [owner/organization of IP] - Marks an IP address as shared.`,\n\t\t`Note: the owner/organization (i.e., University of Minnesota) of the shared IP is required. Requires @ ~`,\n\t],\n\n\tunmarkshared(target, room, user) {\n\t\tif (!target) return this.parse('/help unmarkshared');\n\t\tcheckCanPerform(this, user, 'globalban');\n\t\ttarget = target.trim();\n\t\tconst pattern = IPTools.stringToRange(target);\n\t\tif (!pattern) return this.errorReply(\"Please enter a valid IP address.\");\n\t\tif (pattern.minIP !== pattern.maxIP && !user.can('rangeban')) {\n\t\t\treturn this.errorReply(`Only administrators can unmarkshare ranges.`);\n\t\t}\n\n\t\tlet shared = false;\n\t\tif (pattern.minIP !== pattern.maxIP) {\n\t\t\tfor (const range of Punishments.sharedRanges.keys()) {\n\t\t\t\tshared = range.minIP === pattern.minIP && range.maxIP === pattern.maxIP;\n\t\t\t\tif (shared) break;\n\t\t\t}\n\t\t} else {\n\t\t\tshared = Punishments.sharedIps.has(target);\n\t\t}\n\n\t\tif (!shared) return this.errorReply(`That IP/range isn't marked as shared.`);\n\n\t\tPunishments.removeSharedIp(target);\n\n\t\tthis.privateGlobalModAction(`The IP '${target}' was unmarked as shared by ${user.name}.`);\n\t\tthis.globalModlog('UNSHAREDIP', null, null, target);\n\t},\n\tunmarksharedhelp: [`/unmarkshared [IP] - Unmarks a shared IP address. Requires @ ~`],\n\n\tmarksharedblacklist: 'nomarkshared',\n\tmarksharedbl: 'nomarkshared',\n\tnomarkshared: {\n\t\tadd(target, room, user) {\n\t\t\tif (!target) return this.parse(`/help nomarkshared`);\n\t\t\tcheckCanPerform(this, user, 'globalban');\n\t\t\tconst [ip, ...reasonArr] = target.split(',');\n\t\t\tif (!IPTools.ipRangeRegex.test(ip)) return this.errorReply(`Please enter a valid IP address or range.`);\n\t\t\tif (!reasonArr?.length) {\n\t\t\t\tthis.errorReply(`A reason is required.`);\n\t\t\t\tthis.parse(`/help nomarkshared`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (Punishments.isBlacklistedSharedIp(ip)) {\n\t\t\t\treturn this.errorReply(`This IP is already blacklisted from being marked as shared.`);\n\t\t\t}\n\t\t\t// this works because we test ipRangeRegex above, which works for both ranges AND single ips.\n\t\t\t// so we know here this is one of the two.\n\t\t\t// If it doesn't work as a single IP, it's a range.\n\t\t\tif (!IPTools.ipRegex.test(ip)) {\n\t\t\t\t// if it doesn't end with *, it doesn't function as a range in IPTools#stringToRange, only as a single IP.\n\t\t\t\t// that's valid behavior, but it's detrimental here.\n\t\t\t\tif (!ip.endsWith('*')) {\n\t\t\t\t\tthis.errorReply(`That looks like a range, but it is invalid.`);\n\t\t\t\t\tthis.errorReply(`Append * to the end of the range and try again.`);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!user.can('bypassall')) {\n\t\t\t\t\treturn this.errorReply(`Only Administrators can add ranges.`);\n\t\t\t\t}\n\t\t\t\tconst range = IPTools.stringToRange(ip);\n\t\t\t\tif (!range) return this.errorReply(`Invalid IP range.`);\n\t\t\t\tfor (const sharedIp of Punishments.sharedIps.keys()) {\n\t\t\t\t\tconst ipNum = IPTools.ipToNumber(sharedIp);\n\t\t\t\t\tif (IPTools.checkPattern([range], ipNum)) {\n\t\t\t\t\t\tthis.parse(`/unmarkshared ${sharedIp}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (Punishments.isSharedIp(ip)) this.parse(`/unmarkshared ${ip}`);\n\t\t\t}\n\t\t\tconst reason = reasonArr.join(',');\n\n\t\t\tPunishments.addBlacklistedSharedIp(ip, reason);\n\n\t\t\tthis.privateGlobalModAction(`The IP '${ip}' was blacklisted from being marked as shared by ${user.name}.`);\n\t\t\tthis.globalModlog('SHAREDIP BLACKLIST', null, reason.trim(), ip);\n\t\t},\n\t\tremove(target, room, user) {\n\t\t\tif (!target) return this.parse(`/help nomarkshared`);\n\t\t\tcheckCanPerform(this, user);\n\t\t\tif (!IPTools.ipRangeRegex.test(target)) return this.errorReply(`Please enter a valid IP address or range.`);\n\t\t\tif (!Punishments.sharedIpBlacklist.has(target)) {\n\t\t\t\treturn this.errorReply(`This IP is not blacklisted from being marked as shared.`);\n\t\t\t}\n\n\t\t\tPunishments.removeBlacklistedSharedIp(target);\n\n\t\t\tthis.privateGlobalModAction(`The IP '${target}' was unblacklisted from being marked as shared by ${user.name}.`);\n\t\t\tthis.globalModlog('SHAREDIP UNBLACKLIST', null, null, target);\n\t\t},\n\t\tview() {\n\t\t\treturn this.parse(`/join view-sharedipblacklist`);\n\t\t},\n\t\thelp: '',\n\t\t''() {\n\t\t\treturn this.parse(`/help nomarkshared`);\n\t\t},\n\t},\n\tnomarksharedhelp: [\n\t\t`/nomarkshared add [IP], [reason] - Prevents an IP from being marked as shared until it's removed from this list. Requires ~`,\n\t\t`Note: Reasons are required.`,\n\t\t`/nomarkshared remove [IP] - Removes an IP from the nomarkshared list. Requires ~`,\n\t\t`/nomarkshared view - Lists all IPs prevented from being marked as shared. Requires @ ~`,\n\t],\n\n\tsharedips: 'viewsharedips',\n\tviewsharedips() {\n\t\treturn this.parse('/join view-sharedips');\n\t},\n\tviewsharedipshelp: [\n\t\t`/viewsharedips \u2014 Lists IP addresses marked as shared. Requires: hosts manager @ ~`,\n\t],\n};\n"],
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,iBAAsB;AAItB,MAAM,gBAAgB,CAAC,OAAO,SAAS,QAAQ;AAC/C,MAAM,iBAA0C;AAAA,EAC/C,aAAa;AACd;AACA,MAAM,sBAA4B,CAAC;AAEnC,SAAS,gBACR,SAAiD,MAAY,aAA+B,YAC3F;AACD,MAAI,CAAC,oBAAoB,SAAS,KAAK,EAAE;AAAG,YAAQ,SAAS,UAAU;AACxE;AAEA,SAAS,YAAY,MAAc;AAClC,SAAO,KAAK,IAAI;AAChB,MAAI,cAAc,SAAS,IAAI;AAAG,WAAO;AACzC,MAAI,eAAe,IAAI;AAAG,WAAO,eAAe,IAAI;AACpD,QAAM,IAAI,KAAK,aAAa,IAAI,yDAAyD,cAAc,KAAK,IAAI,IAAI;AACrH;AAEO,SAAS,mBAAmB,QAAwB;AAC1D,MAAI,OAAO;AACX,aAAW,SAAS,QAAQ;AAC3B,YAAQ;AACR,YAAQ,OAAO,QAAQ,WAAW,MAAM,KAAK;AAC7C,YAAQ,OAAO,QAAQ,WAAW,MAAM,KAAK;AAC7C,YAAQ,iBAAM,WAAW,MAAM;AAC/B,YAAQ;AAAA,EACT;AACA,SAAO;AACR;AAEA,SAAS,YAAY,OAAqB,uBAAiC;AAC1E,QAAM,eAAe,wBAAwB,MAAM;AACnD,QAAM,aAAa,wBAAwB,MAAM;AAEjD,MAAI,SAAS,GAAG,eAAe,QAAQ,WAAW,MAAM,KAAK,IAAI;AACjE,YAAU,IAAI,eAAe,QAAQ,WAAW,MAAM,KAAK,IAAI;AAC/D,MAAI,MAAM;AAAM,cAAU,KAAK,MAAM;AAErC,SAAO;AACR;AAEO,MAAM,QAAwB;AAAA,EACpC,QAAQ,OAAO,MAAM;AACpB,SAAK,QAAQ;AACb,oBAAgB,MAAM,MAAM,WAAW;AAEvC,UAAM,cAAc,CAAC,GAAG,QAAQ,mBAAmB;AACnD,UAAM,aAAa,CAAC,GAAG,QAAQ,UAAU;AACzC,qBAAM,OAAO,aAAa,QAAM;AAC/B,YAAM,SAAS,QAAQ,WAAW,EAAE;AACpC,UAAI,WAAW,MAAM;AACpB,cAAM,IAAI,YAAY,GAAG,IAAI,8DAA8D,KAAK;AAChG,eAAO;AAAA,MACR;AACA,aAAO;AAAA,IACR,CAAC;AACD,eAAW,KAAK;AAChB,YAAQ,WAAW;AAEnB,QAAI,OAAO;AACX,eAAW,WAAW,aAAa;AAClC,cAAQ,WAAW;AAAA,IACpB;AACA,YAAQ;AAER,YAAQ;AACR,eAAW,aAAa,YAAY;AACnC,cAAQ,WAAW;AAAA,IACpB;AACA,YAAQ;AAER,YAAQ;AACR,YAAQ,mBAAmB,QAAQ,OAAO,OAAO,OAAK,EAAE,MAAM,SAAS,QAAQ,CAAC,CAAC;AACjF,YAAQ;AACR,WAAO;AAAA,EACR;AAAA,EAEA,MAAM,OAAO,MAAM;AAClB,SAAK,QAAQ;AACb,oBAAgB,MAAM,MAAM,WAAW;AACvC,UAAM,OAAO,KAAK,MAAM,CAAC,CAAC,KAAK;AAE/B,YAAQ,WAAW;AACnB,UAAM,cAAc,CAAC,OAAO,QAAQ,EAAE,SAAS,IAAI,IAAI,CAAC,GAAG,QAAQ,WAAW,IAAI,CAAC;AACnF,UAAM,mBAAmB,CAAC,OAAO,eAAe,KAAK,EAAE,SAAS,IAAI,IAAI,CAAC,GAAG,QAAQ,gBAAgB,IAAI,CAAC;AACzG,UAAM,aAAa,CAAC,OAAO,UAAU,MAAM,EAAE,SAAS,IAAI,IACzD,QAAQ,OAAO,OAAO,OAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,SAAS,QAAQ,CAAC,IAC/D,CAAC;AACF,gBAAY,KAAK;AACjB,qBAAiB,KAAK;AAEtB,QAAI,OAAO;AACX,eAAW,cAAc,aAAa;AACrC,cAAQ,WAAW;AAAA,IACpB;AACA,YAAQ;AAER,YAAQ;AACR,eAAW,WAAW,kBAAkB;AACvC,cAAQ,WAAW;AAAA,IACpB;AACA,YAAQ;AAER,YAAQ;AACR,YAAQ,mBAAmB,UAAU;AACrC,YAAQ;AACR,WAAO;AAAA,EACR;AAAA,EAEA,OAAO,OAAO,MAAM;AACnB,SAAK,QAAQ;AACb,oBAAgB,MAAM,MAAM,WAAW;AACvC,UAAM,OAAO,KAAK,MAAM,CAAC,CAAC,KAAK;AAC/B,YAAQ,WAAW;AAEnB,QAAI,OAAO;AACX,QAAI,CAAC,OAAO,QAAQ,EAAE,SAAS,IAAI,GAAG;AACrC,cAAQ;AACR,cAAQ,mBAAmB,QAAQ,OAAO,OAAO,WAAS,MAAM,MAAM,SAAS,SAAS,CAAC,CAAC;AAC1F,cAAQ;AAAA,IACT;AACA,QAAI,CAAC,OAAO,OAAO,aAAa,EAAE,SAAS,IAAI,GAAG;AACjD,cAAQ;AACR,cAAQ,mBAAmB,QAAQ,OAAO,OAAO,WAAS,MAAM,MAAM,SAAS,MAAM,CAAC,CAAC;AACvF,cAAQ;AAAA,IACT;AACA,QAAI,CAAC,OAAO,SAAS,SAAS,EAAE,SAAS,IAAI,GAAG;AAC/C,cAAQ;AACR,cAAQ,mBAAmB,QAAQ,OAAO,OAAO,WAAS,MAAM,MAAM,SAAS,QAAQ,CAAC,CAAC;AACzF,cAAQ;AAAA,IACT;AACA,QAAI,CAAC,OAAO,WAAW,EAAE,SAAS,IAAI,GAAG;AACxC,cAAQ;AACR,iBAAW,MAAM,QAAQ,qBAAqB;AAC7C,gBAAQ,WAAW;AAAA,MACpB;AACA,cAAQ;AAAA,IACT;AACA,WAAO;AAAA,EACR;AAAA,EAEA,kBAAkB,MAAM,MAAM,YAAY;AACzC,SAAK,QAAQ;AACb,oBAAgB,MAAM,MAAM,MAAM;AAElC,QAAI,MAAM;AACV,QAAI,CAAC,YAAY,kBAAkB,MAAM;AACxC,aAAO;AAAA,IACR,OAAO;AACN,aAAO;AACP,YAAM,0BAA0B,CAAC,GAAG,YAAY,iBAAiB;AACjE,uBAAM,OAAO,yBAAyB,CAAC,CAAC,SAAS,MAAM;AACtD,YAAI,QAAQ,QAAQ,KAAK,SAAS,GAAG;AACpC,gBAAM,SAAS,QAAQ,WAAW,SAAS;AAC3C,cAAI,WAAW,MAAM;AACpB,oBAAQ,MAAM,4CAA4C,WAAW;AACrE,mBAAO;AAAA,UACR;AACA,iBAAO;AAAA,QACR;AACA,eAAO,QAAQ,cAAc,SAAS,EAAG;AAAA,MAC1C,CAAC;AACD,iBAAW,CAAC,IAAI,MAAM,KAAK,yBAAyB;AACnD,eAAO,WAAW,cAAc;AAAA,MACjC;AACA,aAAO;AAAA,IACR;AACA,WAAO;AACP,WAAO;AAAA,EACR;AAAA,EAEA,UAAU,MAAM,MAAM,YAAY;AACjC,SAAK,QAAQ;AACb,oBAAgB,MAAM,MAAM,WAAW;AAEvC,QAAI,MAAM;AACV,QAAI,CAAC,YAAY,UAAU,MAAM;AAChC,aAAO;AAAA,IACR,OAAO;AACN,aAAO;AACP,YAAM,kBAAkB,CAAC,GAAG,YAAY,SAAS;AACjD,uBAAM,OAAO,iBAAiB,CAAC,CAAC,EAAE,MAAM;AACvC,cAAM,SAAS,QAAQ,WAAW,EAAE;AACpC,YAAI,WAAW,MAAM;AACpB,kBAAQ,MAAM,+BAA+B,KAAK;AAClD,iBAAO;AAAA,QACR;AACA,eAAO;AAAA,MACR,CAAC;AAED,iBAAW,CAAC,IAAI,QAAQ,KAAK,iBAAiB;AAC7C,eAAO,WAAW,cAAc;AAAA,MACjC;AACA,aAAO;AAAA,IACR;AACA,WAAO;AACP,WAAO;AAAA,EACR;AACD;AAEO,MAAM,WAA8B;AAAA,EAC1C,IAAI;AAAA,EACJ,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,SAAS;AAAA,EACT,UAAU;AAAA,IACT,IAAI;AAAA,IACJ,OAAO;AACN,aAAO,KAAK,MAAM,gBAAgB;AAAA,IACnC;AAAA,IAEA,MAAM;AAAA,IACN,KAAK,QAAQ,MAAM,MAAM;AACxB,sBAAgB,MAAM,MAAM,WAAW;AACvC,YAAM,QAAQ,CAAC,OAAO,eAAe,OAAO,UAAU,SAAS,WAAW;AAC1E,YAAM,OAAO,SAAS,KAAK,MAAM,IAAI;AACrC,UAAI,CAAC,MAAM,SAAS,IAAI,GAAG;AAC1B,eAAO,KAAK,WAAW,IAAI,iDAAiD,MAAM,KAAK,IAAI,IAAI;AAAA,MAChG;AACA,aAAO,KAAK,MAAM,qBAAqB,MAAM;AAAA,IAC9C;AAAA,IACA,UAAU;AAAA,MACT;AAAA,MACA;AAAA,IACD;AAAA;AAAA,IAGA,OAAO;AAAA,IACP,IAAI,QAAQ,MAAM,MAAM,YAAY,KAAK;AACxC,sBAAgB,MAAM,MAAM,WAAW;AACvC,UAAI,CAAC;AAAQ,eAAO,KAAK,MAAM,oBAAoB;AAEnD,YAAM,QAAQ,IAAI,SAAS,OAAO;AAElC,YAAM,CAAC,YAAY,aAAa,IAAI,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI,UAAQ,KAAK,KAAK,CAAC;AACjF,UAAI,CAAC,QAAQ,CAAC,QAAQ,UAAU,KAAK,IAAI,GAAG;AAC3C,eAAO,KAAK,WAAW,iBAAiB,QAAQ;AAAA,MACjD;AACA,YAAM,OAAO,YAAY,UAAU;AACnC,YAAM,QAAQ,QAAQ,cAAc,WAAW;AAC/C,UAAI,CAAC;AAAO,eAAO,KAAK,WAAW,4BAA4B,eAAe;AAC9E,YAAM,OAAO,GAAG,QAAQ,UAAU,IAAI,MAAM;AAE5C,cAAQ,WAAW;AACnB,UAAI;AACJ,UAAI;AACH,iBAAS,QAAQ,oBAAoB,OAAO,QAAQ,QAAQ,KAAK;AAAA,MAClE,SAAS,GAAP;AACD,eAAO,KAAK,WAAW,EAAE,OAAO;AAAA,MACjC;AACA,UAAI,OAAO,WAAW,UAAU;AAE/B,gBAAQ,YAAY,QAAQ,OAAO,MAAM,EAAE,OAAO,QAAQ,OAAO,MAAM,EAAE,KAAK;AAAA,MAC/E;AACA,cAAQ,SAAS,KAAwC;AAEzD,WAAK,uBAAuB,GAAG,KAAK,2BAA2B,YAAY,KAAK,oBAAoB,cAAc;AAClH,WAAK,aAAa,eAAe,MAAM,YAAY,OAAO,IAAI,CAAC;AAAA,IAChE;AAAA,IACA,SAAS;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAAA,IAEA,OAAO,QAAQ,MAAM,MAAM;AAC1B,sBAAgB,MAAM,IAAI;AAC1B,UAAI,CAAC;AAAQ,eAAO,KAAK,MAAM,uBAAuB;AAEtD,YAAM,QAAQ,QAAQ,cAAc,MAAM;AAC1C,UAAI,CAAC;AAAO,eAAO,KAAK,WAAW,gCAAgC,UAAU;AAC7E,UAAI,CAAC,QAAQ,SAAS,MAAM,OAAO,MAAM,KAAK;AAAG,eAAO,KAAK,WAAW,yBAAyB,UAAU;AAE3G,WAAK,QAAQ,YAAY,MAAM,OAAO,MAAM,KAAK;AAEjD,WAAK,uBAAuB,GAAG,KAAK,6BAA6B,YAAY,KAAK,IAAI;AACtF,WAAK,aAAa,kBAAkB,MAAM,YAAY,OAAO,IAAI,CAAC;AAAA,IACnE;AAAA,IACA,YAAY;AAAA,MACX;AAAA,MACA;AAAA,IACD;AAAA,IAEA,OAAO,QAAQ,MAAM,MAAM;AAC1B,sBAAgB,MAAM,IAAI;AAC1B,UAAI,CAAC;AAAQ,eAAO,KAAK,MAAM,uBAAuB;AACtD,YAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI,UAAQ,KAAK,KAAK,CAAC;AAC1E,UAAI,CAAC,KAAK;AACT,eAAO,KAAK,MAAM,uBAAuB;AAAA,MAC1C;AACA,YAAM,WAAW,QAAQ,cAAc,WAAW;AAClD,UAAI,CAAC;AAAU,eAAO,KAAK,WAAW,4BAA4B,eAAe;AACjF,YAAM,SAAS,QAAQ,SAAS,SAAS,OAAO,SAAS,KAAK;AAC9D,UAAI,CAAC;AAAQ,eAAO,KAAK,WAAW,yBAAyB,eAAe;AAE5E,YAAM,QAAQ;AAAA,QACb,OAAO,SAAS;AAAA,QAChB,OAAO,SAAS;AAAA,QAChB,MAAM,GAAG,QAAQ,UAAU,GAAG,MAAM;AAAA,MACrC;AACA,WAAK,QAAQ,SAAS,KAAK;AAE3B,WAAK,uBAAuB,GAAG,KAAK,6BAA6B,YAAY,QAAQ,QAAQ,MAAM,OAAO;AAC1G,WAAK,aAAa,kBAAkB,MAAM,YAAY,YAAY,UAAU,IAAI,QAAQ,MAAM,MAAM;AAAA,IACrG;AAAA,IACA,YAAY;AAAA,MACX;AAAA,IACD;AAAA,EACD;AAAA,EAEA,eAAe;AACd,UAAM,OAAO;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AACA,WAAO,KAAK,UAAU,4CAA4C,KAAK,KAAK,QAAQ,GAAG;AAAA,EACxF;AAAA,EACA,UAAU,QAAQ,MAAM,MAAM;AAC7B,oBAAgB,MAAM,MAAM,WAAW;AACvC,UAAM,QAAQ,CAAC,OAAO,eAAe,UAAU,QAAQ;AACvD,UAAM,OAAO,SAAS,KAAK,MAAM,IAAI;AACrC,QAAI,CAAC,MAAM,SAAS,IAAI,GAAG;AAC1B,aAAO,KAAK,WAAW,IAAI,iDAAiD,MAAM,KAAK,IAAI,IAAI;AAAA,IAChG;AACA,WAAO,KAAK,MAAM,oBAAoB,MAAM;AAAA,EAC7C;AAAA,EACA,eAAe;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAAA,EAEA,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,SAAS;AAAA,EACT,SAAS,QAAQ,MAAM,MAAM,YAAY,KAAK;AAC7C,oBAAgB,MAAM,IAAI;AAC1B,UAAM,WAAW,IAAI,SAAS,QAAQ;AACtC,QAAI,CAAC,MAAM,GAAG,KAAK,IAAI,OAAO,MAAM,GAAG;AACvC,WAAO,KAAK,IAAI;AAChB,YAAQ,MAAM,IAAI,UAAQ,KAAK,KAAK,CAAC;AACrC,QAAI,CAAC,MAAM;AAAQ,aAAO,KAAK,MAAM,gBAAgB;AAErD,YAAQ,MAAM;AAAA,MACd,KAAK;AACJ,mBAAW,QAAQ,OAAO;AACzB,cAAI,CAAC,QAAQ,QAAQ,KAAK,IAAI;AAAG,mBAAO,KAAK,WAAW,IAAI,kCAAkC;AAC9F,cAAI,aAAa,QAAQ,oBAAoB,IAAI,IAAI,GAAG;AACvD,mBAAO,KAAK,WAAW,IAAI,YAAY,WAAW,QAAQ,qCAAqC;AAAA,UAChG;AAAA,QACD;AACA,YAAI,UAAU;AACb,eAAK,QAAQ,kBAAkB,KAAK;AAAA,QACrC,OAAO;AACN,eAAK,QAAQ,eAAe,KAAK;AAAA,QAClC;AACA;AAAA,MACD,KAAK;AACJ,mBAAW,QAAQ,OAAO;AACzB,cAAI,CAAC,QAAQ,UAAU,KAAK,IAAI;AAAG,mBAAO,KAAK,WAAW,IAAI,4BAA4B;AAC1F,cAAI,aAAa,QAAQ,WAAW,IAAI,IAAI,GAAG;AAC9C,mBAAO,KAAK,WAAW,IAAI,YAAY,WAAW,QAAQ,uCAAuC;AAAA,UAClG;AAAA,QACD;AACA,YAAI,UAAU;AACb,eAAK,QAAQ,iBAAiB,KAAK;AAAA,QACpC,OAAO;AACN,eAAK,QAAQ,cAAc,KAAK;AAAA,QACjC;AACA;AAAA,MACD,KAAK;AACJ,mBAAW,QAAQ,OAAO;AACzB,cAAI,CAAC,QAAQ,UAAU,KAAK,IAAI;AAAG,mBAAO,KAAK,WAAW,IAAI,4BAA4B;AAC1F,cAAI,aAAa,QAAQ,iBAAiB,IAAI,IAAI,GAAG;AACpD,mBAAO,KAAK,WAAW,IAAI,YAAY,WAAW,QAAQ,6CAA6C;AAAA,UACxG;AAAA,QACD;AACA,YAAI,UAAU;AACb,eAAK,QAAQ,uBAAuB,KAAK;AAAA,QAC1C,OAAO;AACN,eAAK,QAAQ,oBAAoB,KAAK;AAAA,QACvC;AACA;AAAA,MACD,KAAK;AACJ,mBAAW,QAAQ,OAAO;AACzB,cAAI,CAAC,QAAQ,UAAU,KAAK,IAAI;AAAG,mBAAO,KAAK,WAAW,IAAI,4BAA4B;AAC1F,cAAI,aAAa,QAAQ,YAAY,IAAI,IAAI,GAAG;AAC/C,mBAAO,KAAK,WAAW,IAAI,YAAY,WAAW,QAAQ,wCAAwC;AAAA,UACnG;AAAA,QACD;AACA,YAAI,UAAU;AACb,eAAK,QAAQ,kBAAkB,KAAK;AAAA,QACrC,OAAO;AACN,eAAK,QAAQ,eAAe,KAAK;AAAA,QAClC;AACA;AAAA,MACD;AACC,eAAO,KAAK,WAAW,IAAI,sEAAsE;AAAA,IAClG;AACA,SAAK;AAAA,MACJ,GAAG,KAAK,QAAQ,WAAW,YAAY,WAAW,MAAM,iBAAiB,MAAM,KAAK,IAAI,MAAM,WAAW,SAAS,YAAY;AAAA,IAC/H;AACA,SAAK,aAAa,WAAW,gBAAgB,YAAY,MAAM,GAAG,SAAS,MAAM,KAAK,IAAI,GAAG;AAAA,EAC9F;AAAA,EACA,cAAc;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAAA,EAEA,YAAY,QAAQ,MAAM,MAAM;AAC/B,oBAAgB,MAAM,MAAM,WAAW;AACvC,WAAO,KAAK,MAAM,oBAAoB;AAAA,EACvC;AAAA,EACA,iBAAiB;AAAA,IAChB;AAAA,EACD;AAAA,EAEA,WAAW,QAAQ,MAAM,MAAM;AAC9B,QAAI,CAAC;AAAQ,aAAO,KAAK,MAAM,kBAAkB;AACjD,oBAAgB,MAAM,MAAM,WAAW;AACvC,UAAM,CAAC,IAAI,IAAI,IAAI,KAAK,SAAS,MAAM;AACvC,QAAI,CAAC,QAAQ,QAAQ,KAAK,EAAE,GAAG;AAC9B,YAAM,UAAU,QAAQ,cAAc,EAAE;AACxC,UAAI,CAAC,SAAS;AACb,eAAO,KAAK,WAAW,kCAAkC;AAAA,MAC1D;AACA,UAAI,CAAC,KAAK,IAAI,UAAU,GAAG;AAC1B,eAAO,KAAK,WAAW,wCAAwC;AAAA,MAChE;AACA,iBAAW,SAAS,YAAY,aAAa,KAAK,GAAG;AACpD,YAAI,QAAQ,gBAAgB,OAAO,OAAO,GAAG;AAC5C,iBAAO,KAAK;AAAA,YACX,SAAS,QAAQ,cAAc,OAAO,kCAAkC,QAAQ,cAAc,KAAK;AAAA,UACpG;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,QAAI,YAAY,WAAW,EAAE;AAAG,aAAO,KAAK,WAAW,sCAAsC;AAC7F,QAAI,YAAY,sBAAsB,EAAE,GAAG;AAC1C,aAAO,KAAK,WAAW,qDAAqD;AAAA,IAC7E;AACA,QAAI,CAAC,MAAM;AACV,WAAK,WAAW,2CAA2C;AAC3D,WAAK,MAAM,kBAAkB;AAC7B;AAAA,IACD;AAEA,gBAAY,YAAY,IAAI,IAAI;AAChC,SAAK,uBAAuB,WAAW,+BAA+B,KAAK,UAAU,OAAO;AAC5F,SAAK,aAAa,YAAY,MAAM,MAAM,EAAE;AAAA,EAC7C;AAAA,EACA,gBAAgB;AAAA,IACf;AAAA,IACA;AAAA,EACD;AAAA,EAEA,aAAa,QAAQ,MAAM,MAAM;AAChC,QAAI,CAAC;AAAQ,aAAO,KAAK,MAAM,oBAAoB;AACnD,oBAAgB,MAAM,MAAM,WAAW;AACvC,aAAS,OAAO,KAAK;AACrB,UAAM,UAAU,QAAQ,cAAc,MAAM;AAC5C,QAAI,CAAC;AAAS,aAAO,KAAK,WAAW,kCAAkC;AACvE,QAAI,QAAQ,UAAU,QAAQ,SAAS,CAAC,KAAK,IAAI,UAAU,GAAG;AAC7D,aAAO,KAAK,WAAW,6CAA6C;AAAA,IACrE;AAEA,QAAI,SAAS;AACb,QAAI,QAAQ,UAAU,QAAQ,OAAO;AACpC,iBAAW,SAAS,YAAY,aAAa,KAAK,GAAG;AACpD,iBAAS,MAAM,UAAU,QAAQ,SAAS,MAAM,UAAU,QAAQ;AAClE,YAAI;AAAQ;AAAA,MACb;AAAA,IACD,OAAO;AACN,eAAS,YAAY,UAAU,IAAI,MAAM;AAAA,IAC1C;AAEA,QAAI,CAAC;AAAQ,aAAO,KAAK,WAAW,uCAAuC;AAE3E,gBAAY,eAAe,MAAM;AAEjC,SAAK,uBAAuB,WAAW,qCAAqC,KAAK,OAAO;AACxF,SAAK,aAAa,cAAc,MAAM,MAAM,MAAM;AAAA,EACnD;AAAA,EACA,kBAAkB,CAAC,gEAAgE;AAAA,EAEnF,qBAAqB;AAAA,EACrB,cAAc;AAAA,EACd,cAAc;AAAA,IACb,IAAI,QAAQ,MAAM,MAAM;AACvB,UAAI,CAAC;AAAQ,eAAO,KAAK,MAAM,oBAAoB;AACnD,sBAAgB,MAAM,MAAM,WAAW;AACvC,YAAM,CAAC,IAAI,GAAG,SAAS,IAAI,OAAO,MAAM,GAAG;AAC3C,UAAI,CAAC,QAAQ,aAAa,KAAK,EAAE;AAAG,eAAO,KAAK,WAAW,2CAA2C;AACtG,UAAI,CAAC,WAAW,QAAQ;AACvB,aAAK,WAAW,uBAAuB;AACvC,aAAK,MAAM,oBAAoB;AAC/B;AAAA,MACD;AACA,UAAI,YAAY,sBAAsB,EAAE,GAAG;AAC1C,eAAO,KAAK,WAAW,6DAA6D;AAAA,MACrF;AAIA,UAAI,CAAC,QAAQ,QAAQ,KAAK,EAAE,GAAG;AAG9B,YAAI,CAAC,GAAG,SAAS,GAAG,GAAG;AACtB,eAAK,WAAW,6CAA6C;AAC7D,eAAK,WAAW,iDAAiD;AACjE;AAAA,QACD;AACA,YAAI,CAAC,KAAK,IAAI,WAAW,GAAG;AAC3B,iBAAO,KAAK,WAAW,qCAAqC;AAAA,QAC7D;AACA,cAAM,QAAQ,QAAQ,cAAc,EAAE;AACtC,YAAI,CAAC;AAAO,iBAAO,KAAK,WAAW,mBAAmB;AACtD,mBAAW,YAAY,YAAY,UAAU,KAAK,GAAG;AACpD,gBAAM,QAAQ,QAAQ,WAAW,QAAQ;AACzC,cAAI,QAAQ,aAAa,CAAC,KAAK,GAAG,KAAK,GAAG;AACzC,iBAAK,MAAM,iBAAiB,UAAU;AAAA,UACvC;AAAA,QACD;AAAA,MACD,OAAO;AACN,YAAI,YAAY,WAAW,EAAE;AAAG,eAAK,MAAM,iBAAiB,IAAI;AAAA,MACjE;AACA,YAAM,SAAS,UAAU,KAAK,GAAG;AAEjC,kBAAY,uBAAuB,IAAI,MAAM;AAE7C,WAAK,uBAAuB,WAAW,sDAAsD,KAAK,OAAO;AACzG,WAAK,aAAa,sBAAsB,MAAM,OAAO,KAAK,GAAG,EAAE;AAAA,IAChE;AAAA,IACA,OAAO,QAAQ,MAAM,MAAM;AAC1B,UAAI,CAAC;AAAQ,eAAO,KAAK,MAAM,oBAAoB;AACnD,sBAAgB,MAAM,IAAI;AAC1B,UAAI,CAAC,QAAQ,aAAa,KAAK,MAAM;AAAG,eAAO,KAAK,WAAW,2CAA2C;AAC1G,UAAI,CAAC,YAAY,kBAAkB,IAAI,MAAM,GAAG;AAC/C,eAAO,KAAK,WAAW,yDAAyD;AAAA,MACjF;AAEA,kBAAY,0BAA0B,MAAM;AAE5C,WAAK,uBAAuB,WAAW,4DAA4D,KAAK,OAAO;AAC/G,WAAK,aAAa,wBAAwB,MAAM,MAAM,MAAM;AAAA,IAC7D;AAAA,IACA,OAAO;AACN,aAAO,KAAK,MAAM,8BAA8B;AAAA,IACjD;AAAA,IACA,MAAM;AAAA,IACN,KAAK;AACJ,aAAO,KAAK,MAAM,oBAAoB;AAAA,IACvC;AAAA,EACD;AAAA,EACA,kBAAkB;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAAA,EAEA,WAAW;AAAA,EACX,gBAAgB;AACf,WAAO,KAAK,MAAM,sBAAsB;AAAA,EACzC;AAAA,EACA,mBAAmB;AAAA,IAClB;AAAA,EACD;AACD;",
"names": []
}