creating message component (Button) discord.js - discord

Click at this
I want to create button but I don't know how can I do it? Can anybody give me an example? I want it without packages

Here is a simple example with no modules (just discord.js) to create a simple button and reply on click:
const { Client, MessageActionRow, MessageButton } = require('discord.js')
// The code... (the client.on('message') or .on('interactionCreate'))
const row = new MessageActionRow()
.addComponents(
new MessageButton()
.setCustomId("simple-example") // It is better to have a unique ID for the buttons
.setLabel("Text diplayed on the button")
.setStyle('PRIMARY'), //PRIMARY, SECONDARY, ALERT or SUCCESS
);
// For interactions do like this:
interaction.reply({ content: "Super button below", components: [row] })
// For messages do like this:
message.reply({ content: "Super button below", components: [row] })
client.on('interactionCreate', interaction => {
if (interaction.isButton()) {
if (interaction.customId === "simple-example") {
interaction.reply('Button clicked !')
}
}
})
// Log in with the bot

Related

discord.js modal giving error something went wrong

Whenever i submit the modal it gives me error something went wrong try again..
this is my code -
const { Events, EmbedBuilder, AttachmentBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ActionRowBuilder, ButtonBuilder, ButtonStyle, InteractionType} = require('discord.js');
const { Verification } = require('../models/verificationSchema')
const { Captcha } = require('captcha-canvas')
module.exports = {
name: Events.InteractionCreate,
async execute(interaction, client) {
if (interaction.isButton()){
if (interaction.customId === 'verify') {
await interaction.deferReply({ephemeral: true});
const member = await interaction.guild.members.cache.get(interaction.member.user.id) || await interaction.guild.members.fetch(interaction.member.user.id).catch(err => {});
const captcha = new Captcha();
captcha.async = true;
captcha.addDecoy();
captcha.drawTrace();
captcha.drawCaptcha();
const captchaAnswer = captcha.text;
const captchaImage = new AttachmentBuilder()
.setFile(await captcha.png)
.setName('captcha.png')
const captchaEmbed = new EmbedBuilder()
.setTitle('Verification Captcha')
.setColor('Yellow')
.setImage('attachment://captcha.png')
.setDescription(`Please enter the captcha text`)
const captchaRow = new ActionRowBuilder()
.addComponents([
new ButtonBuilder()
.setLabel('Answer')
.setCustomId('answer')
.setStyle(ButtonStyle.Success)
])
await interaction.editReply({embeds: [captchaEmbed], files: [captchaImage], components: [captchaRow]});
}
}
if (interaction.customId === 'answer') {
const modal = new ModalBuilder()
.setCustomId('verificationModal')
.setTitle('Verification Input')
.addComponents([
new ActionRowBuilder().addComponents([
new TextInputBuilder()
.setCustomId('captchaInput')
.setLabel("Enter the Captcha.")
.setStyle(TextInputStyle.Short),
])
]);
interaction.showModal(modal);
}
if (interaction.isModalSubmit()) {
console.log(interaction)
if (interaction.customId === 'verificationModel') {
const response = interaction.fields.getTextInputValue('captchaInput');
console.log(response)
}
}
}
}
I am trying to make a verification command in discord i ask the user for captcha text via the modal but it gives me error. i don't know how to fix this error i just want to get the user input in modal whenever the modal is submitted..
there is no error in the terminal.
thanks in advance :)
error image
The modal is showing that because Discord expected a response to the modal interaction. If you don't want to send a message to the user when they submit the modal (e.g. by using interaction.reply()) then you can simply defer an update to the interaction using the ModalSubmitInteraction.deferUpdate() method. Example:
if (interaction.isModalSubmit()) {
interaction.deferUpdate()
// all the other stuff you want to do with the modal submission here
}
What should happen here is that when the user clicks the submit button on your modal, Discord sends their submission to your bot, you respond that you simply want to defer the interaction, and then Discord closes the modal for the user without showing an error message.

How do i disable the button after its been clicked a certain amount of times discord js

so basically, i would pass a number as an argument and i want to disable the button after it was clicked that many times.
However, when i use this code, it returns how many times it has been clicked but it doesnt disable the button.
message.channel.send({
content: "Click on the button below to enroll for fate adventure!",
components: [row],
});
const filter = (m) => m.customId === "enrollButton";
const collector = message.channel.createMessageComponentCollector({
filter: filter,
max: parseInt(args[1]),
time: 15000,
});
collector.on("collect", (i) => {
i.reply(`Clicked`);
});
collector.on("end", (collected) => {
row.components[0].setDisabled(true);
message.channel.send(`Clicked ${collected.size} times`);
});
Simply EDIT the message with everything keeping it the same but with the button edited to be disabled. For example:
collector.on("end", collected => {
collected.first().message.edit({
components: collected.first().message.components
.map(c => c.map(c => c.setDisabled(true)))
})
});
One way to give your code context of how many times the button has been pressed is to add a property to your client.
client.buttonClicks = 0;
And increment it on the collect event. Then, check if the limit has been reached. If so, end the collector and disable the button.
collector.on("collect", (i) => {
i.reply(`Clicked`);
client.buttonClicks++;
if (client.buttonClicks == LIMIT) {
collector.end("limit");
}
});
collector.on("end", (collected) => {
// Disable here
});

Trouble on testing onChange property from ant design

I’m having trouble in testing the behaviour of an ant design component.
I use Text component from ant design with ‘editable’ and ‘onChange’ properties for editing a comment. For saving the new content I have to click anywhere on the page or to press enter and the onChange function will be triggered. I tested manually and everything works fine.
In tests, I manage to edit the content of the comment, but when I simulate the enter pressing (or the clicking on any DOM element) the onChange function is not called.
What should I do in order to trigger the onChange function?
Here's my component:
<Text editable={{ onChange: editComment }}
id={"edit-comment-" + props.commentIndex}>
{props.body}
</Text>
Here's my test:
the test includes both methods of triggering the onChange function, but I did not use both of them at the same time
test('Edit comment request', async () => {
const fakeResponse = {
success: 1
};
jest.spyOn(global, "fetch").mockImplementation(() =>
Promise.resolve({
json: () => Promise.resolve(fakeResponse)
})
);
const editButton = container.querySelector("span[aria-label='edit']");
await fireEvent.click(editButton);
// Edit the comment content
fireEvent.change(screen.getByRole('textbox'), { target: { value: "edited comment" } });
// Save the comment content by pressing enter
await fireEvent.keyPress(screen.queryByText(/edited comment/i),
{ key: "Enter", code: "Enter", keyCode:13, charCode: 13 });
// Save the comment content by clicking on a random DOM element
await fireEvent.click(container.querySelector('.ant-comment-content-author'));
await wait(() => expect(global.fetch).toHaveBeenCalled());
});
Try to set _defaultValue property before dispatch the onChange event:
const textbox = screen.getByRole('textbox');
textbox.value = "edited comment";
textbox._valueTracker.setValue(null);
fireEvent.change(textbox, {bubbles: true});
To React the value is still unchanged. Check this issue: https://github.com/facebook/react/issues/11488

I wish to add a progress listener or feedback for this submit function to let the user know when the task is complete

I wish to use Or any Material-UI feedback component to capture the submit progress of the form
const onSubmit = (e) => {
e.preventDefault();
if (eventImage) {
const uploadImage = storage.ref(`EventImages/${values.eventName}`)
uploadImage.put(eventImage).then(() => {
storage.ref('EventImages').child(values.eventName).getDownloadURL().then(url => {
dbref.add({
eventName: values.eventName,
eventVenue: values.eventVenue,
eventAddress: values.eventAddress,
eventCategory: values.eventCategory,
eventOrganizer: values.eventOrganizer,
eventPhone: values.eventPhone,
eventEmail: values.eventEmail,
eventDetails: values.eventDetails,
eventDate: selectedDate.toDateString(),
eventTime: selectedDate.toLocaleTimeString(),
eventImgUrl: url
}).then((docRef) => {
console.log("Document written with ID: ", docRef.id);
setValues("");
setImg("");
setImgName("");
}).catch((error) => {
console.error("Error adding document: ", error);
});
})
})
}
}
I wish to use any Material-UI feedback component to achieve this
Typically a progress bar is used in such situations, so that the user knows how much of the task is completed/remains.
IMO showing a percentage completed and/or time remaining is helpful to. (time is a bit harder to implement)
Material UI Progress Bar : https://material-ui.com/components/progress/#linear-buffer
This might help?
They have an example attached with source code as well. Let me know if you need more info

Show custom dialog setRouteLeaveHook or history.listenBefore react-router/redux?

I cant seem to figure out how to show a custom dialogue instead of using the normal window.confirm that routeWillLeave and history.listenBefore uses. Basically i have built a notification system and check if a form is dirty const { dispatch, history, dirty } = this.props;
if the form is dirty it means the user has unsaved changes. If they change route I would like to show my notification which will have two buttons STAY, IGNORE which can both take an onClick handler.
Ive spent a bit of time googling and havent come across any mention of how i might accomplish this using routeWillLeave. The closest thing i could find was to use history.listenBefore however there docs say that I need to do this.
let history = createHistory({
getUserConfirmation(message, callback) {
callback(window.confirm(message)) // The default behavior
}
})
But I am using browserHistory from react-router to initiate my store const history = syncHistoryWithStore(browserHistory, store);
How can I stop a route change after a link has been clicked, show a notification using my custom notification system and depending on which button is clicked either transition to the new route or stay?
Here is an example of how my notification system works and the direction ive headed in which obviously doesn't work because all this returns is a string to show in the window.confirm dialogue by default.
history.listenBefore((location) => {
if(this.props.dirty){
const acceptBtn = {
title: 'STAY',
handler: ignoreRouteChange() //This can be any function I want
}
const denyBtn = {
title: 'IGNORE',
handler: continueRouteChange() //This can be any function I want
}
return dispatch(addNotification({
message: 'You have unsaved changes!',
type: NOTIFICATION_TYPE_WARNING,
duration: 0,
canDismiss: false,
acceptBtn,
denyBtn
}));
return "Usaved changes!"
}
});
Thanks
Another solution that i have decided to use is to return false in the normal setRouterLeaveHook callback and then show my dialog and use the nextLocation passed to the callback to push the next route depending on button selection.
router.setRouteLeaveHook(route, this.routerWillLeave.bind(this));
routerWillLeave(nextLocation){
let { dirty, dispatch, resetForm } = this.props;
if (dirty) {
let dialog = {
id: Date.now(),
showTitle: true,
titleContent: 'Unsaved Changes',
titleIcon: 'fa fa-warning',
content: <span>You have <strong>unsaved</strong> changes! <strong>Discard</strong> them?</span>,
type: 'confirm',
handleCloseClick: (e) => {
e.preventDefault();
dispatch(closeDialog());
},
acceptBtn: {
title: 'Okay',
handler: (e) => {
e.preventDefault();
resetForm();
// Wait for call stack to unwind and then execute
// the following which will now have the updated values.
setTimeout(() => {
dispatch(push(nextLocation));
dispatch(closeDialog());
}, 0);
}
},
denyBtn: {
title: 'Deny',
handler: (e) => {
e.preventDefault();
dispatch(closeDialog());
}
}
}
dispatch(addDialogWindow(dialog));
dispatch(openDialog(false, (e) => dispatch(closeDialog()), false));
return false;
}
return true;
}

Resources