pidgin/purple-plugin-pack
Clone
Summary
Browse
Changes
Graph
Add the turtles target to keep the foot clan at bay
default
tip
13 months ago, Gary Kramlich
63ad7e4f10b4
Add the turtles target to keep the foot clan at bay
Testing Done:
Ran `ninja turtles` and verified it worked correctly.
Reviewed at https://reviews.imfreedom.org/r/2409/
/*
* 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
)