mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-15 05:41: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);
|
||||
|
||||
createPaginatedMessage(
|
||||
pluginData.client,
|
||||
msg.channel,
|
||||
totalPages,
|
||||
async (page) => {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import {
|
||||
Formatters,
|
||||
GuildMember,
|
||||
Message,
|
||||
MessageActionRow,
|
||||
|
@ -35,6 +36,15 @@ export enum SearchType {
|
|||
BanSearch,
|
||||
}
|
||||
|
||||
interface SearchResult<T> {
|
||||
results: T[];
|
||||
totalResults: number;
|
||||
page: number;
|
||||
lastPage: number;
|
||||
from: number;
|
||||
to: number;
|
||||
}
|
||||
|
||||
class SearchError extends Error {}
|
||||
|
||||
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 loadSearchPage = async (page) => {
|
||||
const loadSearchPage = async (page: number) => {
|
||||
if (searching) return;
|
||||
searching = true;
|
||||
|
||||
|
@ -146,11 +156,9 @@ export async function displaySearch(
|
|||
: formatSearchResultList(searchResult.results);
|
||||
|
||||
const result = trimLines(`
|
||||
${headerText}
|
||||
\`\`\`js
|
||||
${resultList}
|
||||
\`\`\`
|
||||
`);
|
||||
${headerText}
|
||||
${Formatters.codeBlock("js", resultList)}
|
||||
`);
|
||||
|
||||
const searchMsg = await searchMsgPromise;
|
||||
|
||||
|
@ -298,7 +306,7 @@ async function performMemberSearch(
|
|||
args: MemberSearchParams,
|
||||
page = 1,
|
||||
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);
|
||||
|
||||
let matchingMembers = Array.from(pluginData.guild.members.cache.values());
|
||||
|
@ -426,7 +434,7 @@ async function performBanSearch(
|
|||
args: BanSearchParams,
|
||||
page = 1,
|
||||
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);
|
||||
if (member && !hasDiscordPermissions(member.permissions, Permissions.FLAGS.BAN_MEMBERS)) {
|
||||
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";
|
||||
|
||||
if (sortBy === "id") {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import {
|
||||
Client,
|
||||
Constants,
|
||||
Message,
|
||||
MessageActionRow,
|
||||
MessageButton,
|
||||
MessageEditOptions,
|
||||
MessageOptions,
|
||||
MessageReaction,
|
||||
|
@ -25,8 +28,10 @@ const defaultOpts: PaginateMessageOpts = {
|
|||
limitToUserId: null,
|
||||
};
|
||||
|
||||
const forwardId = "forward" as const;
|
||||
const backwardId = "backward" as const;
|
||||
|
||||
export async function createPaginatedMessage(
|
||||
client: Client,
|
||||
channel: TextChannel | User,
|
||||
totalPages: number,
|
||||
loadPageFn: LoadPageFn,
|
||||
|
@ -34,30 +39,37 @@ export async function createPaginatedMessage(
|
|||
): Promise<Message> {
|
||||
const fullOpts = { ...defaultOpts, ...opts } as PaginateMessageOpts;
|
||||
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 pageLoadId = 0; // Used to avoid race conditions when rapidly switching pages
|
||||
const reactionListener = async (
|
||||
reactionMessage: MessageReaction | PartialMessageReaction,
|
||||
reactor: User | PartialUser,
|
||||
) => {
|
||||
if (reactionMessage.message.id !== message.id) {
|
||||
return;
|
||||
|
||||
const collector = message.createMessageComponentCollector({ time: fullOpts.timeout });
|
||||
|
||||
collector.on("collect", async interaction => {
|
||||
if (fullOpts.limitToUserId && interaction.user.id !== fullOpts.limitToUserId) {
|
||||
return interaction.reply({ content: `You are not permitted to use these buttons.`, ephemeral: true });
|
||||
}
|
||||
|
||||
if (fullOpts.limitToUserId && reactor.id !== fullOpts.limitToUserId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reactor.id === client.user!.id) {
|
||||
return;
|
||||
}
|
||||
await interaction.deferUpdate();
|
||||
|
||||
let pageDelta = 0;
|
||||
if (reactionMessage.emoji.name === "⬅️") {
|
||||
if (interaction.customId === backwardId) {
|
||||
pageDelta = -1;
|
||||
} else if (reactionMessage.emoji.name === "➡️") {
|
||||
} else if (interaction.customId === forwardId) {
|
||||
pageDelta = 1;
|
||||
}
|
||||
|
||||
|
@ -71,34 +83,12 @@ export async function createPaginatedMessage(
|
|||
}
|
||||
|
||||
page = newPage;
|
||||
const thisPageLoadId = ++pageLoadId;
|
||||
const newPageContent = await loadPageFn(page);
|
||||
if (thisPageLoadId !== pageLoadId) {
|
||||
return;
|
||||
}
|
||||
void message.edit(await loadPageFn(page)).catch(noop);
|
||||
});
|
||||
|
||||
message.edit(newPageContent).catch(noop);
|
||||
reactionMessage.users.remove(reactor.id).catch(noop);
|
||||
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);
|
||||
collector.on("end", () => {
|
||||
message.edit({ components: [] });
|
||||
});
|
||||
|
||||
return message;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue