[gnome-software/wip/rancell/ubuntu-ratings] Attempt to upload ratings to reviews.ubuntu.com



commit 5fca825651eacd6a5e423a5bfe799d079628f238
Author: Robert Ancell <robert ancell canonical com>
Date:   Fri Dec 11 14:34:55 2015 +1300

    Attempt to upload ratings to reviews.ubuntu.com

 configure.ac                           |    1 +
 src/plugins/Makefile.am                |    3 +-
 src/plugins/gs-plugin-ubuntu-reviews.c |  186 ++++++++++++++++++++++++++++----
 3 files changed, 168 insertions(+), 22 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index b001017..caf89d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -68,6 +68,7 @@ PKG_CHECK_MODULES(GSETTINGS_DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.11.5
 PKG_CHECK_MODULES(GNOME_DESKTOP, gnome-desktop-3.0 >= 3.17.92)
 PKG_CHECK_MODULES(POLKIT, polkit-gobject-1)
 PKG_CHECK_MODULES(JSON_GLIB, json-glib-1.0 >= 0.12)
+PKG_CHECK_MODULES(OAUTH, oauth)
 AC_PATH_PROG(APPSTREAM_UTIL, [appstream-util], [unfound])
 AC_ARG_ENABLE(man,
               [AS_HELP_STRING([--enable-man],
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index ba38d96..aef1e58 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -9,6 +9,7 @@ AM_CPPFLAGS =                                           \
        $(PACKAGEKIT_CFLAGS)                            \
        $(SOUP_CFLAGS)                                  \
        $(SQLITE_CFLAGS)                                \
+       $(OAUTH_CFLAGS)                                 \
        $(FWUPD_CFLAGS)                                 \
        $(LIMBA_CFLAGS)                                 \
        $(JSON_GLIB_CFLAGS)                             \
@@ -133,7 +134,7 @@ libgs_plugin_local_ratings_la_LDFLAGS = -module -avoid-version
 libgs_plugin_local_ratings_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 
 libgs_plugin_ubuntu_reviews_la_SOURCES = gs-plugin-ubuntu-reviews.c
-libgs_plugin_ubuntu_reviews_la_LIBADD = $(GS_PLUGIN_LIBS) $(SOUP_LIBS) $(SQLITE_LIBS) $(JSON_GLIB_LIBS)
+libgs_plugin_ubuntu_reviews_la_LIBADD = $(GS_PLUGIN_LIBS) $(SOUP_LIBS) $(SQLITE_LIBS) $(JSON_GLIB_LIBS) 
$(OAUTH_LIBS)
 libgs_plugin_ubuntu_reviews_la_LDFLAGS = -module -avoid-version
 libgs_plugin_ubuntu_reviews_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARNINGFLAGS_C)
 
diff --git a/src/plugins/gs-plugin-ubuntu-reviews.c b/src/plugins/gs-plugin-ubuntu-reviews.c
index 6e5a203..c63d3e8 100644
--- a/src/plugins/gs-plugin-ubuntu-reviews.c
+++ b/src/plugins/gs-plugin-ubuntu-reviews.c
@@ -25,6 +25,7 @@
 #include <libsoup/soup.h>
 #include <sqlite3.h>
 #include <json-glib/json-glib.h>
+#include <oauth.h>
 
 #include <gs-plugin.h>
 #include <gs-utils.h>
@@ -44,23 +45,17 @@ typedef struct {
        gint64           five_star_count;
 } Histogram;
 
-/**
- * gs_plugin_get_name:
- */
 const gchar *
 gs_plugin_get_name (void)
 {
        return "ubuntu-reviews";
 }
 
-#define GS_PLUGIN_UBUNTU_REVIEWS_SERVER                "https://reviews.ubuntu.com/reviews";
+#define UBUNTU_REVIEWS_SERVER          "https://reviews.ubuntu.com/reviews";
 
 /* 3 months */
 #define GS_PLUGIN_UBUNTU_REVIEWS_AGE_MAX               (60 * 60 * 24 * 7 * 4 * 3)
 
-/**
- * gs_plugin_initialize:
- */
 void
 gs_plugin_initialize (GsPlugin *plugin)
 {
@@ -80,9 +75,6 @@ gs_plugin_initialize (GsPlugin *plugin)
        }
 }
 
-/**
- * gs_plugin_get_deps:
- */
 const gchar **
 gs_plugin_get_deps (GsPlugin *plugin)
 {
@@ -90,9 +82,6 @@ gs_plugin_get_deps (GsPlugin *plugin)
        return deps;
 }
 
-/**
- * gs_plugin_destroy:
- */
 void
 gs_plugin_destroy (GsPlugin *plugin)
 {
@@ -125,16 +114,174 @@ setup_networking (GsPlugin *plugin, GError **error)
        return TRUE;
 }
 
-/**
- * gs_plugin_app_set_rating:
- */
+static void
+add_string_member (JsonBuilder *builder, const gchar *name, const gchar *value)
+{
+       json_builder_set_member_name (builder, name);
+       json_builder_add_string_value (builder, value);
+}
+
+static void
+add_int_member (JsonBuilder *builder, const gchar *name, gint64 value)
+{
+       json_builder_set_member_name (builder, name);
+       json_builder_add_int_value (builder, value);
+}
+
+static void
+sign_message (SoupMessage *message, OAuthMethod method,
+              const gchar *oauth_consumer_key, const gchar *oauth_consumer_secret,
+              const gchar *oauth_token, const gchar *oauth_token_secret)
+{
+       g_autofree gchar *url = NULL, *oauth_authorization_parameters = NULL, *authorization_text = NULL;
+       gchar **url_parameters = NULL;
+       int url_parameters_length;
+
+       url = soup_uri_to_string (soup_message_get_uri (message), FALSE);
+
+       url_parameters_length = oauth_split_url_parameters(url, &url_parameters);
+       oauth_sign_array2_process (&url_parameters_length, &url_parameters,
+                                  NULL,
+                                  method,
+                                  message->method,
+                                  oauth_consumer_key, oauth_consumer_secret,
+                                  oauth_token, oauth_token_secret);
+       oauth_authorization_parameters = oauth_serialize_url_sep (url_parameters_length, 1, url_parameters, 
", ", 6);
+       oauth_free_array (&url_parameters_length, &url_parameters);
+       authorization_text = g_strdup_printf ("OAuth realm=\"Ratings and Reviews\", %s", 
oauth_authorization_parameters);
+       soup_message_headers_append (message->request_headers, "Authorization", authorization_text);
+}
+
+static void
+set_request (SoupMessage *message, JsonBuilder *builder)
+{
+       JsonGenerator *generator = json_generator_new ();
+       json_generator_set_root (generator, json_builder_get_root (builder));
+       gsize length;
+       gchar *data = json_generator_to_data (generator, &length);
+       soup_message_set_request (message, "application/json", SOUP_MEMORY_TAKE, data, length);
+       g_object_unref (generator);
+}
+
+static gboolean
+set_package_rating (GsPlugin *plugin,
+                    GsApp *app,
+                    const gchar *package_name,
+                    GError **error)
+{
+       g_autofree gchar *uri = NULL, *path = NULL;
+       g_autofree gchar *oauth_consumer_key = NULL, *oauth_consumer_secret = NULL, *oauth_token = NULL, 
*oauth_token_secret = NULL;
+       const gchar *review_text = NULL;
+       g_autoptr(GKeyFile) config = NULL;
+       gint rating, n_stars = 0;
+       g_autoptr(SoupMessage) msg = NULL;
+       JsonBuilder *builder;
+       guint status_code;
+
+       /* Ubuntu reviews require a summary and description - just make one up for now */
+       rating = gs_app_get_rating (app);
+       if (rating > 80) {
+               review_text = "★★★★★";
+               n_stars = 5;
+       }
+       else if (rating > 60) {
+               review_text = "★★★★";
+               n_stars = 4;
+       }
+       else if (rating > 40) {
+               review_text = "★★★";
+               n_stars = 3;
+       }
+       else if (rating > 20) {
+               review_text = "★★";
+               n_stars = 2;
+       }
+       else {
+               review_text = "★";
+               n_stars = 1;
+       }
+
+       /* Load OAuth token - FIXME needs to integrate with GNOME Online Accounts / libaccounts */
+       config = g_key_file_new ();
+       path = g_build_filename (g_get_user_config_dir (), "gnome-software", "ubuntu-one-credentials", NULL);
+       g_key_file_load_from_file (config, path, G_KEY_FILE_NONE, NULL);
+       oauth_consumer_key = g_key_file_get_string (config, "gnome-software", "consumer-key", NULL);
+       oauth_consumer_secret = g_key_file_get_string (config, "gnome-software", "consumer-secret", NULL);
+       oauth_token = g_key_file_get_string (config, "gnome-software", "token", NULL);
+       oauth_token_secret = g_key_file_get_string (config, "gnome-software", "token-secret", NULL);
+       if (!oauth_consumer_key || !oauth_consumer_secret || !oauth_token || !oauth_token_secret) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "%s", "No Ubuntu One OAuth tokens");
+               return FALSE;
+       }
+
+       uri = g_strdup_printf ("%s/api/1.0/reviews/", UBUNTU_REVIEWS_SERVER);
+       msg = soup_message_new (SOUP_METHOD_POST, uri);
+       builder = json_builder_new ();
+       json_builder_begin_object (builder);
+       add_string_member (builder, "package_name", package_name);
+       add_string_member (builder, "summary", review_text);
+       add_string_member (builder, "review_text", review_text);
+       add_string_member (builder, "language", "en"); // FIXME
+       add_string_member (builder, "origin", gs_app_get_origin (app));
+       add_string_member (builder, "distroseries", "xenial"); // FIXME
+       add_string_member (builder, "version", gs_app_get_version (app));
+       add_int_member (builder, "rating", n_stars);
+       add_string_member (builder, "arch_tag", "amd64"); // FIXME
+       json_builder_end_object (builder);
+       set_request (msg, builder);
+       g_object_unref (builder);
+       sign_message (msg, OA_HMAC, oauth_consumer_key, oauth_consumer_secret, oauth_token, 
oauth_token_secret);
+
+       status_code = soup_session_send_message (plugin->priv->session, msg);
+       if (status_code != SOUP_STATUS_OK) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "Failed to post review: %s",
+                            soup_status_get_phrase (status_code));
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
 gboolean
 gs_plugin_app_set_rating (GsPlugin *plugin,
                           GsApp *app,
                           GCancellable *cancellable,
                           GError **error)
 {
-       return FALSE;
+       GPtrArray *sources;
+       const gchar *package_name;
+       gboolean ret;
+       guint i;
+       g_autoptr(SoupMessage) msg = NULL;
+
+       /* get the package name */
+       sources = gs_app_get_sources (app);
+       if (sources->len == 0) {
+               g_warning ("no package name for %s", gs_app_get_id (app));
+               return TRUE;
+       }
+
+       if (!setup_networking (plugin, error))
+               return FALSE;
+
+       /* set rating for each package */
+       for (i = 0; i < sources->len; i++) {
+               package_name = g_ptr_array_index (sources, i);
+               ret = set_package_rating (plugin,
+                                         app,
+                                         package_name,
+                                         error);
+               if (!ret)
+                       return FALSE;
+       }
+
+       return TRUE;
 }
 
 static gint
@@ -296,7 +443,7 @@ download_review_stats (GsPlugin *plugin, GError **error)
 
        /* Get the review stats using HTTP */
        uri = g_strdup_printf ("%s/api/1.0/review-stats/any/any/",
-                              GS_PLUGIN_UBUNTU_REVIEWS_SERVER);
+                              UBUNTU_REVIEWS_SERVER);
        msg = soup_message_new (SOUP_METHOD_GET, uri);
        if (!setup_networking (plugin, error))
                return FALSE;
@@ -462,9 +609,6 @@ get_rating (GsPlugin *plugin,
        return TRUE;
 }
 
-/**
- * gs_plugin_refine:
- */
 gboolean
 gs_plugin_refine (GsPlugin *plugin,
                  GList **list,


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