deleting a call recording from twilio in node.js - node.js

How can I delete a call recording from twilio using the npm module ?
I am trying to use the request module like this:
request.del(recording_url, {
'auth': {
'user': accountSid,
'pass': authToken
}
}, function (err, done){
if(err){
console.log("error deleting from twilio", err)
} else {
console.log("removed from twilio", done);
}
});
I am getting the following info in the done object:
body: '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n<TwilioResponse><RestException><Code>20004</Code><Message>Method not allowed</Message><MoreInfo>https://www.twilio.com/docs/errors/20004</MoreInfo><Status>405</Status></RestException></TwilioResponse>'

Twilio evangelist here.
If you are using the Twilio node library you use this code to delete a recording resource:
var accountSid = 'AC3137d76457814a5eabf7de62f346d39a';
var authToken = "{{ auth_token }}";
var client = require('twilio')(accountSid, authToken);
client.recordings("RE557ce644e5ab84fa21cc21112e22c485").delete(function(err, data) {
if (err) {
console.log(err.status);
throw err.message;
} else {
console.log("Sid RE557ce644e5ab84fa21cc21112e22c485 deleted successfully.");
}
});
Check out the Recordings resource documentation for more info, specifically this example on deleting recordings.
Hope that helps.

Related

Failed sending mail through google api

I've been trying to send emails using Google's Gmail API and I kept getting the following error:
The API returned an error: Error: 'raw' RFC822 payload message string or uploading message via /upload/* URL required
I did the setup using the starter code Google gave for NodeJS (documentation).
const google = require('googleapis');
const googleAuth = require('google-auth-library');
const Base64 = require('js-base64').Base64;
// ...
// create the email string
const emailLines = [];
emailLines.push("From: \"My Name\" <MY_EMAIL#gmail.com>");
emailLines.push("To: YOUR_EMAIL#uw.edu");
emailLines.push('Content-type: text/html;charset=iso-8859-1');
emailLines.push('MIME-Version: 1.0');
emailLines.push("Subject: New future subject here");
emailLines.push("");
emailLines.push("And the body text goes here");
emailLines.push("<b>And the bold text goes here</b>");
const email =email_lines.join("\r\n").trim();
// ...
function sendEmail(auth) {
const gmail = google.gmail('v1');
const base64EncodedEmail = Base64.encodeURI(email);
base64EncodedEmail.replace(/\+/g, '-').replace(/\//g, '_')
console.log(base64EncodedEmail);
gmail.users.messages.send({
auth: auth,
userId: "me",
resource: {
raw: base64EncodedEmail
}
}, (err, response) => {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
console.log(response);
});
}
You can picture auth as an object:
{
transporter: ...,
_certificateCache: ...,
_certificateExpiry: ...,
_clientId: ...,
_clientSecret: ...,
_redirectUri: ...,
_opts: {},
credentials: {
access_token: ...,
refresh_token: ...,
token_type: 'Bearer',
expiry_date: 1517563087857
}
}
What matters is the access_token.
I've already tried the solutions proposed which are listed here:
StackOverflow: Failed sending mail through google api with javascript
ExceptionsHub: Failed sending mail through google api in nodejs
StackOverflow: Gmail API for sending mails in Node.js
But none of them worked. However, when I copied and pasted the encoded string onto the Playground of Google's own documentation, and it works (documentation):
Therefore, I changed to using a fetch request instead, and it also worked.
fetch(`https://www.googleapis.com/gmail/v1/users/me/messages/send`, {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + `the_access_token_in_auth_obj`,
'HTTP-Version': 'HTTP/1.1',
'Content-Type': 'application/json',
},
body: JSON.stringify({
raw: base64EncodedEmail
})
})
.then((res) => res.json())
.then((res) => console.info(res));
Can anyone explain why it happened? Is it a bug from googleapi or am I missing something?
I ran into the same "RFC822 payload message string or uploading message via /upload/* URL required". The quickstart/nodejs sample specifies a version of google-auth-library that caused this error. The quickstart specifies:
npm install google-auth-library#0.* --save
When I changed this to
npm install google-auth-library -- save
it pulled in version 1.3.1 vs 0.12.0. Everything started working once I changed the code to account for the breaking changes. The latest version of googleapis also has breaking changes. Here is my tweaks to the quickstart:
package.json
....
"dependencies": {
"google-auth-library": "^1.3.1",
"googleapis": "^26.0.1"
}
quickstart.js
var fs = require('fs');
var readline = require('readline');
var {google} = require('googleapis');
const {GoogleAuth, JWT, OAuth2Client} = require('google-auth-library');
var SCOPES = [
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.compose',
'https://www.googleapis.com/auth/gmail.send'
];
var TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH ||
process.env.USERPROFILE) + '/.credentials/';
var TOKEN_PATH = TOKEN_DIR + 'gmail-nodejs-quickstart.json';
function authorize(credentials, callback) {
var clientSecret = credentials.installed.client_secret;
var clientId = credentials.installed.client_id;
var redirectUrl = credentials.installed.redirect_uris[0];
var auth = new GoogleAuth();
var oauth2Client = new OAuth2Client(clientId, clientSecret, redirectUrl);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, function (err, token) {
if (err) {
getNewToken(oauth2Client, callback);
} else {
oauth2Client.credentials = JSON.parse(token);
callback(oauth2Client);
}
});
}
function getNewToken(oauth2Client, callback) {
var authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES
});
console.log('Authorize this app by visiting this url: ', authUrl);
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Enter the code from that page here: ', function (code) {
rl.close();
oauth2Client.getToken(code, function (err, token) {
if (err) {
console.log('Error while trying to retrieve access token', err);
return;
}
oauth2Client.credentials = token;
storeToken(token);
callback(oauth2Client);
});
});
}
function makeBody(to, from, subject, message) {
var str = ["Content-Type: text/plain; charset=\"UTF-8\"\n",
"MIME-Version: 1.0\n",
"Content-Transfer-Encoding: 7bit\n",
"to: ", to, "\n",
"from: ", from, "\n",
"subject: ", subject, "\n\n",
message
].join('');
var encodedMail = new Buffer(str).toString("base64").replace(/\+/g, '-').replace(/\//g, '_');
return encodedMail;
}
function sendMessage(auth) {
var gmail = google.gmail('v1');
var raw = makeBody('xxxxxxxx#hotmail.com', 'xxxxxxx#gmail.com', 'test subject', 'test message');
gmail.users.messages.send({
auth: auth,
userId: 'me',
resource: {
raw: raw
}
}, function(err, response) {
console.log(err || response)
});
}
const secretlocation = 'client_secret.json'
fs.readFile(secretlocation, function processClientSecrets(err, content) {
if (err) {
console.log('Error loading client secret file: ' + err);
return;
}
// Authorize a client with the loaded credentials, then call the
// Gmail API.
authorize(JSON.parse(content), sendMessage);
});
Now when I run, I get the response
Object {status: 200, statusText: "OK", headers: Object, config: Object, request: ClientRequest, …}
Adding to #grabbag's answer, which excluded the definition for store_token. As the Drive quickstart notes, that function can be defined as follows:
/**
* Store token to disk be used in later program executions.
*
* #param {Object} token The token to store to disk.
*/
function storeToken(token) {
try {
fs.mkdirSync(TOKEN_DIR);
} catch (err) {
if (err.code != 'EEXIST') {
throw err;
}
}
fs.writeFile(TOKEN_PATH, JSON.stringify(token));
console.log('Token stored to ' + TOKEN_PATH);
}

SendGrid Azure Issue

I'm trying to send an email with my Node JS app on Azure and get this error:
TypeError: sendgrid.Email is not a constructor
Here is my code. I used the documentation from Microsoft (https://learn.microsoft.com/en-us/azure/store-sendgrid-nodejs-how-to-send-email).
var sendgrid = require('sendgrid')('SendGrid User ID', 'SendGrid password');
function createEmail() {
console.log('CREATE EMAIL');
var emailToSend = new sendgrid.Email({
to: example#example.com,
from: 'example#example.com',
subject: 'Subject',
text: 'some text';
});
sendEmail(emailToSend);
}
function sendEmail(email) {
console.log('SEND EMAIL');
sendgrid.send(email, function (err, json) {
if (err) {
return console.error(err);
}
});
}
As #David Tansey mentioned, the SendGrid team added a breaking change to support the v3 Web API since v3.0.0. Here is a working code example with the latest version (v5.1.2).
var helper = require('sendgrid').mail;
var fromEmail = new helper.Email('test#example.com');
var toEmail = new helper.Email('test#example.com');
var subject = 'Sending with SendGrid is Fun';
var content = new helper.Content('text/plain', 'and easy to do anywhere, even with Node.js');
var mail = new helper.Mail(fromEmail, subject, toEmail, content);
var sg = require('sendgrid')(process.env.SENDGRID_API_KEY);
var request = sg.emptyRequest({
method: 'POST',
path: '/v3/mail/send',
body: mail.toJSON()
});
sg.API(request, function (error, response) {
if (error) {
console.log('Error response received');
}
console.log(response.statusCode);
console.log(response.body);
console.log(response.headers);
});
However, if you want your provided code run smoothly, you'll need to revert the version to 2.0.0.

Using domain-level delegation with Google Classroom API

I'm trying to access teacher's class info using a node script. I can do it if I authenticate as the teacher themselves but I need a server connection to build a database. I'm not sure if this is a google classroom problem or if this is a bug on my end. I could be just thinking about authentication in the wrong way but I'm not sure. I am using this to authenticate:
module.exports.auth = function auth(type, callback) {
switch(type){
case "jwt":
useJwt(process.env.LXMUSER, callback)
break;
case "default":
useDefaultCred(callback);
break;
case "user":
useUser(callback);
break;
}
}
function useJwt(user, callback){
var google = require('googleapis');
var cfg = require('./config.json');
var key = require(process.env.GOOGLE_APPLICATION_CREDENTIALS);
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
cfg.scopes,
user
);
jwtClient.authorize(function (err, tokens) {
if (err) {
console.error('Unable to authenticate with google:', err);
return
}
callback(err, jwtClient)
})
}
I added these scopes to the Oauth client manager:
classroom.courses,
classroom.coursework.students,
drive.readonly,
drive.file,
drive.metadata.readonly,
drive.appdata
I can successfully use the API call through the google drive API but not the google classroom api. Here is my calling environment:
auth("jwt", function (err, authClient) {
// Make an authorized request to list Drive files.
gclass.courses.list({
auth: authClient,
}, function (err, res) {
if (err) {
utl.errorHandle(res, err);
return;
}
if (res.courses === undefined) {
console.log(res, "You have no courses");
}

How to implement oauth2orize in hapijs

I implemented oauth2orize in hapijs. But when I am calling the api, nothing happen. The function goes inside code.js file of oauth2orize module and hangs in between. Please suggest me how to implement oauth2orize in hapjs. hapi-oauth2orize is also not working as immigration & hapi-oauth2orize plugin throws option error.
const Hapi = require('hapi');
const server = new Hapi.Server();
const oauth2orize = require('oauth2orize');
var oauth = oauth2orize.createServer();
server.connection({
host: 'localhost',
port: 8000
});
server.register([{
register: require('hapi-mongodb'),
options: dbOpts
}], function (err) {
if (err) {
console.error(err);
throw err;
}
server.start();
server.route([
{
method: 'GET',
path: '/oauth/authorizegrant',
config: {
auth: false,
handler: function(request, reply) {
var clientId = request.query.client_id,
redirectUrl = request.query.redirect_uri,
resType = request.query.response_type,
state = request.query.state;
oauth.grant(oauth2orize.grant.code(function(clientId,redirectUrl,resType,state,callback) {
// Create a new authorization code
console.log('client', client);
var db = request.server.plugins['hapi-mongodb'].db;
var code = new Code({
value: uid(16),
clientId: client._id,
redirectUri: redirectUri,
userId: user._id
});
// Save the auth code and check for errors
db.collection('codes').insert(code, function(err) {
if (err) { console.log('err*********', err); return callback(err); }
callback(null, code.value);
});
}));
}
}
},
]);
});
You need to change parameters passed to oauth.grant function, the callback should be removed and replaced by hapi's reply function. A simple snippet would be
if (err) {
return reply(err);
}
return reply(code.value);
I would file an issue in the plugin repo as this is the best way to interface between hapi and oauth2orize.

Set YouTube video title when uploading with Node.js (googleapi module v1.0)

I'm trying to upload video to my YouTube channel using the googleapi module in Node.js (YouTube API V3)
The video is uploaded fine - I just can't find how to pass title and description to the upload command.
This is my code:
//Authorization stuff above
fs.readFile('./youtube_videos/in.avi', function(err, content){
if(err){
console.log('read file error: '+err);
} else {
yt.videos.insert({
part: 'status,snippet',
autoLevels: true,
media: {
body: content
}
}, function(error, data){
if(error){
console.log('error: '+error);
} else {
console.log('https://www.youtube.com/watch?v='+data.id+"\r\n\r\n");
console.log(data);
}
});
}
})
I know how should pass some snippet object like
snippet: {
title: 'test upload2',
description: 'My description2',
}
but I can't find where should it be - I tried every (almost) combination possible
Thank You!
I found the answer
In case someone is looking for it -
The snippet should be part of a resource object in the options of the request
(I also converted the fs.readFile to fs.createReadStream)
function uploadToYoutube(video_file, title, description,tokens, callback){
var google = require("googleapis"),
yt = google.youtube('v3');
var oauth2Client = new google.auth.OAuth2(clientId, appSecret, redirectUrl);
oauth2Client.setCredentials(tokens);
google.options({auth: oauth2Client});
return yt.videos.insert({
part: 'status,snippet',
resource: {
snippet: {
title: title,
description: description
},
status: {
privacyStatus: 'private' //if you want the video to be private
}
},
media: {
body: fs.createReadStream(video_file)
}
}, function(error, data){
if(error){
callback(error, null);
} else {
callback(null, data.id);
}
});
};

Resources