Trying to follow this blog post Create a Smart Voicemail with Twilio, JavaScript and Google Calendar
When I run the code in Google Developer API Test Console, it works. However, the same parameters called within Twilio Function which runs NodeJS returns an error "ReferenceError: calendar is not defined"
I've made the Google Calendar events public and I've tried viewing it using the public URL and it works too. For someone reason calling it withing Twilio Functions is resulting in an error.
const moment = require('moment');
const { google } = require('googleapis');
exports.handler = function(context, event, callback) {
// Initialize Google Calendar API
const cal = google.calendar({
version: 'v3',
auth: context.GOOGLE_API_KEY
});
//Read Appointment Date
let apptDate = event.ValidateFieldAnswer;
var status = false;
const res = {
timeMin: moment().toISOString(),
timeMax: moment().add(10, 'minutes').toISOString(),
items: [{
id: context.GOOGLE_CALENDAR_ID
}]
};
console.log(res);
cal.freebusy.query({
resource: res
}).then((result) => {
const busy = result.data.calendars[calendar].busy;
console.log("Busy: " + busy);
if (busy.length !== 0) {
let respObj1 = {
"valid": false
};
console.log("Failed");
callback(null, respObj1);
} else {
let respObj1 = {
"valid": true
};
console.log("Success");
callback(null, respObj1);
}
}).catch(err => {
console.log('Error: checkBusy ' + err);
let respObj1 = {
"valid": false
};
callback(null, respObj1);
});
};
Have you encountered this before or is anyone able to identify the issue here?
Thanks
This line seems to be the issue:
const busy = result.data.calendars[calendar].busy;
As far as I can tell, calendar is never defined. This should work instead:
const busy = result.data.calendars[context.GOOGLE_CALENDAR_ID].busy;
It looks like this line of the code is different between the "Google Calendar FreeBusy Queries" and "Recording VoiceMails" sections of the tutorial and needs to be updated in the latter code sample.
I have a list of people (first and last name) who I want to follow, but I don't want to Google or search them via Twitter separately. What is the best way to get the Twitter handles? Some GitHub repos or tutorials are also fine.
Twitter offers a "User Search" API request.
If you want to search for a user named "Ada Lovelace" you will need to send an OAuth'd request to
https://api.twitter.com/1.1/users/search.json?q=Ada%20Lovelace
You will get back a list of results. There may be many people who share the same first and last name.
As for how to do it, that rather depends on the programming language you want to use.
If you just want a clickable link, use https://twitter.com/search?q=Terence%20Eden
So firstly this question is off-topic but I will try write an answer for you. You could use the twitter api for this but that might be a little overkill if you just want to do this for you.
I made you an API
I made an API just for you using KimonoLabs. You can use this and just make a script that loops through your list and requests this api every time, then return a list of the results. Here is the API endpoint:
https://www.kimonolabs.com/api/duwxgie4?apikey=D6UKiTtKU93kv0YJj8i3kFBAbsIjdSTC&q=PERSON%20NAME
The &q= is the paramater for the person's name. To seperate the first and last name use %20, like so: Robert%20Keus
The documentation for this api is here:
https://www.kimonolabs.com/apis/duwxgie4
Let me know if you need any help,
Luca
Latest answer # 2016
First Solution: I wrote following node.js script. You need access_token and id of pulicly published google doc spreadsheet. For testing purpose I have provided sample spreadsheet's link and its id in following code.
var Twit = require('twit'),
async = require('async');
var T = new Twit({
consumer_key: 'xxxxxxxx',
consumer_secret: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
access_token: 'xxxxxxxxxxx',
access_token_secret: 'xxxxxxxxxxxxxxxxxxxxxxxxx',
timeout_ms: 60*1000 // optional HTTP request timeout to apply to all requests.
});
//https://docs.google.com/spreadsheets/d/1n7DxgJTTHZ9w3xwiHokUhXMLkBwpP5c9ZLFmsYFDCic/edit?usp=sharing
var GoogleSpreadsheet = require("google-spreadsheet"),
_ = require('underscore');
var sheetId = req.params.sheet || "1n7DxgJTTHZ9w3xwiHokUhXMLkBwpP5c9ZLFmsYFDCic",
sheet = new GoogleSpreadsheet(sheetId);
async.waterfall([
function (cb) {
sheet.getRows(1, {}, function (err, rows) {
if (err) { res.send(err); return;};
var names = [];
_.each(rows, function (row) {
names.push(row.first + " " + row.last);
});
cb(null, names);
});
},
function (names, callback1) {
async.map(names, function(name, cb){
T.get('users/search', { q: name, page: 1 }, function (err, data, response) {
if(data.length)
cb(null, {screen_name: data[0].screen_name, name:data[0].name});
else
cb(null, {screen_name: "no_data_retrieved", name: name});
});
}, function (err, results) {
callback1(null, results);
});
},
function (users, callback) {
console.log(users); //**YOU GET ALL DESIRED DATA HERE**
}
], function (err, result) {
//handle in memory data
});
Second Solution: Clone node-cheat twitter-screen-names, run npm install and shoot node server, Now get all twitter usernames as json in browser.
Happy Helping!
I want to be able to detect if the currently authenticated user is subscribed to a specific YouTube channel in the YouTube API v3.
A possible solution would be to retrieve a list of all the subscriptions of the currently authenticated user and check if the channel ID of the channel is contained in that list. That would would be a very inefficient solution and could take a very long time if the user has hundreds of subscriptions.
Is there any easy method to check this? I looked through the entire API documentation and I couldn't find anything.
Use the subscriptions#list method and pass mine = true and the channel ID you want to check in forChannelId. If the authenticated user is not subscribed to that channel, it will return an empty list.
checkSubscribe (params) {
var request =
gapi.client.youtube.subscriptions.list(removeEmptyParams(params));
request.execute((response) => {
console.log(response);
if (response.code !== 401 && response.code !== 400 && response.items[0] ) {
console.log('response');
console.log(response);
}
});
}
removeEmptyParams(params)[![enter image description here][1]][1]{
for (const pra in params) {
if (!params[pra] || params[pra] === 'undefined') {
delete params[pra];
}
}
return params;
}
checkSubscribe(
{part: 'snippet, contentDetails', mine: true},
{'forChannelId':'PUT-YOUR-CHANEL--ID','onBehalfOfContentOwner': ''}
);
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
I know how to get the count of 'liked' videos using the YouTube API, but I want to get a list of those videos.
After reading the docs, I think it can be done by getting the 'liked' playlist, but I do not know exactly how.
Can I get the 'liked' video list through the Javascript API?
If you're using v3 of the API, then you can get your liked video list. First, do a call to your channels feed, like this:
https://www.googleapis.com/youtube/v3/channels?part=contentDetails&mine=true&key={YOUR_API_KEY}
Then, in the response, you'll have a list of related playlists -- one will be keyed "likes." Take that playlist ID and request its items feed:
https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId={PLAYLIST_ID}&key={YOUR_API_KEY}
If you don't use v3 of the API, you probably won't have a lot of success in getting the liked videos.
As of 2020, the /videos endpoint lets you filter directly for liked videos, e.g.:
GET https://www.googleapis.com/youtube/v3/videos?myRating=like&part=snippet
Authorization: Bearer <oauth token>
If you pass the following arguments to playlistItems.list, you can get the liked videos' playlist associated with the authorized acccount.
auth: "your_auth_key"
playlistId: "LL"
Here's a code snippet from the script I ran to get the liked videos in a text file.
Note: I used the helper code provided in the YouTube API Documentation to get the authkey and pass it to my function.
// get all the liked videos by a channel
async function get_liked_playlist(authkey){
fs.writeFile("./output/"+"all_liked_videos"+".txt", "\n"+time_stamp, { flag: 'a+' }, e => console.log(e) );
let nextPageToken_ = null;
let text__ = "";
let i = 0;
do {
await API.playlistItems.list({
key: process.env.API_KEY,
auth: authkey,
part: "snippet",
maxResults: 50, // 50 is the max value
playlistId: "LL",
pageToken: nextPageToken_
})
.then(res => {
let results = res.data.items;
nextPageToken_ = res.data.nextPageToken;
results.forEach(item => {
// console.log(`Title: ${item.snippet.title}\tURL: https://youtu.be/${item.snippet.resourceId.videoId}`)
i++;
text__ += "\nTitle: "+item.snippet.title+"\tURL: https://youtu.be/"+item.snippet.resourceId.videoId;
});
console.log("items done: "+i+"\tnextPageToken: "+nextPageToken_);
})
.then( fs.writeFile("./output/"+"all_liked_videos"+".txt", text__ , { flag: 'a+' }, e => { if(e) console.log("error with fs\t"+e); }) )
.then( text__ = "" )
.catch( e => console.log("error here\t" + e) )
} while (nextPageToken_ != null)
if(text__.length>1) fs.writeFile("./output/"+"all_liked_videos"+".txt", text__ , { flag: 'a+' }, e => { if(e) console.log("error with fs\t"+e); });
}