/* the callback function after socket is built * we setup the qq protocol related configuration here */ static void connect_cb(gpointer data, gint source, const gchar *error_message) { PurpleConnection *gc; qq_data *qd; qq_connection *conn; gc = (PurpleConnection *) data; g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; /* conn_data will be destoryed */ qd->conn_data = NULL; if (!PURPLE_CONNECTION_IS_VALID(gc)) { purple_debug_info("QQ_CONN", "Invalid connection\n"); close(source); return; } if (source < 0) { /* socket returns -1 */ purple_debug_info("QQ_CONN", "Could not establish a connection with the server:\n%s\n", error_message); if (qd->connect_watcher > 0) purple_timeout_remove(qd->connect_watcher); qd->connect_watcher = purple_timeout_add_seconds(QQ_CONNECT_INTERVAL, qq_connect_later, gc); return; } /* _qq_show_socket("Got login socket", source); */ /* ok, already connected to the server */ qd->fd = source; conn = connection_create(qd, source); g_return_if_fail( conn != NULL ); if (qd->use_tcp) { /* events which match "PURPLE_INPUT_READ" of * "source" would trigger the callback function */ conn->input_handler = purple_input_add(source, PURPLE_INPUT_READ, tcp_pending, gc); } else { conn->input_handler = purple_input_add(source, PURPLE_INPUT_READ, udp_pending, gc); } g_return_if_fail(qd->network_watcher == 0); qd->network_watcher = purple_timeout_add_seconds(qd->itv_config.resend, network_timeout, gc); set_all_keys( gc ); if (qd->client_version >= 2007) { purple_connection_update_progress(gc, _("Getting server"), 2, QQ_CONNECT_STEPS); /* touch required */ qq_request_get_server(gc); return; } purple_connection_update_progress(gc, _("Requesting token"), 2, QQ_CONNECT_STEPS); qq_request_token(gc); }
/*------------------------------------------------------------------------ * We now have a connection established with MXit, so we can start the * login procedure * * @param session The MXit session object */ static void mxit_connected( struct MXitSession* session ) { int state; purple_debug_info( MXIT_PLUGIN_ID, "mxit_connected\n" ); session->flags |= MXIT_FLAG_CONNECTED; purple_connection_update_progress( session->con, _( "Logging In..." ), 2, 4 ); /* create a timer to send a ping packet if the connection is idle */ session->last_tx = mxit_now_milli(); /* encrypt the user password */ session->encpwd = mxit_encrypt_password( session ); state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN ); if ( state == MXIT_STATE_LOGIN ) { /* create and send login packet */ mxit_send_login( session ); } else { if ( !session->profile ) { /* we have lost the session profile, so ask the user to enter it again */ mxit_register_view( session ); } else { /* create and send the register packet */ mxit_send_register( session ); } } /* enable signals */ mxit_enable_signals( session ); #ifdef MXIT_LINK_CLICK /* register for uri click notification */ mxit_register_uri_handler(); #endif /* start the polling if this is a HTTP connection */ if ( session->http ) { session->http_timer_id = purple_timeout_add_seconds( 2, mxit_manage_polling, session ); } /* This timer might already exist if we're registering a new account */ if ( session->q_slow_timer_id == 0 ) { /* start the tx queue manager timer */ session->q_slow_timer_id = purple_timeout_add_seconds( 2, mxit_manage_queue_slow, session ); } }
static void pb_start_polling(PushBulletAccount *pba) { if (!purple_account_is_connected(pba->account)) return; if (!pba->phone_threads_poll && pba->main_sms_device) { pb_get_phone_threads(pba, NULL); pba->phone_threads_poll = purple_timeout_add_seconds(10, (GSourceFunc) pb_poll_phone_threads, pba); } if (!pba->everything_poll) { pb_get_everything_since(pba, purple_account_get_int(pba->account, "last_message_timestamp", 0)); pba->everything_poll = purple_timeout_add_seconds(10, (GSourceFunc) pb_poll_everything, pba); } }
static void connect_cb(gpointer data, gint source, const gchar *error_message) { MsnHttpConn *httpconn; httpconn = data; httpconn->connect_data = NULL; httpconn->fd = source; if (source >= 0) { httpconn->inpa = purple_input_add(httpconn->fd, PURPLE_INPUT_READ, read_cb, data); httpconn->timer = purple_timeout_add_seconds(2, msn_httpconn_poll, httpconn); msn_httpconn_process_queue(httpconn); } else { purple_debug_error("msn", "HTTP: Connection error: %s\n", error_message ? error_message : "(null)"); msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT); } }
static void hide_conv(PidginConversation *gtkconv, gboolean closetimer) { GList *list; purple_signal_emit(pidgin_conversations_get_handle(), "conversation-hiding", gtkconv); for (list = g_list_copy(gtkconv->convs); list; list = g_list_delete_link(list, list)) { PurpleConversation *conv = list->data; if (closetimer) { guint timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); if (timer) purple_timeout_remove(timer); timer = purple_timeout_add_seconds(CLOSE_CONV_TIMEOUT_SECS, close_already, conv); purple_conversation_set_data(conv, "close-timer", GINT_TO_POINTER(timer)); } #if 0 /* I will miss you */ purple_conversation_set_ui_ops(conv, NULL); #else pidgin_conv_window_remove_gtkconv(gtkconv->win, gtkconv); pidgin_conv_window_add_gtkconv(hidden_convwin, gtkconv); #endif } }
void skypeweb_do_all_the_things(SkypeWebAccount *sa) { if (!sa->username) { skypeweb_get_self_details(sa); } else if (sa->registration_token) { skypeweb_get_self_details(sa); if (sa->authcheck_timeout) purple_timeout_remove(sa->authcheck_timeout); skypeweb_check_authrequests(sa); sa->authcheck_timeout = purple_timeout_add_seconds(120, (GSourceFunc)skypeweb_check_authrequests, sa); purple_connection_set_state(sa->pc, PURPLE_CONNECTION_CONNECTED); skypeweb_get_friend_list(sa); skypeweb_poll(sa); skype_web_get_offline_history(sa); skypeweb_set_status(sa->account, purple_account_get_active_status(sa->account)); } else { //Too soon! skypeweb_get_registration_token(sa); } }
static gboolean plugin_load(PurplePlugin *plugin) { void *conv_handle; GHashTable *users; guint id; gpointer *data; users = g_hash_table_new_full((GHashFunc)joinpart_key_hash, (GEqualFunc)joinpart_key_equal, (GDestroyNotify)joinpart_key_destroy, g_free); conv_handle = purple_conversations_get_handle(); purple_signal_connect(conv_handle, "chat-buddy-joining", plugin, PURPLE_CALLBACK(chat_buddy_joining_cb), users); purple_signal_connect(conv_handle, "chat-buddy-leaving", plugin, PURPLE_CALLBACK(chat_buddy_leaving_cb), users); purple_signal_connect(conv_handle, "received-chat-msg", plugin, PURPLE_CALLBACK(received_chat_msg_cb), users); /* Cleanup every 5 minutes */ id = purple_timeout_add_seconds(60 * 5, (GSourceFunc)clean_users_hash, users); data = g_new(gpointer, 2); data[0] = users; data[1] = GUINT_TO_POINTER(id); plugin->extra = data; return TRUE; }
static gboolean plugin_load (PurplePlugin * plugin) { trace("plugin loading"); autostatus_plugin = plugin; /* assign this here so we have a valid handle later */ str_myip = (gchar *)malloc(strlen("xxx.xxx.xxx.xxx")); /* TODO time out */ /* Note: here need to consider serverl situation: * 1. enable/disable account * 2. change status * 3. how to make sure nothing changes * 4. diffenent status for different accounts * 5. move to another place! */ /* refresh each 10 seconds */ guint g_tid = purple_timeout_add_seconds(10, set_status_all, 0); load_config(); if (set_status_all()) trace ("plugin succesfully loaded"); return TRUE; }
static MsnSoapConnection * msn_soap_get_connection(MsnSession *session, const char *host) { MsnSoapConnection *conn = NULL; if (session->soap_table) { conn = g_hash_table_lookup(session->soap_table, host); } else { session->soap_table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)msn_soap_connection_destroy); } if (session->soap_cleanup_handle == 0) session->soap_cleanup_handle = purple_timeout_add_seconds(SOAP_TIMEOUT, msn_soap_cleanup_for_session, session); if (conn == NULL) { conn = msn_soap_connection_new(session, host); g_hash_table_insert(session->soap_table, conn->host, conn); } conn->last_used = time(NULL); return conn; }
static void end_user_display(MsnSlpCall *slpcall, MsnSession *session) { MsnUserList *userlist; g_return_if_fail(session != NULL); if (purple_debug_is_verbose()) purple_debug_info("msn", "End User Display\n"); userlist = session->userlist; /* If the session is being destroyed we better stop doing anything. */ if (session->destroying) return; /* Delay before freeing a buddy icon window slot and requesting the next icon, if appropriate. * If we don't delay, we'll rapidly hit the MSN equivalent of AIM's rate limiting; the server will * send us an error 800 like so: * * C: NS 000: XFR 21 SB * S: NS 000: 800 21 */ if (userlist->buddy_icon_request_timer) { /* Free the window slot used by this previous request */ userlist->buddy_icon_window++; /* Clear our pending timeout */ purple_timeout_remove(userlist->buddy_icon_request_timer); } /* Wait BUDDY_ICON_DELAY s before freeing our window slot and requesting the next icon. */ userlist->buddy_icon_request_timer = purple_timeout_add_seconds(BUDDY_ICON_DELAY, msn_release_buddy_icon_request_timeout, userlist); }
static gboolean plugin_load(PurplePlugin *plugin) { void *conv_handle; PurpleConversationUiOps *ui_ops; purple_prefs_set_bool(PURPLE_NICKCHANGE_PREF, FALSE); userstable = g_hash_table_new_full((GHashFunc)joinpart_key_hash, (GEqualFunc)joinpart_key_equal, (GDestroyNotify)joinpart_key_destroy, g_free); conv_handle = purple_conversations_get_handle(); //purple_signal_connect(conv_handle, "chat-buddy-joining", plugin, PURPLE_CALLBACK(chat_buddy_joining_cb), userstable); //purple_signal_connect(conv_handle, "chat-buddy-leaving", plugin, PURPLE_CALLBACK(chat_buddy_leaving_cb), userstable); purple_signal_connect(conv_handle, "received-chat-msg", plugin, PURPLE_CALLBACK(received_chat_msg_cb), userstable); //purple_prefs_connect_callback(plugin, const char *name, PurplePrefCallback cb, gpointer data) //Attempt overriding the global UI ops ui_ops = pidgin_conversations_get_conv_ui_ops(); /* Cleanup every 5 minutes */ clean_user_timeout = purple_timeout_add_seconds(60 * 5, (GSourceFunc)clean_users_hash, userstable); if (ui_ops) { orig_chat_rename_user = ui_ops->chat_rename_user; ui_ops->chat_rename_user = nickchange_chat_rename_user; } else { //TODO make it work for !Pidgin too return FALSE; } return TRUE; }
/* * We mute sounds for the 10 seconds after you log in so that * you don't get flooded with sounds when the blist shows all * your buddies logging in. */ static void account_signon_cb(PurpleConnection *gc, gpointer data) { if (mute_login_sounds_timeout != 0) g_source_remove(mute_login_sounds_timeout); mute_login_sounds = TRUE; mute_login_sounds_timeout = purple_timeout_add_seconds(10, unmute_login_sounds_cb, NULL); }
static void join_chat(PurpleConnection * gc, GHashTable * data) { if (!purple_find_chat(gc, CHAT_ID)) { purple_debug_misc(PLUGIN_ID, "JOIN CHAT\n"); serv_got_joined_chat(gc, CHAT_ID, CHAT_NAME); gc->proto_data = (void*)purple_timeout_add_seconds(1, timer_cb, gc); } }
void msn_session_activate_login_timeout(MsnSession *session) { if (!session->logged_in && session->connected) { session->login_timeout = purple_timeout_add_seconds(MSN_LOGIN_FQY_TIMEOUT, msn_login_timeout_cb, session); } }
void ggp_avatar_setup(PurpleConnection *gc) { ggp_avatar_session_data *avdata = ggp_avatar_get_avdata(gc); avdata->pending_updates = NULL; avdata->current_update = NULL; avdata->own_data = g_new0(ggp_avatar_own_data, 1); avdata->timer = purple_timeout_add_seconds(1, ggp_avatar_timer_cb, gc); }
gpointer sipe_backend_schedule_seconds(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public, guint timeout, gpointer data) { struct purple_schedule *schedule = g_malloc(sizeof(struct purple_schedule)); schedule->core_data = data; schedule->timeout_handler = purple_timeout_add_seconds(timeout, purple_timeout_execute, schedule); return(schedule); }
FListWebRequestData* flist_web_request(const gchar* url, GHashTable* args, gboolean post, FListWebCallback cb, gpointer data) { gchar *http = http_request(url, FALSE, post, USER_AGENT, args, NULL); FListWebRequestData *ret = g_new0(FListWebRequestData, 1); PurpleUtilFetchUrlData *url_data = purple_util_fetch_url_request(url, FALSE, USER_AGENT, FALSE, http, FALSE, flist_web_request_cb, ret); ret->url_data = url_data; ret->cb = cb; ret->user_data = data; ret->timer = purple_timeout_add_seconds(FLIST_WEB_REQUEST_TIMEOUT, (GSourceFunc) flist_web_request_timeout, ret); g_hash_table_insert(requests, ret, ret); return ret; }
/* * This callback will be called when we're unable to connect to * the remote host in DC_OUTGOING_TIMEOUT seconds. */ gboolean msn_dc_outgoing_connection_timeout_cb(gpointer data) { MsnDirectConn *dc = data; purple_debug_info("msn", "msn_dc_outgoing_connection_timeout_cb %p\n", dc); g_return_val_if_fail(dc != NULL, FALSE); dc->connect_timeout_handle = 0; if (dc->connect_data != NULL) { purple_proxy_connect_cancel(dc->connect_data); dc->connect_data = NULL; } if (dc->ext_ip && dc->ext_port) { /* Try external IP/port if available. */ dc->connect_data = purple_proxy_connect( NULL, dc->slpcall->slplink->session->account, dc->ext_ip, dc->ext_port, msn_dc_connected_to_peer_cb, dc ); g_free(dc->ext_ip); dc->ext_ip = NULL; if (dc->connect_data) { dc->connect_timeout_handle = purple_timeout_add_seconds( DC_OUTGOING_TIMEOUT, msn_dc_outgoing_connection_timeout_cb, dc ); } else { /* * Connection failed * Fall back to SB transfer */ msn_dc_outgoing_connection_timeout_cb(dc); } } else { /* * Both internal and external connection attempts failed. * Fall back to SB transfer. */ msn_dc_fallback_to_sb(dc); } return FALSE; }
void msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb) { if (trans->timer) { purple_debug_error("msn", "This shouldn't be happening\n"); purple_timeout_remove(trans->timer); } trans->timeout_cb = cb; trans->timer = purple_timeout_add_seconds(60, transaction_timeout, trans); }
void FiletransferRepeater::handleFTSendBytestream(Bytestream *bs, const std::string &filename) { Log("SendFileStraight", "new!"); purple_xfer_request_accepted(m_xfer, NULL); if (filename.empty()) m_resender = new SendFileStraight(bs, 0, this); else { User *user = m_main->userManager()->getUserByJID(bs->initiator().bare()); m_resender = new SendFile(bs, 0, filename, user, this); } purple_timeout_add_seconds(3,&ui_got_data,m_xfer); }
static void skypeweb_got_object_for_file(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message) { SkypeWebFileTransfer *swft = user_data; SkypeWebAccount *sa = swft->sa; PurpleXfer *xfer = swft->xfer; JsonParser *parser; JsonNode *node; JsonObject *obj; gchar *id; sa->url_datas = g_slist_remove(sa->url_datas, url_data); //Get back {"id": "0-cus-d3-deadbeefdeadbeef012345678"} parser = json_parser_new(); if (!json_parser_load_from_data(parser, url_text, len, NULL)) { g_free(swft->from); g_free(swft); g_object_unref(parser); return; } node = json_parser_get_root(parser); if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) { g_free(swft->from); g_free(swft); g_object_unref(parser); purple_xfer_cancel_local(xfer); return; } obj = json_node_get_object(node); if (!json_object_has_member(obj, "id")) { g_free(swft->from); g_free(swft); g_object_unref(parser); purple_xfer_cancel_local(xfer); return; } swft->id = g_strdup(json_object_get_string_member(obj, "id")); swft->url = g_strconcat("https://" SKYPEWEB_XFER_HOST "/v1/objects/", purple_url_encode(swft->id), "/views/original/status", NULL); g_object_unref(parser); //Send the data //can't use fetch_url_request because it doesn't handle binary data //TODO make an error handler callback func purple_ssl_connect(sa->account, SKYPEWEB_XFER_HOST, 443, skypeweb_xfer_send_connect_cb, NULL, swft); //poll swft->url for progress purple_timeout_add_seconds(1, poll_file_send_progress, swft); }
static void redirect_server(PurpleConnection *gc) { qq_data *qd; qd = (qq_data *) gc->proto_data; if (qd->check_watcher > 0) { purple_timeout_remove(qd->check_watcher); qd->check_watcher = 0; } if (qd->connect_watcher > 0) purple_timeout_remove(qd->connect_watcher); qd->connect_watcher = purple_timeout_add_seconds(QQ_CONNECT_INTERVAL, qq_connect_later, gc); }
static void servconn_timeout_renew(MsnServConn *servconn) { if (servconn->timeout_handle) { purple_timeout_remove(servconn->timeout_handle); servconn->timeout_handle = 0; } if (servconn->connected && servconn->timeout_sec) { servconn->timeout_handle = purple_timeout_add_seconds( servconn->timeout_sec, (GSourceFunc)servconn_idle_timeout_cb, servconn); } }
static gboolean exec_skype() { if (!connected && !in_progress) { in_progress = TRUE; PurpleAccount *acct = skype_get_account(NULL); purple_proxy_connect(acct->gc, acct, purple_account_get_string(acct, "host", "skype.robbmob.com"), purple_account_get_int(acct, "port", 5000), connect_function, acct); g_thread_create((GThreadFunc)skype_read_thread, acct, FALSE, NULL); purple_timeout_add_seconds(10, connection_timeout, acct); } return TRUE; }
static void msn_dc_init(MsnDirectConn *dc) { g_return_if_fail(dc != NULL); dc->in_size = DC_MAX_PACKET_SIZE + 4; dc->in_pos = 0; dc->in_buffer = g_malloc(dc->in_size); dc->recv_handle = purple_input_add(dc->fd, PURPLE_INPUT_READ, msn_dc_recv_cb, dc); dc->send_handle = purple_input_add(dc->fd, PURPLE_INPUT_WRITE, msn_dc_send_cb, dc); dc->timeout_handle = purple_timeout_add_seconds(DC_TIMEOUT, msn_dc_timeout, dc); }
static void restart_inactivity_timer(PurpleBOSHConnection *conn) { if (conn->inactivity_timer != 0) { purple_timeout_remove(conn->inactivity_timer); conn->inactivity_timer = 0; } if (conn->max_inactivity != 0) { conn->inactivity_timer = purple_timeout_add_seconds(conn->max_inactivity - 5 /* rounding */, bosh_inactivity_cb, conn); } }
void ggp_roster_setup(PurpleConnection *gc) { ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc); rdata->content = NULL; rdata->sent_updates = NULL; rdata->pending_updates = NULL; rdata->timer = 0; rdata->is_updating = FALSE; if (ggp_roster_enabled()) rdata->timer = purple_timeout_add_seconds(2, ggp_roster_timer_cb, gc); }
void mb_conn_fetch_url_cb(PurpleUtilFetchUrlData * url_data, gpointer user_data, const gchar * url_text, gsize len, const gchar * error_message) { MbConnData * conn_data = (MbConnData *)user_data; MbAccount * ma = conn_data->ma; gint retval; purple_debug_info(MB_NET, "%s: url_data = %p\n", __FUNCTION__, url_data); // in whatever situation, url_data should be handled only by libpurple conn_data->fetch_url_data = NULL; if(error_message != NULL) { if(conn_data->handler) { retval = conn_data->handler(conn_data, conn_data->handler_data, error_message); } if(ma->gc != NULL) { purple_connection_error_reason(ma->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message); } mb_conn_data_free(conn_data); } else { mb_http_data_post_read(conn_data->response, url_text, len); if(conn_data->handler) { purple_debug_info(MB_NET, "going to call handler\n"); retval = conn_data->handler(conn_data, conn_data->handler_data, NULL); purple_debug_info(MB_NET, "handler returned, retval = %d\n", retval); if(retval == 0) { // Everything's good. Free data structure and go-on with usual works purple_debug_info(MB_NET, "everything's ok, freeing data\n"); mb_conn_data_free(conn_data); } else if(retval == -1) { // Something's wrong. Requeue the whole process conn_data->retry++; if(conn_data->retry <= conn_data->max_retry) { purple_debug_info(MB_NET, "handler return -1, conn_data %p, retry %d, max_retry = %d\n", conn_data, conn_data->retry, conn_data->max_retry); mb_http_data_truncate(conn_data->response); // retry again in 1 second purple_timeout_add_seconds(1, mb_conn_retry_request, conn_data); } else { purple_debug_info(MB_NET, "retry exceed %d > %d\n", conn_data->retry, conn_data->max_retry); mb_conn_data_free(conn_data); } } } } }
/* Message fetch loop. An invariant here is that get_new_messages() * is the only function which can create a new timer for * new_messages_check_timer. The timer always calls got_new_messages(), * and got_new_messages always calls get_new_messages (either directly * or indirectly). To start the loops off, get_new_messages should be * called ONCE and only ONCE. After that the timers will take care of * themselves until final cleanup. */ gboolean fb_get_new_messages(FacebookAccount *fba) { time_t now; gchar *fetch_url; gchar *fetch_server; const gchar *channel_number; fba->new_messages_check_timer = 0; now = time(NULL); if (fba->last_messages_download_time > now - 3) { /* * Wait a bit before fetching more messages, to make sure we * never hammer their servers. * * TODO: This could be smarter. Like, allow 3 requests per * 10 seconds or something. */ fba->new_messages_check_timer = purple_timeout_add_seconds( 3 - (now - fba->last_messages_download_time), (GSourceFunc)fb_get_new_messages, fba); return FALSE; } if (fba->channel_number == NULL) { return FALSE; } else { channel_number = fba->channel_number; } purple_debug_info("facebook", "getting new messages\n"); fetch_server = g_strdup_printf("%d.%s.facebook.com", 0, channel_number); /* use the current time in the url to get past any transparent proxy caches */ fetch_url = g_strdup_printf("/x/%lu/%s/p_%" G_GINT64_FORMAT "=%d", (gulong)time(NULL), (fba->is_idle?"false":"true"), fba->uid, fba->message_fetch_sequence); fb_post_or_get(fba, FB_METHOD_GET, fetch_server, fetch_url, NULL, got_new_messages, fba->pc, TRUE); fba->last_messages_download_time = now; g_free(fetch_url); g_free(fetch_server); return FALSE; }
static void irc_connected(struct irc_conn *irc, const char *nick) { PurpleConnection *gc; PurpleStatus *status; PurpleBlistNode *gnode, *cnode, *bnode; if ((gc = purple_account_get_connection(irc->account)) == NULL || PURPLE_CONNECTION_IS_CONNECTED(gc)) return; purple_connection_set_display_name(gc, nick); purple_connection_set_state(gc, PURPLE_CONNECTED); /* If we're away then set our away message */ status = purple_account_get_active_status(irc->account); if (!purple_status_get_type(status) != PURPLE_STATUS_AVAILABLE) { PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); prpl_info->set_status(irc->account, status); } /* this used to be in the core, but it's not now */ for (gnode = purple_get_blist()->root; gnode; gnode = gnode->next) { if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) continue; for(cnode = gnode->child; cnode; cnode = cnode->next) { if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) continue; for(bnode = cnode->child; bnode; bnode = bnode->next) { PurpleBuddy *b; if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) continue; b = (PurpleBuddy *)bnode; if(b->account == gc->account) { struct irc_buddy *ib = g_new0(struct irc_buddy, 1); ib->name = g_strdup(b->name); g_hash_table_insert(irc->buddies, ib->name, ib); } } } } irc_blist_timeout(irc); if (!irc->timer) irc->timer = purple_timeout_add_seconds(45, (GSourceFunc)irc_blist_timeout, (gpointer)irc); }