Promt location on Fb message by Bot framework (nodejs v4) - node.js

const quickReply = {
channelData: {
"message": {
"text": "Where are you?",
"quick_replies": [
{
"content_type":"location"
}
]
}
}
}
return await stepContext.prompt(LOCATION, { prompt: quickReply }, InputHints.ExpectingInput);
I read syntax to prompt location is { "content_type":"location"} but fb message don't show button share location and i have error, please help me.

Facebook Messenger removed support for location quick replies last October, which is why the button isn’t rendering in the chat window. Take a look at Facebook’s developer document on quick replies for more details.
https://developers.facebook.com/docs/messenger-platform/send-messages/quick-replies/#locations

Related

Chrome extension contextmenus sendResponse doesn't work on some pages

I want to build a extension which is able to get the English word selected by users when reading some English articles and get the whole sentence at the same time.
↓ This is my background.js file. I use getSelection function to send a message to content.js to request a response which contains selection info.
//background.js
chrome.runtime.onInstalled.addListener((tableId, changeInfo, tab) => {
chrome.contextMenus.create({
id: 'addWords',
title: "Send \"%s\" to background",
contexts: ['all']
})
function getSelection(info, tab) {
if (info.menuItemId === "addWords") {
chrome.tabs.sendMessage(tab.id, {action: "getSelection"}, (response) => {
console.log(response);
});
}
}
chrome.contextMenus.onClicked.addListener(getSelection);
});
↓ This is my content.js file. I use onMessage to respond to the background's request.
//content.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if(request.action === "getSelection"){
let selection = window.getSelection();
if(selection.toString() !== ""){
let arr = selection.anchorNode.data.split(".");
let word = selection.toString();
let sentence = arr.find(str => str.includes(word))
alert(word);
sendResponse({word: word, sentence: sentence});
}
}
})
↓ This is my manifest.json file
{
"manifest_version": 3,
"name": "Words Repeater",
"description": "Repeat words what you want to memorize",
"version": "1.0.0",
"permissions": ["contextMenus", "activeTab", "tabs"],
"action": {
"default_popup": "popup.html"
},
"background": {
"service_worker": "./js/background.js"
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["./js/content.js"]
}
]
}
The extension works correctly initially, but it fails after changing a website and I got a error "Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist."
How to make the context menu run correctly on every tabs? Really appreicate your help!
Your onClicked event listener is misplaced inside onInstalled listener, so it will work only for less than a minute immediately after the installation/update until the background script is auto-terminated, then it will be ignored like it doesn't exist. Move it outside to properly re-register it every time the background script starts on an event like the context menu click.
When the extension is installed/updated its new content script won't be automatically injected into the currently opened tabs in Chrome/ium, so you'll have to do it explicitly yourself as shown here, but there's a much better alternative in cases like yours where the access to the page is necessary only on demand after the user invoked the extension: programmatic injection via executeScript in tandem with the activeTab permission.
remove content_scripts from manifest.json - now your extension won't require broad host permissions i.e. there'll be no installation warning in the web store.
remove "tabs" from "permissions" - it's not necessary and now there'll be no warning about observing the browser history.
add "scripting" to "permissions".
Consider limiting the contexts to "selection" to show it only when text is selected, and not show in the wrong contexts like the built-in menu of the extension's icon in the toolbar.
Parameters of chrome.runtime.onInstalled were incorrectly copied from chrome.tabs.onUpdated listener, but since they are unused you can remove them.
chrome.runtime.onInstalled.addListener(() => {
chrome.contextMenus.create({
id: 'addWords',
title: 'Send "%s" to background',
contexts: ['selection'],
});
});
chrome.contextMenus.onClicked.addListener(async (info, tab) => {
if (info.menuItemId === 'addWords') {
let word = info.selectionText.trim();
let sentence;
try {
[{ result: sentence }] = await chrome.scripting.executeScript({
target: {
tabId: tab.id,
frameIds: [info.frameId],
},
func: () => {
const selection = window.getSelection();
const arr = selection.anchorNode.data.split('.');
const word = selection.toString();
const sentence = arr.find(str => str.includes(word));
return sentence;
},
});
} catch (e) {} // invoked on a page that doesn't allow injection
console.log(word, sentence); // this prints in background console
}
});

Telegram bot inline keyboard markup can not received callback data JSON in google sheet when I use Google Apps Script

I use "Google Apps Script" to develop my telegram bot and I want to create a inline keyboard to receive users response data, so I have reference the telegram bot api "https://core.telegram.org/bots/api#available-methods" and create a function to do that,but Why I click the inline keyboard in my telegram bot, the google sheet table can not received the "callback_data" value ?
enter image description here
Thanks!
function start(estringa){
var InlineKeyboardMarkup = {
inline_keyboard : [
[
{"text":"A",'callback_data': "chinese"},
{"text":"B",'callback_data': "english"}
],
[
{"text":"C",'callback_data': "japanese"},
{"text":"D",'callback_data': "korean"}
]
]
}
var id = estringa.message.chat.id.toFixed()
var payload;
if (estringa.message.text){
payload = {
"method": "sendMessage",
"chat_id": id,
"text": '想到哪個網站呢?' ,
'reply_markup': JSON.stringify(InlineKeyboardMarkup)
}
}
else {
payload = {
"method": "sendMessage",
"chat_id": id,
"text": "hello world!"
}
}
return payload // 返回程式碼上層,重複執行判斷
}

microsoft bots to teams using nodejs fails with missing activityid when updating the same activity

My code has a simple card carousel which has action button like below:
actions = [
{
"type": "Action.Submit",
"title": "Qualify",
"data": { "action" : "qualify_lead" }
},
{
"type": "Action.OpenUrl",
"title": "Retire",
"url": "{viewUrl}"
},
{
"type": "Action.ShowCard",
"title": "Add Note",
"card": this.noteCard(item.LeadId, "leads")
}
]
I am having a method to handle qualify_lead action like below
async qualifyLead(context:any){
console.log("in qualifyLead:" + JSON.stringify(context.activity))
await context.updateActivity(this.successCard('Lead is qualified'))
}
All I am doing on purpose is to replace entire carousel with a simple text message. But it fails with error:
Error: BotFrameworkAdapter.updateActivity(): missing activity.id
Where do i get this ?
I am using google firebase for this and the wrapper code is like below
const {
TurnContext,
TeamsActivityHandler,
CardFactory,
AttachmentLayoutTypes,
ActionTypes
} = require('botbuilder');
class TeamsConversationBot extends TeamsActivityHandler {
constructor() {
super();
this.leadState =
this.conversationState.createProperty('leadCarouselState');
this.onMessage(async (context:any, next:any) => {
TurnContext.removeRecipientMention(context.activity);
let msg = context.activity.text
const action = context.activity.value
let objNum = ''
let keyword = ''
if(msg === undefined && action === undefined)
msg = 'help'
else if(msg !== undefined){
msg = msg.trim().toLowerCase()
if(msg.indexOf("help") > -1)
msg = 'help'
else{
if(msg.startsWith('lead')){
msg = 'lead'
}
}
}
switch (msg) {
case 'lead':
await this.lead(context, userKey, platform)
break;
case 'qualify_lead':
await this.qualifyLead(context)
break;
}
await next();
});
}
I'm not sure exactly what this.successCard('Lead is qualified') does, but presumably it returns an Activity. To my knowledge, in order for this Activity to replace another one, you need to set it's Id property to match the previous message. That means that, when you send the previous message (i.e. the card), you need to capture the reference that's returned from the send method on the context (e.g. into bot state), and then use it for this new activity.
As I explained in my answer to your other question, you need to save the activity ID in bot state and then apply it to the update that you're sending. The Bot Framework can't update an activity unless you tell it which activity to update, and you do that using an activity ID.
This was the part that saves the ID:
const dict = await this.carouselState.get(turnContext, {});
dict[batchId] = {
[KEYACTIVITYID]: response.id,
[KEYLEADS]: leads
};
And this was the part that applies it to the updated activity:
const update = this.createCarousel(batchId, leads);
update.id = info[KEYACTIVITYID];

Botbuilder route action message to correct dialog

I am building a bot with the botbuilder framework using node, and I am now trying to use the CardAction.dialogAction:
builder.CardAction.dialogAction(session, 'help', 'topic:mytopic', 'Click me')
It generates a message that looks like this:
action?help=topic:mytopic
Now I need to route that action to the correct dialog to handle it, but I can't figure out where and how to do that. Seeing as this is a builtin feature, I figured there should be easy ways of doing this already?
Appreciate the help.
For a lack of any other options at this point I resorted to writing my own simple action recognizer. It is no beauty, but it does the trick.
function action_recognizer() {
return {
recognize: function (context, done) {
let intent = { score: 0.0 }
const text = context.message.text
if (text) {
const m = text.match(/action\?(\w+)=?(.+)/)
logger.debug(m)
if (m) {
switch (m[1]) {
case 'help':
intent = { score: 1.0, intent: 'help' }
if (m.length > 2) {
intent.entities = [{entity: m[2], type: 'custom_intent'}]
}
break
}
}
}
done(null, intent)
}
}
}
This will basically direct to my help:/ dialog. Which in turn will read the entities list (if custom_intent types are available).

Sent a picture in a chatbot using botframework

I have a chatbot using the botframework of Microsoft, with my webapp running the chatbot on Azure. How can I return a picture as an answer to a message. We have clients using Skype, Messenger and KiK
Take a look at the docs section on image and file attachments
replyMessage.Attachments.Add(new Attachment()
{
ContentUrl = "https://upload.wikimedia.org/wikipedia/en/a/a6/Bender_Rodriguez.png",
ContentType = "image/png"
});
Or as JSON:
{
"attachments": [
{
"contentType": "image/png",
"contentUrl": "https://upload.wikimedia.org/wikipedia/en/a/a6/Bender_Rodriguez.png"
}
]
}
You can also send Rich Cards:
replyMessage.Attachments = new List<Attachment>();
replyMessage.Attachments.Add(new Attachment()
{
Title = "Bender",
TitleLink = "https://en.wikipedia.org/wiki/Bender_(Futurama)",
ThumbnailUrl = "http://www.theoldrobots.com/images62/Bender-18.JPG",
Text = "Bender Bending Rodríguez, commonly known as Bender, is a main character in the animated television series Futurama.",
FallbackText = "Bender: http://www.theoldrobots.com/images62/Bender-18.JPG"
});

Resources