2 #define PREF_PREFIX "/plugins/gtk/autoanswer"
3 #define PREF_MODE PREF_PREFIX "/use_funny_mode"
4 #define PREF_LIMIT PREF_PREFIX "/limit_of_answers"
5 #define PREF_ROBOT PREF_PREFIX "/unhide_robot"
6 #define PREF_SEARCH PREF_PREFIX "/use_all_logs"
7 #define PREF_DICT PREF_PREFIX "/use_dct"
8 #define PREF_VERBOSE PREF_PREFIX "/use_verbose_mode"
9 #define PREF_PROMPT PREF_PREFIX "/robots_prompt"
11 #define _(String) ((const char *) (String))
16 #include <libpurple/debug.h>
17 #include <libpurple/version.h>
18 #include <libpurple/conversation.h>
19 #include <libpurple/debug.h>
20 #include <libpurple/log.h>
21 #include <libpurple/plugin.h>
22 #include <libpurple/pluginpref.h>
23 #include <libpurple/prefs.h>
24 #include <libpurple/signals.h>
25 #include <libpurple/util.h>
26 #include <libpurple/notify.h>
29 #include <pidgin/gtkaccount.h>
30 #include <pidgin/gtkblist.h>
31 #include <pidgin/gtkconv.h>
32 #include <pidgin/gtkimhtml.h>
33 #include <pidgin/gtkplugin.h>
34 #include <pidgin/gtkprefs.h>
35 #include <pidgin/gtkutils.h>
36 #include <pidgin/pidgin.h>
49 char *buddyname1
= NULL
;
50 char *buddyname1_alias
= NULL
;
51 char *username_alias
= NULL
;
52 char *username
= NULL
;
53 GList
*answers
= NULL
;
54 int limit_of_answers
= 10;
56 int list(const char *, const struct stat
*, int);
57 static void create_send_combo_pidgin(PidginConversation
*gtkconv
);
59 gint
compare_str(gconstpointer a
, gconstpointer b
)
61 if (a
==NULL
) return 1;
62 if (b
==NULL
) return -1;
66 int list (const char *name
, const struct stat
*status
, int type
) {
72 char answer
[1024], *answer_body
, *tmp_ptr
;
73 char *me
; //, *me_end;
75 int current_number_of_answers
= g_list_length(answers
);
77 if (type
== FTW_NS
) return 0;
79 /* purple_debug_misc("auto-answer-history DEBUG", "%-30s\t0%3o\n", name, status->st_mode&0777); */
80 files
= g_list_append(files
, (gpointer
) name
);
83 purple_debug_misc("auto-answer-history DEBUG", "Logdir is: %-30s*\t0%3o\n", name, status->st_mode&0777);
84 purple_debug_misc("auto-answer-history DEBUG", "Going to find \"%s\" from buddy %s (%s)\n", buff, buddyname1, buddyname1_alias);
87 if (username_alias
!= NULL
) me
= username_alias
;
93 /* purple_debug_misc("auto-answer-history DEBUG", "Processing... %s\n", files->data); */
94 if ((curlog
= fopen(files
->data
, "r")) != NULL
) {
95 while (fgets(curline
, sizeof curline
, curlog
) != NULL
) {
96 if ( ((strstr(curline
, buff
)) != NULL
) && ((strstr(curline
, me
)) == NULL
)) {
97 match
= strstr(curline
, buff
);
98 /* purple_debug_misc("auto-answer-history DEBUG", "FOUND in %s, line %d, looking for answer...\n", files->data, counter); */
99 while (fgets(answer
, sizeof answer
, curlog
) !=NULL
) {
100 if ((strstr(answer
, me
)) != NULL
) {
101 if (purple_markup_strip_html(answer
) != NULL
) {
102 if (current_number_of_answers
>limit_of_answers
)
106 /* check if such answer isn't already in a GList */
108 answer_body
=purple_markup_strip_html(answer
);
109 tmp_ptr
=strchr(answer_body
,':')+1; tmp_ptr
=strchr(tmp_ptr
,':')+1;
110 tmp_ptr
=strchr(tmp_ptr
,':')+1; /*skip 3 semi-colons in the preface*/
112 answer_body
=strstr(answer_body
,me
)+me_length
+1; /*skip preface*/
113 if (tmp_ptr
> answer_body
) answer_body
= tmp_ptr
; /* choose the better method of preface skip*/
115 if (!g_list_find_custom(answers
,answer_body
,compare_str
))
116 { g_list_append (answers
, answer_body
);
117 current_number_of_answers
++;
134 send_combo_cb(GtkWidget
*widget
, PidginConversation
*gtkconv
)
135 { /* A button to send item from combobox was pressed */
136 GtkIMHtmlOptions options
;
137 GtkWidget
*send_combo
;
138 gchar
*text
, *pref_prompt
;
139 gtk_imhtml_clear(GTK_IMHTML(gtkconv
->entry
));
140 /* if (purple_prefs_get_bool(PREF_ROBOT))
141 {*/ /*gtk_imhtml_append_text(GTK_IMHTML(gtkconv->entry), _("The possible answer is:<B>"), options);*/
142 pref_prompt
=purple_prefs_get_string(PREF_PROMPT
);
143 if (strlen(pref_prompt
)>0)
144 { gtk_imhtml_append_text(GTK_IMHTML(gtkconv
->entry
), pref_prompt
, options
);
145 gtk_imhtml_append_text(GTK_IMHTML(gtkconv
->entry
), "<B>", options
);
147 // purple_debug_misc("auto-answer-history DEBUG", "the prompt was \"%d\"", strlen(pref_prompt));
150 send_combo
= g_object_get_data(G_OBJECT(gtkconv
->toolbar
), "send_combo");
151 text
=gtk_combo_box_get_active_text(GTK_COMBO_BOX(send_combo
));
152 gtk_imhtml_append_text(GTK_IMHTML(gtkconv
->entry
), text
, options
);
154 g_signal_emit_by_name(gtkconv
->entry
, "message_send");
158 received_im_msg_cb(PurpleAccount
*account
, char *who
, char *buffer
,
159 PurpleConversation
*conv
, PurpleMessageFlags flags
, void *data
)
163 char* foundmessage
= NULL
;
167 GtkWidget
*send_combo
= NULL
;
169 GtkIMHtmlOptions options
;
170 PidginConversation
*gtkconv
= NULL
;
173 limit_of_answers
=purple_prefs_get_int(PREF_LIMIT
);
175 /* A workaround to avoid skipping of the first message as a result on NULL-conv: */
176 if (conv
== NULL
) conv
=purple_conversation_new(PURPLE_CONV_TYPE_IM
, account
, who
);
180 buff
= purple_markup_strip_html(buffer
);
181 printf("\nHarvie received 1: %s\n", buffer
);
182 purple_conv_im_send(purple_conversation_get_im_data(conv
), ":-*");
184 purple_debug_info("auto-answer-history DEBUG", "buff: %s\n", buff
);
185 username
= purple_account_get_username(account
);
186 purple_debug_info("auto-answer-history DEBUG", "username: %s\n", username
);
187 username_alias
= purple_account_get_alias(account
);
188 buddyname1
= purple_conversation_get_name(conv
); /** this shoud work fine, at least with ICQ **/
189 purple_debug_info("auto-answer-history DEBUG", "buddyname: %s\n", buddyname1
);
190 b
= purple_find_buddy(account
, buddyname1
);
191 buddyname1_alias
= purple_buddy_get_alias_only(b
);
193 name
= purple_conversation_get_name(conv
);
194 logdir
= purple_log_get_log_dir(PURPLE_LOG_IM
, name
, account
);
195 /* purple_debug_info("auto-answer-history DEBUG", "LogDir: %s\n", logdir); */
197 answers
=g_list_alloc();
198 ftw(logdir
, list
, 1);
199 purple_debug_misc("auto-answer-history DEBUG", "Number of answers found is: %d\n", (g_list_length(answers
)-1));
201 if (g_list_length(answers
) == 1) return; /* exit if no possible answers found */
203 gtkconv
= PIDGIN_CONVERSATION(conv
);
205 if (purple_prefs_get_bool(PREF_VERBOSE
)) gtk_imhtml_append_text(GTK_IMHTML(gtkconv
->imhtml
), "<HR>", options
);
207 send_combo
= g_object_get_data(G_OBJECT(gtkconv
->toolbar
), "send_combo");
208 if (send_combo
== NULL
) {
209 create_send_combo_pidgin(gtkconv
);
210 send_combo
= g_object_get_data(G_OBJECT(gtkconv
->toolbar
), "send_combo");
212 else { /* clear combo box */
213 number_of_lines
= gtk_tree_model_iter_n_children(gtk_combo_box_get_model(send_combo
), NULL
);
214 for(; number_of_lines
; number_of_lines
--) gtk_combo_box_remove_text(send_combo
, number_of_lines
-1);
215 purple_debug_misc("auto-answer-history DEBUG", "number of lines to delete:%d\n", number_of_lines
);
219 if (answers
->data
!= 0) {
220 g_strchomp(answers
->data
);
221 foundmessage
= (char*) answers
->data
;
223 if (purple_prefs_get_bool(PREF_VERBOSE
)) /* Flood all possible answers into my conversation window */
226 pref_prompt
=purple_prefs_get_string(PREF_PROMPT
);
227 if (strlen(pref_prompt
)>0)
228 { gtk_imhtml_append_text(GTK_IMHTML(gtkconv
->imhtml
), pref_prompt
, options
);
229 gtk_imhtml_append_text(GTK_IMHTML(gtkconv
->imhtml
), "<B>", options
);
233 gtk_imhtml_append_text(GTK_IMHTML(gtkconv
->imhtml
), foundmessage
, options
);
234 gtk_imhtml_append_text(GTK_IMHTML(gtkconv
->imhtml
), "</B><BR>", options
);
236 /* A more flexible (than Copy/Paste) way to select answer: */
237 gtk_combo_box_append_text(send_combo
, foundmessage
);
240 answers
= answers
->next
;
242 number_of_lines
= gtk_tree_model_iter_n_children(gtk_combo_box_get_model(send_combo
), NULL
);
243 gtk_combo_box_set_active(send_combo
, rand()%number_of_lines
);
247 if (purple_prefs_get_bool(PREF_VERBOSE
)) gtk_imhtml_append_text(GTK_IMHTML(gtkconv
->imhtml
), "<HR>", options
);
250 if (purple_prefs_get_bool(PREF_MODE
))
253 /* If "Funny Mode" is ON - going to autosend an answer */
254 foundmessage
=gtk_combo_box_get_active_text(send_combo
);
256 purple_conv_im_send(PURPLE_CONV_IM(conv
), foundmessage
);
257 gtk_imhtml_clear(GTK_IMHTML(gtkconv
->entry
));
258 g_free(foundmessage
);
263 get_plugin_pref_frame(PurplePlugin
*plugin
) {
265 GtkWidget
*vbox
= NULL
;
266 GtkWidget
*frame
= NULL
;
267 GtkWidget
*auto_option
= NULL
;
268 GtkWidget
*limit_option
= NULL
;
269 GtkWidget
*verbose_option
= NULL
;
270 GtkWidget
*prompt_option
= NULL
;
272 vbox
= gtk_vbox_new(TRUE
, PIDGIN_HIG_BOX_SPACE
);
274 frame
= pidgin_make_frame(vbox
, _("Auto-answer options"));
275 limit_option
= pidgin_prefs_labeled_spin_button (frame
, _("Maximum answers to find"), PREF_LIMIT
, 5, 100, NULL
);
276 auto_option
= pidgin_prefs_checkbox(_("Send automatically"), PREF_MODE
, frame
);
277 verbose_option
= pidgin_prefs_checkbox(_("Use verbose mode"), PREF_VERBOSE
, frame
);
278 prompt_option
= pidgin_prefs_labeled_entry(frame
, _("Preface robot's answer with"), PREF_PROMPT
, NULL
);
280 gtk_widget_show_all(vbox
);
286 static PurplePluginUiInfo ui_info
= {
287 get_plugin_pref_frame
,
288 0, /* page_num (Reserved) */
289 NULL
, /* frame (Reserved) */
300 create_send_combo_pidgin(PidginConversation
*gtkconv
)
302 GtkWidget
*send_combo
, *say_button
;
304 /* purple_debug_misc("auto-answer-history DEBUG", "combo created\n");*/
306 send_combo
= gtk_combo_box_new_text();
307 gtk_combo_box_set_focus_on_click(send_combo
, FALSE
);
309 gtk_box_pack_end(GTK_BOX(gtkconv
->toolbar
), send_combo
, TRUE
, TRUE
, 0);
310 gtk_widget_show(send_combo
);
312 gtk_widget_size_request(send_combo
, &greq
);
313 gtk_widget_set_size_request (send_combo
, greq
.width
, greq
.height
);
315 g_object_set_data(G_OBJECT(gtkconv
->toolbar
), "send_combo", send_combo
);
319 say_button
= gtk_button_new_with_mnemonic(_("Say"));
320 gtk_button_set_focus_on_click(say_button
, FALSE
);
321 gtk_button_set_relief(say_button
, GTK_RELIEF_NONE
);
322 g_signal_connect(G_OBJECT(say_button
), "clicked",
323 G_CALLBACK(send_combo_cb
), gtkconv
);
324 gtk_box_pack_end(GTK_BOX(gtkconv
->toolbar
), say_button
, FALSE
, FALSE
, 0);
325 gtk_widget_show(say_button
);
327 g_object_set_data(G_OBJECT(gtkconv
->toolbar
), "say_button", say_button
);
333 remove_send_combo_pidgin(PidginConversation
*gtkconv
)
335 GtkWidget
*send_combo
= NULL
, *say_button
= NULL
;
337 send_combo
= g_object_get_data(G_OBJECT(gtkconv
->toolbar
), "send_combo");
338 if (send_combo
!= NULL
) {
339 gtk_widget_destroy(send_combo
);
342 say_button
= g_object_get_data(G_OBJECT(gtkconv
->toolbar
), "say_button");
343 if (say_button
!= NULL
) {
344 gtk_widget_destroy(say_button
);
352 plugin_load(PurplePlugin
*plugin
)
354 void *conv_handle
= purple_conversations_get_handle();
356 purple_signal_connect(conv_handle
, "received-im-msg",
357 plugin
, PURPLE_CALLBACK(received_im_msg_cb
), NULL
);
362 plugin_unload(PurplePlugin
*plugin
) {
364 GList
*convs
= purple_get_conversations();
367 PurpleConversation
*conv
= (PurpleConversation
*)convs
->data
;
369 /* Remove Send combo */
370 if (PIDGIN_IS_PIDGIN_CONVERSATION(conv
)) {
371 remove_send_combo_pidgin(PIDGIN_CONVERSATION(conv
));
381 static PurplePluginInfo info
=
384 PURPLE_MAJOR_VERSION
,
385 PURPLE_MINOR_VERSION
,
386 PURPLE_PLUGIN_STANDARD
, /**< type */
387 PIDGIN_PLUGIN_TYPE
, /**< ui_requirement */
389 NULL
, /**< dependencies */
390 PURPLE_PRIORITY_DEFAULT
, /**< priority */
392 "pidgin-autokiss", /**< id */
393 "AutoKiss", /**< name */
394 "0.1", /**< version */
396 "Automatically answering based on regexes.",
398 "Automatically answering based on regexp",
399 "Harvie <harvie@email.cz>", /**< author */
400 "http://sourceforge.net/projects/pidgin-autoansw", /**< homepage */
402 plugin_load
, /**< load */
403 plugin_unload
, /**< unload */
404 NULL
, /**< destroy */
405 &ui_info
, /**< ui_info */
406 NULL
, /**< extra_info */
407 NULL
, /**< prefs_info */
408 NULL
, /* this tells libpurple the address of the function to call
409 to get the list of plugin actions. */
419 init_plugin(PurplePlugin
*plugin
)
421 purple_prefs_add_none(PREF_PREFIX
);
422 purple_prefs_add_bool(PREF_MODE
, FALSE
);
423 purple_prefs_add_bool(PREF_VERBOSE
, FALSE
);
424 purple_prefs_add_string(PREF_PROMPT
, "The possible answer is:");
426 /** TODO: Add more search options and uninformative words dictionary support**/
428 purple_prefs_add_bool(PREF_SEARCH
, FALSE
);
429 purple_prefs_add_bool(PREF_DICT
, FALSE
);
433 PURPLE_INIT_PLUGIN(autoanswer
, init_plugin
, info
)