[recipes/todoist-2: 2/3] Send ingredients to todoist
- From: Ekta Nandwani <ektan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [recipes/todoist-2: 2/3] Send ingredients to todoist
- Date: Sat, 5 Aug 2017 15:28:49 +0000 (UTC)
commit 292d006b9fce989d0f011af9a7061c923408b218
Author: Ekta Nandwani <mailnandwaniekta gmail com>
Date: Wed Jul 19 07:52:58 2017 +0530
Send ingredients to todoist
meson.build | 2 +
src/gr-ingredients-exporter.c | 472 ++++++++++++++++++++++++++++++------
src/gr-ingredients-exporter.h | 1 +
src/gr-shopping-page.c | 6 +-
src/gr-shopping-page.h | 2 +
src/ingredients-exporter-dialog.ui | 1 +
6 files changed, 404 insertions(+), 80 deletions(-)
---
diff --git a/meson.build b/meson.build
index 1a7535f..432a672 100644
--- a/meson.build
+++ b/meson.build
@@ -83,6 +83,8 @@ deps = [ dependency('gtk+-3.0', version : '>=3.22'),
dependency('gmodule-export-2.0'),
dependency('libsoup-2.4'),
dependency('goa-1.0'),
+ dependency('rest-0.7'),
+ dependency('json-glib-1.0'),
autoar_dep,
gspell_dep,
canberra_dep,
diff --git a/src/gr-ingredients-exporter.c b/src/gr-ingredients-exporter.c
index 1cfbf7c..0e9bce7 100644
--- a/src/gr-ingredients-exporter.c
+++ b/src/gr-ingredients-exporter.c
@@ -25,14 +25,28 @@
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <goa/goa.h>
+#include <rest/oauth2-proxy.h>
+#include <json-glib/json-glib.h>
#include "gr-ingredients-exporter.h"
+#include "gr-recipe-store.h"
+#include "gr-shopping-page.h"
+
+#define TODOIST_URL "https://todoist.com/API/v7/sync"
+
+static void
+get_project_id (GrIngredientsExporter *exporter);
struct _GrIngredientsExporter
{
GObject parent_instance;
GtkWindow *window;
+ gchar *access_token;
+ GoaObject *account_object;
+ gchar *sync_token;
+ glong project_id;
+
GtkWidget *export_button;
GtkWidget *cancel_button;
GtkWidget *back_button;
@@ -42,6 +56,11 @@
GtkWidget *dialog_stack;
GtkWidget *header_start_stack;
GtkWidget *header;
+ GtkWidget *providers_list;
+ GtkWidget *accounts_list;
+ GtkWidget *account_row_selected;
+
+ GList *ingredients;
};
@@ -82,33 +101,158 @@ gr_ingredients_exporter_new (GtkWindow *parent)
}
static void
+get_ingredients_list(GrIngredientsExporter *exporter)
+{
+ GtkWidget *shopping_page;
+
+ shopping_page = gr_shopping_page_new ();
+ gr_shopping_page_populate (GR_SHOPPING_PAGE(shopping_page));
+ exporter->ingredients = get_ingredients (GR_SHOPPING_PAGE(shopping_page));
+ g_print("inside get_ingredients_list\n");
+}
+
+static void
switch_dialog_contents (GrIngredientsExporter *exporter)
{
- if (gtk_stack_get_visible_child (GTK_STACK (exporter->dialog_stack)) == exporter->accounts_box)
- {
- if (!exporter->providers_box)
- g_print("providers_box empty");
- gtk_widget_set_visible (exporter->export_button, FALSE);
- gtk_stack_set_visible_child_name (GTK_STACK (exporter->dialog_stack), "providers_box");
- gtk_stack_set_visible_child_name (GTK_STACK (exporter->header_start_stack), "back");
- gtk_header_bar_set_title (GTK_HEADER_BAR (exporter->header), "Add Account");
- }
- else
- // if (gtk_stack_get_visible_child (GTK_STACK (exporter->dialog_stack)) == exporter->providers_box)
- {
- gtk_widget_set_visible (exporter->export_button, TRUE);
- gtk_stack_set_visible_child (GTK_STACK (exporter->dialog_stack), exporter->accounts_box);
- gtk_stack_set_visible_child_name (GTK_STACK (exporter->header_start_stack), "cancel_button");
- gtk_header_bar_set_title (GTK_HEADER_BAR (exporter->header), "Export Ingredients");
- }
- //gtk_widget_set_visible (exporter->accounts_box, FALSE);
-
+ if (gtk_stack_get_visible_child (GTK_STACK (exporter->dialog_stack)) ==
exporter->accounts_box)
+ {
+ if (!exporter->providers_box)
+ g_print("providers_box empty");
+ gtk_widget_set_visible (exporter->export_button, FALSE);
+ gtk_stack_set_visible_child_name (GTK_STACK (exporter->dialog_stack),
"providers_box");
+ gtk_stack_set_visible_child_name (GTK_STACK (exporter->header_start_stack), "back");
+ gtk_header_bar_set_title (GTK_HEADER_BAR (exporter->header), "Add Account");
+ }
+ else
+ {
+ gtk_widget_set_visible (exporter->export_button, TRUE);
+ gtk_stack_set_visible_child (GTK_STACK (exporter->dialog_stack),
exporter->accounts_box);
+ gtk_stack_set_visible_child_name (GTK_STACK (exporter->header_start_stack),
"cancel_button");
+ gtk_header_bar_set_title (GTK_HEADER_BAR (exporter->header), "Export Ingredients");
+ }
+}
+static void
+export_shopping_list_callback (RestProxyCall *call, GError *error, GObject *obj, GrIngredientsExporter
*exporter)
+{
+ JsonObject *object;
+ JsonParser *parser;
+ GError *parse_error;
+ const gchar *payload;
+ guint status_code;
+ gsize payload_length;
+ gchar *sync_token;
+ GList *lists;
+ GList *l;
+
+ g_print("reaches do_something_here\n");
+ parse_error = NULL;
+ status_code = rest_proxy_call_get_status_code (call);
+ parser = json_parser_new ();
+
+ if (status_code != 200)
+ {
+ g_print("status code %d", status_code);
+ goto out;
+ }
+
+ payload = rest_proxy_call_get_payload (call);
+ payload_length = rest_proxy_call_get_payload_length (call);
+
+ if (!json_parser_load_from_data (parser, payload, payload_length, &parse_error))
+ {
+ g_clear_error (&parse_error);
+ goto out;
+ }
+
+ object = json_node_dup_object (json_parser_get_root (parser));
+
+ if (!object)
+ {
+ g_print("No Data found");
+ }
+ sync_token = json_object_get_string_member (object, "sync_token");
+ g_print("%s",sync_token);
+ exporter->sync_token;
+
+ json_object_unref (object);
+
+ out:
+ g_object_unref (parser);
}
+
+
static void
-export_shopping_list (GtkLabel *label, const char *uri, GrIngredientsExporter *exporter)
+export_shopping_list (GrIngredientsExporter *exporter)
{
- g_print ("export_shopping_list\n");
+
+ GError *error;
+ JsonObject *params;
+ JsonObject *project;
+ params = json_object_new ();
+ project = json_object_new ();
+ GList *l;
+ RestProxy *proxy;
+ RestProxyCall *call;
+ GString *commands;
+ commands = g_string_new ("");
+ error = NULL;
+ GString *commands_arg;
+
+
+ json_object_set_string_member (project, "type", "project_add");
+ json_object_set_string_member (project, "args", "{\"name\": \"Project4\"}");
+
+ get_ingredients_list(exporter);
+
+ for (l = exporter->ingredients; l != NULL; l = l->next)
+ {
+ GString *s;
+
+ ShoppingListItem *item = l->data;
+ s = g_string_new ("");
+ g_string_append_printf (s, "%s %s", item->amount, item->name);
+ g_print ("appending item");
+ g_print("%s\n",s->str);
+ gchar *uuid = g_uuid_string_random();
+ gchar *temp_id = g_uuid_string_random();
+
+ g_string_append_printf (commands, "{\"type\": \"item_add\",
\"temp_id\":\"%s\",\"uuid\":\"%s\", "
+ "\"args\":{\"content\":\"%s\",\"project_id\":%ld}},",
+ temp_id, uuid,
+ s->str, exporter->project_id);
+ }
+ g_print("exits the loop");
+ g_print("%d",commands->len);
+ commands = g_string_truncate (commands, commands->len-1);
+ commands_arg = g_string_new("[");
+ g_string_append_printf (commands_arg, "%s]", commands->str);
+
+
+ proxy = rest_proxy_new ("https://todoist.com/API/v7/sync", FALSE);
+ call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call, "POST");
+ rest_proxy_call_add_header (call, "content-type", "application/x-www-form-urlencoded");
+ rest_proxy_call_add_param (call, "token", exporter->access_token);
+
+ if(!exporter->sync_token)
+ rest_proxy_call_add_param (call, "sync_token", "\'*\'");
+ else
+ rest_proxy_call_add_param (call, "sync_token", exporter->sync_token);
+
+ rest_proxy_call_add_param (call, "commands", commands_arg->str);
+
+ if (!rest_proxy_call_async (call, (RestProxyCallAsyncCallback) export_shopping_list_callback,
+ NULL,
+ exporter,
+ &error))
+ {
+ g_print("calling async failed\n");
+ }
+
+ g_object_unref (proxy);
+ g_object_unref (call);
+
}
static void
@@ -117,6 +261,228 @@ cancel_export (GrIngredientsExporter *exporter)
g_print ("cancel_export\n");
}
+static GtkWidget *
+get_selected_account (GtkListBox *list, GrIngredientsExporter *exporter)
+{
+ g_print("get_selected_account\n");
+
+ exporter->account_row_selected = GTK_WIDGET (gtk_list_box_get_selected_row (list));
+}
+
+static gboolean
+get_todoist_account(GrIngredientsExporter *exporter)
+{
+
+ GoaClient *client;
+ GList *accounts, *l;
+ GoaAccount *account;
+ GError *error;
+
+ client = goa_client_new_sync (NULL, &error);
+
+ if (!client)
+ {
+ g_error ("Could not create GoaClient: %s", error->message);
+ return;
+ }
+
+ accounts = goa_client_get_accounts (client);
+ for (l = accounts; l != NULL; l = l->next)
+ {
+ const gchar *provider_type;
+
+ account = goa_object_get_account (GOA_OBJECT (l->data));
+ provider_type = goa_account_get_provider_name (account);
+ g_print("%s",provider_type);
+
+ if (g_strcmp0 (provider_type, "Todoist") == 0)
+ {
+ exporter->account_object = GOA_OBJECT(l->data);
+ g_print("provider type %s \n", goa_account_get_provider_type(account));
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+ }
+}
+
+static void get_access_token (GrIngredientsExporter *exporter)
+{
+
+
+ GoaObject *account_object;
+ gchar *access_token;
+ GoaOAuth2Based *oauth2 = NULL;
+ GError *error;
+
+
+
+ error = NULL;
+ oauth2 = goa_object_get_oauth2_based (GOA_OBJECT (exporter->account_object));
+
+ if (!goa_oauth2_based_call_get_access_token_sync (oauth2, &access_token, NULL, NULL, &error))
+ {
+ g_print("access token not found!");
+ }
+
+ if (exporter->todoist_row == exporter->account_row_selected)
+ {
+ g_print ("export the list here\n");
+ }
+ exporter->access_token = access_token;
+ g_print("%s",access_token);
+}
+
+static void
+get_project_id (GrIngredientsExporter *exporter)
+{
+ RestProxy *proxy;
+ RestProxyCall *call;
+ GError *error;
+ JsonObject *params;
+ JsonObject *project;
+ params = json_object_new ();
+ project = json_object_new ();
+
+
+ proxy = rest_proxy_new (TODOIST_URL, FALSE);
+ call = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call, "POST");
+ rest_proxy_call_add_header (call, "content-type", "application/x-www-form-urlencoded");
+ rest_proxy_call_add_param (call, "token", exporter->access_token);
+ if(!exporter->sync_token)
+ rest_proxy_call_add_param (call, "sync_token", "\'*\'");
+ else
+ rest_proxy_call_add_param (call, "sync_token", exporter->sync_token);
+ rest_proxy_call_add_param (call, "resource_types", "[\"projects\"]");
+
+ if (!rest_proxy_call_sync (call,
+ &error))
+
+ {
+ g_clear_error (&error);
+
+ }
+
+ g_object_unref(proxy);
+ JsonObject *object;
+ JsonParser *parser;
+ GError *parse_error;
+ const gchar *payload;
+ guint status_code;
+ gsize payload_length;
+ gchar *sync_token;
+ GList *lists;
+ GList *l;
+ JsonArray *projects;
+ RestProxyCall *call2;
+
+ parse_error = NULL;
+ status_code = rest_proxy_call_get_status_code (call);
+ parser = json_parser_new ();
+
+ if (status_code != 200)
+ {
+ g_print("status code %d", status_code);
+
+ }
+
+ payload = rest_proxy_call_get_payload (call);
+ payload_length = rest_proxy_call_get_payload_length (call);
+
+ if (!json_parser_load_from_data (parser, payload, payload_length, &parse_error))
+ {
+ g_clear_error (&parse_error);
+ }
+
+ object = json_node_dup_object (json_parser_get_root (parser));
+ if (!object)
+ g_print("No Data found");
+
+ projects = json_object_get_array_member (object, "projects");
+
+ lists = json_array_get_elements (projects);
+
+ for (l = lists; l != NULL; l = l->next)
+ {
+ JsonObject *object;
+
+ const gchar *name;
+ double id;
+
+ object = json_node_get_object (l->data);
+
+ name = json_object_get_string_member (object, "name");
+ g_print("%s" , name);
+ if (strcmp (name, "Shopping List from Recipes") == 0)
+ {
+ id = json_object_get_double_member (object, "id");
+ exporter->project_id = (glong)malloc(sizeof(glong));
+ g_print ("size of project_id %d" , sizeof(exporter->project_id));
+ (exporter->project_id) = (glong) id;
+ g_print("id : %ld\n",exporter->project_id);
+ goto export;
+ }
+ }
+
+ if (exporter->project_id == NULL)
+ {
+ gchar *uuid = g_uuid_string_random();
+ gchar *temp_id = g_uuid_string_random();
+ guint status_code2;
+ GString *project_add_commands;
+ project_add_commands = g_string_new ("");
+ g_print("inside the loop to add project_id");
+ proxy = rest_proxy_new (TODOIST_URL, FALSE);
+ call2 = rest_proxy_new_call (proxy);
+ rest_proxy_call_set_method (call2, "POST");
+ rest_proxy_call_add_header (call2, "content-type", "application/x-www-form-urlencoded");
+ rest_proxy_call_add_param (call2, "token", exporter->access_token);
+ if(!exporter->sync_token)
+ rest_proxy_call_add_param (call2, "sync_token", "\'*\'");
+ else
+ rest_proxy_call_add_param (call2, "sync_token", exporter->sync_token);
+
+ g_string_append_printf (project_add_commands, "[{\"type\": \"project_add\",
\"temp_id\":\"%s\",\"uuid\":\"%s\", "
+ "\"args\":{\"name\":\"Shopping List from Recipes\"}}]",
+ temp_id, uuid);
+
+
+ rest_proxy_call_add_param (call2, "commands",project_add_commands->str);
+
+ if (!rest_proxy_call_sync (call2,
+ &error))
+ {
+ g_clear_error (&error);
+
+ }
+ status_code2 = rest_proxy_call_get_status_code (call2);
+ if (status_code2 != 200)
+ {
+ g_print("status code %d", status_code);
+ }
+ get_project_id(exporter);
+ }
+
+ export:
+ if (exporter->project_id)
+ {
+ export_shopping_list (exporter);
+ }
+
+}
+
+static void
+initialize_export (GrIngredientsExporter *exporter) {
+
+ get_access_token (exporter);
+ if (exporter->project_id == NULL)
+ {
+ get_project_id (exporter);
+ }
+}
+
static void
show_export_dialog (GrIngredientsExporter *exporter)
@@ -139,66 +505,19 @@ show_export_dialog (GrIngredientsExporter *exporter)
exporter->dialog_stack = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_stack"));
exporter->header_start_stack = GTK_WIDGET (gtk_builder_get_object (builder, "header_start_stack"));
exporter->header = GTK_WIDGET (gtk_builder_get_object (builder, "header"));
+ exporter->providers_list = GTK_WIDGET (gtk_builder_get_object (builder, "providers_list"));
+ exporter->accounts_list = GTK_WIDGET (gtk_builder_get_object (builder, "accounts_list"));
g_signal_connect_swapped (add_service, "activate-link", G_CALLBACK (switch_dialog_contents),
exporter);
g_signal_connect_swapped (exporter->back_button, "clicked", G_CALLBACK (switch_dialog_contents),
exporter);
- g_signal_connect (exporter->export_button, "clicked", G_CALLBACK (export_shopping_list), exporter);
+ g_signal_connect_swapped (exporter->export_button, "clicked", G_CALLBACK (initialize_export),
exporter);
g_signal_connect (exporter->cancel_button, "clicked", G_CALLBACK (cancel_export), exporter);
+ g_signal_connect (exporter->accounts_list, "selected-rows-changed", G_CALLBACK
(get_selected_account), exporter);
-
-
- GoaClient *client;
- GList *accounts, *l;
- GoaAccount *account;
- GError *error;
-
- client = goa_client_new_sync (NULL, &error);
-
- if (!client)
- {
- g_error ("Could not create GoaClient: %s", error->message);
- return;
- }
-
- accounts = goa_client_get_accounts (client);
- for (l = accounts; l != NULL; l = l->next)
- {
- GoaOAuth2Based *oauth2 = NULL;
-
- account = goa_object_get_account (GOA_OBJECT (l->data));
- if (strcmp (goa_account_get_provider_name (account), "Todoist"))
- {
- gtk_widget_set_visible (exporter->todoist_row, TRUE);
- }
- g_print ("%s at %s (%s)\n",
- goa_account_get_presentation_identity (account),
- goa_account_get_provider_name (account),
- goa_account_get_provider_type (account));
- oauth2 = goa_object_get_oauth2_based (GOA_OBJECT (l->data));
- if (oauth2)
- {
- gchar *access_token;
- if (goa_oauth2_based_call_get_access_token_sync (oauth2,
- &access_token,
- NULL,
- NULL,
- NULL))
- {
- g_print ("\tAccessToken: %s\n", access_token);
- g_free (access_token);
- }
- g_print ("\tClientId: %s\n\tClientSecret: %s\n",
- goa_oauth2_based_get_client_id (oauth2),
- goa_oauth2_based_get_client_secret (oauth2));
- }
- g_clear_object (&oauth2);
- }
-
- //GtkWidget *list;
- //gtk_widget_set_visible (exporter->todoist_row, TRUE);
-
- //gtk_builder_add_callback_symbol (GtkBuilder *builder, const gchar *callback_name,
- // GCallback callback_symbol);
+ if (get_todoist_account (exporter))
+ {
+ gtk_widget_set_visible (exporter->todoist_row, TRUE);
+ }
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (exporter->window));
gtk_widget_show (dialog);
@@ -207,6 +526,5 @@ show_export_dialog (GrIngredientsExporter *exporter)
void
gr_ingredients_exporter_export (GrIngredientsExporter *exporter)
{
- // check_todoist_present(exporter);
show_export_dialog (exporter);
}
diff --git a/src/gr-ingredients-exporter.h b/src/gr-ingredients-exporter.h
index 3de3ec6..6c83d54 100644
--- a/src/gr-ingredients-exporter.h
+++ b/src/gr-ingredients-exporter.h
@@ -22,6 +22,7 @@
#include <gtk/gtk.h>
#include "gr-recipe.h"
+#include "gr-shopping-list-printer.h"
G_BEGIN_DECLS
diff --git a/src/gr-shopping-page.c b/src/gr-shopping-page.c
index e30888d..d536502 100644
--- a/src/gr-shopping-page.c
+++ b/src/gr-shopping-page.c
@@ -625,7 +625,7 @@ clear_list (GrShoppingPage *page)
gr_window_go_back (GR_WINDOW (window));
}
-static GList *
+GList *
get_recipes (GrShoppingPage *page)
{
GList *children, *l, *recipes;
@@ -644,7 +644,7 @@ get_recipes (GrShoppingPage *page)
return recipes;
}
-static GList *
+GList *
get_ingredients (GrShoppingPage *page)
{
GList *children, *l, *ingredients;
@@ -781,7 +781,7 @@ mail_done (GObject *source,
static void
open_export_shopping_list_dialog (GrShoppingPage *page)
{
- g_print("inside share");
+ g_print("inside share\n");
if (!page->exporter) {
GtkWidget *window;
diff --git a/src/gr-shopping-page.h b/src/gr-shopping-page.h
index 6992d63..987f0ec 100644
--- a/src/gr-shopping-page.h
+++ b/src/gr-shopping-page.h
@@ -32,6 +32,8 @@ G_DECLARE_FINAL_TYPE (GrShoppingPage, gr_shopping_page, GR, SHOPPING_PAGE, GtkBo
GtkWidget *gr_shopping_page_new (void);
+GList * get_ingredients (GrShoppingPage *page);
+
void gr_shopping_page_populate (GrShoppingPage *self);
G_END_DECLS
diff --git a/src/ingredients-exporter-dialog.ui b/src/ingredients-exporter-dialog.ui
index 775a2ad..cb50332 100644
--- a/src/ingredients-exporter-dialog.ui
+++ b/src/ingredients-exporter-dialog.ui
@@ -171,6 +171,7 @@
<object class="GtkListBox" id="providers_list">
<property name="selection_mode">single</property>
<property name="visible">1</property>
+ <signal name="selected-rows-changed" handler="row_changed"/>
<style>
<class name="frame"/>
</style>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]