pidgin/purple-plugin-pack
Clone
Summary
Browse
Changes
Graph
This took WAY too long to see. The logs shouldn't be sorted while we're
org.guifications.plugins
2008-08-03, rekkanoryo
f8496a6121df
This took WAY too long to see. The logs shouldn't be sorted while we're
still in the outer loop. Sort at the end once we've collected all the logs
we can.
/*--------------------------------------------------------------------------*
* AUTOPROFILE *
* *
* A Purple away message and profile manager that supports dynamic text *
* *
* AutoProfile is the legal property of its developers. Please refer to *
* the COPYRIGHT file distributed with this source distribution. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
*--------------------------------------------------------------------------*/
#include
"autoprofile.h"
#include
"conversation.h"
#define SECS_BEFORE_RESENDING_AUTORESPONSE 600
#define SEX_BEFORE_RESENDING_AUTORESPONSE "Only after you're married"
#define MILLISECS_BEFORE_PROCESSING_MSG 100
static
guint
pref_cb
;
static
GSList
*
last_auto_responses
=
NULL
;
struct
last_auto_response
{
PurpleConnection
*
gc
;
char
name
[
80
];
time_t
sent
;
};
static
time_t
response_timeout
=
0
;
/*--------------------------------------------------------------------------*
* Auto-response utility functions *
*--------------------------------------------------------------------------*/
static
gboolean
expire_last_auto_responses
(
gpointer
data
)
{
GSList
*
tmp
,
*
cur
;
struct
last_auto_response
*
lar
;
tmp
=
last_auto_responses
;
while
(
tmp
)
{
cur
=
tmp
;
tmp
=
tmp
->
next
;
lar
=
(
struct
last_auto_response
*
)
cur
->
data
;
if
((
time
(
NULL
)
-
lar
->
sent
)
>
SECS_BEFORE_RESENDING_AUTORESPONSE
)
{
last_auto_responses
=
g_slist_remove
(
last_auto_responses
,
lar
);
g_free
(
lar
);
}
}
return
FALSE
;
/* do not run again */
}
static
struct
last_auto_response
*
get_last_auto_response
(
PurpleConnection
*
gc
,
const
char
*
name
)
{
GSList
*
tmp
;
struct
last_auto_response
*
lar
;
/* because we're modifying or creating a lar, schedule the
* function to expire them as the pref dictates */
purple_timeout_add
((
SECS_BEFORE_RESENDING_AUTORESPONSE
+
5
)
*
1000
,
expire_last_auto_responses
,
NULL
);
tmp
=
last_auto_responses
;
while
(
tmp
)
{
lar
=
(
struct
last_auto_response
*
)
tmp
->
data
;
if
(
gc
==
lar
->
gc
&&
!
strncmp
(
name
,
lar
->
name
,
sizeof
(
lar
->
name
)))
return
lar
;
tmp
=
tmp
->
next
;
}
lar
=
(
struct
last_auto_response
*
)
g_new0
(
struct
last_auto_response
,
1
);
g_snprintf
(
lar
->
name
,
sizeof
(
lar
->
name
),
"%s"
,
name
);
lar
->
gc
=
gc
;
lar
->
sent
=
0
;
last_auto_responses
=
g_slist_append
(
last_auto_responses
,
lar
);
return
lar
;
}
/*--------------------------------------------------------------------------*
* Message send/receive general functionality *
*--------------------------------------------------------------------------*/
/* Detecting sent message stuff */
static
void
sent_im_msg_cb
(
PurpleAccount
*
account
,
const
char
*
receiver
,
const
char
*
message
)
{
PurpleConnection
*
gc
;
PurplePresence
*
presence
;
const
gchar
*
auto_reply_pref
;
gc
=
purple_account_get_connection
(
account
);
presence
=
purple_account_get_presence
(
account
);
/*
* FIXME - If "only auto-reply when away & idle" is set, then shouldn't
* this only reset lar->sent if we're away AND idle?
*/
auto_reply_pref
=
purple_prefs_get_string
(
"/plugins/gtk/autoprofile/autorespond/auto_reply"
);
if
((
gc
->
flags
&
PURPLE_CONNECTION_AUTO_RESP
)
&&
!
purple_presence_is_available
(
presence
)
&&
strcmp
(
auto_reply_pref
,
"never"
))
{
struct
last_auto_response
*
lar
;
lar
=
get_last_auto_response
(
gc
,
receiver
);
lar
->
sent
=
time
(
NULL
);
}
}
/* Detecting received message stuff */
struct
received_im_msg
{
PurpleAccount
*
account
;
char
*
sender
;
char
*
message
;
};
static
gint
process_received_im_msg
(
gpointer
data
)
{
struct
received_im_msg
*
received_im
;
PurpleAccount
*
account
;
char
*
sender
;
char
*
message
;
PurpleConnection
*
gc
;
PurpleConversation
*
conv
;
received_im
=
(
struct
received_im_msg
*
)
data
;
account
=
received_im
->
account
;
sender
=
received_im
->
sender
;
message
=
received_im
->
message
;
free
(
data
);
gc
=
purple_account_get_connection
(
account
);
/* search for conversation again in case it was created by other handlers */
conv
=
purple_find_conversation_with_account
(
PURPLE_CONV_TYPE_IM
,
sender
,
gc
->
account
);
if
(
conv
==
NULL
)
conv
=
purple_conversation_new
(
PURPLE_CONV_TYPE_IM
,
account
,
sender
);
/*
* Don't autorespond if:
*
* - it's not supported on this connection
* - we are available
* - or it's disabled
* - or we're not idle and the 'only auto respond if idle' pref
* is set
*/
if
(
gc
->
flags
&
PURPLE_CONNECTION_AUTO_RESP
)
{
PurplePresence
*
presence
;
PurpleStatus
*
status
;
PurpleStatusType
*
status_type
;
PurpleStatusPrimitive
primitive
;
const
gchar
*
auto_reply_pref
;
char
*
away_msg
=
NULL
;
auto_reply_pref
=
purple_prefs_get_string
(
"/plugins/gtk/autoprofile/autorespond/auto_reply"
);
presence
=
purple_account_get_presence
(
account
);
status
=
purple_presence_get_active_status
(
presence
);
status_type
=
purple_status_get_type
(
status
);
primitive
=
purple_status_type_get_primitive
(
status_type
);
if
((
primitive
==
PURPLE_STATUS_AVAILABLE
)
||
(
primitive
==
PURPLE_STATUS_INVISIBLE
)
||
(
primitive
==
PURPLE_STATUS_MOBILE
)
||
!
strcmp
(
auto_reply_pref
,
"never"
)
||
(
!
purple_presence_is_idle
(
presence
)
&&
!
strcmp
(
auto_reply_pref
,
"awayidle"
)))
{
free
(
sender
);
free
(
message
);
return
FALSE
;
}
away_msg
=
ap_get_sample_status_message
(
account
);
if
((
away_msg
!=
NULL
)
&&
(
*
away_msg
!=
'\0'
))
{
struct
last_auto_response
*
lar
;
gboolean
autorespond_enable
;
time_t
now
=
time
(
NULL
);
autorespond_enable
=
purple_prefs_get_bool
(
"/plugins/gtk/autoprofile/autorespond/enable"
);
/*
* This used to be based on the conversation window. But um, if
* you went away, and someone sent you a message and got your
* auto-response, and then you closed the window, and then they
* sent you another one, they'd get the auto-response back too
* soon. Besides that, we need to keep track of this even if we've
* got a queue. So the rest of this block is just the auto-response,
* if necessary.
*/
lar
=
get_last_auto_response
(
gc
,
sender
);
if
((
now
-
lar
->
sent
)
>=
SECS_BEFORE_RESENDING_AUTORESPONSE
)
{
lar
->
sent
=
now
;
// Send basic autoresponse
serv_send_im
(
gc
,
sender
,
away_msg
,
PURPLE_MESSAGE_AUTO_RESP
);
purple_conv_im_write
(
PURPLE_CONV_IM
(
conv
),
NULL
,
away_msg
,
PURPLE_MESSAGE_SEND
|
PURPLE_MESSAGE_AUTO_RESP
,
now
);
// Send additional hint if enabled
if
(
autorespond_enable
)
{
const
gchar
*
query
=
purple_prefs_get_string
(
"/plugins/gtk/autoprofile/autorespond/text"
);
serv_send_im
(
gc
,
sender
,
query
,
PURPLE_MESSAGE_AUTO_RESP
);
purple_conv_im_write
(
PURPLE_CONV_IM
(
conv
),
NULL
,
query
,
PURPLE_MESSAGE_SEND
|
PURPLE_MESSAGE_AUTO_RESP
,
now
);
}
}
else
if
(
autorespond_enable
&&
difftime
(
time
(
NULL
),
response_timeout
)
>
purple_prefs_get_int
(
"/plugins/gtk/autoprofile/autorespond/delay"
))
{
gchar
*
text
=
purple_markup_strip_html
(
message
);
if
(
match_start
(
text
,
purple_prefs_get_string
(
"/plugins/gtk/autoprofile/autorespond/trigger"
))
==
1
)
{
serv_send_im
(
gc
,
sender
,
away_msg
,
PURPLE_MESSAGE_AUTO_RESP
);
purple_conv_im_write
(
PURPLE_CONV_IM
(
conv
),
NULL
,
away_msg
,
PURPLE_MESSAGE_SEND
|
PURPLE_MESSAGE_AUTO_RESP
,
now
);
response_timeout
=
time
(
NULL
);
ap_debug
(
"autorespond"
,
"string matched, responding"
);
}
free
(
text
);
}
}
free
(
away_msg
);
}
free
(
sender
);
free
(
message
);
return
FALSE
;
}
static
void
received_im_msg_cb
(
PurpleAccount
*
account
,
char
*
sender
,
char
*
message
,
PurpleConversation
*
conv
,
PurpleMessageFlags
flags
)
{
struct
received_im_msg
*
received_im
;
received_im
=
(
struct
received_im_msg
*
)
malloc
(
sizeof
(
struct
received_im_msg
));
received_im
->
account
=
account
;
received_im
->
sender
=
strdup
(
sender
);
received_im
->
message
=
strdup
(
message
);
purple_timeout_add
(
MILLISECS_BEFORE_PROCESSING_MSG
,
process_received_im_msg
,
received_im
);
}
static
void
auto_pref_cb
(
const
char
*
name
,
PurplePrefType
type
,
gconstpointer
val
,
gpointer
data
)
{
if
(
!
strcmp
(
purple_prefs_get_string
(
"/core/away/auto_reply"
),
"never"
))
return
;
purple_notify_error
(
NULL
,
NULL
,
N_
(
"This preference is disabled"
),
N_
(
"This preference currently has no effect because AutoProfile is in "
"use. To modify this behavior, use the AutoProfile configuration "
"menu."
));
purple_prefs_set_string
(
"/core/away/auto_reply"
,
"never"
);
}
/*--------------------------------------------------------------------------*
* Global functions *
*--------------------------------------------------------------------------*/
void
ap_autoreply_start
()
{
purple_prefs_set_string
(
"/core/away/auto_reply"
,
"never"
);
purple_signal_connect
(
purple_conversations_get_handle
(),
"sent-im-msg"
,
ap_get_plugin_handle
(),
PURPLE_CALLBACK
(
sent_im_msg_cb
),
NULL
);
purple_signal_connect
(
purple_conversations_get_handle
(),
"received-im-msg"
,
ap_get_plugin_handle
(),
PURPLE_CALLBACK
(
received_im_msg_cb
),
NULL
);
pref_cb
=
purple_prefs_connect_callback
(
ap_get_plugin_handle
(),
"/core/away/auto_reply"
,
auto_pref_cb
,
NULL
);
}
void
ap_autoreply_finish
()
{
GSList
*
tmp
;
// Assumes signals are disconnected globally
purple_prefs_disconnect_callback
(
pref_cb
);
pref_cb
=
0
;
purple_prefs_set_string
(
"/core/away/auto_reply"
,
purple_prefs_get_string
(
"/plugins/gtk/autoprofile/autorespond/auto_reply"
));
while
(
last_auto_responses
)
{
tmp
=
last_auto_responses
->
next
;
g_free
(
last_auto_responses
->
data
);
g_slist_free_1
(
last_auto_responses
);
last_auto_responses
=
tmp
;
}
}