aboutsummaryrefslogtreecommitdiffstats
path: root/protocols/twitter/twitter_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/twitter/twitter_lib.c')
-rw-r--r--protocols/twitter/twitter_lib.c653
1 files changed, 297 insertions, 356 deletions
diff --git a/protocols/twitter/twitter_lib.c b/protocols/twitter/twitter_lib.c
index e8fb3530..14e98c53 100644
--- a/protocols/twitter/twitter_lib.c
+++ b/protocols/twitter/twitter_lib.c
@@ -54,7 +54,6 @@ struct twitter_xml_list {
int type;
gint64 next_cursor;
GSList *list;
- gpointer data;
};
struct twitter_xml_user {
@@ -103,11 +102,13 @@ static void txl_free(struct twitter_xml_list *txl)
GSList *l;
if (txl == NULL)
return;
- for ( l = txl->list; l ; l = g_slist_next(l) )
+ for (l = txl->list; l; l = g_slist_next(l))
if (txl->type == TXL_STATUS)
- txs_free((struct twitter_xml_status *)l->data);
+ txs_free((struct twitter_xml_status *) l->data);
else if (txl->type == TXL_ID)
g_free(l->data);
+ else if (txl->type == TXL_USER)
+ txu_free(l->data);
g_slist_free(txl->list);
g_free(txl);
}
@@ -119,55 +120,48 @@ static void twitter_add_buddy(struct im_connection *ic, char *name, const char *
{
struct twitter_data *td = ic->proto_data;
- // Check if the buddy is allready in the buddy list.
- if (!bee_user_by_handle( ic->bee, ic, name ))
- {
+ // Check if the buddy is already in the buddy list.
+ if (!bee_user_by_handle(ic->bee, ic, name)) {
char *mode = set_getstr(&ic->acc->set, "mode");
-
+
// The buddy is not in the list, add the buddy and set the status to logged in.
- imcb_add_buddy( ic, name, NULL );
- imcb_rename_buddy( ic, name, fullname );
- if (g_strcasecmp(mode, "chat") == 0)
- {
+ imcb_add_buddy(ic, name, NULL);
+ imcb_rename_buddy(ic, name, fullname);
+ if (g_strcasecmp(mode, "chat") == 0) {
/* Necessary so that nicks always get translated to the
exact Twitter username. */
- imcb_buddy_nick_hint( ic, name, name );
- imcb_chat_add_buddy( td->home_timeline_gc, name );
- }
- else if (g_strcasecmp(mode, "many") == 0)
- imcb_buddy_status( ic, name, OPT_LOGGED_IN, NULL, NULL );
+ imcb_buddy_nick_hint(ic, name, name);
+ imcb_chat_add_buddy(td->home_timeline_gc, name);
+ } else if (g_strcasecmp(mode, "many") == 0)
+ imcb_buddy_status(ic, name, OPT_LOGGED_IN, NULL, NULL);
}
}
/* Warning: May return a malloc()ed value, which will be free()d on the next
- call. Only for short-term use. */
-static char *twitter_parse_error(struct http_request *req)
+ call. Only for short-term use. NOT THREADSAFE! */
+char *twitter_parse_error(struct http_request *req)
{
static char *ret = NULL;
struct xt_parser *xp = NULL;
- struct xt_node *node;
-
+ struct xt_node *node, *err;
+
g_free(ret);
ret = NULL;
-
- if (req->body_size > 0)
- {
+
+ if (req->body_size > 0) {
xp = xt_new(NULL, NULL);
xt_feed(xp, req->reply_body, req->body_size);
- if ((node = xt_find_node(xp->root, "hash")) &&
- (node = xt_find_node(node->children, "error")) &&
- node->text_len > 0)
- {
- ret = g_strdup_printf("%s (%s)", req->status_string, node->text);
- xt_free(xp);
- return ret;
- }
-
+ for (node = xp->root; node; node = node->next)
+ if ((err = xt_find_node(node->children, "error")) && err->text_len > 0) {
+ ret = g_strdup_printf("%s (%s)", req->status_string, err->text);
+ break;
+ }
+
xt_free(xp);
}
-
- return req->status_string;
+
+ return ret ? ret : req->status_string;
}
static void twitter_http_get_friends_ids(struct http_request *req);
@@ -177,10 +171,10 @@ static void twitter_http_get_friends_ids(struct http_request *req);
*/
void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor)
{
- // Primitive, but hey! It works...
- char* args[2];
+ // Primitive, but hey! It works...
+ char *args[2];
args[0] = "cursor";
- args[1] = g_strdup_printf ("%lld", (long long) next_cursor);
+ args[1] = g_strdup_printf("%lld", (long long) next_cursor);
twitter_http(ic, TWITTER_FRIENDS_IDS_URL, twitter_http_get_friends_ids, ic, 0, args, 2);
g_free(args[1]);
@@ -189,13 +183,13 @@ void twitter_get_friends_ids(struct im_connection *ic, gint64 next_cursor)
/**
* Function to help fill a list.
*/
-static xt_status twitter_xt_next_cursor( struct xt_node *node, struct twitter_xml_list *txl )
+static xt_status twitter_xt_next_cursor(struct xt_node *node, struct twitter_xml_list *txl)
{
char *end = NULL;
-
- if( node->text )
- txl->next_cursor = g_ascii_strtoll( node->text, &end, 10 );
- if( end == NULL )
+
+ if (node->text)
+ txl->next_cursor = g_ascii_strtoll(node->text, &end, 10);
+ if (end == NULL)
txl->next_cursor = -1;
return XT_HANDLED;
@@ -204,24 +198,23 @@ static xt_status twitter_xt_next_cursor( struct xt_node *node, struct twitter_xm
/**
* Fill a list of ids.
*/
-static xt_status twitter_xt_get_friends_id_list( struct xt_node *node, struct twitter_xml_list *txl )
+static xt_status twitter_xt_get_friends_id_list(struct xt_node *node, struct twitter_xml_list *txl)
{
struct xt_node *child;
-
+
// Set the list type.
txl->type = TXL_ID;
// The root <statuses> node should hold the list of statuses <status>
// Walk over the nodes children.
- for( child = node->children ; child ; child = child->next )
- {
- if ( g_strcasecmp( "id", child->name ) == 0)
- {
- // Add the item to the list.
- txl->list = g_slist_append (txl->list, g_memdup( child->text, child->text_len + 1 ));
- }
- else if ( g_strcasecmp( "next_cursor", child->name ) == 0)
- {
+ for (child = node->children; child; child = child->next) {
+ if (g_strcasecmp("ids", child->name) == 0) {
+ struct xt_node *idc;
+ for (idc = child->children; idc; idc = idc->next)
+ if (g_strcasecmp(idc->name, "id") == 0)
+ txl->list = g_slist_prepend(txl->list,
+ g_memdup(idc->text, idc->text_len + 1));
+ } else if (g_strcasecmp("next_cursor", child->name) == 0) {
twitter_xt_next_cursor(child, txl);
}
}
@@ -229,6 +222,8 @@ static xt_status twitter_xt_get_friends_id_list( struct xt_node *node, struct tw
return XT_HANDLED;
}
+static void twitter_get_users_lookup(struct im_connection *ic);
+
/**
* Callback for getting the friends ids.
*/
@@ -242,34 +237,137 @@ static void twitter_http_get_friends_ids(struct http_request *req)
ic = req->data;
// Check if the connection is still active.
- if( !g_slist_find( twitter_connections, ic ) )
+ if (!g_slist_find(twitter_connections, ic))
return;
-
+
td = ic->proto_data;
- // Check if the HTTP request went well.
- if (req->status_code != 200) {
+ // Check if the HTTP request went well. More strict checks as this is
+ // the first request we do in a session.
+ if (req->status_code == 401) {
+ imcb_error(ic, "Authentication failure");
+ imc_logout(ic, FALSE);
+ return;
+ } else if (req->status_code != 200) {
// It didn't go well, output the error and return.
- if (++td->http_fails >= 5)
- imcb_error(ic, "Could not retrieve friends: %s", twitter_parse_error(req));
-
+ imcb_error(ic, "Could not retrieve %s: %s",
+ TWITTER_FRIENDS_IDS_URL, twitter_parse_error(req));
+ imc_logout(ic, TRUE);
return;
} else {
td->http_fails = 0;
}
+ /* Create the room now that we "logged in". */
+ if (!td->home_timeline_gc && g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0)
+ twitter_groupchat_init(ic);
+
txl = g_new0(struct twitter_xml_list, 1);
+ txl->list = td->follow_ids;
// Parse the data.
- parser = xt_new( NULL, txl );
- xt_feed( parser, req->reply_body, req->body_size );
+ parser = xt_new(NULL, txl);
+ xt_feed(parser, req->reply_body, req->body_size);
twitter_xt_get_friends_id_list(parser->root, txl);
- xt_free( parser );
+ xt_free(parser);
+ td->follow_ids = txl->list;
if (txl->next_cursor)
+ /* These were just numbers. Up to 4000 in a response AFAIK so if we get here
+ we may be using a spammer account. \o/ */
twitter_get_friends_ids(ic, txl->next_cursor);
+ else
+ /* Now to convert all those numbers into names.. */
+ twitter_get_users_lookup(ic);
+
+ txl->list = NULL;
+ txl_free(txl);
+}
+
+static xt_status twitter_xt_get_users(struct xt_node *node, struct twitter_xml_list *txl);
+static void twitter_http_get_users_lookup(struct http_request *req);
+
+static void twitter_get_users_lookup(struct im_connection *ic)
+{
+ struct twitter_data *td = ic->proto_data;
+ char *args[2] = {
+ "user_id",
+ NULL,
+ };
+ GString *ids = g_string_new("");
+ int i;
+
+ /* We can request up to 100 users at a time. */
+ for (i = 0; i < 100 && td->follow_ids; i ++) {
+ g_string_append_printf(ids, ",%s", (char*) td->follow_ids->data);
+ g_free(td->follow_ids->data);
+ td->follow_ids = g_slist_remove(td->follow_ids, td->follow_ids->data);
+ }
+ if (ids->len > 0) {
+ args[1] = ids->str + 1;
+ /* POST, because I think ids can be up to 1KB long. */
+ twitter_http(ic, TWITTER_USERS_LOOKUP_URL, twitter_http_get_users_lookup, ic, 1, args, 2);
+ } else {
+ /* We have all users. Continue with login. (Get statuses.) */
+ td->flags |= TWITTER_HAVE_FRIENDS;
+ twitter_login_finish(ic);
+ }
+ g_string_free(ids, TRUE);
+}
+
+/**
+ * Callback for getting (twitter)friends...
+ *
+ * Be afraid, be very afraid! This function will potentially add hundreds of "friends". "Who has
+ * hundreds of friends?" you wonder? You probably not, since you are reading the source of
+ * BitlBee... Get a life and meet new people!
+ */
+static void twitter_http_get_users_lookup(struct http_request *req)
+{
+ struct im_connection *ic = req->data;
+ struct twitter_data *td;
+ struct xt_parser *parser;
+ struct twitter_xml_list *txl;
+ GSList *l = NULL;
+ struct twitter_xml_user *user;
+ // Check if the connection is still active.
+ if (!g_slist_find(twitter_connections, ic))
+ return;
+
+ td = ic->proto_data;
+
+ if (req->status_code != 200) {
+ // It didn't go well, output the error and return.
+ imcb_error(ic, "Could not retrieve %s: %s",
+ TWITTER_USERS_LOOKUP_URL, twitter_parse_error(req));
+ imc_logout(ic, TRUE);
+ return;
+ } else {
+ td->http_fails = 0;
+ }
+
+ txl = g_new0(struct twitter_xml_list, 1);
+ txl->list = NULL;
+
+ // Parse the data.
+ parser = xt_new(NULL, txl);
+ xt_feed(parser, req->reply_body, req->body_size);
+
+ // Get the user list from the parsed xml feed.
+ twitter_xt_get_users(parser->root, txl);
+ xt_free(parser);
+
+ // Add the users as buddies.
+ for (l = txl->list; l; l = g_slist_next(l)) {
+ user = l->data;
+ twitter_add_buddy(ic, user->screen_name, user->name);
+ }
+
+ // Free the structure.
txl_free(txl);
+
+ twitter_get_users_lookup(ic);
}
/**
@@ -278,20 +376,16 @@ static void twitter_http_get_friends_ids(struct http_request *req)
* - the name and
* - the screen_name.
*/
-static xt_status twitter_xt_get_user( struct xt_node *node, struct twitter_xml_user *txu )
+static xt_status twitter_xt_get_user(struct xt_node *node, struct twitter_xml_user *txu)
{
struct xt_node *child;
// Walk over the nodes children.
- for( child = node->children ; child ; child = child->next )
- {
- if ( g_strcasecmp( "name", child->name ) == 0)
- {
- txu->name = g_memdup( child->text, child->text_len + 1 );
- }
- else if (g_strcasecmp( "screen_name", child->name ) == 0)
- {
- txu->screen_name = g_memdup( child->text, child->text_len + 1 );
+ for (child = node->children; child; child = child->next) {
+ if (g_strcasecmp("name", child->name) == 0) {
+ txu->name = g_memdup(child->text, child->text_len + 1);
+ } else if (g_strcasecmp("screen_name", child->name) == 0) {
+ txu->screen_name = g_memdup(child->text, child->text_len + 1);
}
}
return XT_HANDLED;
@@ -302,7 +396,7 @@ static xt_status twitter_xt_get_user( struct xt_node *node, struct twitter_xml_u
* It sets:
* - all <user>s from the <users> element.
*/
-static xt_status twitter_xt_get_users( struct xt_node *node, struct twitter_xml_list *txl )
+static xt_status twitter_xt_get_users(struct xt_node *node, struct twitter_xml_list *txl)
{
struct twitter_xml_user *txu;
struct xt_node *child;
@@ -312,44 +406,12 @@ static xt_status twitter_xt_get_users( struct xt_node *node, struct twitter_xml_
// The root <users> node should hold the list of users <user>
// Walk over the nodes children.
- for( child = node->children ; child ; child = child->next )
- {
- if ( g_strcasecmp( "user", child->name ) == 0)
- {
+ for (child = node->children; child; child = child->next) {
+ if (g_strcasecmp("user", child->name) == 0) {
txu = g_new0(struct twitter_xml_user, 1);
twitter_xt_get_user(child, txu);
// Put the item in the front of the list.
- txl->list = g_slist_prepend (txl->list, txu);
- }
- }
-
- return XT_HANDLED;
-}
-
-/**
- * Function to fill a twitter_xml_list struct.
- * It calls twitter_xt_get_users to get the <user>s from a <users> element.
- * It sets:
- * - the next_cursor.
- */
-static xt_status twitter_xt_get_user_list( struct xt_node *node, struct twitter_xml_list *txl )
-{
- struct xt_node *child;
-
- // Set the type of the list.
- txl->type = TXL_USER;
-
- // The root <user_list> node should hold a users <users> element
- // Walk over the nodes children.
- for( child = node->children ; child ; child = child->next )
- {
- if ( g_strcasecmp( "users", child->name ) == 0)
- {
- twitter_xt_get_users(child, txl);
- }
- else if ( g_strcasecmp( "next_cursor", child->name ) == 0)
- {
- twitter_xt_next_cursor(child, txl);
+ txl->list = g_slist_prepend(txl->list, txu);
}
}
@@ -370,66 +432,50 @@ static xt_status twitter_xt_get_user_list( struct xt_node *node, struct twitter_
* - the status id and
* - the user in a twitter_xml_user struct.
*/
-static xt_status twitter_xt_get_status( struct xt_node *node, struct twitter_xml_status *txs )
+static xt_status twitter_xt_get_status(struct xt_node *node, struct twitter_xml_status *txs)
{
struct xt_node *child, *rt = NULL;
gboolean truncated = FALSE;
// Walk over the nodes children.
- for( child = node->children ; child ; child = child->next )
- {
- if ( g_strcasecmp( "text", child->name ) == 0)
- {
- txs->text = g_memdup( child->text, child->text_len + 1 );
- }
- else if (g_strcasecmp( "truncated", child->name ) == 0 && child->text)
- {
+ for (child = node->children; child; child = child->next) {
+ if (g_strcasecmp("text", child->name) == 0) {
+ txs->text = g_memdup(child->text, child->text_len + 1);
+ } else if (g_strcasecmp("truncated", child->name) == 0 && child->text) {
truncated = bool2int(child->text);
- }
- else if (g_strcasecmp( "retweeted_status", child->name ) == 0)
- {
+ } else if (g_strcasecmp("retweeted_status", child->name) == 0) {
rt = child;
- }
- else if (g_strcasecmp( "created_at", child->name ) == 0)
- {
+ } else if (g_strcasecmp("created_at", child->name) == 0) {
struct tm parsed;
-
+
/* Very sensitive to changes to the formatting of
this field. :-( Also assumes the timezone used
is UTC since C time handling functions suck. */
- if( strptime( child->text, TWITTER_TIME_FORMAT, &parsed ) != NULL )
- txs->created_at = mktime_utc( &parsed );
- }
- else if (g_strcasecmp( "user", child->name ) == 0)
- {
+ if (strptime(child->text, TWITTER_TIME_FORMAT, &parsed) != NULL)
+ txs->created_at = mktime_utc(&parsed);
+ } else if (g_strcasecmp("user", child->name) == 0) {
txs->user = g_new0(struct twitter_xml_user, 1);
- twitter_xt_get_user( child, txs->user );
- }
- else if (g_strcasecmp( "id", child->name ) == 0)
- {
- txs->id = g_ascii_strtoull (child->text, NULL, 10);
- }
- else if (g_strcasecmp( "in_reply_to_status_id", child->name ) == 0)
- {
- txs->reply_to = g_ascii_strtoull (child->text, NULL, 10);
+ twitter_xt_get_user(child, txs->user);
+ } else if (g_strcasecmp("id", child->name) == 0) {
+ txs->id = g_ascii_strtoull(child->text, NULL, 10);
+ } else if (g_strcasecmp("in_reply_to_status_id", child->name) == 0) {
+ txs->reply_to = g_ascii_strtoull(child->text, NULL, 10);
}
}
-
+
/* If it's a truncated retweet, get the original because dots suck. */
- if (truncated && rt)
- {
+ if (truncated && rt) {
struct twitter_xml_status *rtxs = g_new0(struct twitter_xml_status, 1);
- if (twitter_xt_get_status(rt, rtxs) != XT_HANDLED)
- {
+ if (twitter_xt_get_status(rt, rtxs) != XT_HANDLED) {
txs_free(rtxs);
return XT_HANDLED;
}
-
+
g_free(txs->text);
txs->text = g_strdup_printf("RT @%s: %s", rtxs->user->screen_name, rtxs->text);
txs_free(rtxs);
}
-
+
return XT_HANDLED;
}
@@ -439,7 +485,8 @@ static xt_status twitter_xt_get_status( struct xt_node *node, struct twitter_xml
* - all <status>es within the <status> element and
* - the next_cursor.
*/
-static xt_status twitter_xt_get_status_list( struct im_connection *ic, struct xt_node *node, struct twitter_xml_list *txl )
+static xt_status twitter_xt_get_status_list(struct im_connection *ic, struct xt_node *node,
+ struct twitter_xml_list *txl)
{
struct twitter_xml_status *txs;
struct xt_node *child;
@@ -450,29 +497,23 @@ static xt_status twitter_xt_get_status_list( struct im_connection *ic, struct xt
// The root <statuses> node should hold the list of statuses <status>
// Walk over the nodes children.
- for( child = node->children ; child ; child = child->next )
- {
- if ( g_strcasecmp( "status", child->name ) == 0)
- {
+ for (child = node->children; child; child = child->next) {
+ if (g_strcasecmp("status", child->name) == 0) {
txs = g_new0(struct twitter_xml_status, 1);
twitter_xt_get_status(child, txs);
// Put the item in the front of the list.
- txl->list = g_slist_prepend (txl->list, txs);
-
+ txl->list = g_slist_prepend(txl->list, txs);
+
if (txs->user && txs->user->screen_name &&
- (bu = bee_user_by_handle(ic->bee, ic, txs->user->screen_name)))
- {
+ (bu = bee_user_by_handle(ic->bee, ic, txs->user->screen_name))) {
struct twitter_user_data *tud = bu->data;
-
- if (txs->id > tud->last_id)
- {
+
+ if (txs->id > tud->last_id) {
tud->last_id = txs->id;
tud->last_time = txs->created_at;
}
}
- }
- else if ( g_strcasecmp( "next_cursor", child->name ) == 0)
- {
+ } else if (g_strcasecmp("next_cursor", child->name) == 0) {
twitter_xt_next_cursor(child, txl);
}
}
@@ -489,15 +530,16 @@ void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor)
{
struct twitter_data *td = ic->proto_data;
- char* args[4];
+ char *args[4];
args[0] = "cursor";
- args[1] = g_strdup_printf ("%lld", (long long) next_cursor);
+ args[1] = g_strdup_printf("%lld", (long long) next_cursor);
if (td->home_timeline_id) {
args[2] = "since_id";
- args[3] = g_strdup_printf ("%llu", (long long unsigned int) td->home_timeline_id);
+ args[3] = g_strdup_printf("%llu", (long long unsigned int) td->home_timeline_id);
}
- twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args, td->home_timeline_id ? 4 : 2);
+ twitter_http(ic, TWITTER_HOME_TIMELINE_URL, twitter_http_get_home_timeline, ic, 0, args,
+ td->home_timeline_id ? 4 : 2);
g_free(args[1]);
if (td->home_timeline_id) {
@@ -506,37 +548,33 @@ void twitter_get_home_timeline(struct im_connection *ic, gint64 next_cursor)
}
static char *twitter_msg_add_id(struct im_connection *ic,
- struct twitter_xml_status *txs, const char *prefix)
+ struct twitter_xml_status *txs, const char *prefix)
{
struct twitter_data *td = ic->proto_data;
char *ret = NULL;
-
- if (!set_getbool(&ic->acc->set, "show_ids"))
- {
+
+ if (!set_getbool(&ic->acc->set, "show_ids")) {
if (*prefix)
return g_strconcat(prefix, txs->text, NULL);
else
return NULL;
}
-
+
td->log[td->log_id].id = txs->id;
td->log[td->log_id].bu = bee_user_by_handle(ic->bee, ic, txs->user->screen_name);
- if (txs->reply_to)
- {
+ if (txs->reply_to) {
int i;
- for (i = 0; i < TWITTER_LOG_LENGTH; i ++)
- if (td->log[i].id == txs->reply_to)
- {
- ret = g_strdup_printf( "\002[\002%02d->%02d\002]\002 %s%s",
- td->log_id, i, prefix, txs->text);
+ for (i = 0; i < TWITTER_LOG_LENGTH; i++)
+ if (td->log[i].id == txs->reply_to) {
+ ret = g_strdup_printf("\002[\002%02d->%02d\002]\002 %s%s",
+ td->log_id, i, prefix, txs->text);
break;
}
}
if (ret == NULL)
- ret = g_strdup_printf( "\002[\002%02d\002]\002 %s%s",
- td->log_id, prefix, txs->text);
+ ret = g_strdup_printf("\002[\002%02d\002]\002 %s%s", td->log_id, prefix, txs->text);
td->log_id = (td->log_id + 1) % TWITTER_LOG_LENGTH;
-
+
return ret;
}
@@ -546,25 +584,24 @@ static void twitter_groupchat_init(struct im_connection *ic)
struct groupchat *gc;
struct twitter_data *td = ic->proto_data;
GSList *l;
-
- td->home_timeline_gc = gc = imcb_chat_new( ic, "home/timeline" );
-
- name_hint = g_strdup_printf( "%s_%s", td->prefix, ic->acc->user );
- imcb_chat_name_hint( gc, name_hint );
- g_free( name_hint );
-
- for( l = ic->bee->users; l; l = l->next )
- {
+
+ td->home_timeline_gc = gc = imcb_chat_new(ic, "home/timeline");
+
+ name_hint = g_strdup_printf("%s_%s", td->prefix, ic->acc->user);
+ imcb_chat_name_hint(gc, name_hint);
+ g_free(name_hint);
+
+ for (l = ic->bee->users; l; l = l->next) {
bee_user_t *bu = l->data;
- if( bu->ic == ic )
- imcb_chat_add_buddy( td->home_timeline_gc, bu->handle );
+ if (bu->ic == ic)
+ imcb_chat_add_buddy(td->home_timeline_gc, bu->handle);
}
}
/**
* Function that is called to see the statuses in a groupchat window.
*/
-static void twitter_groupchat(struct im_connection *ic, GSList *list)
+static void twitter_groupchat(struct im_connection *ic, GSList * list)
{
struct twitter_data *td = ic->proto_data;
GSList *l = NULL;
@@ -574,33 +611,32 @@ static void twitter_groupchat(struct im_connection *ic, GSList *list)
// Create a new groupchat if it does not exsist.
if (!td->home_timeline_gc)
twitter_groupchat_init(ic);
-
+
gc = td->home_timeline_gc;
if (!gc->joined)
- imcb_chat_add_buddy( gc, ic->acc->user );
+ imcb_chat_add_buddy(gc, ic->acc->user);
- for ( l = list; l ; l = g_slist_next(l) )
- {
+ for (l = list; l; l = g_slist_next(l)) {
char *msg;
-
+
status = l->data;
if (status->user == NULL || status->text == NULL)
continue;
twitter_add_buddy(ic, status->user->screen_name, status->user->name);
-
+
strip_html(status->text);
msg = twitter_msg_add_id(ic, status, "");
-
+
// Say it!
if (g_strcasecmp(td->user, status->user->screen_name) == 0)
imcb_chat_log(gc, "You: %s", msg ? msg : status->text);
else
imcb_chat_msg(gc, status->user->screen_name,
- msg ? msg : status->text, 0, status->created_at );
-
+ msg ? msg : status->text, 0, status->created_at);
+
g_free(msg);
-
+
// Update the home_timeline_id to hold the highest id, so that by the next request
// we won't pick up the updates already in the list.
td->home_timeline_id = MAX(td->home_timeline_id, status->id);
@@ -610,48 +646,45 @@ static void twitter_groupchat(struct im_connection *ic, GSList *list)
/**
* Function that is called to see statuses as private messages.
*/
-static void twitter_private_message_chat(struct im_connection *ic, GSList *list)
+static void twitter_private_message_chat(struct im_connection *ic, GSList * list)
{
struct twitter_data *td = ic->proto_data;
GSList *l = NULL;
struct twitter_xml_status *status;
char from[MAX_STRING];
gboolean mode_one;
-
- mode_one = g_strcasecmp( set_getstr( &ic->acc->set, "mode" ), "one" ) == 0;
- if( mode_one )
- {
- g_snprintf( from, sizeof( from ) - 1, "%s_%s", td->prefix, ic->acc->user );
- from[MAX_STRING-1] = '\0';
+ mode_one = g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "one") == 0;
+
+ if (mode_one) {
+ g_snprintf(from, sizeof(from) - 1, "%s_%s", td->prefix, ic->acc->user);
+ from[MAX_STRING - 1] = '\0';
}
-
- for ( l = list; l ; l = g_slist_next(l) )
- {
+
+ for (l = list; l; l = g_slist_next(l)) {
char *prefix = NULL, *text = NULL;
-
+
status = l->data;
-
- strip_html( status->text );
- if( mode_one )
+
+ strip_html(status->text);
+ if (mode_one)
prefix = g_strdup_printf("\002<\002%s\002>\002 ",
- status->user->screen_name);
+ status->user->screen_name);
else
twitter_add_buddy(ic, status->user->screen_name, status->user->name);
-
+
text = twitter_msg_add_id(ic, status, prefix ? prefix : "");
-
- imcb_buddy_msg( ic,
- mode_one ? from : status->user->screen_name,
- text ? text : status->text,
- 0, status->created_at );
-
+
+ imcb_buddy_msg(ic,
+ mode_one ? from : status->user->screen_name,
+ text ? text : status->text, 0, status->created_at);
+
// Update the home_timeline_id to hold the highest id, so that by the next request
// we won't pick up the updates already in the list.
- td->home_timeline_id = MAX(td->home_timeline_id, status->id);
-
- g_free( text );
- g_free( prefix );
+ td->home_timeline_id = MAX(td->home_timeline_id, status->id);
+
+ g_free(text);
+ g_free(prefix);
}
}
@@ -666,30 +699,26 @@ static void twitter_http_get_home_timeline(struct http_request *req)
struct twitter_xml_list *txl;
// Check if the connection is still active.
- if( !g_slist_find( twitter_connections, ic ) )
+ if (!g_slist_find(twitter_connections, ic))
return;
-
+
td = ic->proto_data;
// Check if the HTTP request went well.
- if (req->status_code == 200)
- {
+ if (req->status_code == 200) {
td->http_fails = 0;
if (!(ic->flags & OPT_LOGGED_IN))
imcb_connected(ic);
- }
- else if (req->status_code == 401)
- {
- imcb_error( ic, "Authentication failure" );
- imc_logout( ic, FALSE );
+ } else if (req->status_code == 401) {
+ imcb_error(ic, "Authentication failure");
+ imc_logout(ic, FALSE);
return;
- }
- else
- {
+ } else {
// It didn't go well, output the error and return.
if (++td->http_fails >= 5)
- imcb_error(ic, "Could not retrieve " TWITTER_HOME_TIMELINE_URL ": %s", twitter_parse_error(req));
-
+ imcb_error(ic, "Could not retrieve %s: %s",
+ TWITTER_HOME_TIMELINE_URL, twitter_parse_error(req));
+
return;
}
@@ -697,114 +726,26 @@ static void twitter_http_get_home_timeline(struct http_request *req)
txl->list = NULL;
// Parse the data.
- parser = xt_new( NULL, txl );
- xt_feed( parser, req->reply_body, req->body_size );
+ parser = xt_new(NULL, txl);
+ xt_feed(parser, req->reply_body, req->body_size);
// The root <statuses> node should hold the list of statuses <status>
twitter_xt_get_status_list(ic, parser->root, txl);
- xt_free( parser );
+ xt_free(parser);
// See if the user wants to see the messages in a groupchat window or as private messages.
- if (txl->list == NULL)
- ;
+ if (txl->list == NULL);
else if (g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0)
twitter_groupchat(ic, txl->list);
else
twitter_private_message_chat(ic, txl->list);
- // Free the structure.
+ // Free the structure.
txl_free(txl);
}
/**
- * Callback for getting (twitter)friends...
- *
- * Be afraid, be very afraid! This function will potentially add hundreds of "friends". "Who has
- * hundreds of friends?" you wonder? You probably not, since you are reading the source of
- * BitlBee... Get a life and meet new people!
- */
-static void twitter_http_get_statuses_friends(struct http_request *req)
-{
- struct im_connection *ic = req->data;
- struct twitter_data *td;
- struct xt_parser *parser;
- struct twitter_xml_list *txl;
- GSList *l = NULL;
- struct twitter_xml_user *user;
-
- // Check if the connection is still active.
- if( !g_slist_find( twitter_connections, ic ) )
- return;
-
- td = ic->proto_data;
-
- // Check if the HTTP request went well.
- if (req->status_code == 401)
- {
- imcb_error( ic, "Authentication failure" );
- imc_logout( ic, FALSE );
- return;
- } else if (req->status_code != 200) {
- // It didn't go well, output the error and return.
- imcb_error(ic, "Could not retrieve " TWITTER_SHOW_FRIENDS_URL ": %s", twitter_parse_error(req));
- imc_logout( ic, TRUE );
- return;
- } else {
- td->http_fails = 0;
- }
-
- if( !td->home_timeline_gc &&
- g_strcasecmp( set_getstr( &ic->acc->set, "mode" ), "chat" ) == 0 )
- twitter_groupchat_init( ic );
-
- txl = g_new0(struct twitter_xml_list, 1);
- txl->list = NULL;
-
- // Parse the data.
- parser = xt_new( NULL, txl );
- xt_feed( parser, req->reply_body, req->body_size );
-
- // Get the user list from the parsed xml feed.
- twitter_xt_get_user_list(parser->root, txl);
- xt_free( parser );
-
- // Add the users as buddies.
- for ( l = txl->list; l ; l = g_slist_next(l) )
- {
- user = l->data;
- twitter_add_buddy(ic, user->screen_name, user->name);
- }
-
- // if the next_cursor is set to something bigger then 0 there are more friends to gather.
- if (txl->next_cursor > 0)
- {
- twitter_get_statuses_friends(ic, txl->next_cursor);
- }
- else
- {
- td->flags |= TWITTER_HAVE_FRIENDS;
- twitter_login_finish(ic);
- }
-
- // Free the structure.
- txl_free(txl);
-}
-
-/**
- * Get the friends.
- */
-void twitter_get_statuses_friends(struct im_connection *ic, gint64 next_cursor)
-{
- char* args[2];
- args[0] = "cursor";
- args[1] = g_strdup_printf ("%lld", (long long) next_cursor);
-
- twitter_http(ic, TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, args, 2);
-
- g_free(args[1]);
-}
-
-/**
- * Callback to use after sending a post request to twitter.
+ * Callback to use after sending a POST request to twitter.
+ * (Generic, used for a few kinds of queries.)
*/
static void twitter_http_post(struct http_request *req)
{
@@ -812,47 +753,46 @@ static void twitter_http_post(struct http_request *req)
struct twitter_data *td;
// Check if the connection is still active.
- if( !g_slist_find( twitter_connections, ic ) )
+ if (!g_slist_find(twitter_connections, ic))
return;
td = ic->proto_data;
td->last_status_id = 0;
-
+
// Check if the HTTP request went well.
if (req->status_code != 200) {
// It didn't go well, output the error and return.
imcb_error(ic, "HTTP error: %s", twitter_parse_error(req));
return;
}
-
- if (req->body_size > 0)
- {
+
+ if (req->body_size > 0) {
struct xt_parser *xp = NULL;
struct xt_node *node;
-
+
xp = xt_new(NULL, NULL);
xt_feed(xp, req->reply_body, req->body_size);
-
+
if ((node = xt_find_node(xp->root, "status")) &&
(node = xt_find_node(node->children, "id")) && node->text)
- td->last_status_id = g_ascii_strtoull( node->text, NULL, 10 );
-
+ td->last_status_id = g_ascii_strtoull(node->text, NULL, 10);
+
xt_free(xp);
}
}
/**
* Function to POST a new status to twitter.
- */
+ */
void twitter_post_status(struct im_connection *ic, char *msg, guint64 in_reply_to)
{
- char* args[4] = {
+ char *args[4] = {
"status", msg,
"in_reply_to_status_id",
g_strdup_printf("%llu", (unsigned long long) in_reply_to)
};
twitter_http(ic, TWITTER_STATUS_UPDATE_URL, twitter_http_post, ic, 1,
- args, in_reply_to ? 4 : 2);
+ args, in_reply_to ? 4 : 2);
g_free(args[3]);
}
@@ -862,29 +802,29 @@ void twitter_post_status(struct im_connection *ic, char *msg, guint64 in_reply_t
*/
void twitter_direct_messages_new(struct im_connection *ic, char *who, char *msg)
{
- char* args[4];
+ char *args[4];
args[0] = "screen_name";
args[1] = who;
args[2] = "text";
args[3] = msg;
// Use the same callback as for twitter_post_status, since it does basically the same.
twitter_http(ic, TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post, ic, 1, args, 4);
-// g_free(args[1]);
-// g_free(args[3]);
}
void twitter_friendships_create_destroy(struct im_connection *ic, char *who, int create)
{
- char* args[2];
+ char *args[2];
args[0] = "screen_name";
args[1] = who;
- twitter_http(ic, create ? TWITTER_FRIENDSHIPS_CREATE_URL : TWITTER_FRIENDSHIPS_DESTROY_URL, twitter_http_post, ic, 1, args, 2);
+ twitter_http(ic, create ? TWITTER_FRIENDSHIPS_CREATE_URL : TWITTER_FRIENDSHIPS_DESTROY_URL,
+ twitter_http_post, ic, 1, args, 2);
}
void twitter_status_destroy(struct im_connection *ic, guint64 id)
{
char *url;
- url = g_strdup_printf("%s%llu%s", TWITTER_STATUS_DESTROY_URL, (unsigned long long) id, ".xml");
+ url = g_strdup_printf("%s%llu%s", TWITTER_STATUS_DESTROY_URL,
+ (unsigned long long) id, ".xml");
twitter_http(ic, url, twitter_http_post, ic, 1, NULL, 0);
g_free(url);
}
@@ -892,7 +832,8 @@ void twitter_status_destroy(struct im_connection *ic, guint64 id)
void twitter_status_retweet(struct im_connection *ic, guint64 id)
{
char *url;
- url = g_strdup_printf("%s%llu%s", TWITTER_STATUS_RETWEET_URL, (unsigned long long) id, ".xml");
+ url = g_strdup_printf("%s%llu%s", TWITTER_STATUS_RETWEET_URL,
+ (unsigned long long) id, ".xml");
twitter_http(ic, url, twitter_http_post, ic, 1, NULL, 0);
g_free(url);
}