From c4fdc5e381df5be6a583c7f58feb5f78a58d384a Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Fri, 13 Dec 2013 12:32:56 -0800 Subject: [PATCH 001/244] "Added sample: php/upload_banner.php" --- php/upload_banner.php | 153 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 php/upload_banner.php diff --git a/php/upload_banner.php b/php/upload_banner.php new file mode 100644 index 00000000..d78ec9ce --- /dev/null +++ b/php/upload_banner.php @@ -0,0 +1,153 @@ + + * For more information about using OAuth 2.0 to access Google APIs, please see: + * + * Please ensure that you have enabled the YouTube Data API for your project. + */ +$OAUTH2_CLIENT_ID = 'REPLACE_ME'; +$OAUTH2_CLIENT_SECRET = 'REPLACE_ME'; + +$client = new Google_Client(); +$client->setClientId($OAUTH2_CLIENT_ID); +$client->setClientSecret($OAUTH2_CLIENT_SECRET); +$client->setScopes('https://www.googleapis.com/auth/youtube'); +$redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'], + FILTER_SANITIZE_URL); +$client->setRedirectUri($redirect); + +// Define an object that will be used to make all API requests. +$youtube = new Google_Service_YouTube($client); + +if (isset($_GET['code'])) { + if (strval($_SESSION['state']) !== strval($_GET['state'])) { + die('The session state did not match.'); + } + + $client->authenticate($_GET['code']); + $_SESSION['token'] = $client->getAccessToken(); + header('Location: ' . $redirect); +} + +if (isset($_SESSION['token'])) { + $client->setAccessToken($_SESSION['token']); +} + +// Check to ensure that the access token was successfully acquired. +if ($client->getAccessToken()) { + try{ + + // REPLACE with the path to your file that you want to upload for thumbnail + $imagePath = "/path/to/file.jpg"; + + // Specify the size of each chunk of data, in bytes. Set a higher value for + // reliable connection as fewer chunks lead to faster uploads. Set a lower + // value for better recovery on less reliable connections. + $chunkSizeBytes = 1 * 1024 * 1024; + + // Setting the defer flag to true tells the client to return a request which can be called + // with ->execute(); instead of making the API call immediately. + $client->setDefer(true); + + $chan = new Google_Service_YouTube_ChannelBannerResource(); + + // Create a request for the API's channelBanners.insert method to upload the banner. + $insertRequest = $youtube->channelBanners->insert($chan); + + // Create a MediaFileUpload object for resumable uploads. + $media = new Google_Http_MediaFileUpload( + $client, + $insertRequest, + 'image/jpeg', + null, + true, + $chunkSizeBytes + ); + $media->setFileSize(filesize($imagePath)); + + + // Read the media file and upload it chunk by chunk. + $status = false; + $handle = fopen($videoPath, "rb"); + while (!$status && !feof($handle)) { + $chunk = fread($handle, $chunkSizeBytes); + $status = $media->nextChunk($chunk); + } + + fclose($handle); + + // If you want to make other calls after the file upload, set setDefer back to false + $client->setDefer(false); + + $thumbnailUrl = $status['url']; + + // Call the API's channels.list method with mine parameter to fetch authorized user's channel. + $listResponse = $youtube->channels->listChannels('brandingSettings', array( + 'mine' => 'true', + )); + + $responseChannel = $listResponse[0]; + $responseChannel['brandingSettings']['image']['bannerExternalUrl']=$thumbnailUrl; + + // Call the API's channels.update method to update branding settings of the channel. + $updateResponse = $youtube->channels->update('brandingSettings', $responseChannel); + + $bannerMobileUrl = $updateResponse["brandingSettings"]["image"]["bannerMobileImageUrl"]; + + $htmlBody .= "

Thumbnail Uploaded

'; + + } catch (Google_ServiceException $e) { + $htmlBody .= sprintf('

A service error occurred: %s

', + htmlspecialchars($e->getMessage())); + } catch (Google_Exception $e) { + $htmlBody .= sprintf('

An client error occurred: %s

', + htmlspecialchars($e->getMessage())); + } + + $_SESSION['token'] = $client->getAccessToken(); + } else { + // If the user hasn't authorized the app, initiate the OAuth flow + $state = mt_rand(); + $client->setState($state); + $_SESSION['state'] = $state; + + $authUrl = $client->createAuthUrl(); + $htmlBody = <<Authorization Required +

You need to authorize access before proceeding.

+END; + } + ?> + + + + + Banner Uploaded and Set + + + + + From 15f7e0eae39f7ce4144008845a8eed78a6fefce4 Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Fri, 13 Dec 2013 12:33:37 -0800 Subject: [PATCH 002/244] "Updating samples to reflect recent changes." --- php/upload_thumbnail.php | 44 +++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/php/upload_thumbnail.php b/php/upload_thumbnail.php index a97dbf58..b9ed407b 100644 --- a/php/upload_thumbnail.php +++ b/php/upload_thumbnail.php @@ -12,8 +12,8 @@ // Call set_include_path() as needed to point to your client library. -require_once 'Google_Client.php'; -require_once 'contrib/Google_YouTubeService.php'; +require_once 'Google/Client.php'; +require_once 'Google/Service/YouTube.php'; session_start(); /* @@ -29,19 +29,20 @@ $client = new Google_Client(); $client->setClientId($OAUTH2_CLIENT_ID); $client->setClientSecret($OAUTH2_CLIENT_SECRET); +$client->setScopes('https://www.googleapis.com/auth/youtube'); $redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'], FILTER_SANITIZE_URL); $client->setRedirectUri($redirect); // Define an object that will be used to make all API requests. -$youtube = new Google_YoutubeService($client); +$youtube = new Google_Service_YouTube($client); if (isset($_GET['code'])) { if (strval($_SESSION['state']) !== strval($_GET['state'])) { die('The session state did not match.'); } - $client->authenticate(); + $client->authenticate($_GET['code']); $_SESSION['token'] = $client->getAccessToken(); header('Location: ' . $redirect); } @@ -65,26 +66,41 @@ // value for better recovery on less reliable connections. $chunkSizeBytes = 1 * 1024 * 1024; - // Create a MediaFileUpload object for resumable uploads. - $media = new Google_MediaFileUpload('image/png', null, true, $chunkSizeBytes); - $media->setFileSize(filesize($imagePath)); + // Setting the defer flag to true tells the client to return a request which can be called + // with ->execute(); instead of making the API call immediately. + $client->setDefer(true); - // Call the API's thumbnails.set method to upload the image and associate + // Create a request for the API's thumbnails.set method to upload the image and associate // it with the appropriate video. - $setResponse = $youtube->thumbnails->set($videoId, array('mediaUpload' => $media)); + $setRequest = $youtube->thumbnails->set($videoId); - $uploadStatus = false; + // Create a MediaFileUpload object for resumable uploads. + $media = new Google_Http_MediaFileUpload( + $client, + $setRequest, + 'image/png', + null, + true, + $chunkSizeBytes + ); + $media->setFileSize(filesize($imagePath)); - // Read the image file and upload it chunk by chunk. + + // Read the media file and upload it chunk by chunk. + $status = false; $handle = fopen($imagePath, "rb"); - while (!$uploadStatus && !feof($handle)) { + while (!$status && !feof($handle)) { $chunk = fread($handle, $chunkSizeBytes); - $uploadStatus = $media->nextChunk($setResponse, $chunk); + $status = $media->nextChunk($chunk); } fclose($handle); - $thumbnailUrl = $uploadStatus['items'][0]['default']['url']; + // If you want to make other calls after the file upload, set setDefer back to false + $client->setDefer(false); + + + $thumbnailUrl = $status['items'][0]['default']['url']; $htmlBody .= "

Thumbnail Uploaded

    "; $htmlBody .= sprintf('
  • %s (%s)
  • ', $videoId, From dc1e94b0e1f66b040207d853972b1eca333d2bc8 Mon Sep 17 00:00:00 2001 From: Samuel Teixeira Date: Tue, 27 May 2014 13:37:26 -0300 Subject: [PATCH 003/244] Update analytics_codelab.html Rename reference for css and js file --- javascript/analytics_codelab.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/analytics_codelab.html b/javascript/analytics_codelab.html index 7ebfa868..496aba44 100644 --- a/javascript/analytics_codelab.html +++ b/javascript/analytics_codelab.html @@ -2,10 +2,10 @@ Google I/O YouTube Codelab - + - + From 953ac20133afa7e4e210cd10547ef11494bad8e6 Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:08 -0400 Subject: [PATCH 004/244] "Updating samples to reflect recent changes." --- java/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/README b/java/README index c40cf499..b71843bc 100644 --- a/java/README +++ b/java/README @@ -13,7 +13,7 @@ To build this code sample from the command line, type: To run the code sample from the command line, enter the following: - mvn exec:java + mvn exec:java -Dexec.mainClass="FULL_CLASS_NAME" For more instructions about how to set up Maven and/or your IDE to run YouTube API samples, see this video: From b30a0cb829a2d6ca66fc2a6a3e47ec5db621984a Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:08 -0400 Subject: [PATCH 005/244] "Added sample: python/geolocation_search.py" --- python/geolocation_search.py | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 python/geolocation_search.py diff --git a/python/geolocation_search.py b/python/geolocation_search.py new file mode 100644 index 00000000..c051943d --- /dev/null +++ b/python/geolocation_search.py @@ -0,0 +1,66 @@ +#!/usr/bin/python + +from apiclient.discovery import build +from apiclient.errors import HttpError +from oauth2client.tools import argparser + + +# Set DEVELOPER_KEY to the API key value from the APIs & auth > Registered apps +# tab of +# https://cloud.google.com/console +# Please ensure that you have enabled the YouTube Data API for your project. +DEVELOPER_KEY = "REPLACE_ME" +YOUTUBE_API_SERVICE_NAME = "youtube" +YOUTUBE_API_VERSION = "v3" + +def youtube_search(options): + youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, + developerKey=DEVELOPER_KEY) + + # Call the search.list method to retrieve results matching the specified + # query term. + search_response = youtube.search().list( + q=options.q, + type="video", + location=options.location, + locationRadius=options.location_radius, + part="id,snippet", + maxResults=options.max_results + ).execute() + + search_videos = [] + + # Merge video ids + for search_result in search_response.get("items", []): + search_videos.append(search_result["id"]["videoId"]) + video_ids = ",".join(search_videos) + + # Call the videos.list method to retrieve location details for each video. + video_response = youtube.videos().list( + id=video_ids, + part='snippet, recordingDetails' + ).execute() + + videos = [] + + # Add each result to the list, and then display the list of matching videos. + for video_result in video_response.get("items", []): + videos.append("%s, (%s,%s)" % (video_result["snippet"]["title"], + video_result["recordingDetails"]["location"]["latitude"], + video_result["recordingDetails"]["location"]["longitude"])) + + print "Videos:\n", "\n".join(videos), "\n" + + +if __name__ == "__main__": + argparser.add_argument("--q", help="Search term", default="Google") + argparser.add_argument("--location", help="Location", default="37.42307,-122.08427") + argparser.add_argument("--location-radius", help="Location radius", default="5km") + argparser.add_argument("--max-results", help="Max results", default=25) + args = argparser.parse_args() + + try: + youtube_search(args) + except HttpError, e: + print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content) + From ff587d01a722e9b6b3c612e3ee3c20f570f8348e Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:09 -0400 Subject: [PATCH 006/244] "Updating samples to reflect recent changes." --- go/upload_video.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/upload_video.go b/go/upload_video.go index 04d3ed5f..fc0ce1bc 100644 --- a/go/upload_video.go +++ b/go/upload_video.go @@ -45,7 +45,7 @@ func main() { Status: &youtube.VideoStatus{PrivacyStatus: *privacy}, } - // The API returns a 400 Bad Request response if tags is an empty string. + // If tags is an empty string, this will cause the API to return a 400 Bad Request if strings.Trim(*keywords, "") != "" { upload.Snippet.Tags = strings.Split(*keywords, ",") } From 0aaede47366dcbbe2812a9d1325d10962735b60d Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:10 -0400 Subject: [PATCH 007/244] "Updating samples to reflect recent changes." --- go/post_bulletin.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/go/post_bulletin.go b/go/post_bulletin.go index e76d06c7..291afdd9 100644 --- a/go/post_bulletin.go +++ b/go/post_bulletin.go @@ -17,9 +17,9 @@ var ( func main() { flag.Parse() - // A bulletin must contain a message and may also contain a video or a - // playlist. You can post a message with or without an accompanying video - // or playlist, but you can't post a video and playlist at the same time. + // A bulletin needs to contain a message and either a video or playlist. + // You can post a message with or without an accompanying video or playlist. + // You can't post both a video and playlist at the same time. if *message == "" { log.Fatalf("Please provide a message.") } @@ -38,7 +38,7 @@ func main() { log.Fatalf("Error creating YouTube client: %v", err) } - // Start making YouTube API calls. + // Starting making YouTube API calls parts := "snippet" bulletin := &youtube.Activity{ Snippet: &youtube.ActivitySnippet{ @@ -49,7 +49,7 @@ func main() { if *videoID != "" || *playlistID != "" { parts = "snippet,contentDetails" - // The resource ID element value differs depending on + // The resource ID element will be different depending on // whether a playlist or a video is being posted. var resourceId *youtube.ResourceId switch { From 95602f2920bf46a5c3ded1851e82e77e6ddc56ff Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:10 -0400 Subject: [PATCH 008/244] "Updating samples to reflect recent changes." --- go/oauth.go | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/go/oauth.go b/go/oauth.go index 58ff987b..f4d2dda7 100644 --- a/go/oauth.go +++ b/go/oauth.go @@ -19,13 +19,13 @@ import ( const missingClientSecretsMessage = ` Please configure OAuth 2.0 -To make this sample run, you need to populate the client_secrets.json file +To make this sample run you will need to populate the client_secrets.json file found at: %v -with information from the {{ Google Cloud Console }} -{{ https://cloud.google.com/console }} +with information from the APIs Console +https://code.google.com/apis/console#access For more information about the client_secrets.json file format, please visit: https://developers.google.com/api-client-library/python/guide/aaa_client_secrets @@ -36,8 +36,8 @@ var ( cacheFile = flag.String("cache", "request.token", "Token cache file") ) -// ClientConfig is a data structure definition for the client_secrets.json file. -// The code unmarshals the JSON configuration file into this structure. +// ClientConfig is data structure definition for client_secrets.json. +// This is what we'll unmarshal the JSON configuration file into. type ClientConfig struct { ClientID string `json:"client_id"` ClientSecret string `json:"client_secret"` @@ -46,14 +46,14 @@ type ClientConfig struct { TokenURI string `json:"token_uri"` } -// Config is a root-level configuration object. +// Config is root level configuration object. type Config struct { Installed ClientConfig `json:"installed"` Web ClientConfig `json:"web"` } -// openURL opens a browser window to the specified location. -// This code originally appeared at: +// openURL opens a browser window to that location. +// This code taken from: // http://stackoverflow.com/questions/10377243/how-can-i-launch-a-process-that-is-not-a-file-in-go func openURL(url string) error { var err error @@ -71,7 +71,7 @@ func openURL(url string) error { } // readConfig reads the configuration from clientSecretsFile. -// It returns an oauth configuration object for use with the Google API client. +// Returns an oauth configuration object to be used with the Google API client func readConfig(scope string) (*oauth.Config, error) { // Read the secrets file data, err := ioutil.ReadFile(*clientSecretsFile) @@ -104,16 +104,16 @@ func readConfig(scope string) (*oauth.Config, error) { TokenURL: cfg.Installed.TokenURI, RedirectURL: redirectUri, TokenCache: oauth.CacheFile(*cacheFile), - // Get a refresh token so we can use the access token indefinitely + // This gives us a refresh token so we can use this access token indefinitely AccessType: "offline", - // If we want a refresh token, we must set this attribute - // to force an approval prompt or the code won't work. + // If we want a refresh token, we must set this to force an approval prompt or + // this won't work ApprovalPrompt: "force", }, nil } // startWebServer starts a web server that listens on http://localhost:8080. -// The webserver waits for an oauth code in the three-legged auth flow. +// The purpose of this webserver is to wait for a oauth code in the three-legged auth flow. func startWebServer() (codeCh chan string, err error) { listener, err := net.Listen("tcp", "localhost:8080") if err != nil { @@ -132,10 +132,9 @@ func startWebServer() (codeCh chan string, err error) { } // buildOAuthHTTPClient takes the user through the three-legged OAuth flow. -// It opens a browser in the native OS or outputs a URL, then blocks until -// the redirect completes to the /oauth2callback URI. -// It returns an instance of an HTTP client that can be passed to the -// constructor of the YouTube client. +// Opens a browser in the native OS or outputs a URL, blocking until the redirect +// completes to the /oauth2callback URI. Returns an instance of an HTTP client +// that can be passed to the constructor of the YouTube client. func buildOAuthHTTPClient(scope string) (*http.Client, error) { config, err := readConfig(scope) if err != nil { @@ -146,13 +145,11 @@ func buildOAuthHTTPClient(scope string) (*http.Client, error) { transport := &oauth.Transport{Config: config} // Try to read the token from the cache file. - // If an error occurs, do the three-legged OAuth flow because - // the token is invalid or doesn't exist. + // If there's an error, the token is invalid or doesn't exist, do the 3-legged OAuth flow. token, err := config.TokenCache.Token() if err != nil { // Start web server. - // This is how this program receives the authorization code - // when the browser redirects. + // This is how this program receives the authorization code when the browser redirects. codeCh, err := startWebServer() if err != nil { return nil, err @@ -173,9 +170,8 @@ func buildOAuthHTTPClient(scope string) (*http.Client, error) { // Wait for the web server to get the code. code := <-codeCh - // This code caches the authorization code on the local - // filesystem, if necessary, as long as the TokenCache - // attribute in the config is set. + // This will take care of caching the code on the local filesystem, if necessary, + // as long as the TokenCache attribute in the config is set token, err = transport.Exchange(code) if err != nil { return nil, err From 2199c774ccec71058445e92d985ecbf964b1e832 Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:12 -0400 Subject: [PATCH 009/244] "Updating samples to reflect recent changes." --- go/post_bulletin.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/go/post_bulletin.go b/go/post_bulletin.go index 291afdd9..e76d06c7 100644 --- a/go/post_bulletin.go +++ b/go/post_bulletin.go @@ -17,9 +17,9 @@ var ( func main() { flag.Parse() - // A bulletin needs to contain a message and either a video or playlist. - // You can post a message with or without an accompanying video or playlist. - // You can't post both a video and playlist at the same time. + // A bulletin must contain a message and may also contain a video or a + // playlist. You can post a message with or without an accompanying video + // or playlist, but you can't post a video and playlist at the same time. if *message == "" { log.Fatalf("Please provide a message.") } @@ -38,7 +38,7 @@ func main() { log.Fatalf("Error creating YouTube client: %v", err) } - // Starting making YouTube API calls + // Start making YouTube API calls. parts := "snippet" bulletin := &youtube.Activity{ Snippet: &youtube.ActivitySnippet{ @@ -49,7 +49,7 @@ func main() { if *videoID != "" || *playlistID != "" { parts = "snippet,contentDetails" - // The resource ID element will be different depending on + // The resource ID element value differs depending on // whether a playlist or a video is being posted. var resourceId *youtube.ResourceId switch { From 4def5de33f5e811e40c71ec5e5635e13a637de4c Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:12 -0400 Subject: [PATCH 010/244] "Added sample: php/geolocation_search.php" --- php/geolocation_search.php | 108 +++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 php/geolocation_search.php diff --git a/php/geolocation_search.php b/php/geolocation_search.php new file mode 100644 index 00000000..5ce52127 --- /dev/null +++ b/php/geolocation_search.php @@ -0,0 +1,108 @@ + +
    + Search Term: +
    +
    + Location: +
    +
    + Location Radius: +
    +
    + Max Results: +
    + + +END; + +// This code executes if the user enters a search query in the form +// and submits the form. Otherwise, the page displays the form above. +if ($_GET['q'] && $_GET['maxResults']) { + // Call set_include_path() as needed to point to your client library. + require_once 'Google/Client.php'; + require_once 'Google/Service/YouTube.php'; + + /* + * Set $DEVELOPER_KEY to the "API key" value from the "Access" tab of the + * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}> + * Please ensure that you have enabled the YouTube Data API for your project. + */ + $DEVELOPER_KEY = 'REPLACE_ME'; + + $client = new Google_Client(); + $client->setDeveloperKey($DEVELOPER_KEY); + + // Define an object that will be used to make all API requests. + $youtube = new Google_Service_YouTube($client); + + try { + // Call the search.list method to retrieve results matching the specified + // query term. + $searchResponse = $youtube->search->listSearch('id,snippet', array( + 'type' => 'video', + 'q' => $_GET['q'], + 'location' => $_GET['location'], + 'locationRadius' => $_GET['locationRadius'], + 'maxResults' => $_GET['maxResults'], + )); + + $videoResults = array(); + # Merge video ids + foreach ($searchResponse['items'] as $searchResult) { + array_push($videoResults, $searchResult['id']['videoId']); + } + $videoIds = join(',', $videoResults); + + # Call the videos.list method to retrieve location details for each video. + $videosResponse = $youtube->videos->listVideos('snippet, recordingDetails', array( + 'id' => $videoIds, + )); + + $videos = ''; + + // Display the list of matching videos. + foreach ($videosResponse['items'] as $videoResult) { + $videos .= sprintf('
  • %s (%s,%s)
  • ', + $videoResult['snippet']['title'], + $videoResult['recordingDetails']['location']['latitude'], + $videoResult['recordingDetails']['location']['longitude']); + } + + $htmlBody .= <<Videos +
      $videos
    +END; + } catch (Google_ServiceException $e) { + $htmlBody .= sprintf('

    A service error occurred: %s

    ', + htmlspecialchars($e->getMessage())); + } catch (Google_Exception $e) { + $htmlBody .= sprintf('

    An client error occurred: %s

    ', + htmlspecialchars($e->getMessage())); + } +} +?> + + + + +YouTube Geolocation Search + + + + + From 3300bddd3090f4d3e3d2ce86eb504ceec4233bda Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:13 -0400 Subject: [PATCH 011/244] "Updating samples to reflect recent changes." --- go/search_by_keyword.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/go/search_by_keyword.go b/go/search_by_keyword.go index 38fa7fb6..4ecd8629 100644 --- a/go/search_by_keyword.go +++ b/go/search_by_keyword.go @@ -29,7 +29,7 @@ func main() { log.Fatalf("Error creating new YouTube client: %v", err) } - // Make the API call to YouTube. + // Make the API call to YouTube call := service.Search.List("id,snippet"). Q(*query). MaxResults(*maxResults) @@ -38,12 +38,11 @@ func main() { log.Fatalf("Error making search API call: %v", err) } - // Group video, channel, and playlist results in separate lists. videos := make(map[string]string) channels := make(map[string]string) playlists := make(map[string]string) - // Iterate through each item and add it to the correct list. + // Iterate through each item and add it to its respective list for _, item := range response.Items { switch item.Id.Kind { case "youtube#video": @@ -60,10 +59,8 @@ func main() { printIDs("Playlists", playlists) } -// Print the ID and title of each result in a list as well as a name that -// identifies the list. For example, print the word section name "Videos" -// above a list of video search results, followed by the video ID and title -// of each matching video. +// Given a string section name and list, prints the section name +// and IDs separated by commas func printIDs(sectionName string, matches map[string]string) { fmt.Printf("%v:\n", sectionName) for id, title := range matches { From 05e8907021bcacd2defd18290e5de90737179121 Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:13 -0400 Subject: [PATCH 012/244] "Updating samples to reflect recent changes." --- go/search_by_topic.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/go/search_by_topic.go b/go/search_by_topic.go index f5be7151..50d9dc6a 100644 --- a/go/search_by_topic.go +++ b/go/search_by_topic.go @@ -40,7 +40,7 @@ type FreebaseTopic struct { Score float64 } -// FreebaseResponse is struct for unmarshalling JSON values from the Freebase API. +// FreebaseResponse is struct for unmarshalling JSON values from the freebase API. type FreebaseResponse struct { Status string Result []FreebaseTopic @@ -60,9 +60,9 @@ func main() { } } -// getTopicID queries Freebase with the given string. It then prompts the user -// to select a topic, then returns the selected topic so that the topic can be -// used to search YouTube for videos, channels or playlists. +// getTopicID queries Freebase with the given string. Prompts user +// to select a topic, then returns to search YouTube for videos, +// channels or playlists with the given topic. func getTopicID(topic string) (string, error) { urlParams := url.Values{ "query": []string{topic}, @@ -95,7 +95,7 @@ func getTopicID(topic string) (string, error) { return "", errors.New("No matching terms were found in Freebase.") } - // Print a list of topics for the user to select. + // Print a list of topics for the user to select fmt.Println("The following topics were found:") for index, topic := range data.Result { if topic.Notable.Name == "" { @@ -114,8 +114,8 @@ func getTopicID(topic string) (string, error) { return choice.Mid, nil } -// readInt reads an integer from standard input and verifies that the value -// is between the allowed min and max values (inclusive). +// readInt reads an integer from standard input, validating that the input is equal to or +// greater than the min, while being equal to or lesser than the max value. func readInt(prompt string, min int, max int) (int, error) { // Loop until we have a valid input. for { @@ -133,9 +133,8 @@ func readInt(prompt string, min int, max int) (int, error) { } } -// youtubeSearch searches YouTube for the topic given in the query flag and -// prints the results. This function takes a mid parameter, which specifies -// a value retrieved using the Freebase API. +// youtubeSearch searches YouTube for the topic given in the query flag and prints the results. +// Takes a mid parameter as supplied by Freebase. func youtubeSearch(mid string) error { client := &http.Client{ Transport: &transport.APIKey{Key: developerKey}, @@ -146,7 +145,7 @@ func youtubeSearch(mid string) error { return err } - // Make the API call to YouTube. + // Make the API call to YouTube call := service.Search.List("id,snippet"). TopicId(mid). Type(*resultType). @@ -156,7 +155,7 @@ func youtubeSearch(mid string) error { return err } - // Iterate through each item and output it. + // Iterate through each item and output it for _, item := range response.Items { itemID := "" switch item.Id.Kind { From 104c2fe6d5f09ccb3a68cbda86aa12d48ff9abd2 Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:14 -0400 Subject: [PATCH 013/244] "Updating samples to reflect recent changes." --- go/my_uploads.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/go/my_uploads.go b/go/my_uploads.go index 39849aa5..cdddbf87 100644 --- a/go/my_uploads.go +++ b/go/my_uploads.go @@ -21,20 +21,28 @@ func main() { log.Fatalf("Error creating YouTube client: %v", err) } - // Starting making YouTube API calls + // Start making YouTube API calls. + // Call the channels.list method. Set the mine parameter to true to + // retrieve the playlist ID for uploads to the authenticated user's + // channel. call := service.Channels.List("contentDetails").Mine(true) response, err := call.Do() if err != nil { + // The channels.list method call returned an error. log.Fatalf("Error making API call to list channels: %v", err.Error()) } for _, channel := range response.Items { playlistId := channel.ContentDetails.RelatedPlaylists.Uploads + // Print the playlist ID for the list of uploaded videos. fmt.Printf("Videos in list %s\r\n", playlistId) nextPageToken := "" for { + // Call the playlistItems.list method to retrieve the + // list of uploaded videos. Each request retrieves 50 + // videos until all videos have been retrieved. playlistCall := service.PlaylistItems.List("snippet"). PlaylistId(playlistId). MaxResults(50). @@ -43,6 +51,7 @@ func main() { playlistResponse, err := playlistCall.Do() if err != nil { + // The playlistItems.list method call returned an error. log.Fatalf("Error fetching playlist items: %v", err.Error()) } @@ -52,6 +61,8 @@ func main() { fmt.Printf("%v, (%v)\r\n", title, videoId) } + // Set the token to retrieve the next page of results + // or exit the loop if all results have been retrieved. nextPageToken = playlistResponse.NextPageToken if nextPageToken == "" { break From 294e20fdc3ba31ed431502da5864ae1ddab053e4 Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:14 -0400 Subject: [PATCH 014/244] "Added sample: python/unset_watermark.py" --- python/unset_watermark.py | 88 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 python/unset_watermark.py diff --git a/python/unset_watermark.py b/python/unset_watermark.py new file mode 100644 index 00000000..5179a86b --- /dev/null +++ b/python/unset_watermark.py @@ -0,0 +1,88 @@ +#!/usr/bin/python + +# Usage example: +# python unset_watermark.py --channelId='' --unset + +import json +import os +import sys +import httplib2 + +from apiclient.discovery import build +from apiclient.errors import HttpError +from oauth2client.file import Storage +from oauth2client.client import flow_from_clientsecrets +from oauth2client.tools import run +from optparse import OptionParser + + +# CLIENT_SECRETS_FILE, name of a file containing the OAuth 2.0 information for +# this application, including client_id and client_secret. You can acquire an +# ID/secret pair from the API Access tab on the Google APIs Console +# http://code.google.com/apis/console#access +# For more information about using OAuth2 to access Google APIs, please visit: +# https://developers.google.com/accounts/docs/OAuth2 +# For more information about the client_secrets.json file format, please visit: +# https://developers.google.com/api-client-library/python/guide/aaa_client_secrets +# Please ensure that you have enabled the YouTube Data API for your project. +CLIENT_SECRETS_FILE = "client_secrets.json" + +# An OAuth 2 access scope that allows for full read/write access. +YOUTUBE_READ_WRITE_SCOPE = "https://www.googleapis.com/auth/youtube" +YOUTUBE_API_SERVICE_NAME = "youtube" +YOUTUBE_API_VERSION = "v3" + +# Helpful message to display if the CLIENT_SECRETS_FILE is missing. +MISSING_CLIENT_SECRETS_MESSAGE = """ +WARNING: Please configure OAuth 2.0 + +To make this sample run you will need to populate the client_secrets.json file +found at: + %s +with information from the APIs Console +https://developers.google.com/console + +For more information about the client_secrets.json file format, please visit: +https://developers.google.com/api-client-library/python/guide/aaa_client_secrets +""" % os.path.abspath(os.path.join(os.path.dirname(__file__), + CLIENT_SECRETS_FILE)) + +# Authorize the request and store authorization credentials. +def get_authenticated_service(): + flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, + scope=YOUTUBE_READ_WRITE_SCOPE, + message=MISSING_CLIENT_SECRETS_MESSAGE) + + storage = Storage("%s-oauth2.json" % sys.argv[0]) + credentials = storage.get() + + if credentials is None or credentials.invalid: + credentials = run(flow, storage) + + return build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, + http=credentials.authorize(httplib2.Http())) + + +# Call the API's watermarks.unset method to remove the watermark image. +def unset_watermark(youtube, channel_id): + try: + youtube.watermarks().unset(channelId=channel_id).execute() + except HttpError as e: + print "Error while unsetting watermark: %s" % e.content + raise e + + +if __name__ == "__main__": + parser = OptionParser() + parser.add_option("--channelid", dest="channelid", + help="Required; id of channel whose watermark you're updating.") + (options, args) = parser.parse_args() + + if not options.channelid: + parser.print_help() + exit() + + youtube = get_authenticated_service() + + unset_watermark(youtube, options.channelid) + print "The watermark was successfully unset." From 3d4bbb5403efaa44b1be05610383fba0a793623d Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:16 -0400 Subject: [PATCH 015/244] "Updating samples to reflect recent changes." --- go/search_by_topic.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/go/search_by_topic.go b/go/search_by_topic.go index 50d9dc6a..f5be7151 100644 --- a/go/search_by_topic.go +++ b/go/search_by_topic.go @@ -40,7 +40,7 @@ type FreebaseTopic struct { Score float64 } -// FreebaseResponse is struct for unmarshalling JSON values from the freebase API. +// FreebaseResponse is struct for unmarshalling JSON values from the Freebase API. type FreebaseResponse struct { Status string Result []FreebaseTopic @@ -60,9 +60,9 @@ func main() { } } -// getTopicID queries Freebase with the given string. Prompts user -// to select a topic, then returns to search YouTube for videos, -// channels or playlists with the given topic. +// getTopicID queries Freebase with the given string. It then prompts the user +// to select a topic, then returns the selected topic so that the topic can be +// used to search YouTube for videos, channels or playlists. func getTopicID(topic string) (string, error) { urlParams := url.Values{ "query": []string{topic}, @@ -95,7 +95,7 @@ func getTopicID(topic string) (string, error) { return "", errors.New("No matching terms were found in Freebase.") } - // Print a list of topics for the user to select + // Print a list of topics for the user to select. fmt.Println("The following topics were found:") for index, topic := range data.Result { if topic.Notable.Name == "" { @@ -114,8 +114,8 @@ func getTopicID(topic string) (string, error) { return choice.Mid, nil } -// readInt reads an integer from standard input, validating that the input is equal to or -// greater than the min, while being equal to or lesser than the max value. +// readInt reads an integer from standard input and verifies that the value +// is between the allowed min and max values (inclusive). func readInt(prompt string, min int, max int) (int, error) { // Loop until we have a valid input. for { @@ -133,8 +133,9 @@ func readInt(prompt string, min int, max int) (int, error) { } } -// youtubeSearch searches YouTube for the topic given in the query flag and prints the results. -// Takes a mid parameter as supplied by Freebase. +// youtubeSearch searches YouTube for the topic given in the query flag and +// prints the results. This function takes a mid parameter, which specifies +// a value retrieved using the Freebase API. func youtubeSearch(mid string) error { client := &http.Client{ Transport: &transport.APIKey{Key: developerKey}, @@ -145,7 +146,7 @@ func youtubeSearch(mid string) error { return err } - // Make the API call to YouTube + // Make the API call to YouTube. call := service.Search.List("id,snippet"). TopicId(mid). Type(*resultType). @@ -155,7 +156,7 @@ func youtubeSearch(mid string) error { return err } - // Iterate through each item and output it + // Iterate through each item and output it. for _, item := range response.Items { itemID := "" switch item.Id.Kind { From 452ada396e3c6f17a5f6f995deba1c2c236e0974 Mon Sep 17 00:00:00 2001 From: Ibrahim Ulukaya Date: Thu, 5 Jun 2014 15:26:17 -0400 Subject: [PATCH 016/244] "Added sample: java/src/main/java/com/google/api/services/samples/youtube/cmdline/data/GeolocationSearch.java" --- .../cmdline/data/GeolocationSearch.java | 248 ++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 java/src/main/java/com/google/api/services/samples/youtube/cmdline/data/GeolocationSearch.java diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/data/GeolocationSearch.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/data/GeolocationSearch.java new file mode 100644 index 00000000..d063073b --- /dev/null +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/data/GeolocationSearch.java @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2014 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.api.services.samples.youtube.cmdline.data; + +import com.google.api.client.googleapis.json.GoogleJsonResponseException; +import com.google.api.client.http.HttpRequest; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.util.Joiner; +import com.google.api.services.samples.youtube.cmdline.Auth; +import com.google.api.services.youtube.YouTube; +import com.google.api.services.youtube.model.GeoPoint; +import com.google.api.services.youtube.model.SearchListResponse; +import com.google.api.services.youtube.model.SearchResult; +import com.google.api.services.youtube.model.Thumbnail; +import com.google.api.services.youtube.model.Video; +import com.google.api.services.youtube.model.VideoListResponse; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; + +/** + * This sample lists videos that are associated with a particular keyword and are in the radius of + * particular geographic coordinates by: + * + * 1. Searching videos with "youtube.search.list" method and setting "type", "q", "location" and + * "locationRadius" parameters. + * 2. Retrieving location details for each video with "youtube.videos.list" method and setting + * "id" parameter to comma separated list of video IDs in search result. + * + * @author Ibrahim Ulukaya + */ +public class GeolocationSearch { + + /** + * Define a global variable that identifies the name of a file that + * contains the developer's API key. + */ + private static final String PROPERTIES_FILENAME = "youtube.properties"; + + private static final long NUMBER_OF_VIDEOS_RETURNED = 25; + + /** + * Define a global instance of a Youtube object, which will be used + * to make YouTube Data API requests. + */ + private static YouTube youtube; + + /** + * Initialize a YouTube object to search for videos on YouTube. Then + * display the name and thumbnail image of each video in the result set. + * + * @param args command line args. + */ + public static void main(String[] args) { + // Read the developer key from the properties file. + Properties properties = new Properties(); + try { + InputStream in = GeolocationSearch.class.getResourceAsStream("/" + PROPERTIES_FILENAME); + properties.load(in); + + } catch (IOException e) { + System.err.println("There was an error reading " + PROPERTIES_FILENAME + ": " + e.getCause() + + " : " + e.getMessage()); + System.exit(1); + } + + try { + // This object is used to make YouTube Data API requests. The last + // argument is required, but since we don't need anything + // initialized when the HttpRequest is initialized, we override + // the interface and provide a no-op function. + youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, new HttpRequestInitializer() { + @Override + public void initialize(HttpRequest request) throws IOException { + } + }).setApplicationName("youtube-cmdline-geolocationsearch-sample").build(); + + // Prompt the user to enter a query term. + String queryTerm = getInputQuery(); + + // Prompt the user to enter location coordinates. + String location = getInputLocation(); + + // Prompt the user to enter a location radius. + String locationRadius = getInputLocationRadius(); + + // Define the API request for retrieving search results. + YouTube.Search.List search = youtube.search().list("id,snippet"); + + // Set your developer key from the {{ Google Cloud Console }} for + // non-authenticated requests. See: + // {{ https://cloud.google.com/console }} + String apiKey = properties.getProperty("youtube.apikey"); + search.setKey(apiKey); + search.setQ(queryTerm); + search.setLocation(location); + search.setLocationRadius(locationRadius); + + // Restrict the search results to only include videos. See: + // https://developers.google.com/youtube/v3/docs/search/list#type + search.setType("video"); + + // As a best practice, only retrieve the fields that the + // application uses. + search.setFields("items(id/videoId)"); + search.setMaxResults(NUMBER_OF_VIDEOS_RETURNED); + + // Call the API and print results. + SearchListResponse searchResponse = search.execute(); + List searchResultList = searchResponse.getItems(); + List videoIds = new ArrayList(); + + if (searchResultList != null) { + + // Merge video IDs + for (SearchResult searchResult : searchResultList) { + videoIds.add(searchResult.getId().getVideoId()); + } + Joiner stringJoiner = Joiner.on(','); + String videoId = stringJoiner.join(videoIds); + + // Call the YouTube Data API's youtube.videos.list method to + // retrieve the resources that represent the specified videos. + YouTube.Videos.List listVideosRequest = youtube.videos().list("snippet, recordingDetails").setId(videoId); + VideoListResponse listResponse = listVideosRequest.execute(); + + List
'; - } catch (Google_ServiceException $e) { + } catch (Google_Service_Exception $e) { $htmlBody .= sprintf('

A service error occurred: %s

', htmlspecialchars($e->getMessage())); } catch (Google_Exception $e) { From b9ff66d6be291644fb59fc2acb1540adcc1a5f47 Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:49:46 -0700 Subject: [PATCH 049/244] "Updating samples to reflect recent changes." --- php/add_channel_section.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/add_channel_section.php b/php/add_channel_section.php index de27a566..41f26b7d 100644 --- a/php/add_channel_section.php +++ b/php/add_channel_section.php @@ -130,7 +130,7 @@ } $htmlBody .= ''; - } catch (Google_ServiceException $e) { + } catch (Google_Service_Exception $e) { $htmlBody .= sprintf('

A service error occurred: %s

', htmlspecialchars($e->getMessage())); } catch (Google_Exception $e) { From bcc922a4e3cf719fe12c9b9b2cf58a7cdc49f610 Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:49:47 -0700 Subject: [PATCH 050/244] "Updating samples to reflect recent changes." --- php/resumable_upload.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/resumable_upload.php b/php/resumable_upload.php index 2b4b23cc..4819239e 100644 --- a/php/resumable_upload.php +++ b/php/resumable_upload.php @@ -114,7 +114,7 @@ $htmlBody .= ''; - } catch (Google_ServiceException $e) { + } catch (Google_Service_Exception $e) { $htmlBody .= sprintf('

A service error occurred: %s

', htmlspecialchars($e->getMessage())); } catch (Google_Exception $e) { From 536f2a12516b1f54ea9bb0d8cb9c15fa0721dd65 Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:49:49 -0700 Subject: [PATCH 051/244] "Updating samples to reflect recent changes." --- go/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/README b/go/README index d64463dd..c64bde18 100644 --- a/go/README +++ b/go/README @@ -4,7 +4,7 @@ To run these code samples, you will need to install the dependent libraries via the "go get" command. These code samples require the goauth2 and google-api-go-client libraries which can be installed with the following commands: - go get golang.org/x/oauth2 + go get code.google.com/p/goauth2/oauth go get code.google.com/p/google-api-go-client/youtube/v3 The keyword search and topic search samples can be run via the standard "go run" command From d8e3cc02623838165e37b07c37aa5845d8fc8ef4 Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:49:51 -0700 Subject: [PATCH 052/244] "Updating samples to reflect recent changes." --- php/upload_thumbnail.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/upload_thumbnail.php b/php/upload_thumbnail.php index b9ed407b..274ab894 100644 --- a/php/upload_thumbnail.php +++ b/php/upload_thumbnail.php @@ -109,7 +109,7 @@ $htmlBody .= ''; - } catch (Google_ServiceException $e) { + } catch (Google_Service_Exception $e) { $htmlBody .= sprintf('

A service error occurred: %s

', htmlspecialchars($e->getMessage())); } catch (Google_Exception $e) { From 5bd9154a38cf9ccfd3d08bb10c22f0bfd0c2acee Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:49:51 -0700 Subject: [PATCH 053/244] "Updating samples to reflect recent changes." --- php/create_broadcast.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/create_broadcast.php b/php/create_broadcast.php index f8b5be0d..c0070e59 100644 --- a/php/create_broadcast.php +++ b/php/create_broadcast.php @@ -114,7 +114,7 @@ $bindBroadcastResponse['contentDetails']['boundStreamId']); $htmlBody .= ''; - } catch (Google_ServiceException $e) { + } catch (Google_Service_Exception $e) { $htmlBody .= sprintf('

A service error occurred: %s

', htmlspecialchars($e->getMessage())); } catch (Google_Exception $e) { From be765e955b8323129f4cdf6bdb8569870b7364be Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:49:54 -0700 Subject: [PATCH 054/244] "Updating samples to reflect recent changes." --- php/list_streams.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/list_streams.php b/php/list_streams.php index 13ca5fe0..b5df3ab4 100644 --- a/php/list_streams.php +++ b/php/list_streams.php @@ -56,7 +56,7 @@ } $htmlBody .= ''; - } catch (Google_ServiceException $e) { + } catch (Google_Service_Exception $e) { $htmlBody .= sprintf('

A service error occurred: %s

', htmlspecialchars($e->getMessage())); } catch (Google_Exception $e) { From dc065d364e8961ddd178fdab981a8fcd36e7327f Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:49:55 -0700 Subject: [PATCH 055/244] "Added sample: dotnet/dotnet.csproj" --- dotnet/dotnet.csproj | 127 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 dotnet/dotnet.csproj diff --git a/dotnet/dotnet.csproj b/dotnet/dotnet.csproj new file mode 100644 index 00000000..14c5c299 --- /dev/null +++ b/dotnet/dotnet.csproj @@ -0,0 +1,127 @@ + + + + + Debug + AnyCPU + {9D5E6D9D-A78A-4F5B-9325-849FDA2C0576} + Exe + Properties + dotnet + dotnet + v4.0 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Google.Apis.1.7.0-beta\lib\net40\Google.Apis.dll + + + ..\packages\Google.Apis.Auth.1.7.0-beta\lib\net40\Google.Apis.Auth.dll + + + ..\packages\Google.Apis.Auth.1.7.0-beta\lib\net40\Google.Apis.Auth.PlatformServices.dll + + + ..\packages\Google.Apis.Core.1.7.0-beta\lib\portable-net4+sl4+wp71+win8\Google.Apis.Core.dll + + + ..\packages\Google.Apis.1.7.0-beta\lib\net40\Google.Apis.PlatformServices.dll + + + ..\packages\Google.Apis.YouTube.v3.1.7.0.91-beta\lib\portable-net4+sl4+wp71+win8\Google.Apis.YouTube.v3.dll + + + ..\packages\log4net.2.0.3\lib\net40-full\log4net.dll + + + ..\packages\Microsoft.Bcl.Async.1.0.165\lib\net40\Microsoft.Threading.Tasks.dll + + + ..\packages\Microsoft.Bcl.Async.1.0.165\lib\net40\Microsoft.Threading.Tasks.Extensions.dll + + + ..\packages\Microsoft.Bcl.Async.1.0.165\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll + + + ..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll + + + + + + False + ..\packages\Microsoft.Net.Http.2.1.10\lib\net40\System.Net.Http.dll + + + ..\packages\Microsoft.Net.Http.2.1.10\lib\net40\System.Net.Http.Extensions.dll + + + ..\packages\Microsoft.Net.Http.2.1.10\lib\net40\System.Net.Http.Primitives.dll + + + False + ..\packages\Microsoft.Net.Http.2.1.10\lib\net40\System.Net.Http.WebRequest.dll + + + ..\packages\Microsoft.Bcl.1.0.19\lib\net40\System.Runtime.dll + + + ..\packages\Microsoft.Bcl.1.0.19\lib\net40\System.Threading.Tasks.dll + + + + + + + + ..\packages\Zlib.Portable.1.9.2\lib\portable-net4+sl4+wp71+win8\Zlib.Portable.dll + + + + + + + + + PreserveNewest + + + + PreserveNewest + + + + + + + + + + + \ No newline at end of file From 670a1650524a41537ae14766ea2a938b4919ad69 Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:49:56 -0700 Subject: [PATCH 056/244] "Updating samples to reflect recent changes." --- php/my_uploads.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/php/my_uploads.php b/php/my_uploads.php index e8275676..15fdecab 100644 --- a/php/my_uploads.php +++ b/php/my_uploads.php @@ -68,7 +68,7 @@ } $htmlBody .= ''; } - } catch (Google_ServiceException $e) { + } catch (Google_Service_Exception $e) { $htmlBody .= sprintf('

A service error occurred: %s

', htmlspecialchars($e->getMessage())); } catch (Google_Exception $e) { From c68aa2ce1491c91130b29f713331d3c8931c3ee0 Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:50:02 -0700 Subject: [PATCH 057/244] "Added sample: python/captions.py" --- python/captions.py | 206 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 python/captions.py diff --git a/python/captions.py b/python/captions.py new file mode 100644 index 00000000..132d7608 --- /dev/null +++ b/python/captions.py @@ -0,0 +1,206 @@ +#!/usr/bin/python + +# Usage example: +# python captions.py --videoid='' --name='' --file='' --language='' --action='action' + +import httplib2 +import os +import sys + +from apiclient.discovery import build_from_document +from apiclient.errors import HttpError +from oauth2client.client import flow_from_clientsecrets +from oauth2client.file import Storage +from oauth2client.tools import argparser, run_flow + + +# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains + +# the OAuth 2.0 information for this application, including its client_id and +# client_secret. You can acquire an OAuth 2.0 client ID and client secret from +# the {{ Google Cloud Console }} at +# {{ https://cloud.google.com/console }}. +# Please ensure that you have enabled the YouTube Data API for your project. +# For more information about using OAuth2 to access the YouTube Data API, see: +# https://developers.google.com/youtube/v3/guides/authentication +# For more information about the client_secrets.json file format, see: +# https://developers.google.com/api-client-library/python/guide/aaa_client_secrets +CLIENT_SECRETS_FILE = "client_secrets.json" + +# This OAuth 2.0 access scope allows for full read/write access to the +# authenticated user's account and requires requests to use an SSL connection. +YOUTUBE_READ_WRITE_SSL_SCOPE = "https://www.googleapis.com/auth/youtube.force-ssl" +YOUTUBE_API_SERVICE_NAME = "youtube" +YOUTUBE_API_VERSION = "v3" + +# This variable defines a message to display if the CLIENT_SECRETS_FILE is +# missing. +MISSING_CLIENT_SECRETS_MESSAGE = """ +WARNING: Please configure OAuth 2.0 + +To make this sample run you will need to populate the client_secrets.json file +found at: + %s +with information from the APIs Console +https://developers.google.com/console + +For more information about the client_secrets.json file format, please visit: +https://developers.google.com/api-client-library/python/guide/aaa_client_secrets +""" % os.path.abspath(os.path.join(os.path.dirname(__file__), + CLIENT_SECRETS_FILE)) + +# Authorize the request and store authorization credentials. +def get_authenticated_service(args): + flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, scope=YOUTUBE_READ_WRITE_SSL_SCOPE, + message=MISSING_CLIENT_SECRETS_MESSAGE) + + storage = Storage("%s-oauth2.json" % sys.argv[0]) + credentials = storage.get() + + if credentials is None or credentials.invalid: + credentials = run_flow(flow, storage, args) + + # Trusted testers can download this discovery document from the developers page + # and it should be in the same directory with the code. + with open("youtube-v3-api-captions.json", "r") as f: + doc = f.read() + return build_from_document(doc, http=credentials.authorize(httplib2.Http())) + + +# Call the API's captions.list method to list the existing caption tracks. +def list_captions(youtube, video_id): + results = youtube.captions().list( + part="snippet", + videoId=video_id + ).execute() + + for item in results["items"]: + id = item["id"] + name = item["snippet"]["name"] + language = item["snippet"]["language"] + print "Caption track '%s(%s)' in '%s' language." % (name, id, language) + + return results["items"] + + +# Call the API's captions.insert method to upload a caption track in draft status. +def upload_caption(youtube, video_id, language, name, file): + insert_result = youtube.captions().insert( + part="snippet", + body=dict( + snippet=dict( + videoId=video_id, + language=language, + name=name, + isDraft=True + ) + ), + media_body=file + ).execute() + + id = insert_result["id"] + name = insert_result["snippet"]["name"] + language = insert_result["snippet"]["language"] + status = insert_result["snippet"]["status"] + print "Uploaded caption track '%s(%s) in '%s' language, '%s' status." % (name, + id, language, status) + + +# Call the API's captions.update method to update an existing caption track's draft status +# and publish it. If a new binary file is present, update the track with the file as well. +def update_caption(youtube, caption_id, file): + update_result = youtube.captions().update( + part="snippet", + body=dict( + id=caption_id, + snippet=dict( + isDraft=False + ) + ), + media_body=file + ).execute() + + name = update_result["snippet"]["name"] + isDraft = update_result["snippet"]["isDraft"] + print "Updated caption track '%s' draft status to be: '%s'" % (name, isDraft) + if file: + print "and updated the track with the new uploaded file." + + +# Call the API's captions.download method to download an existing caption track. +def download_caption(youtube, caption_id, tfmt): + subtitle = youtube.captions().download( + id=caption_id, + tfmt=tfmt + ).execute() + + print "First line of caption track: %s" % (subtitle) + +# Call the API's captions.delete method to delete an existing caption track. +def delete_caption(youtube, caption_id): + youtube.captions().delete( + id=caption_id + ).execute() + + print "caption track '%s' deleted succesfully" % (caption_id) + + +if __name__ == "__main__": + # The "videoid" option specifies the YouTube video ID that uniquely + # identifies the video for which the caption track will be uploaded. + argparser.add_argument("--videoid", + help="Required; ID for video for which the caption track will be uploaded.") + # The "name" option specifies the name of the caption trackto be used. + argparser.add_argument("--name", help="Caption track name", default="YouTube for Developers") + # The "file" option specifies the binary file to be uploaded as a caption track. + argparser.add_argument("--file", help="Captions track file to upload") + # The "language" option specifies the language of the caption track to be uploaded. + argparser.add_argument("--language", help="Caption track language", default="en") + # The "captionid" option specifies the ID of the caption track to be processed. + argparser.add_argument("--captionid", help="Required; ID of the caption track to be processed") + # The "action" option specifies the action to be processed. + argparser.add_argument("--action", help="Action", default="all") + + + args = argparser.parse_args() + + if (args.action in ('upload', 'list', 'all')): + if not args.videoid: + exit("Please specify videoid using the --videoid= parameter.") + + if (args.action in ('update', 'download', 'delete')): + if not args.captionid: + exit("Please specify captionid using the --captionid= parameter.") + + if (args.action in ('upload', 'all')): + if not args.file: + exit("Please specify a caption track file using the --file= parameter.") + if not os.path.exists(args.file): + exit("Please specify a valid file using the --file= parameter.") + + youtube = get_authenticated_service(args) + try: + if args.action == 'upload': + upload_caption(youtube, args.videoid, args.language, args.name, args.file) + elif args.action == 'list': + list_captions(youtube, args.videoid) + elif args.action == 'update': + update_caption(youtube, args.captionid, args.file); + elif args.action == 'download': + download_caption(youtube, args.captionid, 'srt') + elif args.action == 'delete': + delete_caption(youtube, args.captionid); + else: + # All the available methods are used in sequence just for the sake of an example. + upload_caption(youtube, args.videoid, args.language, args.name, args.file) + captions = list_captions(youtube, args.videoid) + + if captions: + first_caption_id = captions[0]['id']; + update_caption(youtube, first_caption_id, None); + download_caption(youtube, first_caption_id, 'srt') + delete_caption(youtube, first_caption_id); + except HttpError, e: + print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content) + else: + print "Created and managed caption tracks." From 78d88a28b7324195ec16150503d230deb6b24e7c Mon Sep 17 00:00:00 2001 From: Andy Diamondstein Date: Wed, 10 Jun 2015 11:50:04 -0700 Subject: [PATCH 058/244] "Updating samples to reflect recent changes." --- .../samples/youtube/cmdline/data/GeolocationSearch.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/data/GeolocationSearch.java b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/data/GeolocationSearch.java index 2c026b12..d063073b 100644 --- a/java/src/main/java/com/google/api/services/samples/youtube/cmdline/data/GeolocationSearch.java +++ b/java/src/main/java/com/google/api/services/samples/youtube/cmdline/data/GeolocationSearch.java @@ -140,10 +140,6 @@ public void initialize(HttpRequest request) throws IOException { // Call the YouTube Data API's youtube.videos.list method to // retrieve the resources that represent the specified videos. YouTube.Videos.List listVideosRequest = youtube.videos().list("snippet, recordingDetails").setId(videoId); - - // Set your developer key - listVideosRequest.setKey(apiKey); - VideoListResponse listResponse = listVideosRequest.execute(); List