postUrl runs only once - bixby

I am calling postUrl in action-javascript that is referenced from Bixby sample on https://github.com/bixbydevelopers/capsule-samples-collection/tree/master/http-api-calls
var http = require('http')
var console = require('console')
var config = require('config')
module.exports.function = function adjustVolume (volume) {
var o = { };
var options = {
passAsJson: true,
returnHeaders: true,
format: 'json'
};
var response = http.postUrl(config.get('remote.url') + '/api/gvm/control/volume/' + volume, o, options);
return "ok";
}
BTW, postUrl to my remote service runs only one time, all later postUrl does not come into my remote service. Then I need to restart Bixby developer studio again to get postUrl to my remote service.
With getUrl, there is no symptom above.
Did I miss any constraint about using postUrl ?
Thanks in advance.

It looks like the Bixby platform caches the response from your remote server, and keeps re-serving it to your capsule code. I found that the solution is to set the cacheTime in the options to 0, and this makes the Bixby platform call your remote server again every time. Substitute the following for your options above (adding cacheTime on its own line):
var options = {
passAsJson: true,
returnHeaders: true,
format: 'json',
cacheTime: 0 // <--- this is the new line to add
};
I found this out when I wrote a tutorial capsule using remote storage. I was using http.postUrl to access my remote server and had to update the options for the postUrl call at this place in the code, or it wouldn't call the remote server more than once. The solution was setting the cacheTime to 0, as I mentioned above.

Related

Refreshing PubSubHubbub subscription for Youtube API in NodeJS

I managed to subscribe to a Youtube Feed through https://pubsubhubbub.appspot.com/subscribe on a web browser, I've been trying to refresh my subscription to PubSubHubbub through Fetch on NodeJS, the code I used is below
const details = {
'hub.mode': 'subscribe',
'hub.topic': 'https://www.youtube.com/xml/feeds/videos.xml?channel_id=${process.env.ID}',
'hub.callback': process.env.callback,
'hub.secret': process.env.secret
};
const endpoint = 'http://pubsubhubbub.appspot.com/subscribe'
var formBody = [];
for (const property in details) {
const encodedKey = encodeURIComponent(property);
const encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
const result = await fetch(endpoint, { method: "POST", body: formBody, 'Content-Type': 'application/x-www-form-urlencoded'})
console.log(result.status, await result.text())
Expected:
Status 204
Actual:
Status 400, content: "Invalid value for hub.mode:"
I expected at least for the content to tell me what the invalid value was, however it ended up being blank, it appears to me that it did not manage to read the POSTed content at all. I'm looking for ways to improve my code so that I don't encounter this problem.
I realised that I was supposed to specify in the content type header that charset=UTF-8. I'm not particularly well-versed in sending requests as of yet so this is definitely an eye-opener for me. After adding it in the server responds with 204 as expected and so I'll close my question.
A workout that I tried while trying to fix this was to import the exec() function from child_process module to run cURL and post the request instead. However I would recommend to stick to one language to make things more readable and using exec() runs commands directly from the shell which may have undesirable effects.

"Proxy-Authorization" is removed at the destination server

i use request module to consume web services. the web services expect Proxy-Authorization field in the header.
i send this value, but in the destination server, Proxy-Authorization is gone.
please help.
I got some helps from my colleage, here is the way to work-around.
just override proxyHeaderExclusiveList
const proxyHeaderExclusiveList = [];
proxyHeaderExclusiveList.concat = function newConcat() {
return this;
};
const options = {
url: SOME_URL,
headers: SOME_HEADERS,
proxyHeaderExclusiveList: proxyHeaderExclusiveList
};

Cannot read property 'getPayload' of undefined

I am implementing OAuth Google Sign in using backend (written in node.js, express framework at Heroku). Front end is Android and it sends the token id to the server just fine. And server receives the token id correctly.
Here is the code (which is ripped off straight from Google Documents)
var auth = new GoogleAuth;
var client = new auth.OAuth2(CLIENT_ID, '', '');
client.verifyIdToken(
token,
CLIENT_ID,
// Or, if multiple clients access the backend:
//[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3],
function(e, login) {
var payload = login.getPayload();
var userid = payload['sub'];
// If request specified a G Suite domain:
//var domain = payload['hd'];
});
But at times login in undefined. Its so strange that this problem occurs 1/10 rather than for every try so that I am not able to track the source of issue. For every other 9/10 it works just fine.
Any suggestions on how to solve this?
The problem in your code is that you are not checking if your callback get's any error.
The standard way in node.js to use a callback function is using two parameters - error is the first, the actual (success) returned data is the second, and the convention is that if an error exists - you should address it, and you're not gauranteed to get the data, and if everything went well- error will be null and you'll get your data.
So in your code, you are not checking that there's an error (and like you say, not always there's one).
Should be something like:
function(e, login) {
if (e) {
// handle error here
return; // don't continue, you don't have login
}
// if we got here, login is defined
var payload = login.getPayload();
var userid = payload['sub'];
// If request specified a G Suite domain:
//var domain = payload['hd'];
});
The first parameter to the callback function is an error that needs to handled.
function(error, login) {
if (error) return console.error(error)
var payload = login.getPayload();
var userid = payload['sub'];
// If request specified a G Suite domain:
//var domain = payload['hd'];
});

check on server side if youtube video exist

How to check if youtube video exists on node.js app server side:
var youtubeId = "adase268_";
// pseudo code
youtubeVideoExist = function (youtubeId){
return true; // if youtube video exists
}
You don't need to use the youtube API per-se, you can look for the thumbnail image:
Valid video = 200 - OK:
http://img.youtube.com/vi/gC4j-V585Ug/0.jpg
Invalid video = 404 - Not found:
http://img.youtube.com/vi/gC4j-V58xxx/0.jpg
I thought I could make this work from the browser since you can load images from a third-party site without security problems. But testing it, it's failing to report the 404 as an error, probably because the content body is still a valid image. Since you're using node, you should be able to look at the HTTP response code directly.
I can't think of an approach that doesn't involve making a separate HTTP request to the video link to see if it exists or not unless you know beforehand of a set of video IDs that are inactive,dead, or wrong.
Here's an example of something that might work for you. I can't readily tell if you're using this as a standalone script or as part of a web server. The example below assumes the latter, assuming you call a web server on /video?123videoId and have it respond or do something depending on whether or not the video with that ID exists. It uses Node's request library, which you can install with npm install request:
var request = require('request');
// Your route here. Example on what route may look like if called on /video?id=123videoId
app.get('/video', function(req, response, callback){
var videoId = 'adase268_'; // Could change to something like request.params['id']
request.get('https://www.youtube.com/watch?v='+videoId, function(error, response, body){
if(response.statusCode === 404){
// Video doesn't exist. Do what you need to do here.
}
else{
// Video exists.
// Can handle other HTTP response codes here if you like.
}
});
});
// You could refactor the above to take out the 'request.get()', wrap it in a function
// that takes a callback and re-use in multiple routes, depending on your problem.
#rodrigomartell is on the right track, in that your check function will need to make an HTTP call; however, just checking the youtube.com URL won't work in most cases. You'll get back a 404 if the videoID is a malformed ID (i.e. less than 11 characters or using characters not valid in their scheme), but if it's a properly formed videoID that just happens to not correspond to a video, you'll still get back a 200. It would be better to use an API request, like this (note that it might be easier to use the request-json library instead of just the request library):
request = require('request-json');
var client = request.newClient('https://www.googleapis.com/youtube/v3/');
youtubeVideoExist = function (youtubeId){
var apikey ='YOUR_API_KEY'; // register for a javascript API key at the Google Developer's Console ... https://console.developers.google.com/
client.get('videos/?part=id&id='+youtubeId+'&key='+apikey, function(err, res, body) {
if (body.items.length) {
return true; // if youtube video exists
}
else {
return false;
}
});
};
Using youtube-feeds module. Works fast (~200ms) and no need API_KEY
youtube = require("youtube-feeds");
existsFunc = function(youtubeId, callback) {
youtube.video(youtubeId, function(err, result) {
var exists;
exists = result.id === youtubeId;
console.log("youtubeId");
console.log(youtubeId);
console.log("exists");
console.log(exists);
callback (exists);
});
};
var notExistentYoutubeId = "y0srjasdkfjcKC4eY"
existsFunc (notExistentYoutubeId, console.log)
var existentYoutubeId = "y0srjcKC4eY"
existsFunc (existentYoutubeId, console.log)
output:
❯ node /pathToFileWithCodeAbove/FileWithCodeAbove.js
youtubeId
y0srjcKC4eY
exists
true
true
youtubeId
y0srjasdkfjcKC4eY
exists
false
false
All you need is to look for the thumbnail image. In NodeJS it would be something like
var http = require('http');
function isValidYoutubeID(youtubeID) {
var options = {
method: 'HEAD',
host: 'img.youtube.com',
path: '/vi/' + youtubeID + '/0.jpg'
};
var req = http.request(options, function(res) {
if (res.statusCode == 200){
console.log("Valid Youtube ID");
} else {
console.log("Invalid Youtube ID");
}
});
req.end();
}
API_KEY is not needed. It is quite fast because there is only header check for statusCode 200/404 and image is not loaded.

How to use tropo with node.js-socketstream framework?

In my application im using node.js with socketstream framework.Now i need to use tropo module to send an sms,receive an sms,make a call and answering an incoming call.I installed tropo-webapi using npm.i added this node code in server side.While running the below code i didn't get any output.i dont know how to link this file in tropo website and how to receive the sms and phone call.
exports.actions = function(req, res, ss) {
return{
sendMessage:function(){
var tropoAPI = require('tropo-webapi');
var tropo = new tropoAPI.TropoWebAPI();
tropo.call("+18197924547", null, null, null, null, null, "SMS", null, null,null);
tropo.say("HI How Are You!!");
},
makeCall:function(){
var tropoAPI = require('tropo-webapi');
var tropo = new tropoAPI.TropoWebAPI();
tropo.call("+18197924547");
tropo.say("Hi,how ary yoo!");
}
};
};
So you did not specify from which file is this snippet from but I got the feeling, it is from one under server/rpc/<yourfilename> where the Remote Procedure Calls are.
!!! NOTE THE <yourfilename>
The methods which you define are generated for the client in a way that he can trigger it trough the socket interfaces, let me write a snippet, I think you will understand:
- lets write into this file => client/code/app/app.js
ss.rpc('<yourfilename>.sendMessage','here comes params which is now a string');
To get a sense what this ss object is look into your client/code/app/entry.js you will see it.

Resources