[libgdata] demos: Expand youtube-cli functionality



commit 7887424aed686642fa1ed61dff1409fb89eab7e1
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sun Apr 19 17:59:18 2015 +0100

    demos: Expand youtube-cli functionality
    
    Add support for all of the major features which our YouTube service
    currently supports: querying single videos, related videos, standard
    feeds, categories, and uploading videos.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=687597

 demos/youtube/youtube-cli.c |  494 +++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 480 insertions(+), 14 deletions(-)
---
diff --git a/demos/youtube/youtube-cli.c b/demos/youtube/youtube-cli.c
index 7bb23b4..7f3186f 100644
--- a/demos/youtube/youtube-cli.c
+++ b/demos/youtube/youtube-cli.c
@@ -21,7 +21,10 @@
 #include <locale.h>
 #include <string.h>
 
-#define DEVELOPER_KEY 
"AI39si7Me3Q7zYs6hmkFvpRBD2nrkVjYYsUO5lh_3HdOkGRc9g6Z4nzxZatk_aAo2EsA21k7vrda0OO6oFg2rnhMedZXPyXoEw"
+#define CLIENT_ID "1074795795536-necvslvs0pchk65nf6ju4i6mniogg8fr.apps.googleusercontent.com"
+#define CLIENT_SECRET "8totRi50eo2Zfr3SD2DeNAzo"
+#define REDIRECT_URI "urn:ietf:wg:oauth:2.0:oob"
+#define DEVELOPER_KEY "AIzaSyCENhl8yDxDZbyhTF6p-ok-RefK07xdXUg"
 
 static int
 print_usage (char *argv[])
@@ -30,18 +33,125 @@ print_usage (char *argv[])
        return -1;
 }
 
+static void
+print_video (GDataYouTubeVideo *video)
+{
+       const gchar *title, *player_uri, *id, *description;
+       GList/*<unowned GDataMediaThumbnail>*/ *thumbnails;
+       GTimeVal date_published_tv = { 0, };
+       gchar *date_published = NULL;  /* owned */
+       guint duration;  /* seconds */
+       guint rating_min = 0, rating_max = 0, rating_count = 0;
+       gdouble rating_average = 0.0;
+
+       title = gdata_entry_get_title (GDATA_ENTRY (video));
+       player_uri = gdata_youtube_video_get_player_uri (video);
+       id = gdata_entry_get_id (GDATA_ENTRY (video));
+       description = gdata_youtube_video_get_description (video);
+       thumbnails = gdata_youtube_video_get_thumbnails (video);
+       date_published_tv.tv_sec = gdata_entry_get_published (GDATA_ENTRY (video));
+       date_published = g_time_val_to_iso8601 (&date_published_tv);
+       duration = gdata_youtube_video_get_duration (video);
+       gdata_youtube_video_get_rating (video, &rating_min, &rating_max,
+                                       &rating_count, &rating_average);
+
+       g_print ("%s — %s\n", player_uri, title);
+       g_print ("   ID: %s\n", id);
+       g_print ("   Published: %s\n", date_published);
+       g_print ("   Duration: %us\n", duration);
+       g_print ("   Rating: %.2f (min: %u, max: %u, count: %u)\n",
+                rating_average, rating_min, rating_max, rating_count);
+       g_print ("   Description:\n      %s\n", description);
+       g_print ("   Thumbnails:\n");
+
+       for (; thumbnails != NULL; thumbnails = thumbnails->next) {
+               GDataMediaThumbnail *thumbnail;
+
+               thumbnail = GDATA_MEDIA_THUMBNAIL (thumbnails->data);
+               g_print ("    • %s\n",
+                        gdata_media_thumbnail_get_uri (thumbnail));
+       }
+
+       g_print ("\n");
+
+       g_free (date_published);
+}
+
+static void
+print_category (GDataCategory *category)
+{
+       const gchar *term, *label;
+
+       term = gdata_category_get_term (category);
+       label = gdata_category_get_label (category);
+
+       g_print ("%s — %s\n", term, label);
+}
+
+static GDataAuthorizer *
+create_authorizer (GError **error)
+{
+       GDataOAuth2Authorizer *authorizer = NULL;  /* owned */
+       gchar *uri = NULL;
+       gchar code[100];
+       GError *child_error = NULL;
+
+       /* Go through the interactive OAuth dance. */
+       authorizer = gdata_oauth2_authorizer_new (CLIENT_ID, CLIENT_SECRET,
+                                                 REDIRECT_URI,
+                                                 GDATA_TYPE_YOUTUBE_SERVICE);
+
+       /* Get an authentication URI */
+       uri = gdata_oauth2_authorizer_build_authentication_uri (authorizer,
+                                                               NULL, FALSE);
+
+       /* Wait for the user to retrieve and enter the verifier. */
+       g_print ("Please navigate to the following URI and grant access:\n"
+                "   %s\n", uri);
+       g_print ("Enter verifier (EOF to abort): ");
+
+       g_free (uri);
+
+       if (scanf ("%100s", code) != 1) {
+               /* User chose to abort. */
+               g_print ("\n");
+               g_clear_object (&authorizer);
+               return NULL;
+       }
+
+       /* Authorise the token. */
+       gdata_oauth2_authorizer_request_authorization (authorizer, code, NULL,
+                                                      &child_error);
+
+       if (child_error != NULL) {
+               g_propagate_error (error, child_error);
+               g_clear_object (&authorizer);
+               return NULL;
+       }
+
+       return GDATA_AUTHORIZER (authorizer);
+}
+
+/* Search for videos given a simple query string. */
 static int
-command_search (char *argv[])
+command_search (int argc, char *argv[])
 {
        GDataYouTubeService *service = NULL;
        GDataYouTubeQuery *query = NULL;
        GDataFeed *feed = NULL;
-       GList *entries;
+       GList/*<unowned GDataYouTubeVideo>*/ *entries;
        GError *error = NULL;
        gint retval = 0;
+       const gchar *query_string;
+
+       if (argc < 3) {
+               return print_usage (argv);
+       }
+
+       query_string = argv[2];
 
        service = gdata_youtube_service_new (DEVELOPER_KEY, NULL);
-       query = gdata_youtube_query_new (argv[2]);
+       query = gdata_youtube_query_new (query_string);
        feed = gdata_youtube_service_query_videos (service, GDATA_QUERY (query),
                                                   NULL, NULL, NULL, &error);
 
@@ -57,22 +167,373 @@ command_search (char *argv[])
        for (entries = gdata_feed_get_entries (feed); entries != NULL;
             entries = entries->next) {
                GDataYouTubeVideo *video;
-               const gchar *title, *player_uri;
 
                video = GDATA_YOUTUBE_VIDEO (entries->data);
-               title = gdata_entry_get_title (GDATA_ENTRY (video));
-               player_uri = gdata_youtube_video_get_player_uri (video);
+               print_video (video);
+       }
+
+       g_print ("Total of %u results.\n", gdata_feed_get_total_results (feed));
+
+done:
+       g_clear_object (&feed);
+       g_clear_object (&query);
+       g_clear_object (&service);
+
+       return retval;
+}
+
+/* Display information about a single video. */
+static int
+command_info (int argc, char *argv[])
+{
+       GDataYouTubeService *service = NULL;
+       GDataEntry *result = NULL;
+       GDataYouTubeVideo *video;  /* unowned */
+       GError *error = NULL;
+       gint retval = 0;
+       const gchar *entry_id;
+
+       if (argc < 3) {
+               return print_usage (argv);
+       }
+
+       entry_id = argv[2];
+
+       service = gdata_youtube_service_new (DEVELOPER_KEY, NULL);
+       result = gdata_service_query_single_entry (GDATA_SERVICE (service),
+                                                  NULL, entry_id, NULL,
+                                                  GDATA_TYPE_YOUTUBE_VIDEO,
+                                                  NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("%s: Error querying YouTube: %s\n",
+                           argv[0], error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
+       }
+
+       /* Print results. */
+       video = GDATA_YOUTUBE_VIDEO (result);
+       print_video (video);
+
+done:
+       g_clear_object (&result);
+       g_clear_object (&service);
+
+       return retval;
+}
+
+static gboolean
+standard_feed_type_from_name (const gchar *name,
+                              GDataYouTubeStandardFeedType *out)
+{
+       /* Indexed by GDataYouTubeStandardFeedType. */
+       const gchar *feed_type_names[] = {
+               "top-rated",
+               "top-favorites",
+               "most-viewed",
+               "most-popular",
+               "most-recent",
+               "most-discussed",
+               "most-linked",
+               "most-responded",
+               "recently-featured",
+               "watch-on-mobile",
+       };
+       guint i;
+
+       G_STATIC_ASSERT (G_N_ELEMENTS (feed_type_names) ==
+                        GDATA_YOUTUBE_WATCH_ON_MOBILE_FEED + 1);
+
+       for (i = 0; i < G_N_ELEMENTS (feed_type_names); i++) {
+               if (g_strcmp0 (feed_type_names[i], name) == 0) {
+                       *out = (GDataYouTubeStandardFeedType) i;
+                       return TRUE;
+               }
+       }
+
+       return FALSE;
+}
+
+/* List all videos in a standard feed. */
+static int
+command_standard_feed (int argc, char *argv[])
+{
+       GDataYouTubeService *service = NULL;
+       GDataFeed *feed = NULL;
+       GList/*<unowned GDataYouTubeVideo>*/ *entries;
+       GError *error = NULL;
+       gint retval = 0;
+       GDataYouTubeStandardFeedType feed_type;
+
+       if (argc < 3) {
+               return print_usage (argv);
+       }
+
+       if (!standard_feed_type_from_name (argv[2], &feed_type)) {
+               g_printerr ("%s: Invalid feed type ‘%s’.\n", argv[0], argv[2]);
+               retval = 1;
+               goto done;
+       }
+
+       service = gdata_youtube_service_new (DEVELOPER_KEY, NULL);
+       feed = gdata_youtube_service_query_standard_feed (service, feed_type,
+                                                         NULL, NULL, NULL,
+                                                         NULL, &error);
 
-               g_print ("%s — %s\n", player_uri, title);
+       if (error != NULL) {
+               g_printerr ("%s: Error querying YouTube: %s\n",
+                           argv[0], error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
        }
 
-       if (gdata_feed_get_entries (feed) == NULL) {
-               g_print ("No results.\n");
+       /* Print results. */
+       for (entries = gdata_feed_get_entries (feed); entries != NULL;
+            entries = entries->next) {
+               GDataYouTubeVideo *video;
+
+               video = GDATA_YOUTUBE_VIDEO (entries->data);
+               print_video (video);
        }
 
+       g_print ("Total of %u results.\n", gdata_feed_get_total_results (feed));
+
 done:
        g_clear_object (&feed);
-       g_clear_object (&query);
+       g_clear_object (&service);
+
+       return retval;
+}
+
+/* List videos related to a given one. */
+static int
+command_related (int argc, char *argv[])
+{
+       GDataYouTubeService *service = NULL;
+       GDataFeed *feed = NULL;
+       GList/*<unowned GDataYouTubeVideo>*/ *entries;
+       GError *error = NULL;
+       gint retval = 0;
+       const gchar *entry_id;
+       GDataYouTubeVideo *query_video = NULL;
+
+       if (argc < 3) {
+               return print_usage (argv);
+       }
+
+       entry_id = argv[2];
+       query_video = gdata_youtube_video_new (entry_id);
+
+       service = gdata_youtube_service_new (DEVELOPER_KEY, NULL);
+       feed = gdata_youtube_service_query_related (service, query_video, NULL,
+                                                   NULL, NULL, NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("%s: Error querying YouTube: %s\n",
+                           argv[0], error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
+       }
+
+       /* Print results. */
+       for (entries = gdata_feed_get_entries (feed); entries != NULL;
+            entries = entries->next) {
+               GDataYouTubeVideo *video;
+
+               video = GDATA_YOUTUBE_VIDEO (entries->data);
+               print_video (video);
+       }
+
+       g_print ("Total of %u results.\n", gdata_feed_get_total_results (feed));
+
+done:
+       g_clear_object (&query_video);
+       g_clear_object (&feed);
+       g_clear_object (&service);
+
+       return retval;
+}
+
+/* List all available video categories. */
+static int
+command_categories (int argc, char *argv[])
+{
+       GDataYouTubeService *service = NULL;
+       GDataAPPCategories *app_categories = NULL;
+       GList/*<unowned GDataCategory>*/ *categories;
+       GError *error = NULL;
+       gint retval = 0;
+
+       service = gdata_youtube_service_new (DEVELOPER_KEY, NULL);
+       app_categories = gdata_youtube_service_get_categories (service, NULL,
+                                                              &error);
+
+       if (error != NULL) {
+               g_printerr ("%s: Error querying YouTube: %s\n",
+                           argv[0], error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
+       }
+
+       /* Print results. */
+       for (categories = gdata_app_categories_get_categories (app_categories);
+            categories != NULL;
+            categories = categories->next) {
+               GDataCategory *category;
+
+               category = GDATA_CATEGORY (categories->data);
+               print_category (category);
+       }
+
+       g_print ("Total of %u results.\n",
+                g_list_length (gdata_app_categories_get_categories (app_categories)));
+
+done:
+       g_clear_object (&app_categories);
+       g_clear_object (&service);
+
+       return retval;
+}
+
+/* Upload a video. */
+static int
+command_upload (int argc, char *argv[])
+{
+       GDataYouTubeService *service = NULL;
+       GDataUploadStream *upload_stream = NULL;
+       GError *error = NULL;
+       gint retval = 0;
+       const gchar *filename;
+       GFile *video_file = NULL;
+       GFileInputStream *video_file_stream = NULL;
+       GFileInfo *video_file_info = NULL;
+       GDataYouTubeVideo *video = NULL;
+       GDataYouTubeVideo *uploaded_video = NULL;
+       gssize transfer_size;
+       const gchar *content_type, *slug;
+       GDataAuthorizer *authorizer = NULL;
+       const gchar *title, *description;
+
+       if (argc < 3) {
+               return print_usage (argv);
+       }
+
+       filename = argv[2];
+       title = (argc > 3) ? argv[3] : NULL;
+       description = (argc > 4) ? argv[4] : NULL;
+
+       /* Load the file and query its details. */
+       video_file = g_file_new_for_commandline_arg (filename);
+
+       video_file_info = g_file_query_info (video_file,
+                                            G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+                                            G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
+                                            G_FILE_QUERY_INFO_NONE, NULL,
+                                            &error);
+
+       if (error != NULL) {
+               g_printerr ("%s: Error loading video information ‘%s’: %s\n",
+                           argv[0], filename, error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
+       }
+
+       content_type = g_file_info_get_content_type (video_file_info);
+       slug = g_file_info_get_display_name (video_file_info);
+
+       video_file_stream = g_file_read (video_file, NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("%s: Error loading video ‘%s’: %s\n",
+                           argv[0], filename, error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
+       }
+
+       /* Build the video. */
+       video = gdata_youtube_video_new (NULL);
+       gdata_entry_set_title (GDATA_ENTRY (video), title);
+       gdata_entry_set_summary (GDATA_ENTRY (video), description);
+
+       /* Authenticate and create a service. */
+       authorizer = create_authorizer (&error);
+
+       if (error != NULL) {
+               g_printerr ("%s: Error authenticating: %s\n",
+                           argv[0], error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
+       } else if (authorizer == NULL) {
+               g_printerr ("%s: User chose to abort authentication.\n",
+                           argv[0]);
+               retval = 1;
+               goto done;
+       }
+
+       service = gdata_youtube_service_new (DEVELOPER_KEY,
+                                            GDATA_AUTHORIZER (authorizer));
+
+       /* Start the upload. */
+       upload_stream = gdata_youtube_service_upload_video (service, video,
+                                                           slug, content_type,
+                                                           NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("%s: Error initializing upload with YouTube: %s\n",
+                           argv[0], error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
+       }
+
+       /* Upload the video */
+       transfer_size = g_output_stream_splice (G_OUTPUT_STREAM (upload_stream),
+                                               G_INPUT_STREAM (video_file_stream),
+                                               G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
+                                               G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+                                               NULL, &error);
+
+       if (error != NULL) {
+               g_printerr ("%s: Error transferring file: %s\n",
+                           argv[0], error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
+       }
+
+       /* Finish off the upload */
+       uploaded_video = gdata_youtube_service_finish_video_upload (service,
+                                                                   upload_stream,
+                                                                   &error);
+
+       if (error != NULL) {
+               g_printerr ("%s: Error finishing upload with YouTube: %s\n",
+                           argv[0], error->message);
+               g_error_free (error);
+               retval = 1;
+               goto done;
+       }
+
+       /* Print the uploaded video as confirmation. */
+       g_print ("Uploaded %" G_GSSIZE_FORMAT " bytes.\n", transfer_size);
+       print_video (uploaded_video);
+
+done:
+       g_clear_object (&authorizer);
+       g_clear_object (&uploaded_video);
+       g_clear_object (&video);
+       g_clear_object (&video_file_info);
+       g_clear_object (&video_file_stream);
+       g_clear_object (&video_file);
+       g_clear_object (&upload_stream);
        g_clear_object (&service);
 
        return retval;
@@ -80,9 +541,14 @@ done:
 
 static const struct {
        const gchar *command;
-       int (*handler_fn) (char **argv);
+       int (*handler_fn) (int argc, char **argv);
 } command_handlers[] = {
        { "search", command_search },
+       { "info", command_info },
+       { "standard-feed", command_standard_feed },
+       { "categories", command_categories },
+       { "related", command_related },
+       { "upload", command_upload },
 };
 
 int
@@ -93,13 +559,13 @@ main (int argc, char *argv[])
 
        setlocale (LC_ALL, "");
 
-       if (argc < 3) {
+       if (argc < 2) {
                return print_usage (argv);
        }
 
        for (i = 0; i < G_N_ELEMENTS (command_handlers); i++) {
                if (strcmp (argv[1], command_handlers[i].command) == 0) {
-                       retval = command_handlers[i].handler_fn (argv);
+                       retval = command_handlers[i].handler_fn (argc, argv);
                }
        }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]