From fd1451a33f32bfc208e799e0f81139b790e315d3 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 6 Feb 2017 10:02:46 +0100 Subject: demos: Add a demo of Google Tasks This is a simple read-only demo of the Tasks service, similar to the Calendar demo. https://bugzilla.gnome.org/show_bug.cgi?id=775813 --- Makefile.am | 33 +++++ demos/tasks/tasks-cli.c | 350 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 383 insertions(+) create mode 100644 demos/tasks/tasks-cli.c diff --git a/Makefile.am b/Makefile.am index fd3e7544..70633d3f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -634,6 +634,7 @@ CODE_COVERAGE_LCOV_OPTIONS = --base-directory $(abs_top_srcdir) noinst_PROGRAMS = \ demos/youtube/youtube-cli \ demos/calendar/calendar-cli \ + demos/tasks/tasks-cli \ $(NULL) if ENABLE_GOA @@ -809,6 +810,38 @@ demos_calendar_calendar_cli_LDADD = \ $(AM_LDADD) \ $(NULL) +demos_tasks_tasks_cli_SOURCES = \ + demos/tasks/tasks-cli.c \ + $(NULL) + +demos_tasks_tasks_cli_CPPFLAGS = \ + -I$(top_srcdir)/ \ + -I$(top_srcdir)/gdata \ + -DG_LOG_DOMAIN=\"tasks\" \ + -DLIBGDATA_DISABLE_DEPRECATED \ + $(DISABLE_DEPRECATED) \ + $(AM_CPPFLAGS) \ + $(NULL) + +demos_tasks_tasks_cli_CFLAGS = \ + $(WARN_CFLAGS) \ + $(GDATA_CFLAGS) \ + $(GNOME_CFLAGS) \ + $(AM_CFLAGS) \ + $(NULL) + +demos_tasks_tasks_cli_LDFLAGS = \ + $(WARN_LDFLAGS) \ + $(AM_LDFLAGS) \ + $(NULL) + +demos_tasks_tasks_cli_LDADD = \ + $(top_builddir)/gdata/libgdata.la \ + $(GDATA_LIBS) \ + $(GNOME_LIBS) \ + $(AM_LDADD) \ + $(NULL) + # Cleaning EXTRA_DIST += \ autogen.sh \ diff --git a/demos/tasks/tasks-cli.c b/demos/tasks/tasks-cli.c new file mode 100644 index 00000000..c795761a --- /dev/null +++ b/demos/tasks/tasks-cli.c @@ -0,0 +1,350 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * GData Client + * Copyright © 2017 Philip Withnall + * + * GData Client is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * GData Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GData Client. If not, see . + */ + +#include +#include +#include + +#define CLIENT_ID "1074795795536-necvslvs0pchk65nf6ju4i6mniogg8fr.apps.googleusercontent.com" +#define CLIENT_SECRET "8totRi50eo2Zfr3SD2DeNAzo" +#define REDIRECT_URI "urn:ietf:wg:oauth:2.0:oob" + +static int +print_usage (char *argv[]) +{ + g_printerr ("%s: Usage — %s \n" + "Subcommands:\n" + " tasklists\n" + " tasks [query string]\n", + argv[0], argv[0]); + return -1; +} + +static void +print_tasklist (GDataTasksTasklist *tasklist) +{ + const gchar *id, *title, *description; + + id = gdata_entry_get_id (GDATA_ENTRY (tasklist)); + title = gdata_entry_get_title (GDATA_ENTRY (tasklist)); + description = gdata_entry_get_summary (GDATA_ENTRY (tasklist)); + + g_print ("%s — %s\n", id, title); + g_print (" Description:\n %s\n", description); + + g_print ("\n"); +} + +static const gchar * +format_status (const gchar *status) +{ + if (g_strcmp0 (status, GDATA_TASKS_STATUS_NEEDS_ACTION) == 0) + return "needs action"; + else if (g_strcmp0 (status, GDATA_TASKS_STATUS_COMPLETED) == 0) + return "completed"; + else + return status; +} + +static void +print_task (GDataTasksTask *task) +{ + const gchar *title, *id, *description, *parent_id, *position, *notes; + const gchar *status; + GTimeVal date_published_tv = { 0, }; + gchar *date_published = NULL; /* owned */ + GTimeVal due_tv = { 0, }; + gchar *due = NULL; /* owned */ + GTimeVal completed_tv = { 0, }; + gchar *completed = NULL; /* owned */ + gboolean is_deleted, is_hidden; + + title = gdata_entry_get_title (GDATA_ENTRY (task)); + id = gdata_entry_get_id (GDATA_ENTRY (task)); + description = gdata_entry_get_content (GDATA_ENTRY (task)); + date_published_tv.tv_sec = gdata_entry_get_published (GDATA_ENTRY (task)); + date_published = g_time_val_to_iso8601 (&date_published_tv); + parent_id = gdata_tasks_task_get_parent (task); + position = gdata_tasks_task_get_position (task); + notes = gdata_tasks_task_get_notes (task); + status = gdata_tasks_task_get_status (task); + due_tv.tv_sec = gdata_tasks_task_get_due (task); + due = g_time_val_to_iso8601 (&due_tv); + completed_tv.tv_sec = gdata_tasks_task_get_completed (task); + completed = g_time_val_to_iso8601 (&completed_tv); + is_deleted = gdata_tasks_task_is_deleted (task); + is_hidden = gdata_tasks_task_is_hidden (task); + + g_print ("%s — %s\n", id, title); + g_print (" Published: %s\n", date_published_tv.tv_sec != 0 ? date_published : "unknown"); + g_print (" Status: %s\n", format_status (status)); + g_print (" Due: %s\n", due_tv.tv_sec != 0 ? due : "not set"); + g_print (" Completed: %s\n", completed_tv.tv_sec != 0 ? completed : "not yet"); + g_print (" Deleted? %s\n", is_deleted ? "Yes" : "No"); + g_print (" Hidden? %s\n", is_hidden ? "Yes" : "No"); + g_print (" Position: %s\n", position); + g_print (" Parent ID: %s\n", parent_id); + g_print (" Description:\n %s\n", description); + g_print (" Notes:\n %s\n", notes); + + g_print ("\n"); + + g_free (completed); + g_free (due); + g_free (date_published); +} + +/* FIXME: Factor all this code out of all the demos */ +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_TASKS_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); +} + +/* List all the user’s task-lists. */ +static int +command_tasklists (int argc, char *argv[]) +{ + GDataTasksService *service = NULL; + GDataTasksQuery *query = NULL; + GDataFeed *feed = NULL; + GList/**/ *entries; + GError *error = NULL; + gint retval = 0; + GDataAuthorizer *authorizer = NULL; + + if (argc != 2) { + return print_usage (argv); + } + + /* 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_tasks_service_new (authorizer); + query = gdata_tasks_query_new (NULL); + + feed = gdata_tasks_service_query_all_tasklists (service, + GDATA_QUERY (query), + NULL, NULL, + NULL, + &error); + + if (error != NULL) { + g_printerr ("%s: Error querying tasklists: %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) { + GDataTasksTasklist *tasklist; + + tasklist = GDATA_TASKS_TASKLIST (entries->data); + print_tasklist (tasklist); + } + + g_print ("Total of %u results.\n", + g_list_length (gdata_feed_get_entries (feed))); + +done: + g_clear_object (&feed); + g_clear_object (&query); + g_clear_object (&authorizer); + g_clear_object (&service); + + return retval; +} + +/* Query the tasks in a tasklist. */ +static int +command_tasks (int argc, char *argv[]) +{ + GDataTasksService *service = NULL; + GDataTasksTasklist *tasklist = NULL; + GDataTasksQuery *query = NULL; + GError *error = NULL; + gint retval = 0; + const gchar *query_string, *tasklist_id; + GDataAuthorizer *authorizer = NULL; + guint n_results; + + if (argc < 3) { + return print_usage (argv); + } + + tasklist_id = argv[2]; + query_string = (argc > 3) ? argv[3] : NULL; + + /* 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_tasks_service_new (authorizer); + query = gdata_tasks_query_new (query_string); + gdata_query_set_max_results (GDATA_QUERY (query), 10); + tasklist = gdata_tasks_tasklist_new (tasklist_id); + n_results = 0; + + while (TRUE) { + GList/**/ *entries, *l; + GDataFeed *feed = NULL; + + feed = gdata_tasks_service_query_tasks (service, tasklist, + GDATA_QUERY (query), + NULL, NULL, NULL, + &error); + + if (error != NULL) { + g_printerr ("%s: Error querying tasks: %s\n", + argv[0], error->message); + g_error_free (error); + retval = 1; + goto done; + } + + /* Print results. */ + entries = gdata_feed_get_entries (feed); + + if (entries == NULL) { + retval = 0; + g_object_unref (feed); + break; + } + + for (l = entries; l != NULL; l = l->next) { + GDataTasksTask *task; + + task = GDATA_TASKS_TASK (l->data); + print_task (task); + n_results++; + } + + gdata_query_next_page (GDATA_QUERY (query)); + g_object_unref (feed); + } + + g_print ("Total of %u results.\n", n_results); + +done: + g_clear_object (&query); + g_clear_object (&authorizer); + g_clear_object (&tasklist); + g_clear_object (&service); + + return retval; +} + +static const struct { + const gchar *command; + int (*handler_fn) (int argc, char **argv); +} command_handlers[] = { + { "tasklists", command_tasklists }, + { "tasks", command_tasks }, +}; + +int +main (int argc, char *argv[]) +{ + guint i; + gint retval = -1; + + setlocale (LC_ALL, ""); + + 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 (argc, argv); + } + } + + if (retval == -1) { + retval = print_usage (argv); + } + + return retval; +} -- cgit v1.2.1