pidgin/purple-plugin-pack
Clone
Summary
Browse
Changes
Graph
Updating the ChangeLog, step 1 in release process.
2009-08-30, John Bailey
ebe69a8d5441
Updating the ChangeLog, step 1 in release process.
/*
* Autoreply - Autoreply feature for all the protocols
* Copyright (C) 2005-2008 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02111-1301, USA.
*/
/* If you can't figure out what this line is for, DON'T TOUCH IT. */
#include
"../common/pp_internal.h"
#define PLUGIN_ID "core-plugin_pack-autoreply"
#define PLUGIN_STATIC_NAME "Autoreply"
#define PLUGIN_AUTHOR "Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>"
/* Purple headers */
#include
<account.h>
#include
<accountopt.h>
#include
<blist.h>
#include
<conversation.h>
#include
<plugin.h>
#include
<pluginpref.h>
#include
<request.h>
#include
<savedstatuses.h>
#include
<status.h>
#include
<util.h>
#define PREFS_PREFIX "/plugins/core/" PLUGIN_ID
#define PREFS_IDLE PREFS_PREFIX "/idle"
#define PREFS_AWAY PREFS_PREFIX "/away"
#define PREFS_GLOBAL PREFS_PREFIX "/global"
#define PREFS_MINTIME PREFS_PREFIX "/mintime"
#define PREFS_MAXSEND PREFS_PREFIX "/maxsend"
#define PREFS_USESTATUS PREFS_PREFIX "/usestatus"
#define PREFS_PREFIX_MSG PREFS_PREFIX "/prefix"
#define PREFS_X_INVISIBLE PREFS_PREFIX "/invisible"
typedef
struct
_PurpleAutoReply
PurpleAutoReply
;
typedef
struct
_AutoReplyProtocolOptions
AutoReplyProtocolOptions
;
struct
_PurpleAutoReply
{
PurpleBuddy
*
buddy
;
char
*
reply
;
};
struct
_AutoReplyProtocolOptions
{
PurpleAccountOption
*
message
;
PurpleAccountOption
*
off
;
};
typedef
enum
{
STATUS_NEVER
,
STATUS_ALWAYS
,
STATUS_FALLBACK
}
UseStatusMessage
;
static
GHashTable
*
options
=
NULL
;
/**
* Returns the auto-reply message for buddy
*/
static
const
char
*
get_autoreply_message
(
PurpleBuddy
*
buddy
,
PurpleAccount
*
account
)
{
const
char
*
reply
=
NULL
;
UseStatusMessage
use_status
;
use_status
=
purple_prefs_get_int
(
PREFS_USESTATUS
);
if
(
use_status
==
STATUS_ALWAYS
)
{
PurpleStatus
*
status
=
purple_account_get_active_status
(
account
);
PurpleStatusType
*
type
=
purple_status_get_type
(
status
);
if
(
purple_status_type_get_attr
(
type
,
"message"
)
!=
NULL
)
reply
=
purple_status_get_attr_string
(
status
,
"message"
);
else
reply
=
purple_savedstatus_get_message
(
purple_savedstatus_get_current
());
}
if
((
!
reply
||
!*
reply
)
&&
buddy
)
{
/* Is there any special auto-reply for this buddy? */
reply
=
purple_blist_node_get_string
((
PurpleBlistNode
*
)
buddy
,
"autoreply"
);
if
((
!
reply
||
!*
reply
)
&&
PURPLE_BLIST_NODE_IS_BUDDY
((
PurpleBlistNode
*
)
buddy
))
{
/* Anything for the contact, then? */
reply
=
purple_blist_node_get_string
(((
PurpleBlistNode
*
)
buddy
)
->
parent
,
"autoreply"
);
}
}
if
(
!
reply
||
!*
reply
)
{
/* Is there any specific auto-reply for this account? */
reply
=
purple_account_get_string
(
account
,
"autoreply"
,
NULL
);
}
if
(
!
reply
||
!*
reply
)
{
/* Get the global auto-reply message */
reply
=
purple_prefs_get_string
(
PREFS_GLOBAL
);
}
if
(
*
reply
==
' '
||
*
reply
==
'\0'
)
reply
=
NULL
;
if
(
!
reply
&&
use_status
==
STATUS_FALLBACK
)
reply
=
purple_status_get_attr_string
(
purple_account_get_active_status
(
account
),
"message"
);
return
reply
;
}
static
void
written_msg
(
PurpleAccount
*
account
,
const
char
*
who
,
const
char
*
message
,
PurpleConversation
*
conv
,
PurpleMessageFlags
flags
,
gpointer
null
)
{
PurpleBuddy
*
buddy
;
PurplePresence
*
presence
;
const
char
*
reply
=
NULL
;
gboolean
trigger
=
FALSE
;
if
(
!
(
flags
&
PURPLE_MESSAGE_RECV
))
return
;
if
(
!
message
||
!*
message
)
return
;
/* Do not send an autoreply for an autoreply or a 'delayed' (offline?) message */
if
(
flags
&
(
PURPLE_MESSAGE_AUTO_RESP
|
PURPLE_MESSAGE_DELAYED
))
return
;
if
(
purple_account_get_bool
(
account
,
"ar_off"
,
FALSE
))
return
;
g_return_if_fail
(
purple_conversation_get_type
(
conv
)
==
PURPLE_CONV_TYPE_IM
);
presence
=
purple_account_get_presence
(
account
);
if
(
purple_prefs_get_bool
(
PREFS_X_INVISIBLE
)
&&
purple_presence_is_status_primitive_active
(
presence
,
PURPLE_STATUS_INVISIBLE
))
return
;
if
(
purple_prefs_get_bool
(
PREFS_AWAY
)
&&
!
purple_presence_is_available
(
presence
))
trigger
=
TRUE
;
if
(
purple_prefs_get_bool
(
PREFS_IDLE
)
&&
purple_presence_is_idle
(
presence
))
trigger
=
TRUE
;
if
(
!
trigger
)
return
;
buddy
=
purple_find_buddy
(
account
,
who
);
reply
=
get_autoreply_message
(
buddy
,
account
);
if
(
reply
)
{
PurpleConnection
*
gc
;
PurpleMessageFlags
flag
=
PURPLE_MESSAGE_SEND
;
time_t
last_sent
,
now
;
int
count_sent
,
maxsend
;
char
*
send
=
NULL
;
const
char
*
prefix
;
last_sent
=
GPOINTER_TO_INT
(
purple_conversation_get_data
(
conv
,
"autoreply_lastsent"
));
now
=
time
(
NULL
);
/* Have we spent enough time after our last autoreply? */
if
(
now
-
last_sent
>=
(
purple_prefs_get_int
(
PREFS_MINTIME
)
*
60
))
{
count_sent
=
GPOINTER_TO_INT
(
purple_conversation_get_data
(
conv
,
"autoreply_count"
));
maxsend
=
purple_prefs_get_int
(
PREFS_MAXSEND
);
/* Have we sent the autoreply enough times? */
if
(
count_sent
<
maxsend
||
maxsend
==
-1
)
{
purple_conversation_set_data
(
conv
,
"autoreply_count"
,
GINT_TO_POINTER
(
++
count_sent
));
purple_conversation_set_data
(
conv
,
"autoreply_lastsent"
,
GINT_TO_POINTER
(
now
));
gc
=
purple_account_get_connection
(
account
);
prefix
=
purple_prefs_get_string
(
PREFS_PREFIX_MSG
);
if
(
gc
->
flags
&
PURPLE_CONNECTION_AUTO_RESP
)
{
flag
|=
PURPLE_MESSAGE_AUTO_RESP
;
prefix
=
NULL
;
/* The prpl knows about auto-response. So ignore the prefix string. */
}
send
=
g_strdup_printf
(
"%s%s"
,
prefix
?
prefix
:
""
,
reply
);
purple_conv_im_send_with_flags
(
PURPLE_CONV_IM
(
conv
),
send
,
flag
);
g_free
(
send
);
}
}
}
}
static
void
set_auto_reply_cb
(
PurpleBlistNode
*
node
,
char
*
message
)
{
if
(
!
message
||
!*
message
)
message
=
" "
;
purple_blist_node_set_string
(
node
,
"autoreply"
,
message
);
}
static
void
set_auto_reply
(
PurpleBlistNode
*
node
,
gpointer
plugin
)
{
char
*
message
;
PurpleBuddy
*
buddy
;
PurpleAccount
*
account
;
PurpleConnection
*
gc
;
if
(
PURPLE_BLIST_NODE_IS_BUDDY
(
node
))
buddy
=
(
PurpleBuddy
*
)
node
;
else
buddy
=
purple_contact_get_priority_buddy
((
PurpleContact
*
)
node
);
account
=
purple_buddy_get_account
(
buddy
);
gc
=
purple_account_get_connection
(
account
);
/* XXX: There should be a way to reset to the default/account-default autoreply */
message
=
g_strdup_printf
(
_
(
"Set autoreply message for %s"
),
purple_buddy_get_contact_alias
(
buddy
));
purple_request_input
(
plugin
,
_
(
"Set Autoreply Message"
),
message
,
_
(
"The following message will be sent to the buddy when "
"the buddy sends you a message and autoreply is enabled."
),
get_autoreply_message
(
buddy
,
account
),
TRUE
,
FALSE
,
(
gc
->
flags
&
PURPLE_CONNECTION_HTML
)
?
"html"
:
NULL
,
_
(
"_Save"
),
G_CALLBACK
(
set_auto_reply_cb
),
_
(
"_Cancel"
),
NULL
,
account
,
purple_buddy_get_name
(
buddy
),
NULL
,
node
);
g_free
(
message
);
}
static
void
context_menu
(
PurpleBlistNode
*
node
,
GList
**
menu
,
gpointer
plugin
)
{
PurpleMenuAction
*
action
;
if
(
purple_blist_node_get_flags
(
node
)
&
PURPLE_BLIST_NODE_FLAG_NO_SAVE
)
return
;
if
(
!
PURPLE_BLIST_NODE_IS_BUDDY
(
node
)
&&
!
PURPLE_BLIST_NODE_IS_CONTACT
(
node
))
return
;
action
=
purple_menu_action_new
(
_
(
"Set _Autoreply Message"
),
PURPLE_CALLBACK
(
set_auto_reply
),
plugin
,
NULL
);
(
*
menu
)
=
g_list_prepend
(
*
menu
,
action
);
}
static
void
add_options_for_protocol
(
PurplePlugin
*
plg
)
{
AutoReplyProtocolOptions
*
arpo
;
PurplePluginProtocolInfo
*
info
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
plg
);
arpo
=
g_new
(
AutoReplyProtocolOptions
,
1
);
arpo
->
message
=
purple_account_option_string_new
(
_
(
"Autoreply message"
),
"autoreply"
,
NULL
);
arpo
->
off
=
purple_account_option_bool_new
(
_
(
"Turn off autoreply"
),
"ar_off"
,
FALSE
);
info
->
protocol_options
=
g_list_append
(
info
->
protocol_options
,
arpo
->
message
);
info
->
protocol_options
=
g_list_append
(
info
->
protocol_options
,
arpo
->
off
);
if
(
!
g_hash_table_lookup
(
options
,
plg
))
g_hash_table_insert
(
options
,
plg
,
arpo
);
}
static
void
remove_options_for_protocol
(
PurplePlugin
*
plg
)
{
PurplePluginProtocolInfo
*
info
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
plg
);
AutoReplyProtocolOptions
*
arpo
=
g_hash_table_lookup
(
options
,
plg
);
GList
*
l
=
NULL
;
if
(
!
arpo
)
return
;
/*
* 22:55 < sadrul> grim: the check when removing is required, iirc, when
* pidgin quits, and a prpl is unloaded before the plugin
*/
if
((
l
=
g_list_find
(
info
->
protocol_options
,
arpo
->
message
)))
{
info
->
protocol_options
=
g_list_remove_link
(
info
->
protocol_options
,
l
);
purple_account_option_destroy
(
arpo
->
message
);
}
if
((
l
=
g_list_find
(
info
->
protocol_options
,
arpo
->
off
)))
{
info
->
protocol_options
=
g_list_remove_link
(
info
->
protocol_options
,
l
);
purple_account_option_destroy
(
arpo
->
off
);
}
g_hash_table_remove
(
options
,
plg
);
g_free
(
arpo
);
}
static
void
plugin_load_cb
(
PurplePlugin
*
plugin
,
gboolean
load
)
{
if
(
plugin
->
info
&&
plugin
->
info
->
type
==
PURPLE_PLUGIN_PROTOCOL
)
{
if
(
load
)
add_options_for_protocol
(
plugin
);
else
remove_options_for_protocol
(
plugin
);
}
}
static
gboolean
plugin_load
(
PurplePlugin
*
plugin
)
{
GList
*
list
;
purple_signal_connect
(
purple_conversations_get_handle
(),
"wrote-im-msg"
,
plugin
,
PURPLE_CALLBACK
(
written_msg
),
NULL
);
purple_signal_connect
(
purple_blist_get_handle
(),
"blist-node-extended-menu"
,
plugin
,
PURPLE_CALLBACK
(
context_menu
),
plugin
);
purple_signal_connect
(
purple_plugins_get_handle
(),
"plugin-load"
,
plugin
,
PURPLE_CALLBACK
(
plugin_load_cb
),
GINT_TO_POINTER
(
TRUE
));
purple_signal_connect
(
purple_plugins_get_handle
(),
"plugin-unload"
,
plugin
,
PURPLE_CALLBACK
(
plugin_load_cb
),
GINT_TO_POINTER
(
FALSE
));
/* Perhaps it's necessary to do this after making sure the prpl-s have been loaded? */
options
=
g_hash_table_new
(
g_direct_hash
,
g_direct_equal
);
list
=
purple_plugins_get_protocols
();
while
(
list
)
{
add_options_for_protocol
(
list
->
data
);
list
=
list
->
next
;
}
return
TRUE
;
}
static
gboolean
plugin_unload
(
PurplePlugin
*
plugin
)
{
GList
*
list
;
if
(
options
==
NULL
)
return
TRUE
;
list
=
purple_plugins_get_protocols
();
while
(
list
)
{
remove_options_for_protocol
(
list
->
data
);
list
=
list
->
next
;
}
g_hash_table_destroy
(
options
);
options
=
NULL
;
return
TRUE
;
}
static
PurplePluginPrefFrame
*
get_plugin_pref_frame
(
PurplePlugin
*
plugin
)
{
PurplePluginPrefFrame
*
frame
;
PurplePluginPref
*
pref
;
frame
=
purple_plugin_pref_frame_new
();
pref
=
purple_plugin_pref_new_with_label
(
_
(
"Send autoreply messages when"
));
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_name_and_label
(
PREFS_AWAY
,
_
(
"When my account is _away"
));
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_name_and_label
(
PREFS_IDLE
,
_
(
"When my account is _idle"
));
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_name_and_label
(
PREFS_GLOBAL
,
_
(
"_Default reply"
));
purple_plugin_pref_set_type
(
pref
,
PURPLE_PLUGIN_PREF_STRING_FORMAT
);
purple_plugin_pref_set_format_type
(
pref
,
PURPLE_STRING_FORMAT_TYPE_MULTILINE
|
PURPLE_STRING_FORMAT_TYPE_HTML
);
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_name_and_label
(
PREFS_PREFIX_MSG
,
_
(
"Autoreply Prefix
\n
(only when necessary)"
));
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_name_and_label
(
PREFS_X_INVISIBLE
,
_
(
"Do not autoreply when invisible."
));
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_label
(
_
(
"Status message"
));
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_name_and_label
(
PREFS_USESTATUS
,
_
(
"Autoreply with status message"
));
purple_plugin_pref_set_type
(
pref
,
PURPLE_PLUGIN_PREF_CHOICE
);
purple_plugin_pref_add_choice
(
pref
,
_
(
"Never"
),
GINT_TO_POINTER
(
STATUS_NEVER
));
purple_plugin_pref_add_choice
(
pref
,
_
(
"Always when there is a status message"
),
GINT_TO_POINTER
(
STATUS_ALWAYS
));
purple_plugin_pref_add_choice
(
pref
,
_
(
"Only when there's no autoreply message"
),
GINT_TO_POINTER
(
STATUS_FALLBACK
));
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_label
(
_
(
"Delay between autoreplies"
));
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_name_and_label
(
PREFS_MINTIME
,
_
(
"_Minimum delay (mins)"
));
purple_plugin_pref_set_bounds
(
pref
,
0
,
9999
);
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_label
(
_
(
"Times to send autoreplies"
));
purple_plugin_pref_frame_add
(
frame
,
pref
);
pref
=
purple_plugin_pref_new_with_name_and_label
(
PREFS_MAXSEND
,
_
(
"Ma_ximum count"
));
purple_plugin_pref_set_bounds
(
pref
,
0
,
9999
);
purple_plugin_pref_frame_add
(
frame
,
pref
);
return
frame
;
}
static
PurplePluginUiInfo
prefs_info
=
{
get_plugin_pref_frame
,
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
};
static
PurplePluginInfo
info
=
{
PURPLE_PLUGIN_MAGIC
,
/* Magic */
PURPLE_MAJOR_VERSION
,
/* Purple Major Version */
PURPLE_MINOR_VERSION
,
/* Purple Minor Version */
PURPLE_PLUGIN_STANDARD
,
/* plugin type */
NULL
,
/* ui requirement */
0
,
/* flags */
NULL
,
/* dependencies */
PURPLE_PRIORITY_DEFAULT
,
/* priority */
PLUGIN_ID
,
/* plugin id */
NULL
,
/* name */
PP_VERSION
,
/* version */
NULL
,
/* summary */
NULL
,
/* description */
PLUGIN_AUTHOR
,
/* author */
PP_WEBSITE
,
/* website */
plugin_load
,
/* load */
plugin_unload
,
/* unload */
NULL
,
/* destroy */
NULL
,
/* ui_info */
NULL
,
/* extra_info */
&
prefs_info
,
/* prefs_info */
NULL
,
/* actions */
NULL
,
/* reserved 1 */
NULL
,
/* reserved 2 */
NULL
,
/* reserved 3 */
NULL
/* reserved 4 */
};
static
void
init_plugin
(
PurplePlugin
*
plugin
)
{
#ifdef ENABLE_NLS
bindtextdomain
(
GETTEXT_PACKAGE
,
PP_LOCALEDIR
);
bind_textdomain_codeset
(
GETTEXT_PACKAGE
,
"UTF-8"
);
#endif
/* ENABLE_NLS */
info
.
name
=
_
(
"Autoreply"
);
info
.
summary
=
_
(
"Autoreply for all the protocols"
);
info
.
description
=
_
(
"This plugin lets you set autoreply message for any "
"protocol. You can set the global autoreply message from the "
"plugin options dialog. To set some specific autoreply message for "
"a particular buddy, right click on the buddy in the buddy-list "
"window. To set autoreply messages for some accounts, go to the "
"`Advanced' tab of the account edit dialog."
);
purple_prefs_add_none
(
PREFS_PREFIX
);
purple_prefs_add_bool
(
PREFS_IDLE
,
TRUE
);
purple_prefs_add_bool
(
PREFS_AWAY
,
TRUE
);
purple_prefs_add_string
(
PREFS_GLOBAL
,
_
(
"I am currently not available. Please leave your message, "
"and I will get back to you as soon as possible."
));
purple_prefs_add_int
(
PREFS_MINTIME
,
10
);
purple_prefs_add_int
(
PREFS_MAXSEND
,
10
);
purple_prefs_add_int
(
PREFS_USESTATUS
,
STATUS_NEVER
);
purple_prefs_add_string
(
PREFS_PREFIX_MSG
,
_
(
"This is an autoreply: "
));
purple_prefs_add_bool
(
PREFS_X_INVISIBLE
,
TRUE
);
}
PURPLE_INIT_PLUGIN
(
PLUGIN_STATIC_NAME
,
init_plugin
,
info
)