From 756db075bebd6bc03b0ede08ec840a3b81eb0188 Mon Sep 17 00:00:00 2001 From: Mia <49593536+mia-pi-git@users.noreply.github.com> Date: Tue, 25 May 2021 17:21:32 -0500 Subject: [PATCH] Usersearch: Support setting a list of most-searched names (#8283) --- server/chat-plugins/usersearch.ts | 102 ++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 5 deletions(-) diff --git a/server/chat-plugins/usersearch.ts b/server/chat-plugins/usersearch.ts index 5e6c348151..ee80a8e2d3 100644 --- a/server/chat-plugins/usersearch.ts +++ b/server/chat-plugins/usersearch.ts @@ -1,4 +1,8 @@ -import {Utils} from '../../lib'; +import {Utils, FS} from '../../lib'; + +export const nameList: string[] = JSON.parse( + FS('config/chat-plugins/usersearch.json').readIfExistsSync() || "[]" +); const ONLINE_SYMBOL = ` \u25C9 `; const OFFLINE_SYMBOL = ` \u25CC `; @@ -63,6 +67,10 @@ function searchUsernames(target: string, page = false) { return buf; } +function saveNames() { + FS('config/chat-plugins/usersearch.json').writeUpdate(() => JSON.stringify(nameList)); +} + export const commands: Chat.ChatCommands = { us: 'usersearch', uspage: 'usersearch', @@ -70,7 +78,8 @@ export const commands: Chat.ChatCommands = { usersearch(target, room, user, connection, cmd) { this.checkCan('lock'); target = toID(target); - if (!target) { + if (!target) { // just join directly if it's the page cmd, they're likely looking for the full list + if (cmd.includes('page')) return this.parse(`/j view-usersearch`); return this.parse(`/help usersearch`); } if (target.length < 3) { @@ -87,14 +96,97 @@ export const commands: Chat.ChatCommands = { `/usersearch [pattern]: Looks for all names matching the [pattern]. Requires: % @ &`, `Adding "page" to the end of the command, i.e. /usersearchpage OR /uspage will bring up a page.`, ], + usnames: 'usersearchnames', + usersearchnames: { + '': 'list', + list() { + this.parse(`/join view-usersearch`); + }, + add(target, room, user) { + this.checkCan('lock'); + const targets = target.split(',').map(toID).filter(Boolean); + if (!targets.length) { + return this.errorReply(`Specify at least one term.`); + } + for (const [i, arg] of targets.entries()) { + if (nameList.includes(arg)) { + targets.splice(i, 1); + this.errorReply(`Term ${arg} is already on the usersearch term list.`); + continue; + } + if (arg.length < 3) { + targets.splice(i, 1); + this.errorReply(`Term ${arg} is too short for the usersearch term list. Must be more than 3 characters.`); + continue; + } + } + nameList.push(...targets); + Rooms.get('staff')?.addByUser(user, `${user.name} added ${Chat.count(targets, 'terms')} to the usersearch name list.`); + this.globalModlog(`USERSEARCH ADD`, null, targets.join(', ')); + if (!room || room.roomid !== 'staff') { + this.sendReply(`Added ${Chat.count(targets, 'terms')} to the usersearch name list.`); + } + saveNames(); + }, + remove(target, room, user) { + this.checkCan('lock'); + const targets = target.split(',').map(toID).filter(Boolean); + if (!targets.length) { + return this.errorReply(`Specify at least one term.`); + } + for (const [i, arg] of targets.entries()) { + const idx = nameList.indexOf(arg); + if (idx < 0) { + targets.splice(i, 1); + this.errorReply(`${arg} is not in the usersearch name list, and has been skipped.`); + continue; + } + nameList.splice(idx, 1); + } + Rooms.get('staff')?.addByUser(user, `${user.name} removed ${Chat.count(targets, 'terms')} from the usersearch name list.`); + this.globalModlog(`USERSEARCH REMOVE`, null, targets.join(', ')); + if (!room || room.roomid !== 'staff') { + this.sendReply(`You removed ${Chat.count(targets, 'terms')} from the usersearch name list.`); + } + saveNames(); + }, + }, }; export const pages: Chat.PageTable = { usersearch(query, user) { this.checkCan('lock'); - if (!query.length) return this.close(); - this.title = `[Usersearch] ${query[0]}`; - const target = toID(query[0]); + const target = toID(query.shift()); + if (!target) { + this.title = `[Usersearch Terms]`; + let buf = `
Usersearch term list`; + buf += ``; + buf += `
`; + if (!nameList.length) { + buf += `None found.`; + return buf; + } + const sorted: {[k: string]: number} = {}; + for (const curUser of Users.users.values()) { + for (const term of nameList) { + if (curUser.id.includes(term)) { + if (!sorted[term]) sorted[term] = 0; + sorted[term]++; + } + } + } + buf += `
`; + buf += ``; + for (const k of Utils.sortBy(Object.keys(sorted), v => -sorted[v])) { + buf += ``; + buf += ``; + buf += ``; + buf += ``; + buf += ``; + } + return buf; + } + this.title = `[Usersearch] ${target}`; return searchUsernames(target, true); }, };
TermCurrent matches
${k}${sorted[k]}