1 /* MySpaceIM Protocol Plugin, header file
3 * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
22 static void msim_check_username_availability_cb(PurpleConnection
*gc
, const char *username_to_check
);
24 static char *msim_username_to_set
;
27 * Format the "now playing" indicator, showing the artist and song.
29 * @return Return a new string (must be g_free()'d), or NULL.
32 msim_format_now_playing(const gchar
*band
, const gchar
*song
)
34 if ((band
&& *band
) || (song
&& *song
)) {
35 return g_strdup_printf("%s - %s",
36 (band
&& *band
) ? band
: "Unknown Artist",
37 (song
&& *song
) ? song
: "Unknown Song");
44 * Get the MsimUser from a PurpleBuddy, optionally creating it if needed.
47 msim_get_user_from_buddy(PurpleBuddy
*buddy
, gboolean create
)
55 user
= purple_buddy_get_protocol_data(buddy
);
56 if (create
&& !user
) {
57 PurpleBlistNode
*node
= PURPLE_BLIST_NODE(buddy
);
59 /* No MsimUser for this buddy; make one. */
61 user
= g_new0(MsimUser
, 1);
63 user
->id
= purple_blist_node_get_int(node
, "UserID");
64 purple_buddy_set_protocol_data(buddy
, user
);
70 void msim_user_free(MsimUser
*user
)
75 if (user
->url_data
!= NULL
)
76 purple_util_fetch_url_cancel(user
->url_data
);
78 g_free(user
->client_info
);
80 g_free(user
->location
);
81 g_free(user
->headline
);
82 g_free(user
->display_name
);
83 g_free(user
->username
);
84 g_free(user
->band_name
);
85 g_free(user
->song_name
);
86 g_free(user
->image_url
);
91 * Find and return an MsimUser * representing a user on the buddy list, or NULL.
94 msim_find_user(MsimSession
*session
, const gchar
*username
)
98 buddy
= purple_find_buddy(session
->account
, username
);
103 return msim_get_user_from_buddy(buddy
, TRUE
);
107 * Append user information to a PurpleNotifyUserInfo, given an MsimUser.
108 * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile.
111 msim_append_user_info(MsimSession
*session
, PurpleNotifyUserInfo
*user_info
, MsimUser
*user
, gboolean full
)
113 PurplePresence
*presence
;
117 /* Useful to identify the account the tooltip refers to.
118 * Other prpls show this. */
119 if (user
->username
) {
120 purple_notify_user_info_add_pair(user_info
, _("User"), user
->username
);
123 /* a/s/l...the vitals */
126 g_snprintf(age
, sizeof(age
), "%d", user
->age
);
127 purple_notify_user_info_add_pair(user_info
, _("Age"), age
);
130 if (user
->gender
&& *user
->gender
) {
131 purple_notify_user_info_add_pair(user_info
, _("Gender"), user
->gender
);
134 if (user
->location
&& *user
->location
) {
135 purple_notify_user_info_add_pair(user_info
, _("Location"), user
->location
);
138 /* Other information */
139 if (user
->headline
&& *user
->headline
) {
140 purple_notify_user_info_add_pair(user_info
, _("Headline"), user
->headline
);
143 if (user
->buddy
!= NULL
) {
144 presence
= purple_buddy_get_presence(user
->buddy
);
146 if (purple_presence_is_status_primitive_active(presence
, PURPLE_STATUS_TUNE
)) {
147 PurpleStatus
*status
;
148 const char *artist
, *title
;
150 status
= purple_presence_get_status(presence
, "tune");
151 title
= purple_status_get_attr_string(status
, PURPLE_TUNE_TITLE
);
152 artist
= purple_status_get_attr_string(status
, PURPLE_TUNE_ARTIST
);
154 str
= msim_format_now_playing(artist
, title
);
156 purple_notify_user_info_add_pair(user_info
, _("Song"), str
);
162 /* Note: total friends only available if looked up by uid, not username. */
163 if (user
->total_friends
) {
165 g_snprintf(friends
, sizeof(friends
), "%d", user
->total_friends
);
166 purple_notify_user_info_add_pair(user_info
, _("Total Friends"), friends
);
170 /* Client information */
173 str
= user
->client_info
;
174 cv
= user
->client_cv
;
176 if (str
&& cv
!= 0) {
177 client
= g_strdup_printf("%s (build %d)", str
, cv
);
179 client
= g_strdup(str
);
181 client
= g_strdup_printf("Build %d", cv
);
183 if (client
&& *client
)
184 purple_notify_user_info_add_pair(user_info
, _("Client Version"), client
);
188 if (full
&& user
->id
) {
189 /* TODO: link to username, if available */
191 purple_notify_user_info_add_section_break(user_info
);
192 if (user
->buddy
!= NULL
)
193 profile
= g_strdup_printf("<a href=\"http://myspace.com/%s\">%s</a>",
194 purple_buddy_get_name(user
->buddy
), _("View web profile"));
196 profile
= g_strdup_printf("<a href=\"http://myspace.com/%d\">%s</a>",
197 user
->id
, _("View web profile"));
198 purple_notify_user_info_add_pair(user_info
, NULL
, profile
);
204 * Callback for when a buddy icon finished being downloaded.
207 msim_downloaded_buddy_icon(PurpleUtilFetchUrlData
*url_data
,
209 const gchar
*url_text
,
211 const gchar
*error_message
)
213 MsimUser
*user
= (MsimUser
*)user_data
;
214 const char *name
= purple_buddy_get_name(user
->buddy
);
215 PurpleAccount
*account
;
217 user
->url_data
= NULL
;
219 purple_debug_info("msim_downloaded_buddy_icon",
220 "Downloaded %" G_GSIZE_FORMAT
" bytes\n", len
);
223 purple_debug_info("msim_downloaded_buddy_icon",
224 "failed to download icon for %s",
229 account
= purple_buddy_get_account(user
->buddy
);
230 purple_buddy_icons_set_for_user(account
, name
,
231 g_memdup((gchar
*)url_text
, len
), len
,
232 /* Use URL itself as buddy icon "checksum" (TODO: ETag) */
233 user
->image_url
); /* checksum */
237 * Set the currently playing song artist and or title.
239 * @param user User associated with the now playing information.
241 * @param new_artist New artist to set, or NULL/empty to not change artist.
243 * @param new_title New title to set, or NULL/empty to not change title.
245 * If new_artist and new_title are NULL/empty, deactivate PURPLE_STATUS_TUNE.
247 * This function is useful because it lets you set the artist or title
248 * individually, which purple_prpl_got_user_status() doesn't do.
250 static void msim_set_artist_or_title(MsimUser
*user
, const char *new_artist
, const char *new_title
)
252 PurplePresence
*presence
;
253 PurpleAccount
*account
;
254 const char *prev_artist
, *prev_title
;
257 if (user
->buddy
== NULL
)
258 /* User not on buddy list so nothing to do */
264 if (new_artist
&& !*new_artist
)
266 if (new_title
&& !*new_title
)
269 account
= purple_buddy_get_account(user
->buddy
);
270 name
= purple_buddy_get_name(user
->buddy
);
272 if (!new_artist
&& !new_title
) {
273 purple_prpl_got_user_status_deactive(account
, name
, "tune");
277 presence
= purple_buddy_get_presence(user
->buddy
);
279 if (purple_presence_is_status_primitive_active(presence
, PURPLE_STATUS_TUNE
)) {
280 PurpleStatus
*status
;
282 status
= purple_presence_get_status(presence
, "tune");
283 prev_title
= purple_status_get_attr_string(status
, PURPLE_TUNE_TITLE
);
284 prev_artist
= purple_status_get_attr_string(status
, PURPLE_TUNE_ARTIST
);
288 new_artist
= prev_artist
;
291 new_title
= prev_title
;
293 purple_prpl_got_user_status(account
, name
, "tune",
294 PURPLE_TUNE_TITLE
, new_title
,
295 PURPLE_TUNE_ARTIST
, new_artist
,
300 * Store a field of information about a buddy.
302 * @param key_str Key to store.
303 * @param value_str Value string, either user takes ownership of this string
304 * or it is freed if MsimUser doesn't store the string.
305 * @param user User to store data in. Existing data will be replaced.
308 msim_store_user_info_each(const gchar
*key_str
, gchar
*value_str
, MsimUser
*user
)
310 const char *name
= user
->buddy
? purple_buddy_get_name(user
->buddy
) : NULL
;
312 if (g_str_equal(key_str
, "UserID") || g_str_equal(key_str
, "ContactID")) {
313 /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */
314 user
->id
= atol(value_str
);
318 purple_debug_info("msim", "associating uid %s with username %s\n", key_str
, name
);
319 purple_blist_node_set_int(PURPLE_BLIST_NODE(user
->buddy
), "UserID", user
->id
);
321 /* Need to store in MsimUser, too? What if not on blist? */
322 } else if (g_str_equal(key_str
, "Age")) {
323 user
->age
= atol(value_str
);
325 } else if (g_str_equal(key_str
, "Gender")) {
326 g_free(user
->gender
);
327 user
->gender
= value_str
;
328 } else if (g_str_equal(key_str
, "Location")) {
329 g_free(user
->location
);
330 user
->location
= value_str
;
331 } else if (g_str_equal(key_str
, "TotalFriends")) {
332 user
->total_friends
= atol(value_str
);
334 } else if (g_str_equal(key_str
, "DisplayName")) {
335 g_free(user
->display_name
);
336 user
->display_name
= value_str
;
337 } else if (g_str_equal(key_str
, "BandName")) {
338 msim_set_artist_or_title(user
, value_str
, NULL
);
340 } else if (g_str_equal(key_str
, "SongName")) {
341 msim_set_artist_or_title(user
, NULL
, value_str
);
343 } else if (g_str_equal(key_str
, "UserName") || g_str_equal(key_str
, "IMName") || g_str_equal(key_str
, "NickName")) {
344 /* Ignore because PurpleBuddy knows this already */
346 } else if (g_str_equal(key_str
, "ImageURL") || g_str_equal(key_str
, "AvatarURL")) {
347 const gchar
*previous_url
;
349 if (user
->temporary_user
) {
350 /* This user will be destroyed soon; don't try to look up its image or avatar,
351 * since that won't return immediately and we will end up accessing freed data.
357 g_free(user
->image_url
);
359 user
->image_url
= value_str
;
361 /* Instead of showing 'no photo' picture, show nothing. */
362 if (g_str_equal(user
->image_url
, "http://x.myspace.com/images/no_pic.gif"))
364 purple_buddy_icons_set_for_user(purple_buddy_get_account(user
->buddy
),
365 name
, NULL
, 0, NULL
);
369 /* TODO: use ETag for checksum */
370 previous_url
= purple_buddy_icons_get_checksum_for_user(user
->buddy
);
372 /* Only download if URL changed */
373 if (!previous_url
|| !g_str_equal(previous_url
, user
->image_url
)) {
374 if (user
->url_data
!= NULL
)
375 purple_util_fetch_url_cancel(user
->url_data
);
376 user
->url_data
= purple_util_fetch_url(user
->image_url
, TRUE
, NULL
, TRUE
, msim_downloaded_buddy_icon
, (gpointer
)user
);
378 } else if (g_str_equal(key_str
, "LastImageUpdated")) {
379 /* TODO: use somewhere */
380 user
->last_image_updated
= atol(value_str
);
382 } else if (g_str_equal(key_str
, "Headline")) {
383 g_free(user
->headline
);
384 user
->headline
= value_str
;
386 /* TODO: other fields in MsimUser */
389 msg
= g_strdup_printf("msim_store_user_info_each: unknown field %s=%s",
393 msim_unrecognized(NULL
, NULL
, msg
);
400 * Save buddy information to the buddy list from a user info reply message.
403 * @param msg The user information reply, with any amount of information.
404 * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data.
406 * Variable information is saved to the passed MsimUser structure. Permanent
407 * information (UserID) is stored in the blist node of the buddy list (and
408 * ends up in blist.xml, persisted to disk) if it exists.
410 * If the function has no buddy information, this function
411 * is a no-op (and returns FALSE).
414 msim_store_user_info(MsimSession
*session
, const MsimMessage
*msg
, MsimUser
*user
)
417 MsimMessage
*body
, *body_node
;
419 g_return_val_if_fail(msg
!= NULL
, FALSE
);
421 body
= msim_msg_get_dictionary(msg
, "body");
426 if (msim_msg_get_integer(msg
, "dsn") == MG_OWN_IM_INFO_DSN
&&
427 msim_msg_get_integer(msg
, "lid") == MG_OWN_IM_INFO_LID
)
430 * Some of this info will be available on the buddy list if the
431 * user has themselves as their own buddy.
433 * Much of the info is already available in MsimSession,
434 * stored in msim_we_are_logged_on().
438 tmpstr
= msim_msg_get_string(body
, "ShowOnlyToList");
439 if (tmpstr
!= NULL
) {
440 session
->show_only_to_list
= g_str_equal(tmpstr
, "True");
444 session
->privacy_mode
= msim_msg_get_integer(body
, "PrivacyMode");
445 session
->offline_message_mode
= msim_msg_get_integer(body
, "OfflineMessageMode");
448 "blocklist", MSIM_TYPE_BOOLEAN
, TRUE
,
449 "sesskey", MSIM_TYPE_INTEGER
, session
->sesskey
,
450 "idlist", MSIM_TYPE_STRING
,
451 g_strdup_printf("w%d|c%d",
452 session
->show_only_to_list
? 1 : 0,
453 session
->privacy_mode
& 1),
455 } else if (msim_msg_get_integer(msg
, "dsn") == MG_OWN_MYSPACE_INFO_DSN
&&
456 msim_msg_get_integer(msg
, "lid") == MG_OWN_MYSPACE_INFO_LID
) {
457 /* TODO: same as above, but for MySpace info. */
460 username
= msim_msg_get_string(body
, "UserName");
463 purple_debug_info("msim",
464 "msim_process_reply: not caching body, no UserName\n");
470 /* Null user = find and store in PurpleBuddy's proto_data */
472 user
= msim_find_user(session
, username
);
480 /* TODO: make looping over MsimMessage's easier. */
481 for (body_node
= body
;
483 body_node
= msim_msg_get_next_element_node(body_node
))
485 const gchar
*key_str
;
487 MsimMessageElement
*elem
;
489 elem
= (MsimMessageElement
*)body_node
->data
;
490 key_str
= elem
->name
;
492 value_str
= msim_msg_get_string_from_element(elem
);
493 msim_store_user_info_each(key_str
, value_str
, user
);
504 * Return whether a given username is syntactically valid.
505 * Note: does not actually check that the user exists.
508 msim_is_valid_username(const gchar
*user
)
510 return !msim_is_userid(user
) && /* Not all numeric */
511 strlen(user
) <= MSIM_MAX_USERNAME_LENGTH
512 && strspn(user
, "0123456789"
513 "abcdefghijklmnopqrstuvwxyz"
515 "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(user
);
520 * Check if a string is a userid (all numeric).
522 * @param user The user id, email, or name.
524 * @return TRUE if is userid, FALSE if not.
527 msim_is_userid(const gchar
*user
)
529 g_return_val_if_fail(user
!= NULL
, FALSE
);
531 return strspn(user
, "0123456789") == strlen(user
);
535 * Check if a string is an email address (contains an @).
537 * @param user The user id, email, or name.
539 * @return TRUE if is an email, FALSE if not.
541 * This function is not intended to be used as a generic
542 * means of validating email addresses, but to distinguish
543 * between a user represented by an email address from
544 * other forms of identification.
547 msim_is_email(const gchar
*user
)
549 g_return_val_if_fail(user
!= NULL
, FALSE
);
551 return strchr(user
, '@') != NULL
;
555 * Asynchronously lookup user information, calling callback when receive result.
558 * @param user The user id, email address, or username. Not freed.
559 * @param cb Callback, called with user information when available.
560 * @param data An arbitray data pointer passed to the callback.
562 /* TODO: change to not use callbacks */
564 msim_lookup_user(MsimSession
*session
, const gchar
*user
, MSIM_USER_LOOKUP_CB cb
, gpointer data
)
570 g_return_if_fail(user
!= NULL
);
571 /* Callback can be null to not call anything, just lookup & store information. */
572 /*g_return_if_fail(cb != NULL);*/
574 purple_debug_info("msim", "msim_lookup_userid: "
575 "asynchronously looking up <%s>\n", user
);
577 /* Setup callback. Response will be associated with request using 'rid'. */
578 rid
= msim_new_reply_callback(session
, cb
, data
);
582 if (msim_is_userid(user
)) {
583 field_name
= "UserID";
584 dsn
= MG_MYSPACE_INFO_BY_ID_DSN
;
585 lid
= MG_MYSPACE_INFO_BY_ID_LID
;
586 } else if (msim_is_email(user
)) {
587 field_name
= "Email";
588 dsn
= MG_MYSPACE_INFO_BY_STRING_DSN
;
589 lid
= MG_MYSPACE_INFO_BY_STRING_LID
;
591 field_name
= "UserName";
592 dsn
= MG_MYSPACE_INFO_BY_STRING_DSN
;
593 lid
= MG_MYSPACE_INFO_BY_STRING_LID
;
597 field_name
, MSIM_TYPE_STRING
, g_strdup(user
),
600 g_return_if_fail(msim_send(session
,
601 "persist", MSIM_TYPE_INTEGER
, 1,
602 "sesskey", MSIM_TYPE_INTEGER
, session
->sesskey
,
603 "cmd", MSIM_TYPE_INTEGER
, MSIM_CMD_GET
,
604 "dsn", MSIM_TYPE_INTEGER
, dsn
,
605 "uid", MSIM_TYPE_INTEGER
, session
->userid
,
606 "lid", MSIM_TYPE_INTEGER
, lid
,
607 "rid", MSIM_TYPE_INTEGER
, rid
,
608 "body", MSIM_TYPE_DICTIONARY
, body
,
613 * Called after username is set.
615 static void msim_username_is_set_cb(MsimSession
*session
, const MsimMessage
*userinfo
, gpointer data
)
622 gint cmd
,dsn
,uid
,lid
,code
;
623 /* \persistr\\cmd\258\dsn\9\uid\204084363\lid\14\rid\369\body\UserName=TheAlbinoRhino1.Code=0\final\ */
625 purple_debug_info("msim","username_is_set made\n");
627 cmd
= msim_msg_get_integer(userinfo
, "cmd");
628 dsn
= msim_msg_get_integer(userinfo
, "dsn");
629 uid
= msim_msg_get_integer(userinfo
, "uid");
630 lid
= msim_msg_get_integer(userinfo
, "lid");
631 body
= msim_msg_get_dictionary(userinfo
, "body");
632 errmsg
= _("An error occurred while trying to set the username. "
633 "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
634 "fuseaction=profile.username to set your username.");
637 purple_debug_info("msim_username_is_set_cb", "No body");
638 /* Error: No body! */
639 purple_connection_error_reason(session
->gc
, PURPLE_CONNECTION_ERROR_OTHER_ERROR
, errmsg
);
641 username
= msim_msg_get_string(body
, "UserName");
642 code
= msim_msg_get_integer(body
,"Code");
646 purple_debug_info("msim_username_is_set_cb",
647 "cmd = %d, dsn = %d, lid = %d, code = %d, username = %s\n",
648 cmd
, dsn
, lid
, code
, username
);
650 if (cmd
== (MSIM_CMD_BIT_REPLY
| MSIM_CMD_PUT
)
651 && dsn
== MC_SET_USERNAME_DSN
652 && lid
== MC_SET_USERNAME_LID
)
654 purple_debug_info("msim_username_is_set_cb", "Proper cmd,dsn,lid for username_is_set!\n");
655 purple_debug_info("msim_username_is_set_cb", "Username Set with return code %d\n",code
);
658 session
->username
= username
;
659 msim_we_are_logged_on(session
);
661 purple_debug_info("msim_username_is_set", "code is %d",code
);
662 /* TODO: what to do here? */
664 } else if (cmd
== (MSIM_CMD_BIT_REPLY
| MSIM_CMD_GET
)
665 && dsn
== MG_MYSPACE_INFO_BY_STRING_DSN
666 && lid
== MG_MYSPACE_INFO_BY_STRING_LID
) {
667 /* Not quite done... ONE MORE STEP :) */
668 rid
= msim_new_reply_callback(session
, msim_username_is_set_cb
, data
);
669 body
= msim_msg_new("UserName", MSIM_TYPE_STRING
, g_strdup(username
), NULL
);
670 if (!msim_send(session
, "persist", MSIM_TYPE_INTEGER
, 1,
671 "sesskey", MSIM_TYPE_INTEGER
, session
->sesskey
,
672 "cmd", MSIM_TYPE_INTEGER
, MSIM_CMD_PUT
,
673 "dsn", MSIM_TYPE_INTEGER
, MC_SET_USERNAME_DSN
,
674 "uid", MSIM_TYPE_INTEGER
, session
->userid
,
675 "lid", MSIM_TYPE_INTEGER
, MC_SET_USERNAME_LID
,
676 "rid", MSIM_TYPE_INTEGER
, rid
,
677 "body", MSIM_TYPE_DICTIONARY
, body
,
680 /* Can't set... Disconnect */
681 purple_connection_error_reason(session
->gc
, PURPLE_CONNECTION_ERROR_OTHER_ERROR
, errmsg
);
686 purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination");
687 purple_connection_error_reason(session
->gc
, PURPLE_CONNECTION_ERROR_OTHER_ERROR
, errmsg
);
692 * Asynchronously set new username, calling callback when receive result.
695 * @param username The username we're setting for ourselves. Not freed.
696 * @param cb Callback, called with user information when available.
697 * @param data An arbitray data pointer passed to the callback.
700 msim_set_username(MsimSession
*session
, const gchar
*username
,
701 MSIM_USER_LOOKUP_CB cb
, gpointer data
)
706 g_return_if_fail(username
!= NULL
);
707 g_return_if_fail(cb
!= NULL
);
709 purple_debug_info("msim", "msim_set_username: "
710 "Setting username %s\n", username
);
712 /* Setup callback. Response will be associated with request using 'rid'. */
713 rid
= msim_new_reply_callback(session
, cb
, data
);
715 /* TODO: I dont know if the ContactType is -/ALWAYS/- 1 */
717 body
= msim_msg_new("UserName", MSIM_TYPE_STRING
, g_strdup(username
),NULL
);
718 /* \setinfo\\sesskey\469958979\info\Age=21.AvatarUrl=.BandName=.ContactType=1.DisplayName=Msim.Gender=M.ImageURL=http:/1/1x.myspace.com/1images/1no_pic.gif.LastLogin=128335268400000000.Location=US.ShowAvatar=False.SongName=.TotalFriends=1.UserName=msimprpl2\final\
722 g_return_if_fail(msim_send(session
,
723 "setinfo", MSIM_TYPE_BOOLEAN
, TRUE
,
724 "sesskey", MSIM_TYPE_INTEGER
, session
->sesskey
,
725 "info", MSIM_TYPE_DICTIONARY
, body
,
727 body
= msim_msg_new("UserName", MSIM_TYPE_STRING
, g_strdup(username
),NULL
);
728 g_return_if_fail(msim_send(session
,
729 "persist", MSIM_TYPE_INTEGER
, 1,
730 "sesskey", MSIM_TYPE_INTEGER
, session
->sesskey
,
731 "cmd", MSIM_TYPE_INTEGER
, MSIM_CMD_GET
,
732 "dsn", MSIM_TYPE_INTEGER
, MG_MYSPACE_INFO_BY_STRING_DSN
,
733 "uid", MSIM_TYPE_INTEGER
, session
->userid
,
734 "lid", MSIM_TYPE_INTEGER
, MG_MYSPACE_INFO_BY_STRING_LID
,
735 "rid", MSIM_TYPE_INTEGER
, rid
,
736 "body", MSIM_TYPE_DICTIONARY
, body
,
741 * They've confirmed that username that was available, Lets make the call to set it
743 static void msim_set_username_confirmed_cb(PurpleConnection
*gc
)
745 MsimMessage
*user_msg
;
746 MsimSession
*session
;
748 g_return_if_fail(gc
!= NULL
);
750 session
= (MsimSession
*)gc
->proto_data
;
752 user_msg
= msim_msg_new(
753 "user", MSIM_TYPE_STRING
, g_strdup(msim_username_to_set
),
756 purple_debug_info("msim_set_username_confirmed_cb", "Setting username to %s\n", msim_username_to_set
);
758 /* Sets our username... keep your fingers crossed :) */
759 msim_set_username(session
, msim_username_to_set
, msim_username_is_set_cb
, user_msg
);
760 g_free(msim_username_to_set
);
764 * This is where we do a bit more than merely prompt the user.
765 * Now we have some real data to tell us the state of their requested username
766 * \persistr\\cmd\257\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=TheAlbinoRhino1\final\
768 static void msim_username_is_available_cb(MsimSession
*session
, const MsimMessage
*userinfo
, gpointer data
)
775 purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");
777 msg
= (MsimMessage
*)data
;
778 g_return_if_fail(msg
!= NULL
);
780 username
= msim_msg_get_string(msg
, "user");
781 body
= msim_msg_get_dictionary(userinfo
, "body");
784 purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username
);
785 purple_connection_error_reason(session
->gc
, PURPLE_CONNECTION_ERROR_OTHER_ERROR
,
786 _("An error occurred while trying to set the username. "
787 "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
788 "fuseaction=profile.username to set your username."));
792 userid
= msim_msg_get_integer(body
, "UserID");
794 purple_debug_info("msim_username_is_available_cb", "Returned username is %s and userid is %d\n", username
, userid
);
798 /* The response for a free username will ONLY have the UserName in it..
799 * thus making UserID return 0 when we msg_get_integer it */
801 /* This username is currently unused */
802 purple_debug_info("msim_username_is_available_cb", "Username available. Prompting to Confirm.\n");
803 msim_username_to_set
= g_strdup(username
);
805 purple_request_yes_no(session
->gc
,
806 _("MySpaceIM - Username Available"),
807 _("This username is available. Would you like to set it?"),
808 _("ONCE SET, THIS CANNOT BE CHANGED!"),
814 G_CALLBACK(msim_set_username_confirmed_cb
),
815 G_CALLBACK(msim_do_not_set_username_cb
));
817 /* Looks like its in use or we have an invalid response */
818 purple_debug_info("msim_username_is_available_cb", "Username unavaiable. Prompting for new entry.\n");
819 purple_request_input(session
->gc
, _("MySpaceIM - Please Set a Username"),
820 _("This username is unavailable."),
821 _("Please try another username:"),
822 "", FALSE
, FALSE
, NULL
,
823 _("OK"), G_CALLBACK(msim_check_username_availability_cb
),
824 _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb
),
833 * Once they've submitted their desired new username,
834 * check if it is available here.
836 static void msim_check_username_availability_cb(PurpleConnection
*gc
, const char *username_to_check
)
838 MsimMessage
*user_msg
;
839 MsimSession
*session
;
841 g_return_if_fail(gc
!= NULL
);
843 session
= (MsimSession
*)gc
->proto_data
;
845 purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check
);
847 user_msg
= msim_msg_new(
848 "user", MSIM_TYPE_STRING
, g_strdup(username_to_check
),
851 /* 25 characters: letters, numbers, underscores */
852 /* TODO: VERIFY ABOVE */
854 /* \persist\1\sesskey\288500516\cmd\1\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=Jaywalker\final\ */
855 /* Official client uses a standard lookup... So do we! */
856 msim_lookup_user(session
, username_to_check
, msim_username_is_available_cb
, user_msg
);
860 * If they hit cancel or no at any point in the Setting Username process,
861 * we come here. Currently we're safe letting them get by without
862 * setting it, unless we hear otherwise. So for now give them a menu.
863 * If this becomes an issue with the official client then boot them here.
865 void msim_do_not_set_username_cb(PurpleConnection
*gc
)
867 purple_debug_info("msim", "Don't set username");
869 /* Protocol won't log in now without a username set.. Disconnect */
870 purple_connection_error_reason(gc
, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED
, _("No username set"));
874 * They've decided to set a username! Yay!
876 void msim_set_username_cb(PurpleConnection
*gc
)
878 g_return_if_fail(gc
!= NULL
);
879 purple_debug_info("msim","Set username\n");
880 purple_request_input(gc
, _("MySpaceIM - Please Set a Username"),
881 _("Please enter a username to check its availability:"),
883 "", FALSE
, FALSE
, NULL
,
884 _("OK"), G_CALLBACK(msim_check_username_availability_cb
),
885 _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb
),
886 purple_connection_get_account(gc
),