js 13 discord buttons clicked one - node.js

I am writing tickets to the system. Reports come to a special channel. There is an "accept" button, it works, but when more than one report arrives, if you click on the "accept" button, then all reports will be accepted
2 reports IMAGE
i clicked one IMAGE
client.on('interactionCreate', async interaction => {
if(interaction.isButton()) {
if (interaction.customId.includes(`acceptB`)) {
myacceptB.edit({embeds:[editEmbRep]})
interaction
let channelx = interaction.guild.channels.cache.get(myreportChannel)
if(channelx){
channelx.permissionOverwrites.edit(interaction.user.id,{ VIEW_CHANNEL: true,SEND_MESSAGES: true,ATTACH_FILES: true,READ_MESSAGE_HISTORY:true })}
Might need to use a unique idButton each time, but I don't know how to check that

This code should only edit the message that the button clicked is attached to. There is no need for unique ID’s for each button when you edit the message the interaction is attached to.
client.on('interactionCreate', async interaction => {
if(interaction.isButton()) {
if (interaction.customId === `acceptB`) {
const editEmbRep = new MessageEmbed()
.setTitle('New Embed')
interaction.message.edit({
content: 'updated text', // to change the text
embeds: [editEmbRep], // to change the embed
components: [] // if you want to remove the button
})
// Not sure what you are trying to do with this part so I didn’t do anything with it.
let channelx = interaction.guild.channels.cache.get(myreportChannel)
if (channelx) {
channelx.permissionOverwrites.edit(
interaction.user.id,
{
VIEW_CHANNEL: true,
SEND_MESSAGES: true,
ATTACH_FILES: true,
READ_MESSAGE_HISTORY:true
}
)
}
}
}
})

Related

How to make chrome.contextMenus.onClicked.addListener distinguish for different context menu ids?

While developing contextmenu based extension for Chrome, i'm facing a situation where invoking chrome.contextMenus.onClicked.addListener in a loop adds action cumulatively for each subcontext menu item.
So, when subcontextmenu is clicked it triggers event listener for all subcontext menus, instead for the context menu which was clicked.
var parent;
chrome.runtime.onInstalled.addListener(() => {
parent = chrome.contextMenus.create({"title": "CCM", "id":"CCM", "contexts":["selection"]});
});
Object.keys(msgs).forEach(function(key) {
chrome.runtime.onInstalled.addListener(() => {
var createCM = chrome.contextMenus.create(
{"title": "subcontextmenu"+key, "id":"scm"+key, "parentId": parent, "contexts":["selection"]});
});
chrome.contextMenus.onClicked.addListener(function(info,tab){openAction(info,tab,JSON.stringify(msgs[key]['msg']));}
);
});
In the above example, msgs is a JSON object containing message to be displayed when each subcontextmenu is clicked. Also, the msgs JSON context is bound to change dynamically. So, we can't tweak openAction to hardcode the numbers and associate the messages.
Hope my question is clear. Any help for clearing this confusion will be a great time saver for me.
Use one listener for onInstalled and onClicked (it provides menuItemId in its parameter).
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({title: 'CCM', id: 'CCM', contexts: ['selection']});
Object.keys(msgs).forEach(key => {
chrome.contextMenus.create({
title: 'subcontextmenu' + key,
id: 'scm' + key,
parentId: 'CCM',
contexts: ['selection'],
});
});
});
chrome.contextMenus.onClicked.addListener((info, tab) => {
openAction(info, tab, JSON.stringify(msgs[info.menuItemId].msg));
});

Telegraf.js pass data from button to a function that handle a WizardScene

I need to pass some data retrieved from a Database.
When i click into a button i send a private message to the user who have cliecked. I need to pass some datas from that button, to the message sent. Because, into that message i have an other button that starts a WizardScene. SO how can i do to pass data? Thank you.
Here is my code.
This is into a function that post a photo with a description and with a callbackup button.
my function() {
...
let productId = //obtain from a db;
await bot.telegram.sendPhoto(
channel_id,
{ source: filepath },
{
caption: description.join("\n"),
parse_mode: 'MarkdownV2',
reply_markup: productButtons.reply_markup
}
)
return productId;
...}
and the button is:
const productButtons = Extra.markup((m) =>
m.inlineKeyboard([
[m.callbackButton('TEST', 'test_btn')],
])
)
when someone clicsk on it, it sends a message on a private user with this:
bot.action('testa_btn', (ctx) => {
console.log('testa')
let text = `My text about ${productId}`
ctx.telegram.sendMessage(ctx.from.id, o_functions.escapeReplace(text), {
parse_mode: 'MarkdownV2',
reply_markup: startBtn.reply_markup
})
});
this sends a text where i need to write my productid, and an other button where i start my wizard scene:
const startBtn = Extra.markup((m) =>
m.inlineKeyboard([
[m.callbackButton('START', 'start_btn_wizard')],
])
);
bot.action('start_btn_wizard', (ctx) => {
return ctx.scene.enter('super-wizard');
})
So how can i pass my productId variable, first to the button TEST, then to the wizard scene? I need to use it on the Wizard on the user dialogue.
THank you
You need to do a couple of things to pass data from a callback button to a handler and then towards a wizard scene.
Add the desired data to the button. Notice how I attached the product Id to the callback data.
const startBtn = Extra.markup((m) =>
m.inlineKeyboard([
[m.callbackButton('START', `start_btn_wizard_${product_id}`)],
])
);
Receive the button callback using a regex rather than using a literal string and extract the product ID from the callback data.
bot.action(/start_btn_wizard_+/, (ctx) => {
let product_id = ctx.match.input.substring(17);
// add all necessary validations for the product_id here
return ctx.scene.enter('super-wizard');
});
Pass the acquired id to the wizard scene and extract it again from inside the scene using ctx.scene.state.
bot.action(/start_btn_wizard_+/, (ctx) => {
let product_id = ctx.match.input.substring(17);
// add all necessary validations for the product_id here
return ctx.scene.enter('super-wizard', {product_id: product_id});
});
From inside the wizard, you can access the product_id using ctx.scene.state.product_id.
Hope this helps someone even though it's probably too late for the OP

Botframework TextPrompt how to send user input as postback

I built a bot that needs to ask the user for a password.
In my current implementation, the bot logic sends an event to the webchat-client to trigger the rendering of a password input field.
const askPwd =
{
name: 'passwordInput',
type: 'event'
};
await stepContext.context.sendActivity(askPwd);
return await stepContext.prompt(SSD_PASSWORD_PROMPT);
In the webchat client, I use activity middleware to render the password input field (and hide the regular input field).
const activityMiddleware = () => next => ({ activity, nextVisibleActivity, ...otherArgs }) => {
const { from: { role }, name, type } = activity;
if (type === 'event' && name === 'passwordInput'){ return () => <PasswordInputActivity activity={activity} nextVisibleActivity={nextVisibleActivity} />;
}}
This works but is confusing to the user. I would rather use the regular input field. I would be able to dynamically turn this into a password type field. The problem is that the input is indeed masked but the password is shown in the chat timeline (unmasked ofcourse).
Is there a way to use a text-prompt and send the input as postback to the bot-logic?

Suggestions are not working in actions on google

I create a chat bot using dialogflow and actions on google library. In the back-end code I have created function including if else. I added new suggestions in the "else if". That are not display in the actions on google simulator.Another suggestions are working. Only that time it is not displayed. Please give me some instructions for fixed that.
this is my code:
'use strict';
const functions = require('firebase-functions');
const {
dialogflow,
Suggestions,
Carousel,
Image,
Table,
List,
} = require('actions-on-google');
const app = dialogflow({debug: true});
// Constants for list and carousel selection
const Order_Food = 'order food';
const Extra_Product = 'extra product';
const Spa_Reservation = 'spa reservation';
const Restaurant_Booking = 'restaurant booking';
app.intent('user.provide_room_number', (conv) => {
conv.ask('Great! I can help you with the following. Please select
from the options below.');
//conv.ask(new Suggestions('Order Food', 'Extra Product',
'Restaurant', 'Spa'));
// Create a carousel
conv.ask(new Carousel({
items: {
// Add the first item to the carousel
[Order_Food]: {
synonyms: [
'order food',
'food',
],
title: 'Food',
description: 'Can order some food',
image: new Image({
url: 'http://www.restauranteelpalacete.com/wp-content/uploads/2018/01/Online-Food-Ordering.jpg',
alt: 'Food',
}),
},
// Add third item to the carousel
[Spa_Reservation]: {
synonyms: [
'spa',
'spa reservation',
],
title: 'Spa Reservation',
description: 'Can put the reservation on the spa.',
image: new Image({
url: 'https://res.klook.com/images/fl_lossy.progressive,q_65/c_fill,w_1295,h_720,f_auto/w_80,x_15,y_15,g_south_west,l_klook_water/activities/kykzulvt1t71kwhnmkik/OasisSpa.jpg',
alt: 'Spa',
}),
},
// Add fourth item to the carousel
[Restaurant_Booking]: {
synonyms: [
'restaurant',
'restaurant booking',
],
title: 'Restaurant',
description: 'Can put the reservation on the Restaurant.',
image: new Image({
url: 'https://cdn-image.foodandwine.com/sites/default/files/1501607996/opentable-scenic-restaurants-marine-room-FT-BLOG0818.jpg',
alt: 'Restaurant',
}),
},
},
}));
});
app.intent('actions_intent_OPTION-handler', (conv, params, option) => {
// Get the user's selection
// Compare the user's selections to each of the item's keys
if (!option) {
conv.ask('You did not select any item from the list or carousel');
} else if (option === 'order food') {
conv.ask(new SimpleResponse({speech:"Absolutely, have you decided what you like or you could go through the in room dinning menu. \n Do you need order Food.?",text:"Absolutely, have you decided what you like or you could go through the in room dinning menu. Do you need order Food.?"}));
conv.ask(new Suggestions(["Ok", "Done", "Thanks"]));
} else if (option === 'spa reservation') {
conv.ask(new Suggestions('Yes I need Spa.'));
conv.ask(`We have an excellent Spa that offer exquisite treatment packages. You can select one of the options. We have quite a few free slots today. Do you need information about that.`);
} else if (option === 'restaurant booking') {
conv.ask(`We have some dining options for you today. Do you want more information. `);
conv.ask(new Suggestions('I need restaurant.'));
} else {
conv.ask('You selected an unknown item from the list, or carousel');
}
});
You should design your conversation bot more efficiently.In second elseif condition, after a suggestion no further conversation should happen in an intent.Suggestion are for triggering intent. For your case best scenario would be to create a follow up intent.
Suggestion is not appearing in conversation because, in every rich response at least one simple response should be present. Try below code. Hope this helps you.
conv.ask(new SimpleResponse({speech:"Absolutely, have you decided what you like or you could go through the in room dinning menu. \n Do you need order Food.?",text:"Absolutely, have you decided what you like or you could go through the in room dinning menu. Do you need order Food.?"}));
conv.ask(new Suggestions(["Ok", "Done", "Thanks"]));

Extjs Grid - Click next page button with search condition

I have a gridpanel and i create store in initComponet function like
,initComponent: function() {
var store = Ext.create('Ext.data.Store', {
model: 'MyObject',
autoLoad: false,
pageSize:22,
remoteSort:true,
proxy: {
type: 'ajax',
url: 'example.php',
reader: {
type: 'json',
totalProperty: 'total',
root: 'results'
}
}
});
this.store = store;
this.dockedItems = [{
xtype: 'pagingtoolbar',
store: this.store,
displayMsg: '{0} - {1} / {2}',
emptyMsg: 'empty',
dock: 'bottom',
displayInfo: true,
pageSize: 22
}];
this.callParent(arguments);
this.store.load({params:{start:0, limit:22}});
}
I make a form search with some value and when i press search button i will do below code
grid.store.load({
params:{
start:0,
limit:22,
signalSearch: 1,
search1: myValue1,
search2: myValue2,
}
});
In my php file will catch that to know that's search
if ( have $_REQUEST["signalSearch"]) {
// print json with condition search
}else {
// print json with all data
}
And results return with 2 page (it well). But when i press Next page button to see some results on page 2 But my store load fail (i think they call store.load({params:{start:0, limit:22}}); when i press next page button and in my php file that will run with else case).
That's not call
grid.store.load({
params:{
start:0,
limit:22,
search1: myValue1,
search2: myValue2,
}
});
My idea to make search is not good? How can i fix that thank
If you use params in the "load" function of the store, those are referred to the single request only so if you click next page of the toolbar you won't post the signalSearch param.
You should register a custom listener on the before load event and add your params:
initComponent: function(){
....
this.callParent(arguments);
this.store.addListener('beforeload', function(store, operation){
Ext.apply(operation.params, {
signalSearch: 1 // Or you could make conditions if apply this search param
});
return true;
}, this);
}

Resources