3
0
Fork 0
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:
almeidx 2021-08-22 12:17:47 +01:00
parent 5042d9997f
commit e8bc549dd4
No known key found for this signature in database
GPG key ID: C5FF0C40763546C5
3 changed files with 52 additions and 55 deletions

View file

@ -43,7 +43,6 @@ export const CasesModCmd = modActionsCmd({
const prefix = getGuildPrefix(pluginData);
createPaginatedMessage(
pluginData.client,
msg.channel,
totalPages,
async (page) => {

View file

@ -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") {

View file

@ -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;
}