Telegram bot inline keyboard markup callback usage for channel messages - javascript

My Telegram bot needs to send messages to channel and provide inline keyboard for every message, it looks like this: inline message keyboard
I need to react on this keyboard button click event, but I can't find docs or examples showing how to do it. Here in docs I can only see that such buttons can open URL or switch chat, but it's not the functionality I need.
Currently my code for message sending looks like this (I use NodeJS Telegraf framework):
const Telegraf = require('telegraf');
const { Markup, Telegram } = Telegraf;
const telegram = new Telegram(process.env.BOT_TOKEN);
const inlineMessageRatingKeyboard = [[
{ text: '👍', callback_data: 'like' },
{ text: '👎', callback_data: 'dislike' }
]];
telegram.sendMessage(
process.env.TELEGRAM_CHANNEL,
'test',
{ reply_markup: JSON.stringify({ inline_keyboard: inlineMessageRatingKeyboard }) }
)
);
So, I need to know, how to make bot react on inline message keyboard interaction in channel messages.

you can use event action() or in TelegrafContext with callbackQuery() and answerCallbackQuery()
context methods on GitHubGist
it's work:
const Telegraf = require('telegraf')
const { Router, Markup } = Telegraf
const telegram = new Telegraf(process.env.BOT_TOKEN)
const inlineMessageRatingKeyboard = Markup.inlineKeyboard([
Markup.callbackButton('👍', 'like'),
Markup.callbackButton('👎', 'dislike')
]).extra()
telegram.on('message', (ctx) => ctx.telegram.sendMessage(
ctx.from.id,
'Like?',
inlineMessageRatingKeyboard)
)
telegram.action('like', (ctx) => ctx.editMessageText('🎉 Awesome! 🎉'))
telegram.action('dislike', (ctx) => ctx.editMessageText('okey'))
telegram.startPolling()
full example here

Related

Automated github issue bot?

I would like to make a discord bot that creates an issue based on user input from discord. Any idea how I would do this? I am using JavaScript and would like to integrate it into an existing bot. Thanks!
You can take ideas from the LeagueSandbox/IssueBot (Typescript), which does create issues.
It does use npmjs.com/package/github-api, from github-tools/github
export class IssueCommand extends Command {
execute() {
if(!this.args) {
return
}
let issueBody = ISSUE_TEMPLATE
.replace("{PLACEHOLDER}", this.args[2] || "_No content_")
.replace("{CHANNEL}", this.message.channel.name)
.replace("{USER}", this.message.author.username)
Bot.gitHub.api.issues.create({
owner: config.githubName,
repo: this.args[0],
title: this.args[1],
body: <any>issueBody // Typings for the `github` package are incorrect, so we have to cast to any here.
},
(error, response) => this.handleGithubResponse(error, response)
)
}
handleGithubResponse(error, response) {
if(error) {
let formattedError = JSON.stringify(error, null, 4)
let reply = ERROR_TEMPLATE.replace('{PLACEHOLDER}', formattedError)
this.message.reply(reply)
return
}
let reply = SUCCESS_TEMPLATE.replace('{PLACEHOLDER}', response.html_url)
this.message.reply(reply)
}
}
You have to set up that bot in your Discord application.
Maybe see the GitHub API docs for Creating Issues
You might need to create an app for it.

Discord.js - How to change style of Button

This is how I create and send the button:
client.on('messageCreate', (message) => {
/* ... Checking Command ... */
const actionRow = new MessageActionRow().addComponents(
new MessageButton()
.setStyle("PRIMARY")
.setLabel("X")
.setCustomId("test"));
message.channel.send({ content: "Test", components: [actionRow] });
}
A blue Button appears in the chat, as expected.
This is my Button-Listener:
client.on("interactionCreate", (interaction) => {
if (interaction.isButton()) {
if (interaction.customId === "test") {
//Before: console.log(interaction.component);
interaction.component.setStyle("DANGER");
//After: console.log(interaction.component);
}
}
});
Logging the component-object before and after .setStyle("DANGER") also reveals, that the style got changed from Primary to Danger successfully.
But in my Discord Client, the Style/Color didn't change, and ontop of that I am getting an error, saying that the interaction failed.
The style-property doesn't seem to be read-only: https://discord.js.org/#/docs/main/stable/class/MessageButton?scrollTo=style
So what am I doing wrong?
You updated the style only locally, you didn't send the changed component back to the Discord API.
To get rid of the error "This interaction failed", you need to respond to the interaction. One way to respond is to use MessageComponentInteraction.update(), which updates the original message.
client.on("interactionCreate", (interaction) => {
if (interaction.isButton()) {
if (interaction.customId === "test") {
// Change the style of received button component
interaction.component.setStyle("DANGER");
// Respond to the interaction,
// and send updated component to the Discord API
interaction.update({
components: [
new MessageActionRow().addComponents(interaction.component)
]
});
}
}
});
To make this work with multiple buttons, use the example below.
client.on("interactionCreate", (interaction) => {
if (interaction.isButton()) {
// Make this work only for certain buttons,
// with IDs like switch_0, switch_1, etc.
if (interaction.customId.startsWith("switch_")) {
// Change the style of the button component,
// that triggered this interaction
interaction.component.setStyle("DANGER");
// Respond to the interaction,
// and send updated components to the Discord API
interaction.update({
components: interaction.message.components
});
}
}
});
For any future viewers who might be using Discordjs V14+ you can't edit the components directly anymore, so you need to recreate them in order to edit them. This is a solution I came up with that flips the color when clicked!
const collector = interaction.channel.createMessageComponentCollector({ time: 15000 });
collector.on('collect', async i => {
//loop through each action row on the embed and update it accordingly
let newActionRowEmbeds = i.message.components.map(oldActionRow => {
//create a new action row to add the new data
updatedActionRow = new ActionRowBuilder();
// Loop through old action row components (which are buttons in this case)
updatedActionRow.addComponents(oldActionRow.components.map(buttonComponent => {
//create a new button from the old button, to change it if necessary
newButton = ButtonBuilder.from(buttonComponent)
//if this was the button that was clicked, this is the one to change!
if(i.component.customId == buttonComponent.customId){
//If the button was a primary button then change to secondary, or vise versa
if(buttonComponent.style == ButtonStyle.Primary){
newButton.setStyle(ButtonStyle.Secondary)
}
else if (buttonComponent.style == ButtonStyle.Secondary){
newButton.setStyle(ButtonStyle.Primary)
}
}
return newButton
}));
return updatedActionRow
});
// and then finally update the message
await i.update({components: newActionRowEmbeds})
});

webshare API multiple instances on same page

Hopefuly someone can assist/direct me here.
I'm making use of the webshare API on my site. The site contains an array of posts that will have a share link. This is built using a foreach and all have unique urls to use. I want to add a share button to each of those images. I currently have it working on a singular instance but unable to get it to loop through all the share buttons.
Here is the current script:
const shareButton = document.querySelector('.share-button');
const url = document.querySelector('.post-link a').href;
shareButton.addEventListener('click', event => {
if (navigator.share) {
navigator.share({
title: 'Check out this ad I saw on ...',
url
}).then(() => {
console.log('Shared');
})
.catch(console.error);
}
});
I'm really struggling with how to get it to loop through all share buttons and not just be usable on the first instance.
Apologeis if this is simple.
For a start, you need to add a click listener to all buttons, not just the first. You can do this exclusively when the API is supported, else, you may want to hide the buttons. Here's the modified script (note that you need to get the URL of each post individually, see the comment):
const shareButtons = document.querySelectorAll('.share-button');
if ('share' in navigator) {
shareButtons.forEach((shareButton) => {
shareButton.addEventListener('click', () => {
// Get the URL from the dataset or query the DOM.
const url = shareButton.dataset(url);
navigator.share({
title: 'Check out this ad I saw on ...',
url
}).then(() => {
console.log('Shared');
}).catch(console.error);
});
});
} else {
shareButtons.forEach((shareButton) => {
shareButton.style.display = 'none';
});
}

intercept user message to modify it , bot framework

I am using a bot framework with direct line, and I would like to intercept the user's message before sending it to the server to modify it.
The idea is that if the user enters some phone number, credit card, etc, modify that part of the message by asterisks for example, and that does not travel the message with that data to the server.
I have tried to configure some event or activity but I can not do it.
I have tried using javascript, create an addeventlistener to the inputBox and the button, but when that event is launched the message can no longer be modified
any ideas?
conect.activity$
.filter(function (activity) {
return activity.type === 'endOfConversation';
})
.subscribe(function (activity) {
console.log('RemoveLocalStorage endOfConversation');
RemoveLocalStorage("paramCon");
});
BotChat.App({
botConnection : conect,
speechOptions: speechOptions,
user: user,
bot: bot,
typing:false,
locale: (params.locale !== undefined) ? params.locale : "es-es",
resize: 'detect'
},window.parent.frames["chatBot"].document.getElementById('bot'));
//window.frames[0].document.getElementById('bot')
//document.getElementById("bot")
window.parent.frames["chatBot"].document.getElementsByClassName("wc-send")[0].addEventListener("click", disableSensitiveData);
window.parent.frames["chatBot"].document.getElementsByClassName("wc-textbox")[0].addEventListener("keyup", disableSensitiveData);
You can create a custom middleware to intercept and modify the text attribute of messages when the user hits send. I created examples in V3 and V4 of Webchat below that convert the entire message to asterisks.
WebChat V4
// We are adding a new middleware to customize the behavior of WEB_CHAT/SEND_MESSAGE.
const store = window.WebChat.createStore(
{},
({ dispatch }) => next => action => {
if (action.type === 'WEB_CHAT/SEND_MESSAGE') {
// Edit text when user sends message
action.payload.text = action.payload.text.split('').map(_ => '*').join('')
}
return next(action);
}
);
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
store
}, document.getElementById('webchat'));
Checkout the WebChat Repository for more samples and information about v4.
WebChat V3
We are going to modify how the bot handles posting activities to intercept and modify the message from the user.
var dl = new BotChat.DirectLine({ secret: '<SECRET>' });
BotChat.App({
botConnection: Object.assign({}, dl, {
postActivity: activity => {
// Edit text when user sends message
activity.text = activity.text.split('').map(_ => '*').join('');
return dl.postActivity(activity);
}
}),
bot: 'bot',
user: 'user',
resize: 'detect',
}, document.getElementById('bot'));
Hope this helps!

inline keyboard click doesnt call callback_query why?

bot.onText(/(.+)$/, function (msg, match) {
const opts = {
reply_markup: {
inline_keyboard: [
[
{
text: 'Edit Text',
callback_data: 'edit'
}
]
]
}
};
bot.sendMessage(msg.from.id, 'Original Text', opts);
});
bot.on("callback_query", function(callbackQuery) {
// 'callbackQuery' is of type CallbackQuery
console.log(callbackQuery);
});
I have looking for answer to this question, tried all the resources available on call_back. Such as
Telegram bot inline keyboard via Node.JS
Telegram inline keyboard and keyboard
How can create menu for telegram bot in bot father?
How about trying this like that?
bot.on('callback_query', function onCallbackQuery(callbackQuery) {
const action = callbackQuery.data;
const msg = callbackQuery.message;
// do your stuff
if (action === 'adress') {
// do something if callback data is "adress", you can have multiple if statements for various cases
}
});
That's how I got it working, hope it helps!

Categories

Resources