I am trying to add pagination to my Zapier trigger.
The API I am using for the trigger supports pagination, but not using a page number in the traditional sense (ie. page 1,2,3,...). Instead, the API response includes a key (ie. "q1w2e3r4") which should be passed as a parameter to the next request to get the next page of results.
From looking at the docs, I can use {{bundle.meta.page}} (which defaults to 0 unless otherwise set).
I am trying to set {{bundle.meta.page}} in the code editor, with an example shown below:
const options = {
url: 'company_xyz.com/api/widgets',
method: 'GET',
...,
params: {
...,
'pagination_key': bundle.meta.page,
}
}
return z.request(options)
.then((response) => {
response.throwForStatus();
const json_response = response.json;
widgets = json_response.widgets
...
bundle.meta.page = json_response["next_pagination_key"]
return widgets;
});
The problem is that when Zapier tries to retrieve the next page, bundle.meta.page will be 1 instead of the value of "next_pagination_key" from the result of the previous request.
There are docs on cursor-based pagination in the CLI docs.
The relevant block is:
const performWithAsync = async (z, bundle) => {
let cursor;
if (bundle.meta.page) {
cursor = await z.cursor.get(); // string | null
}
const response = await z.request(
'https://5ae7ad3547436a00143e104d.mockapi.io/api/recipes',
{
// if cursor is null, it's sent as an empty query
// param and should be ignored by the server
params: { cursor: cursor }
}
);
// we successfully got page 1, should store the cursor in case the user wants page 2
await z.cursor.set(response.nextPage);
return response.items;
};
This should work in the Zapier Visual Builder, but you might need to use the CLI instead. You can export your integration using the zapier convert CLI command (docs).
I Created a android app in which if a press a button and value changes in Firebase database (0/1) , i want to do this using google assistant, please help me out, i searched out but didn't found any relevant guide please help me out
The code to do this is fairly straightforward - in your webhook fulfillment you'll need a Firebase database object, which I call fbdb below. In your Intent handler, you'll get a reference to the location you want to change and make the change.
In Javascript, this might look something like this:
app.intent('value.update', conv => {
var newValue = conv.prameters.value;
var ref = fbdb.ref('path/to/value');
return ref.set(newValue)
.then(result => {
return conv.ask(`Ok, I've set it to ${newValue}, what do you want to do now?`);
})
.catch(err => {
console.error( err );
return conv.close('I had a problem with the database. Try again later.');
});
return
});
The real problem you have is what user you want to use to do the update. You can do this with an admin-level connection, which can give you broad access beyond what your security rules allow. Consult the authentication guides and be careful.
I am actually working on a project using Dialogflow webhook and integrated Firebase database. To make this posible you have to use the fulfilment on JSON format ( you cant call firebasedatabase in the way you are doing)
Here is an example to call firebase database and display a simple text on a function.
First you have to take the variable from the json.. its something loike this (on my case, it depends on your Entity Name, in my case it was "tema")
var concepto = request.body.queryResult.parameters.tema;
and then in your function:
'Sample': () => {
db.child(variable).child("DESCRIP").once('value', snap => {
var descript = snap.val(); //firebasedata
let responseToUser = {
"fulfillmentMessages": [
{ //RESPONSE FOR WEB PLATFORM===================================
'platform': 'PLATFORM_UNSPECIFIED',
"text": {
"text": [
"Esta es una respuesta por escritura de PLATFORM_UNSPECIFIED" + descript;
]
},
}
]
}
sendResponse(responseToUser); // Send simple response to user
});
},
these are links to format your json:
Para formatear JSON:
A) https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/Shared.Types/Platform
B) https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/Shared.Types/Message#Text
And finally this is a sample that helped a lot!!
https://www.youtube.com/watch?v=FuKPQJoHJ_g
Nice day!
after searching out i find guide which can help on this :
we need to first create chat bot on dialogflow/ api.pi
Then need to train our bot and need to use webhook as fullfillment in
response.
Now we need to setup firebase-tools for sending reply and doing
changes in firebase database.
At last we need to integrate dialogflow with google assistant using google-actions
Here is my sample code i used :
`var admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
var database = admin.database();
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
exports.hello = functions.https.onRequest((request, response) => {
let params = request.body.result.parameters;
database.ref().set(params);
response.send({
speech: "Light controlled successfully"
});
});`
I'm trying to create a Java Script Code Action on Zapier to fetch Klout Scores for any given Twitter user name...
I've realized that this needs to be done in 2 stages:
1) First get the Klout ID for any Twitter screen_name:
http://api.klout.com/v2/identity.json/twitter?screenName="+screen_name+"&key="+klout_apikey"
Klout replies back to that with JSon:
{"id":"85568398087870011","network":"ks"}
2) second get the Klout score for that Klout id:
http://api.klout.com/v2/user.json/"+klout.id+"/score?key="+klout_apikey"
Klout replies back to this with JSon:
{"score":65.68382904221806,"scoreDelta":{"dayChange":-0.03663891859041257,"weekChange":-0.5495711661078815,"monthChange":-1.4045672671990417},"bucket":"60-69"}
Of course, what I need is the "score":65.68382904221806 object of the JSon reply array.
I use these following JS functions proposed by #KayCee:
var klout_apikey = '<my klout api key>';
fetch("http://api.klout.com/v2/identity.json/twitter?screenName="+screen_name+"&key="+klout_apikey")
.then(function(res) {
return res.json();
})
.then(function(klout) {
console.log(klout);
if(klout.id) {
return fetch("http://api.klout.com/v2/user.json/"+klout.id+"/score?key="+klout_apikey")
}
}).then(function(res) {
return res.json();
}).then(function(body) {
// console.log(body.score);
//Here is where you are telling Zapier what you want to output.
callback(null, body.score)
}).catch(callback); //Required by Zapier for all asynchronous functions.
In the "input data" section of the Zapier code action i pass the screen_name as a variable:
screen_name: [the twitter handle]
What I get back is the following error message:
SyntaxError: Invalid or unexpected token
What is the error that you see? You could do this by simply using the fetch client. You might want to remove the variable declarations before adding this to the code step.
var inputData = {'screen_name': 'jtimberlake'}
//Remove the line above before pasting in the Code step. You will need to configure it in the Zap.
var klout_apikey = '2gm5rt3hsdsdrzgvnskmgm'; //Not a real key
fetch("http://api.klout.com/v2/identity.json/twitter?screenName="+inputData.screen_name+"&key="+klout_apikey)
.then(function(res) {
return res.json();
})
.then(function(body) {
console.log(body);
if(body.id) {
return fetch("http://api.klout.com/v2/user.json/"+body.id+"/score?key="+klout_apikey)
}
}).then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
//Here is where you are telling Zapier what you want to output.
callback(null, body)
}).catch(callback); //Required by Zapier for all asynchronous functions.
Refer to their documentation here - https://zapier.com/help/code/#introductory-http-example
Also refer to their Store client which allows you to store values (for cache) - https://zapier.com/help/code/#storeclient-javascript
I'm still very new to appcelerator but I'm trying to do a small experiment with geolocation. I have some code similar to below, which returns the long and lat to the console. What I would like to is get the long and lat and append them to a URL, e.g http://www.mywebsite.com/lat/long.
I've tried creating a simple alert to show me the current location in the but all it says is Alert: [object GeolocationModule].
Could somebody point me in the right direction so I can learn some more? Thank you
if (Ti.Geolocation.locationServicesEnabled) {
Titanium.Geolocation.purpose = 'Get Current Location';
Titanium.Geolocation.getCurrentPosition(function(e) {
if (e.error) {
Ti.API.error('Error: ' + e.error);
} else {
Ti.API.info(e.coords);
}
});
} else {
alert('Please enable location services');
}
This is how you need to follow the API documentation:
You can have a look at the LocationResults page: https://docs.appcelerator.com/platform/latest/#!/api/LocationResults which leads you to LocationCoordinates: https://docs.appcelerator.com/platform/latest/#!/api/LocationCoordinates
There you can see, that you can use e.coords.latitude or longitude to get the values. Or have a look at the console output. It should show you a JSON output with the key-value pairs.
Once you have the values you can create a HTTP request (demo: https://docs.appcelerator.com/platform/latest/#!/guide/HTTPClient_and_the_Request_Lifecycle) and open your page:
var url = "https://www.appcelerator.com/"+e.coords.longitude+"/"+e.coords.latitude;
var xhr = Ti.Network.createHTTPClient({
onload: function(e) {
// this function is called when data is returned from the server and available for use
// this.responseText holds the raw text return of the message (used for text/JSON)
// this.responseXML holds any returned XML (including SOAP)
// this.responseData holds any returned binary data
Ti.API.debug(this.responseText);
alert('success');
},
onerror: function(e) {
// this function is called when an error occurs, including a timeout
Ti.API.debug(e.error);
alert('error');
},
timeout:5000 /* in milliseconds */
});
xhr.open("GET", url);
xhr.send(); // request is actually sent with this statement
or if you plan to use more request have a look at RESTe (https://github.com/jasonkneen/RESTe) which is an awesome library that makes it easy to create API requests
With Youtube api v2, there's easy way to get videos. Just send a query like this:
http://gdata.youtube.com/feeds/mobile/videos?max-results=5&alt=rss&orderby=published&author=OneDirectionVEVO
The Youtube api v2 also has an interactive demo page for building query:
http://gdata.youtube.com/demo/index.html
With Youtube api v3, I don't know the corresponding way. Please point me the way with api v3.
Thank you!
The channels#list method will return a JSON with some information about the channel, including the playlist ID for the "uploads" playlist:
https://www.googleapis.com/youtube/v3/channels?part=contentDetails&forUsername=OneDirectionVEVO&key={YOUR_API_KEY}
With the playlist ID you can get the videos with the playlistItems#list method:
https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=UUbW18JZRgko_mOGm5er8Yzg&key={YOUR_API_KEY}
You can test those at the end of the documentation pages.
This should do it. This code just gets and outputs the title but you can get any details you want
// Get Uploads Playlist
$.get(
"https://www.googleapis.com/youtube/v3/channels",{
part : 'contentDetails',
forUsername : 'USER_CHANNEL_NAME',
key: 'YOUR_API_KEY'},
function(data) {
$.each( data.items, function( i, item ) {
pid = item.contentDetails.relatedPlaylists.uploads;
getVids(pid);
});
}
);
//Get Videos
function getVids(pid){
$.get(
"https://www.googleapis.com/youtube/v3/playlistItems",{
part : 'snippet',
maxResults : 20,
playlistId : pid,
key: 'YOUR_API_KEY'},
function(data) {
var results;
$.each( data.items, function( i, item ) {
results = '<li>'+ item.snippet.title +'</li>';
$('#results').append(results);
});
}
);
}
<!--In your HTML -->
<ul id="results"></ul>
If quota cost is a consideration, it may be beneficial to follow this simple algorithm.
First grab the data from https://www.youtube.com/feeds/videos.xml?channel_id=... This is a simple XML feed which will give you the video ID's, but you cannot specify further 'parts' (stats, etc).
Using the video ID's from that list, do a query on the /videos API endpoint which allows for a comma-separated-list of video ID's which should only result in 1 quota cost, plus 0-2 for any additional part parameters. As #chrismacp points out, using the /search endpoint is simpler but has a quota cost of 100, which can add up quickly.
There is a resource consideration here (cpu, memory, etc) as you are making a second call, but I believe in many scenarios this can be a useful method.
Things have changed alot in V3 of the API. Here is a video that walks you through the v3 API calls needed to get a list of the videos uploaded in a given channel, with live demos using the API Explorer.
YouTube Developers Live: Getting a Channel's Uploads in v3 - https://www.youtube.com/watch?v=RjUlmco7v2M
In case it helps anyone here this is what I discovered and so far seems to be working well for me. I am authenticating the member via OAuth 2.0 prior to making this request, which will give me the authenticated members videos. As always, your personal mileage may vary :D
curl https://www.googleapis.com/youtube/v3/search -G \
-d part=snippet \
-d forMine=true \
-d type=video \
-d order=date \
-d access_token={AUTHENTICATED_ACCESS_TOKEN}
The equivalent of the request you posted is actually a search in the 3.0 api, not a playlist request. It's easier too to do it that way. You do need to excange the username for a channel ID though.
ex. GET https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=UUGhCVGZ0ZSpe5hJHWyiLwHA&key={YOUR_API_KEY}
Here is some code using the offical Google APIs Node library (https://github.com/google/google-api-nodejs-client)
const readJson = require("r-json");
const google = require('googleapis');
const Youtube = google.youtube('v3');
// DONT store your credentials in version control
const CREDENTIALS = readJson("/some/directory/credentials.json");
let user = "<youruser>";
let numberItems = 10;
let channelConfig = {
key: CREDENTIALS.youtube.API_KEY,
part: "contentDetails",
forUsername: user
};
Youtube.channels.list(channelConfig, function (error, data) {
if (error) {
console.log("Error fetching YouTube user video list", error);
return;
}
// Get the uploads playlist Id
let uploadsPlaylistId = data.items[0].contentDetails.relatedPlaylists.uploads;
let playlistConfig = {
part : 'snippet',
maxResults : size,
playlistId : uploadsPlaylistId,
key: CREDENTIALS.youtube.API_KEY
};
// Fetch items from upload playlist
Youtube.playlistItems.list(playlistConfig, function (error, data) {
if (error) {
console.log("Error fetching YouTube user video list", error);
}
doSomethingWithYourData(data.items);
});
});
An alternative method may be to get the playlists for the currently oauth authenticated user via: property mine=true
where the oauth access_token is retrieved following authentification:
https://developers.google.com/youtube/v3/guides/authentication
https://www.googleapis.com/youtube/v3/playlists?part=id&mine=true&access_token=ya29.0gC7xyzxyzxyz
Please don't use playlistitems.list if you want to get the videos of playlist with more then 300 videos. You can try it live in google link "https://developers.google.com/youtube/v3/docs/playlistItems/list" in "Try it" section. It returns undefined.
I have used in my project also. It returns undefined only.
In PHP:
I used pageToken attribute to go to all page of playlist.I hope it can help you.
//step 1: get playlist id
$response = file_get_contents("https://www.googleapis.com/youtube/v3/channels?key={$api_key}&forUsername={$channelName}&part=contentDetails");
$searchResponse = json_decode($response,true);
$data = $searchResponse['items'];
$pid = $data[0]['contentDetails']['relatedPlaylists']['uploads'];
//step 2: get all videos in playlist
$nextPageToken = '';
while(!is_null($nextPageToken)) {
$request = "https://www.googleapis.com/youtube/v3/playlistItems?key={$api_key}&playlistId={$pid}&part=snippet&maxResults=50&pageToken=$nextPageToken";
$response = file_get_contents($request);
$videos = json_decode($response,true);
//get info each video here...
//go next page
$nextPageToken = $videos['nextPageToken'];
}
In node.js, it can be achieved with following code.
Requires authKey and channelId as options object parameter.
cb callback is called after data is fetched.
async function fetchChannelInfo(options) {
const channelUrl = `https://www.googleapis.com/youtube/v3/channels?part=contentDetails,statistics&id=${
options.channelId
}&key=${options.authKey}`;
const channelData = await axios.get(channelUrl);
return channelData.data.items[0];
}
function fetch(options, cb) {
fetchChannelInfo(options).then((channelData) => {
options.playlistId = channelData.contentDetails.relatedPlaylists.uploads;
const paylistUrl = `https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=${
options.playlistId
}&key=${options.authKey}`;
axios
.get(paylistUrl)
.then((response) => {
const payloadData = ;
const videoList = [];
response.data.items.forEach((video) => {
videoList.push({
publishedAt: video.snippet.publishedAt,
title: video.snippet.title,
thumbnails: thumbnails,
videoId: video.snippet.resourceId.videoId,
});
});
cb(null, videoList);
})
.catch((err) => {
cb(err, null);
});
});
}
Note: axios is used for RESTful requests. To install
npm install axios
$.get(
"https://www.googleapis.com/youtube/v3/channels",{
part: 'snippet,contentDetails,statistics,brandingSettings',
id: viewid,
key: api},
function(data){
$.each(data.items, function(i, item){
channelId = item.id;
pvideo = item.contentDetails.relatedPlaylists.uploads;
uploads(pvideo);
});
});
Uploads Function can be
function uploads(pvideo){
$.get(
"https://www.googleapis.com/youtube/v3/playlistItems",{
part: 'snippet',
maxResults:12,
playlistId:pvideo,
key: api},
function(data){
$.each(data.items, function(i, item){
videoTitle = item.snippet.title;
videoId = item.id;
description = item.snippet.description;
thumb = item.snippet.thumbnails.high.url;
channelTitle = item.snippet.channelTitle;
videoDate = item.snippet.publishedAt;
Catagoryid = item.snippet.categoryId;
cID = item.snippet.channelId;
})
}
);
}
function tplawesome(e,t){res=e;for(var n=0;n<t.length;n++){res=res.replace(/\{\{(.*?)\}\}/g,function(e,r){return t[n][r]})}return res}
$(function() {
$(".form-control").click(function(e) {
e.preventDefault();
// prepare the request
var request = gapi.client.youtube.search.list({
part: "snippet",
type: "video",
q: encodeURIComponent($("#search").val()).replace(/%20/g, "+"),
maxResults: 20,
order: "viewCount",
publishedAfter: "2017-01-01T00:00:00Z"
});
// execute the request
request.execute(function(response) {
var results = response.result;
$("#results").html("");
$.each(results.items, function(index, item) {
$.get("tpl/item.html", function(data) {
$("#results").append(tplawesome(data, [{"title":item.snippet.title, "videoid":item.id.videoId ,"descrip":item.snippet.description ,"date":item.snippet.publishedAt ,"channel":item.snippet.channelTitle ,"kind":item.id.kind ,"lan":item.id.etag}]));
});
});
resetVideoHeight();
});
});
$(window).on("resize", resetVideoHeight);
});
function resetVideoHeight() {
$(".video").css("height", $("#results").width() * 9/16);
}
function init() {
gapi.client.setApiKey("YOUR API KEY .... USE YOUR KEY");
gapi.client.load("youtube", "v3", function() {
// yt api is ready
});
}
Check the Complete code here https://thecodingshow.blogspot.com/2018/12/youtube-search-api-website.html