📄 cap.c
字号:
statistics->last_status_id = purple_status_get_id(status); purple_debug_info("cap", "Executing: insert into cap_status (buddy, account, protocol, status, event_time) values(%s, %s, %s, %s, now());\n", buddy_name, account_id, protocol_id, status_id); sql = sqlite3_mprintf("insert into cap_status values (%Q, %Q, %Q, %Q, now());", buddy_name, account_id, protocol_id, status_id); rc = sqlite3_exec(_db, sql, NULL, NULL, NULL); sqlite3_free(sql);}static void insert_word_count(const char *sender, const char *receiver, guint count) { /* TODO! */ /* dbi_result result; */ /* result = dbi_conn_queryf(_conn, "insert into cap_message values(\'%s\', \'%s\', %d, now());", sender, receiver, count); */}/* Callbacks */void display_statistics_action_cb(PurpleBlistNode *node, gpointer data) { PurpleBuddy *buddy; g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); buddy = (PurpleBuddy *)node; purple_debug_info("cap", "Statistics for %s requested.\n", buddy->name);}/* Purple plugin specific code */static gboolean plugin_load(PurplePlugin *plugin) { _plugin_pointer = plugin; _signals_connected = FALSE; /* buddy_stats is a hashtable where strings are keys * and the keys are a buddies account id (PurpleBuddy.name). * keys/values are automatically deleted */ _buddy_stats = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, destroy_stats); /* ? - Can't remember at the moment */ _my_offline_times = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); if(create_database_connection()) { add_plugin_functionality(plugin); } return TRUE;}static void add_plugin_functionality(PurplePlugin *plugin) { if(_signals_connected) return; purple_debug_info("cap", "Adding plugin functionality.\n"); /* Connect all the signals */ purple_signal_connect(purple_conversations_get_handle(), "sent-im-msg", plugin, PURPLE_CALLBACK(sent_im_msg), NULL); purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", plugin, PURPLE_CALLBACK(received_im_msg), NULL); purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", plugin, PURPLE_CALLBACK(buddy_status_changed), NULL); purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", plugin, PURPLE_CALLBACK(buddy_signed_on), NULL); purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", plugin, PURPLE_CALLBACK(buddy_signed_off), NULL); /*purple_signal_connect(purple_blist_get_handle(), "blist-node-extended-menu", plugin, PURPLE_CALLBACK(blist_node_extended_menu), NULL);*/ purple_signal_connect(pidgin_blist_get_handle(), "drawing-tooltip", plugin, PURPLE_CALLBACK(drawing_tooltip), NULL); purple_signal_connect(purple_connections_get_handle(), "signed-on", plugin, PURPLE_CALLBACK(signed_on), NULL); purple_signal_connect(purple_connections_get_handle(), "signed-off", plugin, PURPLE_CALLBACK(signed_off), NULL); purple_signal_connect(purple_blist_get_handle(), "buddy-idle-changed", plugin, PURPLE_CALLBACK(buddy_idle), NULL); _signals_connected = TRUE;}static void cancel_conversation_timeouts(gpointer key, gpointer value, gpointer user_data) { CapStatistics *stats = value; if(stats->timeout_source_id != 0) { g_source_remove(stats->timeout_source_id); stats->timeout_source_id = 0; }}static void remove_plugin_functionality(PurplePlugin *plugin) { if(!_signals_connected) return; purple_debug_info("cap", "Removing plugin functionality.\n"); /* If there are any timeouts waiting to be processed then cancel them */ g_hash_table_foreach(_buddy_stats, cancel_conversation_timeouts, NULL); /* Connect all the signals */ purple_signal_disconnect(purple_conversations_get_handle(), "sent-im-msg", plugin, PURPLE_CALLBACK(sent_im_msg)); purple_signal_disconnect(purple_conversations_get_handle(), "received-im-msg", plugin, PURPLE_CALLBACK(received_im_msg)); purple_signal_disconnect(purple_blist_get_handle(), "buddy-status-changed", plugin, PURPLE_CALLBACK(buddy_status_changed)); purple_signal_disconnect(purple_blist_get_handle(), "buddy-signed-on", plugin, PURPLE_CALLBACK(buddy_signed_on)); purple_signal_disconnect(purple_blist_get_handle(), "buddy-signed-off", plugin, PURPLE_CALLBACK(buddy_signed_off)); /*purple_signal_disconnect(purple_blist_get_handle(), "blist-node-extended-menu", plugin, PURPLE_CALLBACK(blist_node_extended_menu));*/ purple_signal_disconnect(pidgin_blist_get_handle(), "drawing-tooltip", plugin, PURPLE_CALLBACK(drawing_tooltip)); purple_signal_disconnect(purple_connections_get_handle(), "signed-on", plugin, PURPLE_CALLBACK(signed_on)); purple_signal_disconnect(purple_connections_get_handle(), "signed-off", plugin, PURPLE_CALLBACK(signed_off)); purple_signal_disconnect(purple_blist_get_handle(), "buddy-idle-changed", plugin, PURPLE_CALLBACK(buddy_idle)); _signals_connected = FALSE;}static void write_stats_on_unload(gpointer key, gpointer value, gpointer user_data) { CapStatistics *stats = value; if(stats->last_message != -1 && stats->buddy != NULL) { insert_cap_failure(stats); }}static gboolean plugin_unload(PurplePlugin *plugin) { purple_debug_info("cap", "CAP plugin unloading\n"); /* clean up memory allocations */ if(_buddy_stats) { g_hash_table_foreach(_buddy_stats, write_stats_on_unload, NULL); g_hash_table_destroy(_buddy_stats); } /* close database connection */ destroy_database_connection(); return TRUE;}static CapPrefsUI * create_cap_prefs_ui() { CapPrefsUI *ui = g_malloc(sizeof(CapPrefsUI)); ui->ret = gtk_vbox_new(FALSE, 18); gtk_container_set_border_width(GTK_CONTAINER(ui->ret), 10); ui->cap_vbox = pidgin_make_frame(ui->ret, _("Statistics Configuration")); /* msg_difference spinner */ ui->msg_difference_label = gtk_label_new(_("Maximum response timeout:")); gtk_misc_set_alignment(GTK_MISC(ui->msg_difference_label), 0, 0.5); ui->msg_difference_input = gtk_spin_button_new_with_range(1, 1440, 1); ui->msg_difference_minutes_label = gtk_label_new(_("minutes")); gtk_misc_set_alignment(GTK_MISC(ui->msg_difference_minutes_label), 0, 0.5); /* last_seen spinner */ ui->last_seen_label = gtk_label_new(_("Maximum last-seen difference:")); gtk_misc_set_alignment(GTK_MISC(ui->last_seen_label), 0, 0.5); ui->last_seen_input = gtk_spin_button_new_with_range(1, 1440, 1); ui->last_seen_minutes_label = gtk_label_new(_("minutes")); gtk_misc_set_alignment(GTK_MISC(ui->last_seen_minutes_label), 0, 0.5); /* threshold spinner */ ui->threshold_label = gtk_label_new(_("Threshold:")); gtk_misc_set_alignment(GTK_MISC(ui->threshold_label), 0, 0.5); ui->threshold_input = gtk_spin_button_new_with_range(1, 1440, 1); ui->threshold_minutes_label = gtk_label_new(_("minutes")); gtk_misc_set_alignment(GTK_MISC(ui->threshold_minutes_label), 0, 0.5); /* Layout threshold/last-seen/response-timeout input items */ ui->table_layout = gtk_table_new(3, 3, FALSE); gtk_table_attach(GTK_TABLE(ui->table_layout), ui->threshold_label, 0, 1, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(ui->table_layout), ui->threshold_input, 1, 2, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(ui->table_layout), ui->threshold_minutes_label, 2, 3, 0, 1, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(ui->table_layout), ui->msg_difference_label, 0, 1, 1, 2, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(ui->table_layout), ui->msg_difference_input, 1, 2, 1, 2, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(ui->table_layout), ui->msg_difference_minutes_label, 2, 3, 1, 2, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(ui->table_layout), ui->last_seen_label, 0, 1, 2,3, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(ui->table_layout), ui->last_seen_input, 1, 2, 2, 3, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); gtk_table_attach(GTK_TABLE(ui->table_layout), ui->last_seen_minutes_label, 2, 3, 2, 3, (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), (GtkAttachOptions) (0), 0, 0); /* Config window - lay it out */ gtk_box_pack_start(GTK_BOX(ui->cap_vbox), ui->table_layout, FALSE, FALSE, 0); /* Set the input areas to contain the configuration values from * purple prefs. */ if(purple_prefs_exists("/plugins/gtk/cap/max_msg_difference")) { int max_msg_diff = purple_prefs_get_int("/plugins/gtk/cap/max_msg_difference"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(ui->msg_difference_input), max_msg_diff); } if(purple_prefs_exists("/plugins/gtk/cap/max_seen_difference")) { int max_seen_diff = purple_prefs_get_int("/plugins/gtk/cap/max_seen_difference"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(ui->last_seen_input), max_seen_diff); } if(purple_prefs_exists("/plugins/gtk/cap/threshold")) { int threshold = purple_prefs_get_int("/plugins/gtk/cap/threshold"); gtk_spin_button_set_value(GTK_SPIN_BUTTON(ui->threshold_input), threshold); } /* Add the signals */ g_signal_connect(G_OBJECT(ui->ret), "destroy", G_CALLBACK(cap_prefs_ui_destroy_cb), ui); g_signal_connect(G_OBJECT(ui->msg_difference_input), "value-changed", G_CALLBACK(numeric_spinner_prefs_cb), "/plugins/gtk/cap/max_msg_difference"); g_signal_connect(G_OBJECT(ui->last_seen_input), "value-changed", G_CALLBACK(numeric_spinner_prefs_cb), "/plugins/gtk/cap/max_seen_difference"); g_signal_connect(G_OBJECT(ui->threshold_input), "value-changed", G_CALLBACK(numeric_spinner_prefs_cb), "/plugins/gtk/cap/threshold"); return ui;}static void cap_prefs_ui_destroy_cb(GtkObject *object, gpointer user_data) { CapPrefsUI *ui = user_data; if(_db) { add_plugin_functionality(_plugin_pointer); } g_free(ui);}static void numeric_spinner_prefs_cb(GtkSpinButton *spinbutton, gpointer user_data) { purple_prefs_set_int(user_data, gtk_spin_button_get_value_as_int(spinbutton));}static PidginPluginUiInfo ui_info = { get_config_frame, 0 /* page_num (reserved) */};static PurplePluginInfo info = { PURPLE_PLUGIN_MAGIC, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_PLUGIN_STANDARD, /**< type */ PIDGIN_PLUGIN_TYPE, /**< ui_requirement */ 0, /**< flags */ NULL, /**< dependencies */ PURPLE_PRIORITY_DEFAULT, /**< priority */ CAP_PLUGIN_ID, /**< id */ N_("Contact Availability Prediction"), /**< name */ VERSION, /**< version */ N_("Contact Availability Prediction plugin."), /** summary */ N_("The contact availability plugin (cap) is used to display statistical information about buddies in a users contact list."), /** description */ "Geoffrey Foster <geoffrey.foster@gmail.com>", /**< author */ PURPLE_WEBSITE, /**< homepage */ plugin_load, /**< load */ plugin_unload, /**< unload */ NULL, /**< destroy */ &ui_info, /**< ui_info */ NULL, /**< extra_info */ NULL, /**< prefs_info */ NULL};static GtkWidget * get_config_frame(PurplePlugin *plugin) { CapPrefsUI *ui = create_cap_prefs_ui(); /* * Prevent database stuff from occuring since we are editing values */ remove_plugin_functionality(_plugin_pointer); return ui->ret;}static void init_plugin(PurplePlugin *plugin) { purple_prefs_add_none("/plugins/gtk/cap"); purple_prefs_add_int("/plugins/gtk/cap/max_seen_difference", 1); purple_prefs_add_int("/plugins/gtk/cap/max_msg_difference", 10); purple_prefs_add_int("/plugins/gtk/cap/threshold", 5);}PURPLE_INIT_PLUGIN(cap, init_plugin, info);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -