-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Switch to guildConfig and finish url monitoring
Finished the switch from Keyv to guild-config JSON files. More-or-less finished the implementation of URL monitoring and URL detection in embed-message. Added Replyable module to help with some util functions that could be used for both interactions and normal message replies. Added splitMessageRegex module, which is a substitue for DiscordJS/util.splitMessage which has a bug: discordjs/discord.js#7674 Added paginatedReply module, which is a clean way to send information that may not fit in a single message. This is combined with splitMessageRegex for a relatively easy way to send unlimited-length messages (such as with /http-monitor list) without flooding a guild channel or bashing Discord's API.
- Loading branch information
Showing
22 changed files
with
648 additions
and
229 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* A monad for replying to either interactions or messages, and then potentially | ||
* editing those replies. This is needed because the Interaction.reply and | ||
* Message.reply methods are actually a little different in options. | ||
*/ | ||
export class Replyable { | ||
#message; | ||
#interaction; | ||
#useMessage; | ||
#sentReply; | ||
constructor({ message, interaction } = {}) { | ||
if (message) { | ||
this.#message = message; | ||
this.#useMessage = true; | ||
} | ||
else if (interaction) { | ||
this.#interaction = interaction; | ||
this.#useMessage = false; | ||
} | ||
else { | ||
throw new Error('When constructing a Replyable, you must include a message and/or interaction, but neither was received.'); | ||
} | ||
} | ||
async reply(messageOptions) { | ||
if (this.#useMessage) { | ||
this.#sentReply = await this.#message.reply(messageOptions); | ||
return this.#sentReply; | ||
} | ||
await this.#interaction.reply(messageOptions); | ||
return this.#interaction.fetchReply(); | ||
} | ||
async editReply(messageOptions) { | ||
if (this.#useMessage) { | ||
return this.#sentReply.edit(messageOptions); | ||
} | ||
return this.#interaction.editReply(messageOptions); | ||
} | ||
getUser() { | ||
if (this.#useMessage) { | ||
return this.#message.author; | ||
} | ||
return this.#interaction.user; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// import { ButtonInteraction } from 'discord.js'; | ||
import { MessageEmbed, MessageActionRow, MessageButton } from 'discord.js'; | ||
|
||
export async function paginatedReply({ | ||
contents, | ||
replyable, | ||
} = {}) { | ||
const numPages = contents.length; | ||
const contentEmbeds = contents.map( | ||
str => new MessageEmbed().setDescription(str) | ||
); | ||
// If there is only one page, do not include the page buttons: | ||
if (numPages === 1) { | ||
return replyable.reply({ embeds: contentEmbeds }); | ||
} | ||
let currentPage = 0; | ||
const buttonOrder = [ | ||
{ | ||
id: 'first-page', | ||
label: '❚◀', | ||
press() { currentPage = 0; }, | ||
}, | ||
{ | ||
id: 'previous-page', | ||
label: '◀', | ||
disabled: true, | ||
press() { --currentPage; }, | ||
}, | ||
{ | ||
id: 'page-number', | ||
label: `1 / ${numPages}`, | ||
disabled: true, | ||
}, | ||
{ | ||
id: 'next-page', | ||
label: '▶', | ||
press() { ++currentPage; }, | ||
}, | ||
{ | ||
id: 'last-page', | ||
label: '▶❚', | ||
press() { currentPage = numPages - 1; }, | ||
}, | ||
]; | ||
const buttonData = Object.create(null); | ||
const buttonComponents = []; | ||
for (const button of buttonOrder) { | ||
buttonData[button.id] = button; | ||
const component = (new MessageButton() | ||
.setCustomId(button.id) | ||
.setLabel(button.label) | ||
.setStyle(button.style ?? 'SECONDARY') | ||
.setDisabled(button.disabled ?? false) | ||
); | ||
button.component = component; | ||
buttonComponents.push(component); | ||
} | ||
const row = new MessageActionRow().addComponents(buttonComponents); | ||
const getPageResponse = page => { | ||
buttonData['first-page'].component.setDisabled(page <= 0); | ||
buttonData['previous-page'].component.setDisabled(page <= 0); | ||
buttonData['next-page'].component.setDisabled(page >= numPages - 1); | ||
buttonData['last-page'].component.setDisabled(page >= numPages - 1); | ||
buttonData['page-number'].component.setLabel( | ||
`${currentPage + 1} / ${numPages}` | ||
); | ||
return { | ||
embeds: [ | ||
contentEmbeds[page], | ||
], | ||
components: [row], | ||
}; | ||
}; | ||
const botMessage = await replyable.reply(getPageResponse(currentPage)); | ||
// make listener for buttons which changes the currentPage var and calls | ||
// getPageResponse or w/e. This should be ez | ||
|
||
const userId = replyable.getUser().id; | ||
const filter = buttonInteraction => buttonInteraction.user.id === userId; | ||
const collector = botMessage.createMessageComponentCollector({ | ||
filter, | ||
idle: 5 * 60_000, | ||
}); | ||
collector.on('collect', buttonInteraction => { | ||
const buttonId = buttonInteraction.customId; | ||
buttonData[buttonId].press(); | ||
buttonInteraction.update(getPageResponse(currentPage)); | ||
}); | ||
collector.on('end', () => { | ||
for (const button of buttonOrder) { | ||
button.component.setDisabled(); | ||
} | ||
const content = 'This paginated message has timed out. Please re-use the original command to see the other pages again.'; | ||
// If the message was deleted, trying to edit it will throw: | ||
try { | ||
return replyable.editReply({ content }); | ||
} | ||
catch (error) { | ||
return; | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.