how to receive and process a photo mms using twilio - node.js

Looking for an example, of how to receive and process images via mms to my app using Twilio.
Looking at the number configuration screen in the twilio dashboard, I assume that I set up an incoming phone number and a HTTP POST url to send incoming mms to. However, I'm not sure what gets posted to that url and don't know the structure of that data.
Does someone have an example of what data gets POSTed to the url and in what format? Any javascript examples of what data the server would process would be great.

Firstly use the twilio-node module(npm install twilio). Once you have that in place, you can just access the webhook request body like you would any request body req.body.
As depicted in twilio's docs, the structure is like so:
{
MessageSid: String, //ID pertaining to this message
AccountSid: String, //ID pertaining to your twilio account
From: String, //phone number of sender
To: String, //recipients phone number, you in this case
Body: String, //Message body
NumMedia: Number, //number of attached media
//these values only appear when media is present(NumMedia.length > 0)
MediaContentType: [String] //type of content in SMS
MediaUrl: [String] //URL to download the media
}
You can then do something like this using the twilio modules, caolan/async module, and the popular request/request module:
var twilio = require('twilio'),
fs = require('fs'),
async = require('async'),
request = require('request');
app.post('/mms', function(req, res) {
var options = { url: 'https://subtle-gradient-188.herokuapp.com/twiml' };
if (!twilio.validateExpressrequire(req, 'YOUR_TWILIO_AUTH_TOKEN', options)) return res.status(401).send("Bad key!");
if(!req.body.hasOwnProperty('MediaUrl')) return res.send("Missing media...");
var media = req.body.MediaUrl;
//download all media
async.map(media, download, function(err, filenames) {
var resp = new twilio.TwimlResponse();
if(err) {
resp.say("Problem occured");
console.log(err);
}
else resp.say('Files recieved: ' + filenames.join(', '));
res.type('text/xml');
res.send(resp.toString());
});
});
//download a single url to a unique filename
function download(url, cb) {
var name = Date.now() + url.split('/').pop();
request
.get(url)
.on('error', cb)
.on('end', function() {
cb(null, name);
})
.pipe(fs.createWriteStream(name));
}

Related

Receiving XML request in strong-soap

I am currently developing a NodeJS project with strong-soap library to receive and transmit SOAP requests and responses. Before asking question, i want to present code sample to ask my question efficiently.
server.js
//Address of this project is http://localhost:8080
const soap = require('strong-soap');
const http = require('http');
const fs = require('fs');
let myService = { //My SOAP server's service (group of methods)
Method:
function(data) //My question literally and directly related with data
{
//... Function content.
}
};
let xmlFile = fs.readFileSync('sample.wsdl');
let path = '/wsdl';
http.createServer(function (req, res) {
let soapServer = soap.listen(server, '/wsdl', myService, xmlFile);
}).listen(8080);
Assume that i have a server with codebase which is is seen above. And assume that have another Node.js project (or another .js file) which send request and transmit response from this server.
client.js
const soap = require('strong-soap');
soap.createClient('http://localhost:8080/wsdl', {forceSoap12Headers: true}, function(error, client){
if(error)
{
reject(error);
//res.sendStatus(404);
//console.log(error);
}
else{
client.Method(requestArgs, function(err, result, envelope) {
//I want to be able to sent an XML data as requestArgs
// Result in SOAP envelope body which is the wrapper element.
// In this case, result object corresponds to GetCityForecastByZIPResponse.
console.log(JSON.stringify(result));
}, null, customRequestHeader);
}
});
My question is: how i can send an XML in client.js? Or how i can receive requests in XML format without any problem in server.js? Most probably, i will deal with raw XML requests, and i want to deal with both XML and JSON requests? Help me developers!

Angular 13 type conversion error from backend that returns BLOBs

Angular and node's aren't my strong suits and I've had the misfortune of inheriting an angular 13 project where I'm tasked with implementing a minor JasperReport integration.
To put it brief, 3 different fields from the form are grouped into params that get sent to the backend NODEJS server, which sends it to JasperReports Rest_v2 API which then generates a report with them, however the trouble I'm having is taking return data BLOB and converting it to a PDF file that appears as a file download browser side.
My NODEJS method for connecting to jasper reports rest api:
app.post('/api/accounts/report',(req,res)=>{
//Params from the API call
var acc_id = parseInt(req.body.params['acc_id']);
var start_date = req.body.params['start_date'];
var end_date = req.body.params['end_date'];
var sage_num = req.body.params['sage_num'];
var request = require("request");
qs = require('querystring'),
request = request.defaults({
jar: true
});
//Login call to jasper server
request.post({url: jasper_login, qs: {j_username:jasper_usr, j_password:jasper_pwd}},
function(err, resp, body) {
if(err) {
return console.error(err);
}
//actual report call
request.get(jasper_hst,
function (error, response, body1) {
if (error){
console.log(response.statusCode);
console.log(error);
}
res.type('arraybuffer').send(response.body);
})
}
)
});
this method returns the BLOB of data that is the PDF file e.g.:
Sample Data
However the problem I'm having now is a type conversion error as soon as I call the backend:
console error
My ts methods:
pdfExportBtn(e:any){
//harcoded params for testing
var params={"acc_id":"18785","start_date":"2022/05/01, 00:00:00","end_date":"2022/06/01, 00:00:00","sage_num":"12341234"};
//call the API and generate report
this.getReport(params).subscribe((response)=>{
const newBlob = new Blob([response], {type: 'application/pdf'});
const downloadLink = document.createElement('a');
downloadLink.target = '_self'; const fileName = acc_name+' Transaction Summary '+date1+' to '+date2+'.pdf';
const data = window.URL.createObjectURL(newBlob); downloadLink.href = data;
downloadLink.download = fileName; document.body.appendChild(downloadLink);
downloadLink.click();
});
}
getReport(params){
return this.http.post<Blob>(`${environment.apiUrl}/api/accounts/report`,{responseType: 'arraybuffer'},{params});
}
But I'm specifying the return types as a blob and the 'array buffer' so I have no clue why its trying to parse into JSON.

Post image on twitter using puppeteer

Is it possible to post an image on twitter using nodejs and puppeteer? It find it hard because when you click on the image button on twitter it opens your archive.
It's definetely possible to post image on Twitter automatically (using Node.js). Twitter API Client for node called 'twit' suits for it. You can find the package on github or npm.
// post a tweet with media
var b64content = fs.readFileSync('/path/to/img', { encoding: 'base64' })
// first we must post the media to Twitter
T.post('media/upload', { media_data: b64content }, function (err, data, response) {
// now we can assign alt text to the media, for use by screen readers and
// other text-based presentations and interpreters
var mediaIdStr = data.media_id_string
var altText = "Small flowers in a planter on a sunny balcony, blossoming."
var meta_params = { media_id: mediaIdStr, alt_text: { text: altText } }
T.post('media/metadata/create', meta_params, function (err, data, response) {
if (!err) {
// now we can reference the media and post a tweet (media will attach to the tweet)
var params = { status: 'loving life #nofilter', media_ids: [mediaIdStr] }
T.post('statuses/update', params, function (err, data, response) {
console.log(data)
})
}
})
})
// post media via the chunked media upload API.
// You can then use POST statuses/update to post a tweet with the media attached as in the example above using `media_id_string`.
// Note: You can also do this yourself manually using T.post() calls if you want more fine-grained
// control over the streaming. Example: https://github.com/ttezel/twit/blob/master/tests/rest_chunked_upload.js#L20
//
var filePath = '/absolute/path/to/file.mp4'
T.postMediaChunked({ file_path: filePath }, function (err, data, response) {
console.log(data)
})

Using Bing Speech Recognition API with node.js Bot Framework on Skype

I would like to use the Bing Speech Recognition API to convert speech to text when sending audio attachments in Skype to my node.js chatbot. I have tried using the code from BotBuilder-Samples intelligence-SpeechToText, however the speech recognition only works in the Emulator. When sending an audio/wave file in Skype, the bot does not respond at all instead of "You said: What’s the weather like?".
I suspected that the issue might be due to the fact that a JWT Token is required to access attachments in Skype. Hence, I have tried accessing the audio attachment in Skype using the code from BotBuilder-Samples core-ReceiveAttachment which uses request-promise instead of needle to make the HTTP request. However, the result from request-promise is not a stream and cannot be processed by the function getTextFromAudioStream().
I there would like to ask how to get speech recognition to work with audio attachments in Skype.
Thanks and best regards!
// Add your requirements
var restify = require("restify");
var builder = require("botbuilder");
var fs = require("fs");
var needle = require("needle");
var request = require("request");
var speechService = require("./speech-service.js");
var Promise = require('bluebird');
var request = require('request-promise').defaults({ encoding: null });
//=========================================================
// Bot Setup
//=========================================================
// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.PORT || 3000, function() {
console.log("%s listening to %s", server.name, server.url);
});
// Create chat bot
var connector = new builder.ChatConnector ({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
server.post("/api/messages", connector.listen());
var bot = new builder.UniversalBot(connector);
//=========================================================
// Bots Middleware
//=========================================================
// Anytime the major version is incremented any existing conversations will be restarted.
bot.use(builder.Middleware.dialogVersion({ version: 1.0, resetCommand: /^reset/i }));
//=========================================================
// Bots Dialogs
//=========================================================
bot.dialog("/", [
function (session, results, next) {
var msg = session.message;
if (hasAudioAttachment(msg)) {
// Message with attachment, proceed to download it.
// Skype attachment URLs are secured by a JwtToken, so we need to pass the token from our bot.
var attachment = msg.attachments[0];
var fileDownload = isSkypeMessage(msg)
? requestWithToken(attachment.contentUrl)
: request(attachment.contentUrl);
fileDownload.then(
function (response) {
// Send reply with attachment type & size
var reply = new builder.Message(session)
.text('Attachment from %s of %s type and size of %s bytes received.', msg.source, attachment.contentType, response.length);
session.send(reply);
}).catch(function (err) {
console.log('Error downloading attachment:', { statusCode: err.statusCode, message: err.response.statusMessage });
});
var stream = isSkypeMessage(msg)
? getAudioStreamWithToken(attachment)
: getAudioStream(attachment);
speechService.getTextFromAudioStream(stream)
.then(text => {
session.send("You said: " + text);
})
.catch(error => {
session.send("Oops! Something went wrong. Try again later.");
console.error(error);
});
}
else {
session.send("Did you upload an audio file? I'm more of an audible person. Try sending me a wav file");
}
}
]);
function getAudioStream(attachment) {
return needle.get(attachment.contentUrl, { headers: {'Content-Type': "audio/wav"} });
}
function getAudioStreamWithToken(attachment) {
var headers = {};
connector.getAccessToken((error, token) => {
headers['Authorization'] = 'Bearer ' + token;
});
headers['Content-Type'] = attachment.contentType;
return needle.get(attachment.contentUrl, { headers: headers });
}
// Request file with Authentication Header
function requestWithToken(url) {
return obtainToken().then(function (token) {
return request({
url: url,
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/octet-stream'
}
});
});
};
// Promise for obtaining JWT Token (requested once)
var obtainToken = Promise.promisify(connector.getAccessToken.bind(connector));
function isSkypeMessage(message) {
return message.source === "skype";
};
The code in the sample is already considering Skype when accessing to the attachments (see here). I think the problem you were hitting is because the key in the sample exceeded the quota. Yesterday a new Bing Speech Key was added to the sample, so I would suggest you to try again.
Also, an updated version of the sample is going to be added soon. The code is currently under code review.

mongodb gridfs encoding picture base64

i try to readout an image, saved in mongodb, via gridfs (without temporary file)
it should be directly sent to ajax, which injects it into html
when i use my actual functions a large bit string is formed and sent to client (is saved in ajax response var)
but as it reaches the client, the bits arent correct anymore
so i look for a way to encode the picture before it is sent (into base64)
(or is there any other way?)
Serverside - javascript, gridfs
exports.readFileFromDB = function(req, res, profile, filename, callback){
console.log('Find data from Profile ' + JSON.stringify(profile));
var GridReader = new GridStore(db, filename,"r");
GridReader.open(function(err, gs) {
var streamFile = gs.stream(true);
streamFile.on("end", function(){
});
// Pipe out the data
streamFile.pipe(res);
GridReader.close(function(err, result) {
});
Clientside - javascript ajax call:
function imgUpload(){
var thumb = $("#previewPic");
$('#uploadForm').ajaxSubmit({
beforeSend:function(){
//launchpreloader();
},
error: function(xhr) {
//status('Error: ' + xhr.status);
},
success: function(response) {
console.log(response);
var imageData = $.base64Encode(response);
console.log(imageData);
thumb.attr("src","data:image/png;base64"+imageData);
$("#spanFileName").html("File Uploaded")
}
});
}
I'm doing something similar for a current project, but when the upload is complete, I return a JSON object containing the URL for the uploaded image:
{ success : true, url : '/uploads/GRIDFSID/filename.ext' }
I have a route in Express that handles the /uploads route to retrieve the file from GridFS and stream it back to the client, so I can use the above URL in an IMG SRC. This is effectively what appears in the DOM:
<img src="/uploads/GRIDFSID/filename.ext">
The route handler looks something like this (it uses node-mime and gridfs-stream):
app.get(/^\/uploads\/([a-f0-9]+)\/(.*)$/, function(req, res) {
var id = req.params[0];
var filename = req.params[1];
// Set correct content type.
res.set('Content-type', mime.lookup(filename));
// Find GridFS file by id and pipe it to the response stream.
gridfs
.createReadStream({ _id : id })
.on('error', function(err) {
res.send(404); // or 500
})
.pipe(res);
});
It obviously depends on your exact setup if my solution works for you.

Resources