comparison libpurple/protocols/qq/buddy_list.c @ 24080:818ab62006f5

2008.10.07 - ccpaging <ccpaging(at)gmail.com> * Update qq_buddy
author SHiNE CsyFeK <csyfek@gmail.com>
date Wed, 22 Oct 2008 14:59:55 +0000
parents 1bdf7b602684
children 237e5a94e11c
comparison
equal deleted inserted replaced
24079:1bdf7b602684 24080:818ab62006f5
162 { 162 {
163 qq_data *qd; 163 qq_data *qd;
164 gint bytes, bytes_start; 164 gint bytes, bytes_start;
165 gint count; 165 gint count;
166 guint8 position; 166 guint8 position;
167 qq_buddy *buddy; 167 qq_buddy_data *bd;
168 int entry_len = 38; 168 int entry_len = 38;
169 169
170 qq_buddy_status bs; 170 qq_buddy_status bs;
171 struct { 171 struct {
172 guint16 unknown1; 172 guint16 unknown1;
223 if (bs.uid == qd->uid) { 223 if (bs.uid == qd->uid) {
224 purple_debug_warning("QQ", "I am in online list %d\n", bs.uid); 224 purple_debug_warning("QQ", "I am in online list %d\n", bs.uid);
225 } 225 }
226 226
227 /* update buddy information */ 227 /* update buddy information */
228 buddy = qq_buddy_find(gc, bs.uid); 228 bd = qq_buddy_data_find(gc, bs.uid);
229 if (buddy == NULL) { 229 if (bd == NULL) {
230 purple_debug_error("QQ", 230 purple_debug_error("QQ",
231 "Got an online buddy %d, but not in my buddy list\n", bs.uid); 231 "Got an online buddy %d, but not in my buddy list\n", bs.uid);
232 continue; 232 continue;
233 } 233 }
234 /* we find one and update qq_buddy */ 234 /* we find one and update qq_buddy_data */
235 /* 235 /*
236 if(0 != fe->s->client_tag) 236 if(0 != fe->s->client_tag)
237 q_bud->client_tag = fe->s->client_tag; 237 q_bud->client_tag = fe->s->client_tag;
238 */ 238 */
239 buddy->ip.s_addr = bs.ip.s_addr; 239 bd->ip.s_addr = bs.ip.s_addr;
240 buddy->port = bs.port; 240 bd->port = bs.port;
241 buddy->status = bs.status; 241 bd->status = bs.status;
242 buddy->ext_flag = packet.ext_flag; 242 bd->ext_flag = packet.ext_flag;
243 buddy->comm_flag = packet.comm_flag; 243 bd->comm_flag = packet.comm_flag;
244 qq_update_buddy_status(gc, bs.uid, bs.status, packet.comm_flag); 244 bd->last_update = time(NULL);
245 qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag);
245 count++; 246 count++;
246 } 247 }
247 248
248 if(bytes > data_len) { 249 if(bytes > data_len) {
249 purple_debug_error("QQ", 250 purple_debug_error("QQ",
258 259
259 /* process reply for get_buddies_list */ 260 /* process reply for get_buddies_list */
260 guint16 qq_process_get_buddies(guint8 *data, gint data_len, PurpleConnection *gc) 261 guint16 qq_process_get_buddies(guint8 *data, gint data_len, PurpleConnection *gc)
261 { 262 {
262 qq_data *qd; 263 qq_data *qd;
263 qq_buddy bd; 264 qq_buddy_data bd;
264 gint bytes_expected, count; 265 gint bytes_expected, count;
265 gint bytes, buddy_bytes; 266 gint bytes, buddy_bytes;
266 gint nickname_len; 267 gint nickname_len;
267 guint16 position, unknown; 268 guint16 position, unknown;
268 PurpleBuddy *buddy; 269 PurpleBuddy *buddy;
326 buddy = qq_buddy_find_or_new(gc, bd.uid); 327 buddy = qq_buddy_find_or_new(gc, bd.uid);
327 if (buddy == NULL || buddy->proto_data == NULL) { 328 if (buddy == NULL || buddy->proto_data == NULL) {
328 g_free(bd.nickname); 329 g_free(bd.nickname);
329 continue; 330 continue;
330 } 331 }
332 purple_blist_server_alias_buddy(buddy, bd.nickname);
331 bd.last_update = time(NULL); 333 bd.last_update = time(NULL);
332 purple_blist_server_alias_buddy(buddy, bd.nickname);
333 qq_update_buddy_status(gc, bd.uid, bd.status, bd.comm_flag); 334 qq_update_buddy_status(gc, bd.uid, bd.status, bd.comm_flag);
334 335
335 g_memmove(buddy->proto_data, &bd, sizeof(qq_buddy)); 336 g_memmove(buddy->proto_data, &bd, sizeof(qq_buddy_data));
336 /* nickname has been copy to buddy_data do not free 337 /* nickname has been copy to buddy_data do not free
337 g_free(bd.nickname); 338 g_free(bd.nickname);
338 */ 339 */
339 } 340 }
340 341
341 if(bytes > data_len) { 342 if(bytes > data_len) {
342 purple_debug_error("QQ", 343 purple_debug_error("QQ",
448 } else { 449 } else {
449 return 0; 450 return 0;
450 } 451 }
451 } 452 }
452 453
454 static guint8 get_status_from_purple(PurpleConnection *gc)
455 {
456 qq_data *qd;
457 PurpleAccount *account;
458 PurplePresence *presence;
459 guint8 ret;
460
461 qd = (qq_data *) gc->proto_data;
462 account = purple_connection_get_account(gc);
463 presence = purple_account_get_presence(account);
464
465 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) {
466 ret = QQ_BUDDY_ONLINE_INVISIBLE;
467 } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE))
468 {
469 if (qd->client_version >= 2007) {
470 ret = QQ_BUDDY_ONLINE_BUSY;
471 } else {
472 ret = QQ_BUDDY_ONLINE_INVISIBLE;
473 }
474 } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY)
475 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY)
476 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) {
477 ret = QQ_BUDDY_ONLINE_AWAY;
478 } else {
479 ret = QQ_BUDDY_ONLINE_NORMAL;
480 }
481 return ret;
482 }
483
453 /* send a packet to change my online status */ 484 /* send a packet to change my online status */
454 void qq_request_change_status(PurpleConnection *gc, gint update_class) 485 void qq_request_change_status(PurpleConnection *gc, gint update_class)
455 { 486 {
456 qq_data *qd; 487 qq_data *qd;
457 guint8 raw_data[16] = {0}; 488 guint8 raw_data[16] = {0};
467 498
468 qd = (qq_data *) gc->proto_data; 499 qd = (qq_data *) gc->proto_data;
469 if (!qd->is_login) 500 if (!qd->is_login)
470 return; 501 return;
471 502
472 if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_INVISIBLE)) { 503 away_cmd = get_status_from_purple(gc);
473 away_cmd = QQ_BUDDY_ONLINE_INVISIBLE;
474 } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE))
475 {
476 if (qd->client_version >= 2007) {
477 away_cmd = QQ_BUDDY_ONLINE_BUSY;
478 } else {
479 away_cmd = QQ_BUDDY_ONLINE_INVISIBLE;
480 }
481 } else if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_AWAY)
482 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_EXTENDED_AWAY)
483 || purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_UNAVAILABLE)) {
484 away_cmd = QQ_BUDDY_ONLINE_AWAY;
485 } else {
486 away_cmd = QQ_BUDDY_ONLINE_NORMAL;
487 }
488 504
489 misc_status = 0x00000000; 505 misc_status = 0x00000000;
490 fake_video = purple_prefs_get_bool("/plugins/prpl/qq/show_fake_video"); 506 fake_video = purple_prefs_get_bool("/plugins/prpl/qq/show_fake_video");
491 if (fake_video) 507 if (fake_video)
492 misc_status |= QQ_MISC_STATUS_HAVING_VIIDEO; 508 misc_status |= QQ_MISC_STATUS_HAVING_VIIDEO;
512 void qq_process_change_status(guint8 *data, gint data_len, PurpleConnection *gc) 528 void qq_process_change_status(guint8 *data, gint data_len, PurpleConnection *gc)
513 { 529 {
514 qq_data *qd; 530 qq_data *qd;
515 gint bytes; 531 gint bytes;
516 guint8 reply; 532 guint8 reply;
517 qq_buddy *buddy; 533 qq_buddy_data *bd;
518 534
519 g_return_if_fail(data != NULL && data_len != 0); 535 g_return_if_fail(data != NULL && data_len != 0);
520 536
521 qd = (qq_data *) gc->proto_data; 537 qd = (qq_data *) gc->proto_data;
522 538
526 purple_debug_warning("QQ", "Change status fail 0x%02X\n", reply); 542 purple_debug_warning("QQ", "Change status fail 0x%02X\n", reply);
527 return; 543 return;
528 } 544 }
529 545
530 /* purple_debug_info("QQ", "Change status OK\n"); */ 546 /* purple_debug_info("QQ", "Change status OK\n"); */
531 buddy = qq_buddy_find(gc, qd->uid); 547 bd = qq_buddy_data_find(gc, qd->uid);
532 if (buddy != NULL) { 548 if (bd != NULL) {
533 qq_update_buddy_contact(gc, buddy); 549 bd->status = get_status_from_purple(gc);
550 bd->last_update = time(NULL);
551 qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag);
534 } 552 }
535 } 553 }
536 554
537 /* it is a server message indicating that one of my buddies has changed its status */ 555 /* it is a server message indicating that one of my buddies has changed its status */
538 void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc) 556 void qq_process_buddy_change_status(guint8 *data, gint data_len, PurpleConnection *gc)
539 { 557 {
540 qq_data *qd; 558 qq_data *qd;
541 gint bytes; 559 gint bytes;
542 guint32 my_uid; 560 guint32 my_uid;
543 qq_buddy *buddy; 561 qq_buddy_data *bd;
544 qq_buddy_status bs; 562 qq_buddy_status bs;
545 563
546 g_return_if_fail(data != NULL && data_len != 0); 564 g_return_if_fail(data != NULL && data_len != 0);
547 565
548 qd = (qq_data *) gc->proto_data; 566 qd = (qq_data *) gc->proto_data;
559 /* 031-034: Unknow, maybe my uid */ 577 /* 031-034: Unknow, maybe my uid */
560 /* This has a value of 0 when we've changed our status to 578 /* This has a value of 0 when we've changed our status to
561 * QQ_BUDDY_ONLINE_INVISIBLE */ 579 * QQ_BUDDY_ONLINE_INVISIBLE */
562 bytes += qq_get32(&my_uid, data + bytes); 580 bytes += qq_get32(&my_uid, data + bytes);
563 581
564 buddy = qq_buddy_find(gc, bs.uid); 582 bd = qq_buddy_data_find(gc, bs.uid);
565 if (buddy == NULL) { 583 if (bd == NULL) {
566 purple_debug_warning("QQ", "Get status of unknown buddy %d\n", bs.uid); 584 purple_debug_warning("QQ", "Get status of unknown buddy %d\n", bs.uid);
567 return; 585 return;
568 } 586 }
569 587
570 if(bs.ip.s_addr != 0) { 588 if(bs.ip.s_addr != 0) {
571 buddy->ip.s_addr = bs.ip.s_addr; 589 bd->ip.s_addr = bs.ip.s_addr;
572 buddy->port = bs.port; 590 bd->port = bs.port;
573 } 591 }
574 buddy->status =bs.status; 592 bd->status =bs.status;
575 593
576 if (buddy->status == QQ_BUDDY_ONLINE_NORMAL && buddy->level <= 0) { 594 bd->last_update = time(NULL);
595 qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag);
596
597 if (bd->status == QQ_BUDDY_ONLINE_NORMAL && bd->level <= 0) {
577 if (qd->client_version >= 2007) { 598 if (qd->client_version >= 2007) {
578 qq_request_get_level_2007(gc, buddy->uid); 599 qq_request_get_level_2007(gc, bd->uid);
579 } else { 600 } else {
580 qq_request_get_level(gc, buddy->uid); 601 qq_request_get_level(gc, bd->uid);
581 } 602 }
582 } 603 }
583 qq_update_buddy_contact(gc, buddy);
584 } 604 }
585 605
586 /*TODO: maybe this should be qq_update_buddy_status() ?*/ 606 /*TODO: maybe this should be qq_update_buddy_status() ?*/
587 void qq_update_buddy_status(PurpleConnection *gc, guint32 uid, guint8 status, guint8 flag) 607 void qq_update_buddy_status(PurpleConnection *gc, guint32 uid, guint8 status, guint8 flag)
588 { 608 {
590 gchar *status_id; 610 gchar *status_id;
591 611
592 g_return_if_fail(uid != 0); 612 g_return_if_fail(uid != 0);
593 613
594 who = uid_to_purple_name(uid); 614 who = uid_to_purple_name(uid);
595 615
596 /* purple supports signon and idle time 616 /* purple supports signon and idle time
597 * but it is not much use for QQ, I do not use them */ 617 * but it is not much use for QQ, I do not use them */
598 /* serv_got_update(gc, name, online, 0, q_bud->signon, q_bud->idle, bud->uc); */ 618 /* serv_got_update(gc, name, online, 0, q_bud->signon, q_bud->idle, bud->uc); */
599 status_id = "available"; 619 status_id = "available";
600 switch(status) { 620 switch(status) {
626 646
627 if (flag & QQ_COMM_FLAG_MOBILE && status != QQ_BUDDY_OFFLINE) 647 if (flag & QQ_COMM_FLAG_MOBILE && status != QQ_BUDDY_OFFLINE)
628 purple_prpl_got_user_status(gc->account, who, "mobile", NULL); 648 purple_prpl_got_user_status(gc->account, who, "mobile", NULL);
629 else 649 else
630 purple_prpl_got_user_status_deactive(gc->account, who, "mobile"); 650 purple_prpl_got_user_status_deactive(gc->account, who, "mobile");
631 651
632 g_free(who); 652 g_free(who);
633 }
634
635 /*TODO: maybe this should be qq_update_buddy_status() ?*/
636 void qq_update_buddy_contact(PurpleConnection *gc, qq_buddy *buddy)
637 {
638 gchar *purple_name;
639 PurpleBuddy *purple_buddy;
640 gchar *status_id;
641
642 g_return_if_fail(buddy != NULL);
643
644 purple_name = uid_to_purple_name(buddy->uid);
645 if (purple_name == NULL) {
646 purple_debug_error("QQ", "Not find purple name: %d\n", buddy->uid);
647 return;
648 }
649
650 purple_buddy = purple_find_buddy(gc->account, purple_name);
651 if (purple_buddy == NULL) {
652 purple_debug_error("QQ", "Not find buddy: %d\n", buddy->uid);
653 g_free(purple_name);
654 return;
655 }
656
657 purple_blist_server_alias_buddy(purple_buddy, buddy->nickname); /* server */
658 buddy->last_update = time(NULL);
659
660 /* purple supports signon and idle time
661 * but it is not much use for QQ, I do not use them */
662 /* serv_got_update(gc, name, online, 0, q_bud->signon, q_bud->idle, bud->uc); */
663 status_id = "available";
664 switch(buddy->status) {
665 case QQ_BUDDY_OFFLINE:
666 status_id = "offline";
667 break;
668 case QQ_BUDDY_ONLINE_NORMAL:
669 status_id = "available";
670 break;
671 case QQ_BUDDY_CHANGE_TO_OFFLINE:
672 status_id = "offline";
673 break;
674 case QQ_BUDDY_ONLINE_AWAY:
675 status_id = "away";
676 break;
677 case QQ_BUDDY_ONLINE_INVISIBLE:
678 status_id = "invisible";
679 break;
680 case QQ_BUDDY_ONLINE_BUSY:
681 status_id = "busy";
682 break;
683 default:
684 status_id = "invisible";
685 purple_debug_error("QQ", "unknown status: %x\n", buddy->status);
686 break;
687 }
688 purple_debug_info("QQ", "buddy %d %s\n", buddy->uid, status_id);
689 purple_prpl_got_user_status(gc->account, purple_name, status_id, NULL);
690
691 if (buddy->comm_flag & QQ_COMM_FLAG_MOBILE && buddy->status != QQ_BUDDY_OFFLINE)
692 purple_prpl_got_user_status(gc->account, purple_name, "mobile", NULL);
693 else
694 purple_prpl_got_user_status_deactive(gc->account, purple_name, "mobile");
695
696 g_free(purple_name);
697 } 653 }
698 654
699 /* refresh all buddies online/offline, 655 /* refresh all buddies online/offline,
700 * after receiving reply for get_buddies_online packet */ 656 * after receiving reply for get_buddies_online packet */
701 void qq_update_buddyies_status(PurpleConnection *gc) 657 void qq_update_buddyies_status(PurpleConnection *gc)
702 { 658 {
703 qq_data *qd; 659 qq_data *qd;
704 PurpleBuddy *buddy; 660 PurpleBuddy *buddy;
705 qq_buddy *bd; 661 qq_buddy_data *bd;
706 GSList *buddies, *it; 662 GSList *buddies, *it;
707 time_t tm_limit = time(NULL); 663 time_t tm_limit = time(NULL);
708 664
709 qd = (qq_data *) (gc->proto_data); 665 qd = (qq_data *) (gc->proto_data);
710 666
711 tm_limit -= QQ_UPDATE_ONLINE_INTERVAL; 667 tm_limit -= QQ_UPDATE_ONLINE_INTERVAL;
712 668
713 buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); 669 buddies = purple_find_buddies(purple_connection_get_account(gc), NULL);
714 for (it = buddies; it; it = it->next) { 670 for (it = buddies; it; it = it->next) {
715 buddy = it->data; 671 buddy = it->data;
716 if (buddy == NULL) continue; 672 if (buddy == NULL) continue;
717 if (buddy->proto_data == NULL) continue; 673 if (buddy->proto_data == NULL) continue;
718 674
719 bd = (qq_buddy *)buddy->proto_data; 675 bd = (qq_buddy_data *)buddy->proto_data;
720 if (bd->uid == 0) continue; 676 if (bd->uid == 0) continue;
721 if (bd->uid == qd->uid) continue; /* my status is always online in my buddy list */ 677 if (bd->uid == qd->uid) continue; /* my status is always online in my buddy list */
722 if (tm_limit < bd->last_update) continue; 678 if (tm_limit < bd->last_update) continue;
723 if (bd->status == QQ_BUDDY_ONLINE_INVISIBLE) continue; 679 if (bd->status == QQ_BUDDY_ONLINE_INVISIBLE) continue;
724 680
725 bd->status = QQ_BUDDY_CHANGE_TO_OFFLINE; 681 bd->status = QQ_BUDDY_CHANGE_TO_OFFLINE;
682 bd->last_update = time(NULL);
726 qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag); 683 qq_update_buddy_status(gc, bd->uid, bd->status, bd->comm_flag);
727 } 684 }
728 } 685 }
729 686
730 void qq_buddy_data_free_all(PurpleConnection *gc) 687 void qq_buddy_data_free_all(PurpleConnection *gc)
733 PurpleBuddy *buddy; 690 PurpleBuddy *buddy;
734 GSList *buddies, *it; 691 GSList *buddies, *it;
735 gint count = 0; 692 gint count = 0;
736 693
737 qd = (qq_data *) (gc->proto_data); 694 qd = (qq_data *) (gc->proto_data);
738 695
739 buddies = purple_find_buddies(purple_connection_get_account(gc), NULL); 696 buddies = purple_find_buddies(purple_connection_get_account(gc), NULL);
740 for (it = buddies; it; it = it->next) { 697 for (it = buddies; it; it = it->next) {
741 buddy = it->data; 698 buddy = it->data;
742 if (buddy == NULL) continue; 699 if (buddy == NULL) continue;
743 if (buddy->proto_data == NULL) continue; 700 if (buddy->proto_data == NULL) continue;
744 701
745 qq_buddy_data_free(buddy->proto_data); 702 qq_buddy_data_free(buddy->proto_data);
746 buddy->proto_data = NULL; 703 buddy->proto_data = NULL;
747 704
748 count++; 705 count++;
749 } 706 }
750 707
751 if (count > 0) { 708 if (count > 0) {
752 purple_debug_info("QQ", "%d buddies' data are freed\n", count); 709 purple_debug_info("QQ", "%d buddies' data are freed\n", count);