Index: protocols/twitter/twitter_lib.c
===================================================================
--- protocols/twitter/twitter_lib.c	(revision 11ec07811cc41e1b244467d25772ef021be9db1b)
+++ protocols/twitter/twitter_lib.c	(revision 2a6da96544675726c73a60b588dc26e477ce70f5)
@@ -5,5 +5,5 @@
 *                                                                           *
 *  Copyright 2009-2010 Geert Mulders <g.c.w.m.mulders@gmail.com>            *
-*  Copyright 2010-2011 Wilmer van der Gaast <wilmer@gaast.net>              *
+*  Copyright 2010-2012 Wilmer van der Gaast <wilmer@gaast.net>              *
 *                                                                           *
 *  This library is free software; you can redistribute it and/or            *
@@ -188,4 +188,50 @@
 }
 
+static struct xt_node *twitter_parse_response(struct im_connection *ic, struct http_request *req)
+{
+	gboolean logging_in = !(ic->flags & OPT_LOGGED_IN);
+	gboolean periodic;
+	struct twitter_data *td = ic->proto_data;
+	struct xt_node *ret;
+	char path[64] = "", *s;
+	
+	if ((s = strchr(req->request, ' '))) {
+		path[sizeof(path)-1] = '\0';
+		strncpy(path, s + 1, sizeof(path) - 1);
+		if ((s = strchr(path, '?')) || (s = strchr(path, ' ')))
+			*s = '\0';
+	}
+	
+	/* Kinda nasty. :-( Trying to suppress error messages, but only
+	   for periodic (i.e. mentions/timeline) queries. */
+	periodic = strstr(path, "timeline") || strstr(path, "mentions");
+	
+	if (req->status_code == 401 && logging_in) {
+		/* IIRC Twitter once had an outage where they were randomly
+		   throwing 401s so I'll keep treating this one as fatal
+		   only during login. */
+		imcb_error(ic, "Authentication failure");
+		imc_logout(ic, FALSE);
+		return NULL;
+	} else if (req->status_code != 200) {
+		// It didn't go well, output the error and return.
+		if (!periodic || logging_in || ++td->http_fails >= 5)
+			imcb_error(ic, "Could not retrieve %s: %s",
+				   path, twitter_parse_error(req));
+		
+		if (logging_in)
+			imc_logout(ic, TRUE);
+		return NULL;
+	} else {
+		td->http_fails = 0;
+	}
+
+	if ((ret = xt_from_string(req->reply_body, req->body_size)) == NULL) {
+		imcb_error(ic, "Could not retrieve %s: %s",
+			   path, "XML parse error");
+	}
+	return ret;
+}
+
 static void twitter_http_get_friends_ids(struct http_request *req);
 
@@ -266,20 +312,4 @@
 	td = ic->proto_data;
 
-	// 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.
-		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->timeline_gc && g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0)
@@ -290,5 +320,6 @@
 
 	// Parse the data.
-	parsed = xt_from_string(req->reply_body, req->body_size);
+	if (!(parsed = twitter_parse_response(ic, req)))
+		return;
 	twitter_xt_get_friends_id_list(parsed, txl);
 	xt_free_node(parsed);
@@ -348,5 +379,4 @@
 {
 	struct im_connection *ic = req->data;
-	struct twitter_data *td;
 	struct xt_node *parsed;
 	struct twitter_xml_list *txl;
@@ -358,23 +388,10 @@
 		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.
-	parsed = xt_from_string(req->reply_body, req->body_size);
-
 	// Get the user list from the parsed xml feed.
+	if (!(parsed = twitter_parse_response(ic, req)))
+		return;
 	twitter_xt_get_users(parsed, txl);
 	xt_free_node(parsed);
@@ -787,4 +804,7 @@
 		}
 	}
+	
+	if (!(ic->flags & OPT_LOGGED_IN))
+		imcb_connected(ic);
 
 	// See if the user wants to see the messages in a groupchat window or as private messages.
@@ -894,24 +914,10 @@
 	td = ic->proto_data;
 
-	// Check if the HTTP request went well.
-	if (req->status_code == 200) {
-		td->http_fails = 0;
-		if (!(ic->flags & OPT_LOGGED_IN))
-			imcb_connected(ic);
-	} else {
-		// It didn't go well, output the error and return.
-		if (++td->http_fails >= 5)
-			imcb_error(ic, "Could not retrieve %s: %s",
-				   TWITTER_HOME_TIMELINE_URL, twitter_parse_error(req));
-
-		goto end;
-	}
-
 	txl = g_new0(struct twitter_xml_list, 1);
 	txl->list = NULL;
 
-	// Parse the data.
-	parsed = xt_from_string(req->reply_body, req->body_size);
 	// The root <statuses> node should hold the list of statuses <status>
+	if (!(parsed = twitter_parse_response(ic, req)))
+		goto end;
 	twitter_xt_get_status_list(ic, parsed, txl);
 	xt_free_node(parsed);
@@ -941,24 +947,10 @@
 	td = ic->proto_data;
 
-	// Check if the HTTP request went well.
-	if (req->status_code == 200) {
-		td->http_fails = 0;
-		if (!(ic->flags & OPT_LOGGED_IN))
-			imcb_connected(ic);
-	} else {
-		// It didn't go well, output the error and return.
-		if (++td->http_fails >= 5)
-			imcb_error(ic, "Could not retrieve %s: %s",
-				   TWITTER_MENTIONS_URL, twitter_parse_error(req));
-
-		goto end;
-	}
-
 	txl = g_new0(struct twitter_xml_list, 1);
 	txl->list = NULL;
 
-	// Parse the data.
-	parsed = xt_from_string(req->reply_body, req->body_size);
 	// The root <statuses> node should hold the list of statuses <status>
+	if (!(parsed = twitter_parse_response(ic, req)))
+		goto end;
 	twitter_xt_get_status_list(ic, parsed, txl);
 	xt_free_node(parsed);
@@ -980,4 +972,5 @@
 	struct im_connection *ic = req->data;
 	struct twitter_data *td;
+	struct xt_node *parsed, *node;
 
 	// Check if the connection is still active.
@@ -988,22 +981,10 @@
 	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) {
-		struct xt_node *parsed, *node;
-
-		parsed = xt_from_string(req->reply_body, req->body_size);
-
-		if ((node = xt_find_node(parsed, "status")) &&
-		    (node = xt_find_node(node->children, "id")) && node->text)
-			td->last_status_id = g_ascii_strtoull(node->text, NULL, 10);
-
-		xt_free_node(parsed);
-	}
+	if (!(parsed = twitter_parse_response(ic, req)))
+		return;
+	
+	if ((node = xt_find_node(parsed, "status")) &&
+	    (node = xt_find_node(node->children, "id")) && node->text)
+		td->last_status_id = g_ascii_strtoull(node->text, NULL, 10);
 }
 
