3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-16 22:21:51 +00:00

Utility: add more options to !search, make the results list prettier

This commit is contained in:
Dragory 2019-02-17 22:49:14 +02:00
parent 59204fbf51
commit 151971bb84
2 changed files with 114 additions and 21 deletions

View file

@ -6,8 +6,10 @@ import {
embedPadding, embedPadding,
errorMessage, errorMessage,
isSnowflake, isSnowflake,
multiSorter,
noop, noop,
simpleClosestStringMatch, simpleClosestStringMatch,
sorter,
stripObjectToScalars, stripObjectToScalars,
successMessage, successMessage,
trimLines, trimLines,
@ -177,18 +179,59 @@ export class UtilityPlugin extends ZeppelinPlugin {
msg.channel.createMessage(`The permission level of ${member.username}#${member.discriminator} is **${level}**`); msg.channel.createMessage(`The permission level of ${member.username}#${member.discriminator} is **${level}**`);
} }
@d.command("search", "<query:string$>") @d.command("search", "[query:string$]", {
options: [
{
name: "page",
type: "number",
},
{
name: "role",
type: "string",
},
{
name: "voice",
type: "bool",
},
{
name: "sort",
type: "string",
},
],
})
@d.permission("search") @d.permission("search")
async searchCmd(msg: Message, args: { query: string }) { async searchCmd(
let [, query, inputPageNum] = args.query.match(/^(.*?)(?:\s([0-9]+))?$/); msg: Message,
query = query.toLowerCase(); args: { query?: string; role?: string; page?: number; voice?: boolean; sort?: string },
) {
let matchingMembers = Array.from(this.guild.members.values());
const matchingMembers = this.guild.members.filter(member => { if (args.role) {
const fullUsername = `${member.user.username}#${member.user.discriminator}`; const roleIds = args.role.split(",");
if (member.nick && member.nick.toLowerCase().indexOf(query) !== -1) return true; matchingMembers = matchingMembers.filter(member => {
if (fullUsername.toLowerCase().indexOf(query) !== -1) return true; for (const role of roleIds) {
return false; if (!member.roles.includes(role)) return false;
}); }
return true;
});
}
if (args.voice) {
matchingMembers = matchingMembers.filter(m => m.voiceState.channelID != null);
}
if (args.query) {
let [, query] = args.query.match(/^(.*?)(?:\s([0-9]+))?$/);
query = query.toLowerCase();
matchingMembers = matchingMembers.filter(member => {
const fullUsername = `${member.user.username}#${member.user.discriminator}`;
if (member.nick && member.nick.toLowerCase().indexOf(query) !== -1) return true;
if (fullUsername.toLowerCase().indexOf(query) !== -1) return true;
return false;
});
}
if (matchingMembers.length > 0) { if (matchingMembers.length > 0) {
let header; let header;
@ -196,8 +239,7 @@ export class UtilityPlugin extends ZeppelinPlugin {
const paginated = matchingMembers.length > MAX_SEARCH_RESULTS; const paginated = matchingMembers.length > MAX_SEARCH_RESULTS;
const pageInputMatch = args.query.match(/\s([0-9]+)$/); const inputPage = args.page || 1;
const inputPage = pageInputMatch ? parseInt(pageInputMatch[1], 10) : 1;
const lastPage = Math.ceil(matchingMembers.length / MAX_SEARCH_RESULTS); const lastPage = Math.ceil(matchingMembers.length / MAX_SEARCH_RESULTS);
const page = Math.min(lastPage, Math.max(1, inputPage)); const page = Math.min(lastPage, Math.max(1, inputPage));
@ -210,17 +252,28 @@ export class UtilityPlugin extends ZeppelinPlugin {
header = `Found ${matchingMembers.length} ${resultText}`; header = `Found ${matchingMembers.length} ${resultText}`;
} }
let lines = matchingMembers.map(member => { const pageMembers = matchingMembers.slice(from, to);
return `${member.user.username}#${member.user.discriminator} (${member.id})`;
});
lines.sort((a, b) => {
return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
});
lines = lines.slice(from, to);
const footer = paginated ? "Add a page number to the end of the command to browse results" : ""; const [, sortDir, sortBy] = args.sort ? args.sort.match(/^(-?)(.*)$/) : [null, "ASC", "name"];
const realSortDir = sortDir === "-" ? "DESC" : "ASC";
msg.channel.createMessage(`${header}\n\`\`\`${lines.join("\n")}\`\`\`${footer}`); if (sortBy === "id") {
pageMembers.sort(sorter(m => BigInt(m.id), realSortDir));
} else {
pageMembers.sort(
multiSorter([[m => m.username.toLowerCase(), realSortDir], [m => m.discriminator, realSortDir]]),
);
}
const longestId = pageMembers.reduce((longest, member) => Math.max(longest, member.id.length), 0);
const lines = pageMembers.map(member => {
const paddedId = member.id.padEnd(longestId, " ");
return `${paddedId} ${member.user.username}#${member.user.discriminator}`;
});
const footer = paginated ? "Use --page=n to browse results" : "";
msg.channel.createMessage(`${header}\n\`\`\`js\n${lines.join("\n")}\`\`\`${footer}`);
} else { } else {
msg.channel.createMessage(errorMessage("No results found")); msg.channel.createMessage(errorMessage("No results found"));
} }

View file

@ -383,6 +383,46 @@ export function simpleClosestStringMatch<T>(searchStr, haystack: T[], getter = n
return itemsWithRankings[0][0]; return itemsWithRankings[0][0];
} }
type sorterDirection = "ASC" | "DESC";
type sorterGetterFn = (any) => any;
type sorterGetterFnWithDirection = [sorterGetterFn, sorterDirection];
type sorterGetterResolvable = string | sorterGetterFn;
type sorterGetterResolvableWithDirection = [sorterGetterResolvable, sorterDirection];
type sorterFn = (a: any, b: any) => number;
function resolveGetter(getter: sorterGetterResolvable): sorterGetterFn {
if (typeof getter === "string") {
return obj => obj[getter];
}
return getter;
}
export function multiSorter(getters: Array<sorterGetterResolvable | sorterGetterResolvableWithDirection>): sorterFn {
const resolvedGetters: sorterGetterFnWithDirection[] = getters.map(getter => {
if (Array.isArray(getter)) {
return [resolveGetter(getter[0]), getter[1]] as sorterGetterFnWithDirection;
} else {
return [resolveGetter(getter), "ASC"] as sorterGetterFnWithDirection;
}
});
return (a, b) => {
for (const getter of resolvedGetters) {
const aVal = getter[0](a);
const bVal = getter[0](b);
if (aVal > bVal) return getter[1] === "ASC" ? 1 : -1;
if (aVal < bVal) return getter[1] === "ASC" ? -1 : 1;
}
return 0;
};
}
export function sorter(getter: sorterGetterResolvable, direction: sorterDirection = "ASC"): sorterFn {
return multiSorter([[getter, direction]]);
}
export function noop() { export function noop() {
// IT'S LITERALLY NOTHING // IT'S LITERALLY NOTHING
} }