0
+/* twitter-client.h: Wrapper for the Twitter API
0
+ * Copyright (C) 2008 Emmanuele Bassi <ebassi@gnome.org>
0
+ * This file is part of Twitter-GLib.
0
+ * This library is free software; you can redistribute it and/or
0
+ * modify it under the terms of the GNU Lesser General Public
0
+ * License as published by the Free Software Foundation; either
0
+ * version 2 of the License, or (at your option) any later version.
0
+ * This library is distributed in the hope that it will be useful,
0
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
0
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0
+ * Lesser General Public License for more details.
0
+ * SECTION:twitter-client
0
+ * @short_description: Wrapper for the Twitter API
0
+ * #TwitterClient is the main object wrapping the details of the
0
+ * In order to use Twitter through #TwitterClient, a new instance
0
+ * should be created using twitter_client_new() or
0
+ * twitter_client_new_for_user(). #TwitterClient handles every
0
+ * operation asynchronously, thus requiring a #GMainLoop running.
0
+ * Every result will emit one of the #TwitterClient signals; in
0
+ * case of error, the #GError parameter of the signals will be
0
+ * Authentication is handled automatically by setting the
0
+ * TwitterClient:email and TwitterClient:password properties.
0
+ * These two properties can be set at construction time or by
0
+ * using twitter_client_set_user(). Interactive authentication
0
+ * can be implemented by using the TwitterClient::authenticate
0
#include <libsoup/soup.h>
0
+#include "twitter-api.h"
0
+#include "twitter-client.h"
0
#include "twitter-common.h"
0
#include "twitter-enum-types.h"
0
#include "twitter-marshal.h"
0
#include "twitter-private.h"
0
-#include "twitter-client.h"
0
#include "twitter-status.h"
0
#include "twitter-timeline.h"
0
#include "twitter-user.h"
0
+#include "twitter-user-list.h"
0
-#define TWITTER_API_PUBLIC_TIMELINE "http://twitter.com/statuses/public_timeline.json"
0
-#define TWITTER_API_FRIENDS_TIMELINE "http://twitter.com/statuses/friends_timeline"
0
-#define TWITTER_API_USER_TIMELINE "http://twitter.com/statuses/user_timeline"
0
-#define TWITTER_API_SHOW "http://twitter.com/statuses/show/"
0
#define TWITTER_CLIENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TWITTER_TYPE_CLIENT, TwitterClientPrivate))
0
struct _TwitterClientPrivate
0
+ TwitterClientPrivate *priv = TWITTER_CLIENT (gobject)->priv;
0
+ priv->email = g_value_dup_string (value);
0
+ g_free (priv->password);
0
+ priv->password = g_value_dup_string (value);
0
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
0
+ TwitterClientPrivate *priv = TWITTER_CLIENT (gobject)->priv;
0
+ g_value_set_string (value, priv->email);
0
+ g_value_set_string (value, priv->password);
0
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
0
_twitter_marshal_BOOLEAN__ENUM,
0
TWITTER_TYPE_AUTH_STATE);
0
- client_signals[TIMELINE_RECEIVED] =
0
- g_signal_new ("timeline-received",
0
+ client_signals[USER_RECEIVED] =
0
+ g_signal_new ("user-received",
0
G_TYPE_FROM_CLASS (gobject_class),
0
- G_STRUCT_OFFSET (TwitterClientClass,
timeline_received),
0
+ G_STRUCT_OFFSET (TwitterClientClass,
user_received),
0
_twitter_marshal_VOID__OBJECT_POINTER,
0
- TWITTER_TYPE_
TIMELINE,
0
client_signals[STATUS_RECEIVED] =
0
g_signal_new ("status-received",
0
-twitter_client_new (void)
0
- return g_object_new (TWITTER_TYPE_CLIENT, NULL);
0
-twitter_client_new_for_user (const gchar *email,
0
- const gchar *password)
0
- return g_object_new (TWITTER_TYPE_CLIENT,
0
+static const gchar *action_names[N_CLIENT_ACTIONS] = {
0
+ TwitterClient *client;
0
+ TwitterUserList *user_list;
0
+ TwitterClient *client;
0
-get_timeline_cb (SoupSession *session,
0
+twitter_client_auth (SoupSession *session,
0
- GetTimelineClosure *closure = user_data;
0
- TwitterClient *client = closure->client;
0
+ TwitterClient *client = user_data;
0
+ TwitterClientPrivate *priv = client->priv;
0
+ gboolean retval = FALSE;
0
- status = msg->status_code;
0
- if (!SOUP_STATUS_IS_SUCCESSFUL (status))
0
+ g_signal_emit (client, client_signals[AUTHENTICATE], 0,
0
+ TWITTER_AUTH_NEGOTIATING, &retval);
0
- g_set_error (&error, TWITTER_ERROR,
0
- twitter_error_from_status (status),
0
+ soup_auth_authenticate (auth, priv->email, priv->password);
0
- g_signal_emit (client, client_signals[TIMELINE_RECEIVED], 0,
0
- closure->timeline, error);
0
+ priv->auth_complete = TRUE;
0
+ g_signal_emit (client, client_signals[AUTHENTICATE], 0,
0
+ TWITTER_AUTH_RETRY, &retval);
0
- buffer = g_strndup (msg->response_body->data,
0
- msg->response_body->length);
0
- if (G_UNLIKELY (!buffer))
0
- g_warning ("No data received");
0
+ if (G_LIKELY (retval))
0
+ soup_auth_authenticate (auth, priv->email, priv->password);
0
+ priv->auth_complete = TRUE;
0
- twitter_timeline_load_from_data (closure->timeline, buffer);
0
+ g_signal_emit (client, client_signals[AUTHENTICATE], 0,
0
+ TWITTER_AUTH_FAILED, &retval);
0
+ priv->auth_complete = FALSE;
0
- g_signal_emit (client, client_signals[TIMELINE_RECEIVED], 0,
0
- closure->timeline, NULL);
0
+twitter_client_queue_message (TwitterClient *client,
0
+ gboolean requires_auth,
0
+ SoupSessionCallback callback,
0
+ TwitterClientPrivate *priv = client->priv;
0
+ if (requires_auth && !priv->auth_id)
0
+ priv->auth_id = g_signal_connect (priv->session_async, "authenticate",
0
+ G_CALLBACK (twitter_client_auth),
0
- g_object_unref (closure->timeline);
0
- g_object_unref (closure->client);
0
+ soup_session_queue_message (priv->session_async, msg,
0
+twitter_client_new (void)
0
+ return g_object_new (TWITTER_TYPE_CLIENT, NULL);
0
+twitter_client_new_for_user (const gchar *email,
0
+ const gchar *password)
0
+ return g_object_new (TWITTER_TYPE_CLIENT,
0
+twitter_client_set_user (TwitterClient *client,
0
+ const gchar *password)
0
+ TwitterClientPrivate *priv;
0
+ g_return_if_fail (TWITTER_IS_CLIENT (client));
0
+ g_return_if_fail (email != NULL);
0
+ g_return_if_fail (password != NULL);
0
+ g_free (priv->password);
0
+ priv->email = g_strdup (email);
0
+ priv->password = g_strdup (password);
0
+ priv->auth_complete = FALSE;
0
+ g_object_notify (G_OBJECT (client), "email");
0
+ g_object_notify (G_OBJECT (client), "password");
0
+twitter_client_get_user (TwitterClient *client,
0
+ g_return_if_fail (TWITTER_IS_CLIENT (client));
0
+ *email = g_strdup (client->priv->email);
0
+ *password = g_strdup (client->priv->password);
0
+ TwitterClient *client;
0
+do_emit_user_received (gpointer data)
0
-get_status_cb (SoupSession *session,
0
+cleanup_emit_user_received (gpointer data)
0
+emit_user_received (TwitterClient *client,
0
+ TwitterUserList *list)
0
+get_user_cb (SoupSession *session,
0
GetStatusClosure *closure = user_data;
0
TwitterClient *client = closure->client;
0
+twitter_client_verify_user (TwitterClient *client)
0
+twitter_client_end_session (TwitterClient *client)
0
+ TwitterClient *client;
0
+ TwitterTimeline *timeline;
0
+do_emit_status_received (gpointer data)
0
+ EmitStatusClosure *closure = data;
0
+ TwitterStatus *status;
0
+ status = twitter_timeline_get_pos (closure->timeline,
0
+ closure->current_status);
0
+ g_signal_emit (closure->client, client_signals[STATUS_RECEIVED], 0,
0
+ closure->current_status += 1;
0
+ if (closure->current_status == closure->n_status)
0
-twitter_client_auth (SoupSession *session,
0
+cleanup_emit_status_received (gpointer data)
0
- TwitterClient *client = user_data;
0
- TwitterClientPrivate *priv = client->priv;
0
- gboolean retval = FALSE;
0
+ EmitStatusClosure *closure = data;
0
+ g_object_unref (closure->client);
0
+ g_object_unref (closure->timeline);
0
+emit_status_received (TwitterClient *client,
0
+ TwitterTimeline *timeline)
0
+ EmitStatusClosure *closure;
0
+ count = twitter_timeline_get_count (timeline);
0
+ closure = g_new (EmitStatusClosure, 1);
0
+ closure->client = g_object_ref (client);
0
+ closure->timeline = g_object_ref (timeline);
0
+ closure->n_status = count;
0
+ closure->current_status = 0;
0
+ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
0
+ do_emit_status_received,
0
+ cleanup_emit_status_received);
0
+get_timeline_cb (SoupSession *session,
0
+ GetTimelineClosure *closure = user_data;
0
+ TwitterClient *client = closure->client;
0
+ status = msg->status_code;
0
+ if (!SOUP_STATUS_IS_SUCCESSFUL (status))
0
- g_signal_emit (client, client_signals[AUTHENTICATE], 0,
0
- TWITTER_AUTH_NEGOTIATING, &retval);
0
- soup_auth_authenticate (auth, priv->email, priv->password);
0
+ g_set_error (&error, TWITTER_ERROR,
0
+ twitter_error_from_status (status),
0
- priv->auth_complete = TRUE;
0
+ g_signal_emit (client, client_signals[STATUS_RECEIVED], 0,
0
- g_signal_emit (client, client_signals[AUTHENTICATE], 0,
0
- TWITTER_AUTH_RETRY, &retval);
0
- if (G_LIKELY (retval))
0
- soup_auth_authenticate (auth, priv->email, priv->password);
0
- priv->auth_complete = TRUE;
0
+ buffer = g_strndup (msg->response_body->data,
0
+ msg->response_body->length);
0
+ if (G_UNLIKELY (!buffer))
0
+ g_warning ("No data received");
0
- g_signal_emit (client, client_signals[AUTHENTICATE], 0,
0
- TWITTER_AUTH_FAILED, &retval);
0
- priv->auth_complete = FALSE;
0
+ twitter_timeline_load_from_data (closure->timeline, buffer);
0
-twitter_client_queue_message (TwitterClient *client,
0
- gboolean requires_auth,
0
- SoupSessionCallback callback,
0
- TwitterClientPrivate *priv = client->priv;
0
+ emit_status_received (closure->client, closure->timeline);
0
- msg = soup_message_new (SOUP_METHOD_GET, url);
0
- if (requires_auth && !priv->auth_id)
0
- priv->auth_id = g_signal_connect (priv->session_async, "authenticate",
0
- G_CALLBACK (twitter_client_auth),
0
+ g_object_unref (closure->timeline);
0
+ g_object_unref (closure->client);
0
- soup_session_queue_message (priv->session_async, msg,
0
GetTimelineClosure *clos;
0
g_return_if_fail (TWITTER_IS_CLIENT (client));