EzDevInfo.com

google-api-nodejs-client

Google's officially supported Node.js client library for accessing Google APIs, it comes with OAuth 2.0 support.

Accessing a public calendar using Google API without requiring a user to log in

I'd like to access a public calendar using Google's REST API.

Google's calendar API suggests I need an OAuth token to get access to calendars:

https://developers.google.com/google-apps/calendar/auth

However, I'm accessing a public calendar and am doing this from the server so can't/shouldn't have to ask the user to authenticate.

I'm using the node.js api:

googleapis
  .discover('calendar', 'v3').execute(function(err, client) {
    client.calendar.calendars.get({ calendarId: '***@group.calendar.google.com' })
      .execute(function (err, response) {
        console.log('response from google', response);
      });
  });

This returns "Your client has issued a malformed or illegal request. That’s all we know."

Calling .withApiKey('***') after .calendars.get() returns the same error.

Any suggestions?


Source: (StackOverflow)

Video upload using youtube/google API directly from server using node.js?

I am trying to upload videos from server without any manual authentication by user in the client side . I tried the below code snippet for video upload but it authenticates the user in the browser and asks for the acceptance of the app.

var ResumableUpload = require('node-youtube-resumable-upload');
var googleauth = require('google-auth-cli');
var google = require('googleapis');

var getTokens = function(callback) {
  googleauth({
      access_type: 'offline',
      scope: 'https://www.googleapis.com/auth/youtube.upload' //can do just 'youtube', but 'youtube.upload' is more restrictive
  },
  {     client_id: CLIENT_ID, //replace with your client_id and _secret
      client_secret: CLIENT_SECRET,
      port: 3000
  },
  function(err, authClient, tokens) {
    console.log(tokens);
    callback(tokens);
  });
};

getTokens(function(result) {
  tokens = result;
  upload();
});



var upload = function() {
      var metadata = {snippet: { title: 'title', description: 'Uploaded with ResumableUpload' },
          status: { privacyStatus: 'public' }};
      var resumableUpload = new ResumableUpload(); //create new ResumableUpload
      resumableUpload.tokens = tokens;
      resumableUpload.filepath = 'youtube/test4.mp4';
      resumableUpload.metadata = metadata;
      resumableUpload.monitor = true;
    resumableUpload.eventEmitter.on('progress', function(progress) {
        console.log(progress);
    });
      resumableUpload.initUpload(function(result) {
        console.log(result);
        return;
      });
    }

But for my app it should directly upload the video to youtube from the server. For that I need the access token and refresh token I tried lot to get the access token directly but I couldn't able to get it.

So any help or idea to how to make the video upload directly from server to a channel account. I searched lot in google for a node module to do that but I couldn't able to find it.

I have been using this approach to upload video

  1. Getting the web based generated token using the client library.
  2. Getting the youtube upload permission from user for my application & access_type=offline.
  3. Access type offline gives refresh token in response. This token will help to continue upload from backend server token when its expires.
  4. After getting the permission. It will redirect to URL with code.
  5. Using the given code generate access_token
  6. Save this token for future use.
  7. Use the same token to push the video from your server to youtube server
  8. Refresh the token when it expires.

But is there any way to implement this approach without getting the youtube upload permission from user for my application.


Source: (StackOverflow)

Advertisements

Node.js undefined:1 [SyntaxError: Unexpected end of input]

I am getting the following error when I execute the node.js script, I tried to investigate a lot by adding console.log() to trace the error but could not find any solution. [Note: I have also searched other Stackoverflow solution but none of it helped]

undefined:1
   {"ydht":{"status":{"code":200,"message":"OK"},"records":[
                                                     ^
SyntaxError: Unexpected end of input
at Object.parse (native)
at IncomingMessage.<anonymous> (/tmp/subs_20140130/inc/getData.js:36:24)
at IncomingMessage.EventEmitter.emit (events.js:95:17)
at IncomingMessage.<anonymous> (_stream_readable.js:745:14)
at IncomingMessage.EventEmitter.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:407:10)
at emitReadable (_stream_readable.js:403:5)
at readableAddChunk (_stream_readable.js:165:9)
at IncomingMessage.Readable.push (_stream_readable.js:127:10)
at HTTPParser.parserOnBody [as onBody] (http.js:142:22)

Here is my code:

var options = {
  host: '<my host>',
  port: 3128,
  path: 'http://<some host>:4080'+searchQuery,
  method: 'GET',
  headers: {
     'App-Auth': cert
  }
};
var req = http.request(options, function(res) {   
  res.setEncoding('utf8'); //DEBUG
  for ( var k in options) { console.log("[LOGGING] options :" + k + " = " + options[k]);} //DEBUG
  res.on('data', function (resData) {
    var resObj = "";
    resObj =  JSON.parse(resData);
    console.log("[LOGGING] Response:: "+resObj);               
    if(resObj.ydht.status.code === 200 && resObj.ydht.records[0].key.length > 0) {
      console.log("[LOGGING] Email   "+em+"  Key       "+resObj.ydht.records[0].key);          
      var filePath = basePath + '/setData';
      var setd = require(filePath);
      setd.setMagData(resObj.ydht.records[0].key, ycacert, is_sub);
    } else {
      console.log("[LOGGING] Fail to fetch data em        "+em+"  nl      "+nl);
    }
  });
  res.on('end', function() {
    console.log("[LOGGING] connection closed");
  });
});
req.on('error', function(err) {
  console.log("[LOGGING] Fail to fetch data em        "+em+"  nl      "+nl);
});
req.end();

When I call the api using curl command, I get the below valid json response:

{"ydht":{"status":{"code":200,"message":"OK"},"records":[{"metadata":{"seq_id":"intusnw1-14B3579A577-3","modtime":1422531339,"disk_size":99},"key":"201408271148_zy@gmail.com","fields":{"em":{"value":"xyz1408@yahoo.in"},"is_confirm":{"value":""},"nl":{"value":"offerpop1"}}}],"continuation":{"scan_completed":false,"scan_status":200,"uri_path":"/YDHTWebService/V1/ordered_scan/dts.subs_email?order=asc&start_key=a0"}}}

Source: (StackOverflow)

Inserting Google Analytics Content Experiments using the Node.JS Client Library

I'm trying to configure a content experiment using the Node.js Client Library, and have not been able to work out the syntax. Where do I put the body (an Experiment resource) as described here?

https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtExperimentsGuide#insert

This code, for listing existing experiments, works as expected:

var listExperiments = function(){
  googleapis
  .discover('analytics', 'v3')
  .execute(function(err, client) {
    var request = client
    .analytics.management.experiments.list({
        accountId : accountId,
        webPropertyId : webPropertyId,
        profileId : profileId
        })
    .withApiKey(browserAPIKey)
    .withAuthClient(oauth2Client)

      request.execute(function(err,result){
        if (err){
          console.log(err);
          res.send(402);          
        } else {
          console.log(result);
          res.send(200);
        }
      });
  });
}

However, when I try to insert a new experiment thusly, I receive a "Field resource is required" error.

var body = {       
  "name": "myExperimentName",
  "status": "READY_TO_RUN",
  "objectiveMetric":"ga:bounces",
  "variations": [
    { "name": "text1", "url":"http://www.asite.net", "status":"ACTIVE" },
    { "name": "text2", "url":"http://www.asite.net", "status":"ACTIVE" }
   ]
 };

var insertExperiment = function(){
  googleapis
  .discover('analytics', 'v3')
  .execute(function(err, client) {
    var request = client
    .analytics.management.experiments.insert({
        accountId : accountId,
        webPropertyId : webPropertyId,
        profileId : profileId,
        resource : body
        })
    .withApiKey(browserAPIKey)
    .withAuthClient(oauth2Client)

    request.execute(function(err,result){
      if (err){
        console.log(err);
        res.send(402);          
      } else {
        console.log(result);
        res.send(200);
      }
    });
  });
}

I've tried a few configurations. Management API writes are in limited beta, but I have beta access, so that's not the problem. I've tried inserting the new experiment information directly into the insert() object, calling the experiment info object "body : body " instead of "resource : body", JSON.stringifying the body, and a few other configurations. No luck.

Any help would be great!

I'm aware of this answer, but it uses the Javascript Client Library and makes RESTful requests, whereas I'd like to use the Node Library.

EDIT: Thanks to Burcu Dogan at Google. Here's the correct syntax:

.analytics.management.experiments.insert({
accountId : accountId,
webPropertyId : webPropertyId,
profileId : profileId
}, body)

Source: (StackOverflow)

Error 500 backendError with Gmail API and Google APIs Node Client

I'm trying to use the new Gmail API with the Google API Node client. I created a new project from the developer console, set up a new "Service Account" Client ID, and enabled access to the API.

As a proof of concept, I am simply trying to list the threads in my inbox. When I enable the OAuth 2.0 toggle for the API explorer and enter my email address, the request succeeds and I see a JSON response with data.

Now I try to do the same in Node:

var googleapis = require('googleapis');

var SERVICE_ACCOUNT_EMAIL = '...SNIP...';

// generated by: openssl pkcs12 -in ...SNIP...p12 -out key.pem -nocerts -nodes
var SERVICE_ACCOUNT_KEY_FILE = 'key.pem';
var jwt = new googleapis.auth.JWT(
        SERVICE_ACCOUNT_EMAIL,
        SERVICE_ACCOUNT_KEY_FILE,
        null,
        ['https://www.googleapis.com/auth/gmail.readonly']);

googleapis
    .discover('gmail', 'v1')
    .execute(function(err, client) {

        jwt.authorize(function(err, result) {
            if(err) console.error(err);
            else console.log(result);

            client.gmail.users.threads.list()
                .withAuthClient(jwt)
                .execute(function(err, result) {
                    if(err) console.error(err);
                    else console.log(result);
            });
        });
    });

First I print the results of the authorize() call, which looks like it returns a token, so I think I have all the OAuth stuff setup properly:

{ access_token: '...SNIP...',
  token_type: 'Bearer',
  expires_in: 1404277946,
  refresh_token: 'jwt-placeholder' }

Then I try to actually use the API, but I get an error:

{ errors: 
   [ { domain: 'global',
       reason: 'backendError',
       message: 'Backend Error' } ],
  code: 500,
  message: 'Backend Error' }

At this point, I don't know what else to try. I think the OAuth stuff is working properly, because I haven't gotten any authentication errors. I also think the API itself is working and my account is fine, because I can use it through the API Explorer. I don't see any indication that the Node library is at fault either. In short, I have no idea what the problem is. Any ideas?


Source: (StackOverflow)

how to use the refreshAccessToken method to generate a new accesstoken in google-api-nodejs-client

I see that this pull request adds a method to refresh the access token using a saved refresh token. It is not clear to me how to use it. I have saved the tokens (including the refresh token) from the original getToken request and am now retrieving the token from the Database in a new session. How do I set the credentials on OAuth2Client so that I can call refreshAccessToken and get a new accesstoken?


Source: (StackOverflow)

Google Contacts API nodejs

I've been looking through the Google NodeJS API docs, but I don't see one listed for the Contacts API. Am I missing something or is that not included in the module?


Source: (StackOverflow)

Registering Glass Timeline Notification with Node

I'm trying to register TAKE_A_NOTE with the 'mirror-api-subscription' event listener. I'm not having any luck: I can launch take a note with "my app", however, there's no console log that the event has been recognized.

I would like to recognize when the TAKE_A_NOTE function has occurred or finished, and handle the response afterwards. I do not know whether the subscription should be on a stream or if I am implementing the EventListener in a faulty manner. Your help would be greatly appreciated.

The code I am utilizing is:

// references
// http://www.recursiverobot.com/post/57348836217/getting-started-with-the-mirror-api-using-node-js
// https://www.npmjs.org/package/mirror-api-subscription

var express = require('express')
    , http = require('http')
    , https = require('https')
    , fs = require('fs')
    , googleapis = require('googleapis')
    , OAuth2Client = googleapis.OAuth2Client;
var app = express();
var oauth2Client = new OAuth2Client(process.env.MIRROR_DEMO_CLIENT_ID,
   process.env.MIRROR_DEMO_CLIENT_SECRET, process.env.MIRROR_DEMO_REDIRECT_URL);


// all environments
app.set('port', 8888);
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);

var gotToken = function () {
    googleapis
        .discover('mirror', 'v1')
        .execute(function (err, client) {
            if (!!err) {
                failure();
                return;
            }

            insertContact(client, failure, success);
            insertSubscription(client, failure, success);
        });
    };


var insertContact = function (client, errorCallback, successCallback) {
    client
        .mirror.contacts.insert({
            "id": "myapp",
            "displayName": "myApp",
            "priority": 100,
            "acceptCommands": [
                {"type": "TAKE_A_NOTE"}
            ],
            "speakableName":"my app"
        })
        .withAuthClient(oauth2Client)
        .execute(function (err, data) {
            if (!!err)
                errorCallback(err);
            else
                successCallback(data);
        });
    };

var insertSubscription = function (client, errorCallback, successCallback) {
    client.mirror.subscriptions.insert({
        "callbackUrl":"https://localhost:7777/notification",
        "collection":"timeline",
        "userToken":"001",
        "verifyToken":"secret",
        "operation":["INSERT"]
        });
    }

    var subscription = require('mirror-api-subscription')(
    function () {
    })

    subscription.on('locations#UPDATE',
    function (notification, user, payload) {
      console.log('location of user %s updated', user.id)
    })

    subscription.on('timeline#INSERT:LAUNCH',
    function (notification, user, payload) {
      console.log('subscription timeline#INSERT:LAUNCH')
    })

    subscription.on('timeline#UPDATE:CUSTOM',
    function (notification, user, payload) {
        console.log('subscription timeline#UPDATE:CUSTOM')
    })

    app.post('/notification', subscription.dispatcher())


    app.get('/', function (req, res) {
        if (!oauth2Client.credentials) {
            // generates a url that allows offline access and asks permissions
            // for Mirror API scope.
            var url = oauth2Client.generateAuthUrl({
                access_type: 'offline',
                scope: 'https://www.googleapis.com/auth/glass.timeline'
            });
            res.redirect(url);
        } else {
            gotToken();
        }
        res.write('Glass Mirror API with Node');
        res.end();

    });

    app.get('/oauth2callback', function (req, res) {
        // if we're able to grab the token, redirect the user back to the main page
        grabToken(req.query.code, failure, function () {
            res.redirect('/');
        });
    });

    app.post('/reply', function(req, res){
        console.log('replied',req);
        res.end();
    });

    var options = {
        key: fs.readFileSync('./ssl/key.pem'),
        cert: fs.readFileSync('./ssl/cert.pem'),
    };

    https.createServer(options, app).listen(7777, function() {
        console.log('https listening on 7777');
    });

    http.createServer(app).listen(app.get('port'), function () {
        console.log('Express server listening on port ' + app.get('port'));
    }); 

Source: (StackOverflow)

Send email using Google API with only access token

I want to send an email through Google API without the unnecessary OAUTH2 parameters. I only have the access_token and the refresh_token of that user.

How can I send an email through Gmail API through a basic POST request in NodeJS, with Request npm plugin?


Source: (StackOverflow)

renaming files in Google Cloud Storage?

Can you rename files in Google Cloud Storage?

I am letting users upload photos, but I want to give them the ability to edit the photo, at least by changing the name they uploaded it with. I am using Javascript through Node.js.

Thanks!


Source: (StackOverflow)

Google Drive API push notifications can't be stopped / cancelled

I am watching a Drive resource. Setting up the watch (using the googleapis 0.2.13-alpha client with node.js and drive.file.watch):

exports.subscribeDriveCallbacksCmd = function( user, fileId ){
  var userId = user.id;
  var baseUrl = exports.BASE_URL;
  var subscribeUrl = baseUrl+"/incoming/file";
  var watchId = 'id-'+fileId+'-'+(new Date()).getTime();
  var subscription = {
    id: watchId,
    token: userId+':'+fileId,
    type: 'web_hook',
    address: subscribeUrl,
    params:{
      ttl: 600
    }
  };
  var params = {
    fileId: fileId
  };

//var cmd = client.drive.files.watch( params, subscription );

// FIXME - Hack around bug in RPC implememntation var hack = {channel:subscription}; for( var key in params ){ hack[key] = params[key]; } var cmd = client.drive.files.watch( hack );

return cmd; };

var cmd = exports.subscribeDriveCallbacksCmd( user, '0ZZuoVaqdWGhpUk9PZZ' ); var batch = client.newBatchRequest(); batch.add(cmd); batch.withAuthClient(user.auth).execute(cb);

After this, I'm getting a response of

{ kind: 'api#channel',
    id: 'id-0ZZuoVaqdWGhpUk9PZZ-1374536746592',
    resourceId: 'WT6g4bx-4or2kPWsL53z7YxZZZZ',
    resourceUri: 'https://www.googleapis.com/drive/v2/files/0AHuoVaqdWGhpUkZZZZ?updateViewedDate=false&alt=json',
    token: '101852559274654726533:0ZZuoVaqdWGhpUk9PZZ',
    expiration: '1374537347934' }
and a sync callback with the following headers
  'x-goog-channel-id': 'id-0ZZuoVaqdWGhpUk9PZZ-1374536746592',
  'x-goog-channel-expiration': 'Mon, 22 Jul 2013 23:55:47 GMT',
  'x-goog-resource-state': 'sync',
  'x-goog-message-number': '1',
  'x-goog-resource-id': 'WT6g4bx-4or2kPWsL53z7YxZZZZ',
  'x-goog-resource-uri': 'https://www.googleapis.com/drive/v2/files/0AHuoVaqdWGhpUkZZZZ?updateViewedDate=false&alt=json',
  'x-goog-channel-token': '101852559274654726533:0ZZuoVaqdWGhpUk9PZZ',
  'user-agent': 'APIs-Google; (+http://code.google.com/apis)

There are several problems with this, however:

  • The resource-id returned by both of these do not match the fileId passed when I subscribed to the watch. It does match the ID given in the resource-uri
  • Trying to use either the resourceID returned here, or the fileId passed when I subscribed, returns an error when I try to stop the channel.

The error given for drive.channel.stop varies depending on how I do the call. If I use the API Explorer at the bottom of the Channel: Stop page, providing either the resourceId or the fileId for the resourceId parameter, I get


404 Not Found

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "notFound",
    "message": "Channel not found"
   }
  ],
  "code": 404,
  "message": "Channel not found"
 }
}

If I use the node.js library with this code:

exports.cancelDriveCallbacksCmd = function( watchId, fileId, resourceId ){
  var body = {
    id: watchId,
    resourceId: resourceId
  };
  var cmd = client.drive.channels.stop( body );
  return cmd;
};
var cmd = exports.cancelDriveCallbacksCmd( 'id-0ZZuoVaqdWGhpUk9PZZ-1374536746592', '0ZZuoVaqdWGhpUk9PZZ', 'WT6g4bx-4or2kPWsL53z7YxZZZZ' );
var batch = client.newBatchRequest();
batch.add(cmd);
batch.withAuthClient(user.auth).execute(cb);

I get the error

{ code: 500,
  message: 'Internal Error',
  data: 
   [ { domain: 'global',
       reason: 'internalError',
       message: 'Internal Error' } ] }
which I suspected was related to Bug 59 which has a workaround (which was the hack code I was using above) but should have the fix in place sometime this week, I understand.

So I changed it to this code, which worked around the bug for files.watch:


exports.cancelDriveCallbacksCmd = function( watchId, fileId, resourceId ){
  var params = {};
  var body = {
    id: watchId,
    resourceId: resourceId,
    fileId: fileId
  };

  //var cmd = client.drive.channels.stop( params, body );

  // FIXME - hack around bug in RPC implementation
  var hack = {channel:body};
  for( var key in params ){
    hack[key] = params[key];
  }
  var cmd = client.drive.channels.stop( hack );
  console.log( 'cancelDriveCallbacksCmd', hack );

  return cmd;
};

But I get the same 500 error.

Any thoughts about what I might be doing wrong or how to even go about debugging where I might be going wrong with it?


Source: (StackOverflow)

How to make POST API calls with google-api-nodejs-client?

I am trying to make a Google Calendar push notification API call (https://developers.google.com/google-apps/calendar/v3/push). I figured out how to make a calendar list call. So, I am fairly confident that my Oauth 2.0 authentication piece is working. I am guessing that I need to specify that the push notification call is a POST. Here are my codes:

  var params = { calendarId: calendarId,
                 id: 'my-unique-id-00001',
                 type: "web_hook",
                 address: "https://mydomain.com/notifications" };
  client
    .calendar.events.watch(params)
    .withAuthClient(authClient)
    .execute(callback);

I keep getting this error message:

{ errors: [ { domain: 'global', reason: 'required', message: 'entity.resource', debugInfo: 'com.google.api.server.core.Fault: ImmutableErrorDefinition{base=REQUIRED, category=USER_ERROR, cause=com.google.api.server.core.Fault: Builder{base=REQUIRED, ...


Source: (StackOverflow)

Mirror API and Node.JS

I have a node.js program that I am trying to work with the googleapis module (https://github.com/google/google-api-nodejs-client) version 0.2.5-alpha.

I can make calls using the raw HTTP without problems, so I know I am white listed for the API, I am authenticating and authorizing correctly, and the correct scopes and everything are being requested. If I use the same access_token to do an insert into the timeline, I am getting an error in the callback. I am also discovering the plus API, and calls using this API are working fine.

Code fragment to discover the API, which appears to work without problems:

var client;
googleapis
  .discover( 'plus', 'v1' )
  .discover( 'mirror', 'v1' )
  .execute( function(err,data){
    console.log( err );
    client = data;
  });

Code fragment to do the call:

  client.mirror.timeline.insert({
    text: "test 1 "
  } ).withAuthClient(user.auth).execute(function(err,result,res){
      console.log( '++ start ++' );
      console.log( '+err   ', err );
      console.log( '+result', result );
      //console.log( '+res   ', res );
      console.log( '++ end   ++' );
  });

What is logged during the callback:

++ start ++
+err    { code: 400,
  message: 'Required',
  data: [ { domain: 'global', reason: 'required', message: 'Required' } ] }
+result undefined
++ end   ++

Any indication what is "Required", how to provide it, or how to further debug errors such as this?


Source: (StackOverflow)

Failed sending mail through google api in nodejs

I'm trying to send an email through Google API.

I'm using googleapis for Google API access in node.js .

My issue is that when I try to send a simple mail with no attachments, I get the following error:

'raw' RFC822 payload message string or uploading message via /upload/* URL required

I didn't define in my request that there is an attachment and I don't see any error in the email addresses.

Please help.

My code:

    var google = require('googleapis');
    var gmailClass = google.gmail('v1');

    var email_lines = [];

    email_lines.push("From: \"Some Name Here\" <rootyadaim@gmail.com>");
    email_lines.push("To: hanochg@gmail.com");
    email_lines.push('Content-type: text/html;charset=iso-8859-1');
    email_lines.push('MIME-Version: 1.0');
    email_lines.push("Subject: New future subject here");
    email_lines.push("");
    email_lines.push("And the body text goes here");
    email_lines.push("<b>And the bold text goes here</b>");

    var email =email_lines.join("\r\n").trim();

    var base64EncodedEmail = new Buffer(email).toString('base64');

    gmailClass.users.messages.send({
        auth: OAuth2Client,
        userId: "me",
        message: 
        {
             raw: base64EncodedEmail
        }           
      },
    function(err, results){});

Source: (StackOverflow)

Is the Admin SDK a part of Google APIs?

I'm looking at this Google API nodejs client. I also looked at this list of supported Google APIs, and I noticed that the Admin SDK is not included in the list. I want to use the Directory API for managing Groups, but I'm wondering whether the Admin SDK is a part of Google APIs, or is it a different set of APIs overall?


Source: (StackOverflow)