| 561 * @param gc Connection. |
561 * @param gc Connection. |
| 562 * @param who A user id, email, or username to send the message to. |
562 * @param who A user id, email, or username to send the message to. |
| 563 * @param message Instant message text to send. |
563 * @param message Instant message text to send. |
| 564 * @param flags Flags. |
564 * @param flags Flags. |
| 565 * |
565 * |
| 566 * @return 1 in all cases, even if the message delivery is destined to fail. |
566 * @return 1 if successful or postponed, -1 if failed |
| 567 * |
567 * |
| 568 * Allows sending to a user by username, email address, or userid. If |
568 * Allows sending to a user by username, email address, or userid. If |
| 569 * a username or email address is given, the userid must be looked up. |
569 * a username or email address is given, the userid must be looked up. |
| 570 * This function does that by calling msim_lookup_user(), setting up |
570 * This function does that by calling msim_postprocess_outgoing(). |
| 571 * a msim_send_im_cb() callback function called when the userid |
|
| 572 * response is received from the server. |
|
| 573 * |
|
| 574 * The callback function sends the actual message. But if a userid is |
|
| 575 * specified directly, this function is called immediately here. |
|
| 576 * |
|
| 577 * TODO: change all that above. |
|
| 578 */ |
571 */ |
| 579 int msim_send_im(PurpleConnection *gc, const char *who, |
572 int msim_send_im(PurpleConnection *gc, const char *who, |
| 580 const char *message, PurpleMessageFlags flags) |
573 const char *message, PurpleMessageFlags flags) |
| 581 { |
574 { |
| 582 MsimSession *session; |
575 MsimSession *session; |
| 600 /* 't' will be inserted here */ |
593 /* 't' will be inserted here */ |
| 601 "cv", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(MSIM_CLIENT_VERSION), |
594 "cv", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(MSIM_CLIENT_VERSION), |
| 602 "msg", MSIM_TYPE_STRING, g_strdup(message), |
595 "msg", MSIM_TYPE_STRING, g_strdup(message), |
| 603 NULL); |
596 NULL); |
| 604 |
597 |
| 605 /* If numeric ID, can send message immediately without userid lookup */ |
598 if (msim_postprocess_outgoing(session, msg, (char *)who, "t", "cv")) |
| 606 if (msim_is_userid(who)) |
599 { |
| 607 { |
600 |
| 608 purple_debug_info("msim", |
601 /* Return 1 to have Purple show this IM as being sent, 0 to not. I always |
| 609 "msim_send_im: numeric 'who' detected, sending asap\n"); |
602 * return 1 even if the message could not be sent, since I don't know if |
| 610 /* 't' must be before 'cv', or error in parsing message. */ |
603 * it has failed yet--because the IM is only sent after the userid is |
| 611 msg = msim_msg_insert_before(msg, "cv", "t", MSIM_TYPE_STRING, g_strdup(who)); |
604 * retrieved from the server (which happens after this function returns). |
| 612 |
605 */ |
| 613 if (!msim_msg_send(session, msg)) |
606 return 1; |
| 614 { |
607 } else { |
| 615 msim_msg_free(msg); |
608 return -1; |
| 616 return -1; |
609 } |
| 617 } else { |
610 |
| 618 msim_msg_free(msg); |
611 /* |
| 619 return 1; /* Positive value on success */ |
|
| 620 } |
|
| 621 } |
|
| 622 |
|
| 623 /* TODO XXX: if on buddy list, check if 'uid' is set, and if so, send it there! No lookup. */ |
|
| 624 |
|
| 625 /* Otherwise, add callback to IM when userid of destination is available */ |
|
| 626 |
|
| 627 /* Setup a callback for when the userid is available */ |
|
| 628 |
|
| 629 /* Send the request to lookup the userid */ |
|
| 630 /* TODO: don't use callbacks */ |
|
| 631 msim_lookup_user(session, who, msim_send_im_cb, msg); |
|
| 632 |
|
| 633 /* msim_send_im_cb will now be called once userid is looked up */ |
|
| 634 |
|
| 635 /* Return 1 to have Purple show this IM as being sent, 0 to not. I always |
|
| 636 * return 1 even if the message could not be sent, since I don't know if |
|
| 637 * it has failed yet--because the IM is only sent after the userid is |
|
| 638 * retrieved from the server (which happens after this function returns). |
|
| 639 * |
|
| 640 * TODO: In MySpace, you login with your email address, but don't talk to other |
612 * TODO: In MySpace, you login with your email address, but don't talk to other |
| 641 * users using their email address. So there is currently an asymmetry in the |
613 * users using their email address. So there is currently an asymmetry in the |
| 642 * IM windows when using this plugin: |
614 * IM windows when using this plugin: |
| 643 * |
615 * |
| 644 * you@example.com: hello |
616 * you@example.com: hello |
| 648 * TODO: Make the sent IM's appear as from the user's username, instead of |
620 * TODO: Make the sent IM's appear as from the user's username, instead of |
| 649 * their email address. Purple uses the login (in MSIM, the email)--change this. |
621 * their email address. Purple uses the login (in MSIM, the email)--change this. |
| 650 */ |
622 */ |
| 651 return 1; |
623 return 1; |
| 652 } |
624 } |
| 653 |
|
| 654 /** |
|
| 655 * Callback called when ready to send an IM by userid (the userid has been looked up). |
|
| 656 * |
|
| 657 * @param session |
|
| 658 * @param userinfo User info message from server containing a 'body' field |
|
| 659 * with a 'UserID' key. This is where the user ID is taken from. |
|
| 660 * Will be destroyed after use. |
|
| 661 * @param data A MsimMessage * to send, which will have the 't' field added (userid to). |
|
| 662 * |
|
| 663 */ |
|
| 664 void msim_send_im_cb(MsimSession *session, MsimMessage *userinfo, gpointer data) |
|
| 665 { |
|
| 666 MsimMessage *msg; |
|
| 667 gchar *userid; |
|
| 668 GHashTable *body; |
|
| 669 gchar *body_str; |
|
| 670 |
|
| 671 g_return_if_fail(MSIM_SESSION_VALID(session)); |
|
| 672 g_return_if_fail(userinfo != NULL); |
|
| 673 |
|
| 674 body_str = msim_msg_get_string(userinfo, "body"); |
|
| 675 body = msim_parse_body(body_str); |
|
| 676 g_free(body_str); |
|
| 677 g_return_if_fail(body != NULL); |
|
| 678 |
|
| 679 userid = g_hash_table_lookup(body, "UserID"); |
|
| 680 |
|
| 681 msg = (MsimMessage *)data; |
|
| 682 /* 't' must be before 'cv', or get a server error parsing message. */ |
|
| 683 msg = msim_msg_insert_before(msg, "cv", "t", MSIM_TYPE_STRING, userid); |
|
| 684 |
|
| 685 g_return_if_fail(msim_msg_send(session, msg)); |
|
| 686 |
|
| 687 g_hash_table_destroy(body); |
|
| 688 /* g_hash_table_destroy(userinfo); */ |
|
| 689 /* TODO: do we need to free userinfo here? */ |
|
| 690 /* msim_msg_free(userinfo); */ |
|
| 691 } |
|
| 692 |
625 |
| 693 /** |
626 /** |
| 694 * Handle an incoming instant message. |
627 * Handle an incoming instant message. |
| 695 * |
628 * |
| 696 * @param session The session |
629 * @param session The session |
| 834 { |
767 { |
| 835 if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) |
768 if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) |
| 836 { |
769 { |
| 837 /* 'f' = userid message is from, in buddy messages */ |
770 /* 'f' = userid message is from, in buddy messages */ |
| 838 |
771 |
| 839 /* TODO: if know uid->username mapping already, process immediately */ |
772 /* TODO XXX IMPORTANT TODO: if know uid->username mapping already, process immediately */ |
| |
773 /* TODO XXX Currently, uid is ALWAYS explicitly resolved, on each message, by sending |
| |
774 * a getuserbyuserid message. This is very wasteful. TODO: Be frugal. |
| |
775 */ |
| 840 |
776 |
| 841 /* Send lookup request. */ |
777 /* Send lookup request. */ |
| 842 /* XXX: where is msim_msg_get_string() freed? make _strdup and _nonstrdup. */ |
778 /* XXX: where is msim_msg_get_string() freed? make _strdup and _nonstrdup. */ |
| 843 purple_debug_info("msim", "msim_incoming: sending lookup, setting up callback\n"); |
779 purple_debug_info("msim", "msim_incoming: sending lookup, setting up callback\n"); |
| 844 msim_lookup_user(session, msim_msg_get_string(msg, "f"), msim_incoming_resolved, msim_msg_clone(msg)); |
780 msim_lookup_user(session, msim_msg_get_string(msg, "f"), msim_incoming_resolved, msim_msg_clone(msg)); |
| 1201 POSTPROCESS_INFO *pi; |
1137 POSTPROCESS_INFO *pi; |
| 1202 |
1138 |
| 1203 pi = (POSTPROCESS_INFO *)data; |
1139 pi = (POSTPROCESS_INFO *)data; |
| 1204 |
1140 |
| 1205 /* Obtain userid from userinfo message. */ |
1141 /* Obtain userid from userinfo message. */ |
| 1206 body_str = msim_msg_get_string(pi->msg, "body"); |
1142 body_str = msim_msg_get_string(userinfo, "body"); |
| |
1143 g_return_if_fail(body_str != NULL); |
| 1207 body = msim_parse_body(body_str); |
1144 body = msim_parse_body(body_str); |
| 1208 g_free(body_str); |
1145 g_free(body_str); |
| 1209 |
1146 |
| 1210 uid = g_strdup(g_hash_table_lookup(body, "UserID")); |
1147 uid = g_strdup(g_hash_table_lookup(body, "UserID")); |
| 1211 g_hash_table_destroy(body); |
1148 g_hash_table_destroy(body); |
| 1241 |
1178 |
| 1242 pi->msg = msim_msg_clone(msg); |
1179 pi->msg = msim_msg_clone(msg); |
| 1243 pi->uid_before = uid_before; |
1180 pi->uid_before = uid_before; |
| 1244 pi->uid_field_name = uid_field_name; |
1181 pi->uid_field_name = uid_field_name; |
| 1245 pi->username = username; |
1182 pi->username = username; |
| 1246 |
1183 |
| 1247 buddy = purple_find_buddy(session->account, username); |
1184 /* First, try the most obvious. If numeric userid is given, use that directly. */ |
| 1248 if (!buddy) |
1185 if (msim_is_userid(username)) |
| 1249 { |
1186 { |
| 1250 purple_debug_info("msim", "msim_postprocess_outgoing: couldn't find username %s in blist\n", |
1187 uid = atol(username); |
| 1251 username); |
1188 } else { |
| 1252 msim_lookup_user(session, username, msim_postprocess_outgoing_cb, pi); |
1189 /* Next, see if on buddy list and know uid. */ |
| 1253 return TRUE; /* not sure of status yet - haven't sent! */ |
1190 buddy = purple_find_buddy(session->account, username); |
| |
1191 if (buddy) |
| |
1192 { |
| |
1193 uid = purple_blist_node_get_int(&buddy->node, "uid"); |
| |
1194 } else { |
| |
1195 uid = 0; |
| |
1196 } |
| |
1197 |
| |
1198 if (!buddy || !uid) |
| |
1199 { |
| |
1200 purple_debug_info("msim", ">>> msim_postprocess_outgoing: couldn't find username %s in blist\n", |
| |
1201 username); |
| |
1202 msim_lookup_user(session, username, msim_postprocess_outgoing_cb, pi); |
| |
1203 return TRUE; /* not sure of status yet - haven't sent! */ |
| |
1204 } |
| 1254 } |
1205 } |
| 1255 |
1206 |
| 1256 /* Already have uid, insert it and send msg. */ |
1207 /* Already have uid, insert it and send msg. */ |
| 1257 uid = purple_blist_node_get_int(&buddy->node, "uid"); |
|
| 1258 purple_debug_info("msim", "msim_postprocess_outgoing: found username %s has uid %d\n", |
1208 purple_debug_info("msim", "msim_postprocess_outgoing: found username %s has uid %d\n", |
| 1259 username, uid); |
1209 username, uid); |
| 1260 |
1210 |
| 1261 msg = msim_msg_insert_before(msg, uid_before, uid_field_name, MSIM_TYPE_INTEGER, GUINT_TO_POINTER(uid)); |
1211 msg = msim_msg_insert_before(msg, uid_before, uid_field_name, MSIM_TYPE_INTEGER, GUINT_TO_POINTER(uid)); |
| 1262 |
1212 |