Wit.ai - sending pictures via Facebook Messenger Send API - javascript

I need my Wit.ai chat bot to respond to certain messages with images, and since I've refactored my code to match the latest messenger example in the node-wit SDK I can't figure out how to do so.
Previously this FB message function worked for me:
var newMessage = function (recipientId, msg, atts, cb) {
var opts = {
form: {
recipient: {
id: recipientId
},
}
}
if (atts) {
var message = {
attachment: {
"type": "image",
"payload": {
"url": msg
}
}
}
} else {
var message = {
text: msg
}
}
opts.form.message = message
newRequest(opts, function (err, resp, data) {
if (cb) {
cb(err || data.error && data.error.message, data)
}
})
}
Now I've updated to the node-wit SDK messenger example:
const fbMessage = (id, text) => {
const body = JSON.stringify({
recipient: { id },
message: { text },
});
const qs = 'access_token=' + encodeURIComponent(FB_PAGE_TOKEN);
return fetch('https://graph.facebook.com/me/messages?' + qs, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body,
})
.then(rsp => rsp.json())
.then(json => {
if (json.error && json.error.message) {
throw new Error(json.error.message);
}
return json;
});
};
Which I've modified like this to try and make image replies work:
const fbMessage = (id, text, atts) => {
if (atts) {
var body = {
attachment: {
"type": "image",
"payload": {
"url": { text }
}
},
};
} else {
var body = JSON.stringify({
recipient: { id },
message: { text },
});
}
const qs = 'access_token=' + encodeURIComponent(FB_PAGE_TOKEN);
return fetch('https://graph.facebook.com/me/messages?' + qs, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body,
})
.then(rsp => rsp.json())
.then(json => {
if (json.error && json.error.message) {
throw new Error(json.error.message);
}
return json;
});
};
Text messages are being sent as normal, but when I try to send an image attachment, my image url references are just being sent as strings.
The FB Messenger Send API reference is here
Any help would be greatly appreciated!

Got it working with this:
const fbMessage = (id, text) => {
var x = text.substring(0,4);
if (x == 'http') {
var body = JSON.stringify({
recipient: { id },
message: {
attachment: {
"type": "image",
"payload": {
"url": text
}
}
},
});
} else {
var body = JSON.stringify({
recipient: { id },
message: { text },
});
}
const qs = 'access_token=' + encodeURIComponent(FB_PAGE_TOKEN);
return fetch('https://graph.facebook.com/me/messages?' + qs, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body,
})
.then(rsp => rsp.json())
.then(json => {
if (json.error && json.error.message) {
throw new Error(json.error.message);
}
return json;
});
};
*NB - This obviously won't work if you plan on sending text replies that are just urls i.e. 'http://example.com'. To get around this you can put any symbol in front of the url address in your message like so: '> http://example.com' and links will work fine.

Related

Reactive Native TypeError: undefined is not an object (evaluating 'response.success')

I am trying to get an app working that was built using React Native. I get the error as per the screen shot. Can somebody please help me figure out what it means and how it can be fixed?
enter image description here
See below the code that is related to this error
tatic async func(route, params, verb) {
// console.warn(JSON.stringify(params));
let { orderStore } = Store;
const url = `${host}/${route}`
let options = Object.assign({ method: verb }, params ? { body: JSON.stringify(params) } : null);
options.headers = Api.headers()
const data = await LocalDb.getUserProfile();
if (params != null && params.type === 'social') {
const username = params.email;
const password = '1234';
const hash = new Buffer(`${username}:${password}`).toString('base64');
options.headers['Authorization'] = `Basic ${hash}`;
}
else
if (data != null) {
const username = data.email;
const password = data.password;
const hash = new Buffer(`${username}:${password}`).toString('base64');
options.headers['Authorization'] = `Basic ${hash}`;
}
return fetch(url, options).then(resp => {
// console.log('Api response is ------------->>>>>>', resp);
let json = resp.json();
if (resp.ok) {
return json
}
return json.then(err => { throw err });
}).catch(json => {
console.log('error is ', json)
// console.log('Api response is ------------->>>>>>', json);
Api.showAlert();
return;
});
}
tatic showAlert() {
// Works on both iOS and Android
Alert.alert(
'Network Error!',
'Click Ok To Restart App.',
[
{ text: 'OK', onPress: () => RNRestart.Restart() },
],
{ cancelable: false },
);
}

"Missing required key 'Source' in params"

This is my code:
const aws = require('aws-sdk')
const ses = new aws.SES()
// const myEmail = process.env.EMAIL
// const myDomain = process.env.DOMAIN
const getParamsFromUrl = require('./getParamsFromUrl')
module.exports = (options) => {
const { myEmail, myDomain } = options
function generateResponse (code, payload) {
return {
statusCode: code,
headers: {
'Access-Control-Allow-Origin': myDomain,
'Access-Control-Allow-Headers': 'x-requested-with',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify(payload)
}
}
function generateError (code, err) {
console.log("hi"+ err)
return {
statusCode: code,
headers: {
'Access-Control-Allow-Origin': myDomain,
'Access-Control-Allow-Headers': 'x-requested-with',
'Access-Control-Allow-Credentials': true
},
body: JSON.stringify(err.message)
}
}
function generateEmailParams (body) {
const { email, name, content } = JSON.parse(body)
console.log(email, name, content)
if (!(email && name && content)) {
throw new Error('Missing parameters! Make sure to add parameters \'email\', \'name\', \'content\'.')
}
return {
Source: myEmail,
Destination: { ToAddresses: [myEmail] },
ReplyToAddresses: [email],
Message: {
Body: {
Text: {
Charset: 'UTF-8',
Data: `Message sent from email ${email} by ${name} \nContent: ${content}`
}
},
Subject: {
Charset: 'UTF-8',
Data: `You received a message from ${myDomain}!`
}
}
}
}
async function sendJSON (event) {
try {
const emailParams = generateEmailParams(event.body)
const data = await ses.sendEmail(emailParams).promise()
return generateResponse(200, data)
} catch (err) {
return generateError(500, err)
}
}
return sendJSON
}
/////handler.js
const options = {
myEmail: process.env.EMAIL,
myDomain: process.env.DOMAIN
}
const { sendJSON, sendFormEncoded } = require('./lambdaMailer')(options)
module.exports.sendJSON = sendJSON
I have defined values on node_env and email in secrets.json file. After running a curl link I am getting the error as:
curl --header "Content-Type: application/json" --request POST --data "{\"source\":\"zyx#gmail.com\",\"destination\":\"abc#gmail.com\",\"name\":\"xyz\",\"subject\":\"Hey!\",\"message\":\"Hey!\"}" https://lyt7frokj4.execute-api.us-east-1.amazonaws.com/dev/email/send
"Missing required key 'Source' in params"
I think it maybe the case-sensitivity issue. According to the docs, there should be Source, not source:
Source: 'STRING_VALUE', /* required */

Reading value from JSON array in Node.js during Get request

I need to pull the Indication value from the following array
{
"records": [{
"id": "recBgV3VDiJeMkcwo",
"fields": {
"DrugName": "azatadine",
"nameapi": ["recBgV3VDiJeMkcwo"],
"Indication": "For the relief of the symptoms of upper respiratory mucosal congestion in perennial and allergic rhinitis, and for the relief of nasal congestion and eustachian t.b. congestion.",
"lookup": ["azatadine"],
"drugID": "recBgV3VDiJeMkcwo"
},
"createdTime": "2018-11-09T19:38:24.000Z"
}]
}
When I try to do response.records.fields[0]["Indication"] I get undefined.
Here is my full code:
function httpGet() {
return new Promise(((resolve, reject) => {
var options = {
host: 'api.airtable.com',
port: 443,
path: '/v0/appYqfJ3Rt2F0sRGn/Database?filterByFormula=(DrugName=%27azatadine%27)',
method: 'GET',
headers: {
Authorization: 'Bearer key123456789'
}
};
const request = https.request(options, (response) => {
response.setEncoding('utf8');
let returnData = '';
response.on('data', (chunk) => {
returnData += chunk;
});
response.on('end', () => {
resolve(returnData);
});
response.on('error', (error) => {
reject(error);
});
});
request.end();
}));
}
const UserReplyIntent_Handler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'UserReplyIntent' ;
},
async handle(handlerInput) {
const response = await httpGet();
console.log(response);
return handlerInput.responseBuilder
.speak("Okay. Here we go" + response.records[0].fields.Indication)
.reprompt("say again")
.getResponse();
},
};
Thanks in advance for your help.
it should be response.records[0].fields.Indication
Fields doesn't look like an array. Try response.records.fields.Indication
Show console.log(response) output. Looks like that you made a mistake in getting a response

how to upload data using POST request using params and body using ng2-file-upload angular

here i want to upload some data using "POST method with parameters & body". i am aware of post request but till now for upload i am using the "PUT Method" and sending request body below is my code
this.upload= new FileUploader({ url: this.service.dataUpload('/uploadFile'), queueLimit: 999, method: 'PUT' });
this.upload.onBeforeUploadItem = (item) => {
debugger;
item.withCredentials = false;
};
//Call back for uploaded
this.upload.onCompleteItem = (item: any, response: any, status: any, headers: any) => {
console.log("This is file name::",data['file']['name']);
//It Contains Object
console.log("data::",this.DataTemplate[data['file']['name']]);
if(status == 0){
this.service.saveData(this.DataTemplate[data['file']['name']])
.subscribe(res => { console.log(res.status); });
return;
}
var responsePath = JSON.parse(response);
if (status == 201) {
this.DataTemplate[data['file']['name']]['url'] = response.download;
}
};
this.upload.onBuildItemForm = (item, form) => {
let name = data['file']['name'];
form.append("data", data['file']['rawFile']);
form.append("desc", JSON.stringify(this.fileMap[name]));
};
}
uploadData(){
// For uploading Data
this.upload.uploadAll();
}
this.DataTemplate[data['file']['name']] it contains the below object
{
"product": "laptop",
"info": {
"mimetype": "image/jpeg",
"file_id": "dfldpf9c",
"author": "unknown"
},
"Sr_id": "dfldpf9c"
}
here my issue is **How can i send the "Sr_id" as parameter to the post request **
like below
this.upload= new FileUploader({ url: this.service.dataUpload('/uploadFile/{**Sr_id**}'), queueLimit: 999, method: 'POST' });
this.upload.onBeforeUploadItem = (item) => {
debugger;
item.withCredentials = false;
};

JS convert string to rfc822

I am trying the gmail apis. I've done the auth. Now I want to create a draft. But I am getting this error
{ error:
I20161220-15:53:43.486(4)? { errors: [Object],
I20161220-15:53:43.487(4)? code: 400,
I20161220-15:53:43.488(4)? message: 'Media type \'application/octet-stream\' is not supported. Valid media types: [message/rfc822]' } } }
Gmail api require base64 string with rfc822 standard. I am not sure of any good way to convert a string to rfc822. How do I do that?
I am using meteor for my app and here is my code.
import { Meteor } from 'meteor/meteor'
import { HTTP } from 'meteor/http'
Meteor.startup(() => {
// Meteor.call('createDraft')
Meteor.methods({
'createDraft': function () {
console.log(this.userId)
const user = Meteor.users.findOne(this.userId)
const email = user.services.google.email
console.log(email)
const token = user.services.google.accessToken
const dataObject = {
message: {
raw: CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse('dddd'))
},
headers: {
Authorization: `Bearer ${token}`
}
}
HTTP.post(`https://www.googleapis.com/upload/gmail/v1/users/${email}/drafts`, dataObject, (error, result) => {
if (error) {
console.log('err', error)
}
if (result) {
console.log('res', result)
}
})
}
})
})
Base64 encode the message and replace all + with -, replace all / with _, and remove the trailing = to make it URL-safe:
const rawMessage = btoa(
"From: sender#gmail.com\r\n" +
"To: receiver#gmail.com\r\n" +
"Subject: Subject Text\r\n\r\n" +
"The message text goes here"
).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
const dataObject = {
message: {
raw: rawMessage
},
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`
}
};
I just needed to send content type as message/rfc822. Here is the working code. Note that the raw message has something wrong in ts because the draft that is created has empty content. But the draft itself is created successfully.
import { Meteor } from 'meteor/meteor'
import { HTTP } from 'meteor/http'
Meteor.startup(() => {
// Meteor.call('createDraft')
Meteor.methods({
'createDraft': function () {
console.log(this.userId)
// CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse('dddd'))
const user = Meteor.users.findOne(this.userId)
const email = user.services.google.email
console.log(email)
const token = user.services.google.accessToken
const rawMessage = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(
'From: sender#gmail.com\r\n' +
'To: receiver#gmail.com\r\n' +
'Subject: Subject Text\r\n\r\n' +
'The message text goes here'
)).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
const dataObject = {
message: {
raw: rawMessage
},
headers: {
'Content-Type': 'message/rfc822',
Authorization: `Bearer ${token}`
}
}
HTTP.post(`https://www.googleapis.com/upload/gmail/v1/users/${email}/drafts`, dataObject, (error, result) => {
if (error) {
console.log('err', error)
}
if (result) {
console.log('res', result)
}
})
}
})
})

Categories

Resources