- Timestamp:
- 2011-06-11T17:11:08Z (13 years ago)
- Branches:
- master
- Children:
- c0f33f1
- Parents:
- 5f74987
- Location:
- protocols/twitter
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/twitter/twitter.c
r5f74987 rde923d5 83 83 !(td->flags & TWITTER_HAVE_FRIENDS)) { 84 84 imcb_log(ic, "Getting contact list"); 85 twitter_get_statuses_friends(ic, -1); 85 twitter_get_friends_ids(ic, -1); 86 //twitter_get_statuses_friends(ic, -1); 86 87 } else 87 88 twitter_main_loop_start(ic); … … 168 169 "instead of %s.", sn, ic->acc->user); 169 170 } 171 g_free(td->user); 172 td->user = g_strdup(sn); 170 173 } 171 174 … … 257 260 td = g_new0(struct twitter_data, 1); 258 261 ic->proto_data = td; 262 td->user = g_strdup(acc->user); 259 263 260 264 td->url_ssl = url.proto == PROTO_HTTPS; … … 270 274 td->prefix = g_strdup(url.host); 271 275 272 td->flags |= TWITTER_HAVE_FRIENDS;273 td->user = acc->user;274 276 if (strstr(acc->pass, "oauth_token=")) 275 277 td->oauth_info = oauth_from_string(acc->pass, get_oauth_service(ic)); … … 305 307 if (td) { 306 308 oauth_info_free(td->oauth_info); 309 g_free(td->user); 307 310 g_free(td->prefix); 308 311 g_free(td->url_host); 309 312 g_free(td->url_path); 310 g_free(td->pass);311 313 g_free(td->log); 312 314 g_free(td); -
protocols/twitter/twitter.h
r5f74987 rde923d5 43 43 { 44 44 char* user; 45 char* pass;46 45 struct oauth_info *oauth_info; 46 GSList *follow_ids; 47 47 48 guint64 home_timeline_id; 48 49 guint64 last_status_id; /* For undo */ … … 52 53 twitter_flags_t flags; 53 54 55 /* set base_url */ 54 56 gboolean url_ssl; 55 57 int url_port; … … 59 61 char *prefix; /* Used to generate contact + channel name. */ 60 62 63 /* set show_ids */ 61 64 struct twitter_log_data *log; 62 65 int log_id; -
protocols/twitter/twitter_lib.c
r5f74987 rde923d5 55 55 gint64 next_cursor; 56 56 GSList *list; 57 gpointer data;58 57 }; 59 58 … … 109 108 else if (txl->type == TXL_ID) 110 109 g_free(l->data); 110 else if (txl->type == TXL_USER) 111 txu_free(l->data); 111 112 g_slist_free(txl->list); 112 113 g_free(txl); … … 120 121 struct twitter_data *td = ic->proto_data; 121 122 122 // Check if the buddy is al lready in the buddy list.123 // Check if the buddy is already in the buddy list. 123 124 if (!bee_user_by_handle(ic->bee, ic, name)) { 124 125 char *mode = set_getstr(&ic->acc->set, "mode"); … … 138 139 139 140 /* Warning: May return a malloc()ed value, which will be free()d on the next 140 call. Only for short-term use. */141 call. Only for short-term use. NOT THREADSAFE! */ 141 142 char *twitter_parse_error(struct http_request *req) 142 143 { … … 151 152 xp = xt_new(NULL, NULL); 152 153 xt_feed(xp, req->reply_body, req->body_size); 153 154 if ((node = xt_find_node(xp->root, "hash")) && 155 (node = xt_find_node(node->children, "error")) && node->text_len > 0) { 156 ret = g_strdup_printf("%s (%s)", req->status_string, node->text); 157 } 154 155 for (node = xp->root; node; node = node->next) 156 if ((node = xt_find_node(node->children, "error")) && node->text_len > 0) { 157 ret = g_strdup_printf("%s (%s)", req->status_string, node->text); 158 break; 159 } 158 160 159 161 xt_free(xp); … … 207 209 // Walk over the nodes children. 208 210 for (child = node->children; child; child = child->next) { 209 if (g_strcasecmp("id", child->name) == 0) { 210 // Add the item to the list. 211 txl->list = 212 g_slist_append(txl->list, g_memdup(child->text, child->text_len + 1)); 211 if (g_strcasecmp("ids", child->name) == 0) { 212 struct xt_node *idc; 213 for (idc = child->children; idc; idc = idc->next) 214 if (g_strcasecmp(idc->name, "id") == 0) 215 txl->list = g_slist_prepend(txl->list, 216 g_memdup(idc->text, idc->text_len + 1)); 213 217 } else if (g_strcasecmp("next_cursor", child->name) == 0) { 214 218 twitter_xt_next_cursor(child, txl); … … 218 222 return XT_HANDLED; 219 223 } 224 225 static void twitter_get_users_lookup(struct im_connection *ic); 220 226 221 227 /** … … 237 243 td = ic->proto_data; 238 244 239 // Check if the HTTP request went well. 240 if (req->status_code != 200) { 245 // Check if the HTTP request went well. More strict checks as this is 246 // the first request we do in a session. 247 if (req->status_code == 401) { 248 imcb_error(ic, "Authentication failure"); 249 imc_logout(ic, FALSE); 250 return; 251 } else if (req->status_code != 200) { 241 252 // It didn't go well, output the error and return. 242 i f (++td->http_fails >= 5)243 imcb_error(ic, "Could not retrieve friends: %s", twitter_parse_error(req));244 253 imcb_error(ic, "Could not retrieve %s: %s", 254 TWITTER_FRIENDS_IDS_URL, twitter_parse_error(req)); 255 imc_logout(ic, TRUE); 245 256 return; 246 257 } else { … … 248 259 } 249 260 261 /* Create the room now that we "logged in". */ 262 if (!td->home_timeline_gc && g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0) 263 twitter_groupchat_init(ic); 264 250 265 txl = g_new0(struct twitter_xml_list, 1); 266 txl->list = td->follow_ids; 251 267 252 268 // Parse the data. … … 256 272 xt_free(parser); 257 273 274 td->follow_ids = txl->list; 258 275 if (txl->next_cursor) 276 /* These were just numbers. Up to 4000 in a response AFAIK so if we get here 277 we may be using a spammer account. \o/ */ 259 278 twitter_get_friends_ids(ic, txl->next_cursor); 260 279 else 280 /* Now to convert all those numbers into names.. */ 281 twitter_get_users_lookup(ic); 282 283 txl->list = NULL; 261 284 txl_free(txl); 285 } 286 287 static xt_status twitter_xt_get_users(struct xt_node *node, struct twitter_xml_list *txl); 288 static void twitter_http_get_users_lookup(struct http_request *req); 289 290 static void twitter_get_users_lookup(struct im_connection *ic) 291 { 292 struct twitter_data *td = ic->proto_data; 293 char *args[2] = { 294 "user_id", 295 NULL, 296 }; 297 GString *ids = g_string_new(""); 298 int i; 299 300 /* We can request up to 100 users at a time. */ 301 for (i = 0; i < 100 && td->follow_ids; i ++) { 302 g_string_append_printf(ids, ",%s", (char*) td->follow_ids->data); 303 g_free(td->follow_ids->data); 304 td->follow_ids = g_slist_remove(td->follow_ids, td->follow_ids->data); 305 } 306 if (ids->len > 0) { 307 args[1] = ids->str + 1; 308 /* POST, because I think ids can be up to 1KB long. */ 309 twitter_http(ic, TWITTER_USERS_LOOKUP_URL, twitter_http_get_users_lookup, ic, 1, args, 2); 310 } else { 311 /* We have all users. Continue with login. (Get statuses.) */ 312 td->flags |= TWITTER_HAVE_FRIENDS; 313 twitter_login_finish(ic); 314 } 315 g_string_free(ids, TRUE); 316 } 317 318 /** 319 * Callback for getting (twitter)friends... 320 * 321 * Be afraid, be very afraid! This function will potentially add hundreds of "friends". "Who has 322 * hundreds of friends?" you wonder? You probably not, since you are reading the source of 323 * BitlBee... Get a life and meet new people! 324 */ 325 static void twitter_http_get_users_lookup(struct http_request *req) 326 { 327 struct im_connection *ic = req->data; 328 struct twitter_data *td; 329 struct xt_parser *parser; 330 struct twitter_xml_list *txl; 331 GSList *l = NULL; 332 struct twitter_xml_user *user; 333 334 // Check if the connection is still active. 335 if (!g_slist_find(twitter_connections, ic)) 336 return; 337 338 td = ic->proto_data; 339 340 if (req->status_code != 200) { 341 // It didn't go well, output the error and return. 342 imcb_error(ic, "Could not retrieve %s: %s", 343 TWITTER_USERS_LOOKUP_URL, twitter_parse_error(req)); 344 imc_logout(ic, TRUE); 345 return; 346 } else { 347 td->http_fails = 0; 348 } 349 350 txl = g_new0(struct twitter_xml_list, 1); 351 txl->list = NULL; 352 353 // Parse the data. 354 parser = xt_new(NULL, txl); 355 xt_feed(parser, req->reply_body, req->body_size); 356 357 // Get the user list from the parsed xml feed. 358 twitter_xt_get_users(parser->root, txl); 359 xt_free(parser); 360 361 // Add the users as buddies. 362 for (l = txl->list; l; l = g_slist_next(l)) { 363 user = l->data; 364 twitter_add_buddy(ic, user->screen_name, user->name); 365 } 366 367 // Free the structure. 368 txl_free(txl); 369 370 twitter_get_users_lookup(ic); 262 371 } 263 372 … … 304 413 // Put the item in the front of the list. 305 414 txl->list = g_slist_prepend(txl->list, txu); 306 }307 }308 309 return XT_HANDLED;310 }311 312 /**313 * Function to fill a twitter_xml_list struct.314 * It calls twitter_xt_get_users to get the <user>s from a <users> element.315 * It sets:316 * - the next_cursor.317 */318 static xt_status twitter_xt_get_user_list(struct xt_node *node, struct twitter_xml_list *txl)319 {320 struct xt_node *child;321 322 // Set the type of the list.323 txl->type = TXL_USER;324 325 // The root <user_list> node should hold a users <users> element326 // Walk over the nodes children.327 for (child = node->children; child; child = child->next) {328 if (g_strcasecmp("users", child->name) == 0) {329 twitter_xt_get_users(child, txl);330 } else if (g_strcasecmp("next_cursor", child->name) == 0) {331 twitter_xt_next_cursor(child, txl);332 415 } 333 416 } … … 634 717 // It didn't go well, output the error and return. 635 718 if (++td->http_fails >= 5) 636 imcb_error(ic, "Could not retrieve " TWITTER_HOME_TIMELINE_URL ": %s",637 twitter_parse_error(req));719 imcb_error(ic, "Could not retrieve %s: %s", 720 TWITTER_HOME_TIMELINE_URL, twitter_parse_error(req)); 638 721 639 722 return; … … 662 745 663 746 /** 664 * Callback for getting (twitter)friends... 665 * 666 * Be afraid, be very afraid! This function will potentially add hundreds of "friends". "Who has 667 * hundreds of friends?" you wonder? You probably not, since you are reading the source of 668 * BitlBee... Get a life and meet new people! 669 */ 670 static void twitter_http_get_statuses_friends(struct http_request *req) 671 { 672 struct im_connection *ic = req->data; 673 struct twitter_data *td; 674 struct xt_parser *parser; 675 struct twitter_xml_list *txl; 676 GSList *l = NULL; 677 struct twitter_xml_user *user; 678 679 // Check if the connection is still active. 680 if (!g_slist_find(twitter_connections, ic)) 681 return; 682 683 td = ic->proto_data; 684 685 // Check if the HTTP request went well. 686 if (req->status_code == 401) { 687 imcb_error(ic, "Authentication failure"); 688 imc_logout(ic, FALSE); 689 return; 690 } else if (req->status_code != 200) { 691 // It didn't go well, output the error and return. 692 imcb_error(ic, "Could not retrieve " TWITTER_SHOW_FRIENDS_URL ": %s", 693 twitter_parse_error(req)); 694 imc_logout(ic, TRUE); 695 return; 696 } else { 697 td->http_fails = 0; 698 } 699 700 if (!td->home_timeline_gc && g_strcasecmp(set_getstr(&ic->acc->set, "mode"), "chat") == 0) 701 twitter_groupchat_init(ic); 702 703 txl = g_new0(struct twitter_xml_list, 1); 704 txl->list = NULL; 705 706 // Parse the data. 707 parser = xt_new(NULL, txl); 708 xt_feed(parser, req->reply_body, req->body_size); 709 710 // Get the user list from the parsed xml feed. 711 twitter_xt_get_user_list(parser->root, txl); 712 xt_free(parser); 713 714 // Add the users as buddies. 715 for (l = txl->list; l; l = g_slist_next(l)) { 716 user = l->data; 717 twitter_add_buddy(ic, user->screen_name, user->name); 718 } 719 720 // if the next_cursor is set to something bigger then 0 there are more friends to gather. 721 if (txl->next_cursor > 0) { 722 twitter_get_statuses_friends(ic, txl->next_cursor); 723 } else { 724 td->flags |= TWITTER_HAVE_FRIENDS; 725 twitter_login_finish(ic); 726 } 727 728 // Free the structure. 729 txl_free(txl); 730 } 731 732 /** 733 * Get the friends. 734 */ 735 void twitter_get_statuses_friends(struct im_connection *ic, gint64 next_cursor) 736 { 737 char *args[2]; 738 args[0] = "cursor"; 739 args[1] = g_strdup_printf("%lld", (long long) next_cursor); 740 741 twitter_http(ic, TWITTER_SHOW_FRIENDS_URL, twitter_http_get_statuses_friends, ic, 0, args, 742 2); 743 744 g_free(args[1]); 745 } 746 747 /** 748 * Callback to use after sending a post request to twitter. 747 * Callback to use after sending a POST request to twitter. 748 * (Generic, used for a few kinds of queries.) 749 749 */ 750 750 static void twitter_http_post(struct http_request *req) … … 810 810 // Use the same callback as for twitter_post_status, since it does basically the same. 811 811 twitter_http(ic, TWITTER_DIRECT_MESSAGES_NEW_URL, twitter_http_post, ic, 1, args, 4); 812 // g_free(args[1]);813 // g_free(args[3]);814 812 } 815 813 … … 826 824 { 827 825 char *url; 828 url = 829 g_strdup_printf("%s%llu%s", TWITTER_STATUS_DESTROY_URL, (unsigned long long) id, 830 ".xml"); 826 url = g_strdup_printf("%s%llu%s", TWITTER_STATUS_DESTROY_URL, 827 (unsigned long long) id, ".xml"); 831 828 twitter_http(ic, url, twitter_http_post, ic, 1, NULL, 0); 832 829 g_free(url); … … 836 833 { 837 834 char *url; 838 url = 839 g_strdup_printf("%s%llu%s", TWITTER_STATUS_RETWEET_URL, (unsigned long long) id, 840 ".xml"); 835 url = g_strdup_printf("%s%llu%s", TWITTER_STATUS_RETWEET_URL, 836 (unsigned long long) id, ".xml"); 841 837 twitter_http(ic, url, twitter_http_post, ic, 1, NULL, 0); 842 838 g_free(url); -
protocols/twitter/twitter_lib.h
r5f74987 rde923d5 47 47 48 48 /* Users URLs */ 49 #define TWITTER_SHOW_USERS_URL "/users/show.xml" 50 #define TWITTER_SHOW_FRIENDS_URL "/statuses/friends.xml" 51 #define TWITTER_SHOW_FOLLOWERS_URL "/statuses/followers.xml" 49 #define TWITTER_USERS_LOOKUP_URL "/users/lookup.xml" 52 50 53 51 /* Direct messages URLs */
Note: See TracChangeset
for help on using the changeset viewer.