mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-16 22:21:51 +00:00
use buttons instead of reactions on the casesmodcmd
This commit is contained in:
parent
5042d9997f
commit
e8bc549dd4
3 changed files with 52 additions and 55 deletions
|
@ -43,7 +43,6 @@ export const CasesModCmd = modActionsCmd({
|
||||||
const prefix = getGuildPrefix(pluginData);
|
const prefix = getGuildPrefix(pluginData);
|
||||||
|
|
||||||
createPaginatedMessage(
|
createPaginatedMessage(
|
||||||
pluginData.client,
|
|
||||||
msg.channel,
|
msg.channel,
|
||||||
totalPages,
|
totalPages,
|
||||||
async (page) => {
|
async (page) => {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import {
|
import {
|
||||||
|
Formatters,
|
||||||
GuildMember,
|
GuildMember,
|
||||||
Message,
|
Message,
|
||||||
MessageActionRow,
|
MessageActionRow,
|
||||||
|
@ -35,6 +36,15 @@ export enum SearchType {
|
||||||
BanSearch,
|
BanSearch,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface SearchResult<T> {
|
||||||
|
results: T[];
|
||||||
|
totalResults: number;
|
||||||
|
page: number;
|
||||||
|
lastPage: number;
|
||||||
|
from: number;
|
||||||
|
to: number;
|
||||||
|
}
|
||||||
|
|
||||||
class SearchError extends Error {}
|
class SearchError extends Error {}
|
||||||
|
|
||||||
type MemberSearchParams = ArgsFromSignatureOrArray<typeof searchCmdSignature>;
|
type MemberSearchParams = ArgsFromSignatureOrArray<typeof searchCmdSignature>;
|
||||||
|
@ -90,7 +100,7 @@ export async function displaySearch(
|
||||||
|
|
||||||
const perPage = args.ids ? SEARCH_ID_RESULTS_PER_PAGE : SEARCH_RESULTS_PER_PAGE;
|
const perPage = args.ids ? SEARCH_ID_RESULTS_PER_PAGE : SEARCH_RESULTS_PER_PAGE;
|
||||||
|
|
||||||
const loadSearchPage = async (page) => {
|
const loadSearchPage = async (page: number) => {
|
||||||
if (searching) return;
|
if (searching) return;
|
||||||
searching = true;
|
searching = true;
|
||||||
|
|
||||||
|
@ -146,11 +156,9 @@ export async function displaySearch(
|
||||||
: formatSearchResultList(searchResult.results);
|
: formatSearchResultList(searchResult.results);
|
||||||
|
|
||||||
const result = trimLines(`
|
const result = trimLines(`
|
||||||
${headerText}
|
${headerText}
|
||||||
\`\`\`js
|
${Formatters.codeBlock("js", resultList)}
|
||||||
${resultList}
|
`);
|
||||||
\`\`\`
|
|
||||||
`);
|
|
||||||
|
|
||||||
const searchMsg = await searchMsgPromise;
|
const searchMsg = await searchMsgPromise;
|
||||||
|
|
||||||
|
@ -298,7 +306,7 @@ async function performMemberSearch(
|
||||||
args: MemberSearchParams,
|
args: MemberSearchParams,
|
||||||
page = 1,
|
page = 1,
|
||||||
perPage = SEARCH_RESULTS_PER_PAGE,
|
perPage = SEARCH_RESULTS_PER_PAGE,
|
||||||
): Promise<{ results: GuildMember[]; totalResults: number; page: number; lastPage: number; from: number; to: number }> {
|
): Promise<SearchResult<GuildMember>> {
|
||||||
await refreshMembersIfNeeded(pluginData.guild);
|
await refreshMembersIfNeeded(pluginData.guild);
|
||||||
|
|
||||||
let matchingMembers = Array.from(pluginData.guild.members.cache.values());
|
let matchingMembers = Array.from(pluginData.guild.members.cache.values());
|
||||||
|
@ -426,7 +434,7 @@ async function performBanSearch(
|
||||||
args: BanSearchParams,
|
args: BanSearchParams,
|
||||||
page = 1,
|
page = 1,
|
||||||
perPage = SEARCH_RESULTS_PER_PAGE,
|
perPage = SEARCH_RESULTS_PER_PAGE,
|
||||||
): Promise<{ results: User[]; totalResults: number; page: number; lastPage: number; from: number; to: number }> {
|
): Promise<SearchResult<User>> {
|
||||||
const member = pluginData.guild.members.cache.get(pluginData.client.user!.id);
|
const member = pluginData.guild.members.cache.get(pluginData.client.user!.id);
|
||||||
if (member && !hasDiscordPermissions(member.permissions, Permissions.FLAGS.BAN_MEMBERS)) {
|
if (member && !hasDiscordPermissions(member.permissions, Permissions.FLAGS.BAN_MEMBERS)) {
|
||||||
throw new SearchError(`Unable to search bans: missing "Ban Members" permission`);
|
throw new SearchError(`Unable to search bans: missing "Ban Members" permission`);
|
||||||
|
@ -454,7 +462,7 @@ async function performBanSearch(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const [, sortDir, sortBy] = (args.sort && args.sort.match(/^(-?)(.*)$/)) ?? [null, "ASC", "name"];
|
const [, sortDir, sortBy] = args.sort?.match(/^(-?)(.*)$/) ?? [null, "ASC", "name"];
|
||||||
const realSortDir = sortDir === "-" ? "DESC" : "ASC";
|
const realSortDir = sortDir === "-" ? "DESC" : "ASC";
|
||||||
|
|
||||||
if (sortBy === "id") {
|
if (sortBy === "id") {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import {
|
import {
|
||||||
Client,
|
Client,
|
||||||
|
Constants,
|
||||||
Message,
|
Message,
|
||||||
|
MessageActionRow,
|
||||||
|
MessageButton,
|
||||||
MessageEditOptions,
|
MessageEditOptions,
|
||||||
MessageOptions,
|
MessageOptions,
|
||||||
MessageReaction,
|
MessageReaction,
|
||||||
|
@ -25,8 +28,10 @@ const defaultOpts: PaginateMessageOpts = {
|
||||||
limitToUserId: null,
|
limitToUserId: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const forwardId = "forward" as const;
|
||||||
|
const backwardId = "backward" as const;
|
||||||
|
|
||||||
export async function createPaginatedMessage(
|
export async function createPaginatedMessage(
|
||||||
client: Client,
|
|
||||||
channel: TextChannel | User,
|
channel: TextChannel | User,
|
||||||
totalPages: number,
|
totalPages: number,
|
||||||
loadPageFn: LoadPageFn,
|
loadPageFn: LoadPageFn,
|
||||||
|
@ -34,30 +39,37 @@ export async function createPaginatedMessage(
|
||||||
): Promise<Message> {
|
): Promise<Message> {
|
||||||
const fullOpts = { ...defaultOpts, ...opts } as PaginateMessageOpts;
|
const fullOpts = { ...defaultOpts, ...opts } as PaginateMessageOpts;
|
||||||
const firstPageContent = await loadPageFn(1);
|
const firstPageContent = await loadPageFn(1);
|
||||||
const message = await channel.send(firstPageContent);
|
|
||||||
|
const components: MessageButton[] = [
|
||||||
|
new MessageButton({
|
||||||
|
customId: backwardId,
|
||||||
|
emoji: "⬅",
|
||||||
|
style: Constants.MessageButtonStyles.SECONDARY,
|
||||||
|
}),
|
||||||
|
new MessageButton({
|
||||||
|
customId: forwardId,
|
||||||
|
emoji: "➡",
|
||||||
|
style: Constants.MessageButtonStyles.SECONDARY,
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
const message = await channel.send({ ...firstPageContent, components: [new MessageActionRow({ components })] });
|
||||||
|
|
||||||
let page = 1;
|
let page = 1;
|
||||||
let pageLoadId = 0; // Used to avoid race conditions when rapidly switching pages
|
|
||||||
const reactionListener = async (
|
const collector = message.createMessageComponentCollector({ time: fullOpts.timeout });
|
||||||
reactionMessage: MessageReaction | PartialMessageReaction,
|
|
||||||
reactor: User | PartialUser,
|
collector.on("collect", async interaction => {
|
||||||
) => {
|
if (fullOpts.limitToUserId && interaction.user.id !== fullOpts.limitToUserId) {
|
||||||
if (reactionMessage.message.id !== message.id) {
|
return interaction.reply({ content: `You are not permitted to use these buttons.`, ephemeral: true });
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fullOpts.limitToUserId && reactor.id !== fullOpts.limitToUserId) {
|
await interaction.deferUpdate();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reactor.id === client.user!.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let pageDelta = 0;
|
let pageDelta = 0;
|
||||||
if (reactionMessage.emoji.name === "⬅️") {
|
if (interaction.customId === backwardId) {
|
||||||
pageDelta = -1;
|
pageDelta = -1;
|
||||||
} else if (reactionMessage.emoji.name === "➡️") {
|
} else if (interaction.customId === forwardId) {
|
||||||
pageDelta = 1;
|
pageDelta = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,34 +83,12 @@ export async function createPaginatedMessage(
|
||||||
}
|
}
|
||||||
|
|
||||||
page = newPage;
|
page = newPage;
|
||||||
const thisPageLoadId = ++pageLoadId;
|
void message.edit(await loadPageFn(page)).catch(noop);
|
||||||
const newPageContent = await loadPageFn(page);
|
});
|
||||||
if (thisPageLoadId !== pageLoadId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
message.edit(newPageContent).catch(noop);
|
collector.on("end", () => {
|
||||||
reactionMessage.users.remove(reactor.id).catch(noop);
|
message.edit({ components: [] });
|
||||||
refreshTimeout();
|
});
|
||||||
};
|
|
||||||
client.on("messageReactionAdd", reactionListener);
|
|
||||||
|
|
||||||
// The timeout after which reactions are removed and the pagination stops working
|
|
||||||
// is refreshed each time the page is changed
|
|
||||||
let timeout: Timeout;
|
|
||||||
const refreshTimeout = () => {
|
|
||||||
clearTimeout(timeout);
|
|
||||||
timeout = setTimeout(() => {
|
|
||||||
message.reactions.removeAll().catch(noop);
|
|
||||||
client.off("messageReactionAdd", reactionListener);
|
|
||||||
}, fullOpts.timeout);
|
|
||||||
};
|
|
||||||
|
|
||||||
refreshTimeout();
|
|
||||||
|
|
||||||
// Add reactions
|
|
||||||
message.react("⬅️").catch(noop);
|
|
||||||
message.react("➡️").catch(noop);
|
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue