open-wa / wa-automate-nodejs

💬 🤖 The most reliable tool for chatbots with advanced features. Be sure to 🌟 this repository for updates!
https://docs.openwa.dev/
Other
3.12k stars 592 forks source link

Making onClick on button #1911

Closed BbayuGt closed 3 years ago

BbayuGt commented 3 years ago

Hey i have a suggestion. As you know that button have id. I wonder theres way to hook it. Like when you click it, and send message with text that you get when you click it. It'll run a function. Like

buttonMsg.click(id, callback)

Or more "open-wa" way (using client)

client.buttonClick(messageId, buttonId, callback)

theres no way id has nothing else todo except just key in object.

BbayuGt commented 3 years ago

Update : Client will respond with messageType "buttons_response". You also have selectedButtonId inside. So you know what button the user click without needing what text the user send

bauti-defi commented 3 years ago

Hello, I am also very interested in being able to listen to button clicks.

I'd suggest an implementation similar to Telegram's chat buttons. Here is an example implementation that uses the Telegraf API. Telegraf is a wrapper for the official Telegram API. It adds utility and quality of life methods to the underlying telegram client.

Example:

As we can see in the snippet below, the button schema is predefined. Each button is defined by its text (button text body), callback_data (a simple string), and grid position. The grid position is defined by the index of the button in the 2d-array (helpButtons). We can expect this code snippet to produce a message with 6 buttons organized into 3 rows and 2 columns, respectively.

const helpButtons = [
  [
    { text: "Dólar", callback_data: "dolar-help" },
    { text: "NYSE", callback_data: "nyse-help" },
  ],
  [
    { text: "Cripto", callback_data: "cripto-help" },
    { text: "Granos", callback_data: "granos-help" },
  ],
  [
    { text: "Lista de Comandos", callback_data: "list-commands-help" },
    { text: "Lista de Canales", callback_data: "list-channels-help" },
  ],
];

const helpMessage = ["<strong>Como te puedo ayudar?</strong>"];

const HelpRoute = async (ctx) => {

  await ctx.replyWithHTML(helpMessage.join("\n"), {
    reply_markup: {
      inline_keyboard: helpButtons,
    },
  });
};

const useHelpModule = (bot) => {
  bot.help(HelpRoute);
};

export default useHelpModule;

The callback_data button attribute is registered as an "action" on the Telegraf Bot instance. When a button is clicked, its action is fired, subsequently triggering the listeners for that action. Below is an example of how the "nyse-help" action defined by the "NYSE" button above (helpButtons) is registered to the bot instance with WallstreetHelper as the trigger function.

const WallstreetHelper = async (ctx) => {
  const helpMessage = ["hello" , "world"];

  await ctx.replyWithHTML(helpMessage.join("\n"));
};

const useWallstreetModule = (bot) => {
  bot.action("nyse-help", WallstreetHelper);
};

export default useWallstreetModule;

Relevant documentation links:

Telegram #sendMessage() InlineKeyboardButton Button Callback Query

I'd love to collaborate on the development of this feature through discourse and my own personally coding time. Cheers, friends.

OmarAttia commented 3 years ago

This is really confusing and shouldn’t be open, we already have the onincoming event, on any message and even collectors. You have all the tools to make everything!

bauti-defi commented 3 years ago

This is really confusing and shouldn’t be open, we already have the onincoming event, on any message and even collectors. You have all the tools to make everything!

Could you elaborate how those tools could be used to create a function listener pattern?

BbayuGt commented 3 years ago

This is really confusing and shouldn’t be open, we already have the onincoming event, on any message and even collectors. You have all the tools to make everything!

What is the use of button if you couldn't do anything with it? Idk if it already fixed or not. Message that send because of button doesn't trigger onMessage.

smashah commented 3 years ago

Buttons are a new feature and there can be some more quality of life improvements around working with them.

kmirea commented 3 years ago

Guys is it ok if i ask here, what is the response (onIncoming) for a button press ? is there a way to distinguish which of the (3) buttons were pressed, im assuming its treated like a regular text message.

Wont be able to test for a while, im many builds behind. D: But amazing work @smashah i didnt expect wed get this at all <3

smashah commented 3 years ago

@github-actions run

⚡ Release! ⚡ ```js (async () => { function exec(cmd) { console.log(execSync(cmd).toString()); } // Config const gitUserEmail = "github-actions[bot]@users.noreply.github.com"; const gitUserName = "github-actions[bot]"; exec(`echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc`); exec(`git config --global user.email "${gitUserEmail}"`); exec(`git config --global user.name "${gitUserName}"`); exec(`npm i -D`); exec(`npm run release-ci minor`); //comment on the issue var result = execSync(`npx auto-changelog -o ./tempchangelog.txt --commit-limit false --template ./compact-keepachangelog.hbs --stdout`).toString(); await postComment(result); //create changelog image exec(`npm run release-image`); exec(`git commit -a -m 'updated release-image'`); exec(`git push --force`); })(); ```
smashah commented 3 years ago

Changelog

🚀 Release 4.16.0 (2021-08-18)

smashah commented 3 years ago

Ok here's a bit of a guide to onButton. It basically is the same as onMessage but only emits when a button or list response is detected. The buttonResponse object is the same/an extension of the Message object. The message type itself has been updated to reflect the new changes

client.onButton(async buttonResponse => {
    if (buttonResponse.type == 'buttons_response') {
        //id of selected button is buttonResponse.selectedButtonId
        console.log(`User ${buttonResponse.from} selected ${buttonResponse.selectedButtonId}`)
        const sourceButtons = buttonResponse.quotedMsgObj.buttons
    }
    if (buttonResponse.type == 'list_response') {
        //id of selected list item is buttonResponse.selectedButtonId.rowId
        console.log(`User ${buttonResponse.from} selected ${buttonResponse.listResponse.rowId}`)

        //source list response is buttonResponse.quotedMsgObj.list
        const sourceList = buttonResponse.quotedMsgObj.list
    }
})
cantiir2 commented 2 years ago

Ok here's a bit of a guide to onButton. It basically is the same as onMessage but only emits when a button or list response is detected. The buttonResponse object is the same/an extension of the Message object. The message type itself has been updated to reflect the new changes

client.onButton(async buttonResponse => {
    if (buttonResponse.type == 'buttons_response') {
        //id of selected button is buttonResponse.selectedButtonId
        console.log(`User ${buttonResponse.from} selected ${buttonResponse.selectedButtonId}`)
        const sourceButtons = buttonResponse.quotedMsgObj.buttons
    }
    if (buttonResponse.type == 'list_response') {
        //id of selected list item is buttonResponse.selectedButtonId.rowId
        console.log(`User ${buttonResponse.from} selected ${buttonResponse.listResponse.rowId}`)

        //source list response is buttonResponse.quotedMsgObj.list
        const sourceList = buttonResponse.quotedMsgObj.list
    }
})

I've tried this and it works, but the button can't respond to what I make the button. Link : https://github.com/open-wa/wa-automate-nodejs/issues/2342#issue-1073925816