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/
/*
* libpurple-translate - Autotranslate messages
* Copyright (C) 2010 Eion Robb
*
* 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 02110-1301, USA.
*
*/
#include
"../common/pp_internal.h"
#include
<stdio.h>
#include
<string.h>
#include
<util.h>
#include
<plugin.h>
#include
<debug.h>
#define DEST_LANG_SETTING "eionrobb-translate-lang"
#define LOCALE_PREF "/plugins/core/eionrobb-libpurple-translate/locale"
#define SERVICE_PREF "/plugins/core/eionrobb-libpurple-translate/service"
#define GOOGLE_TRANSLATE_URL "http:
//ajax.googleapis.com/ajax/services/language/translate?v=1.0&langpair=%s%%7C%s&q=%s"
#define BING_APPID "0FFF5300CD157A2E748DFCCF6D67F8028E5B578D"
#define BING_DETECT_URL "http:
//api.microsofttranslator.com/V2/Ajax.svc/Detect?appId=" BING_APPID "&text=%%22%s%%22"
#define BING_TRANSLATE_URL "http:
//api.microsofttranslator.com/V2/Ajax.svc/Translate?appId=" BING_APPID "&text=%%22%s%%22&from=%s&to=%s"
/** This is the list of languages we support, populated in plugin_init */
static
GList
*
supported_languages
=
NULL
;
typedef
void
(
*
TranslateCallback
)(
const
gchar
*
original_phrase
,
const
gchar
*
translated_phrase
,
const
gchar
*
detected_language
,
gpointer
userdata
);
struct
_TranslateStore
{
gchar
*
original_phrase
;
TranslateCallback
callback
;
gpointer
userdata
;
gchar
*
detected_language
;
//optional - needed for Bing
};
/** Converts unicode strings such as \003d into =
* Code blatantly nicked from the Facebook plugin */
gchar
*
convert_unicode
(
const
gchar
*
input
)
{
gunichar
unicode_char
;
gchar
unicode_char_str
[
6
];
gint
unicode_char_len
;
gchar
*
next_pos
;
gchar
*
input_string
;
gchar
*
output_string
;
if
(
input
==
NULL
)
return
NULL
;
next_pos
=
input_string
=
g_strdup
(
input
);
while
((
next_pos
=
strstr
(
next_pos
,
"
\\
u"
)))
{
/* grab the unicode */
sscanf
(
next_pos
,
"
\\
u%4x"
,
&
unicode_char
);
/* turn it to a char* */
unicode_char_len
=
g_unichar_to_utf8
(
unicode_char
,
unicode_char_str
);
/* shove it back into the string */
g_memmove
(
next_pos
,
unicode_char_str
,
unicode_char_len
);
/* move all the data after the \u0000 along */
g_stpcpy
(
next_pos
+
unicode_char_len
,
next_pos
+
6
);
}
output_string
=
g_strcompress
(
input_string
);
g_free
(
input_string
);
return
output_string
;
}
const
gchar
*
get_language_name
(
const
gchar
*
language_key
)
{
GList
*
l
;
const
gchar
*
language_name
=
NULL
;
PurpleKeyValuePair
*
pair
=
NULL
;
for
(
l
=
supported_languages
;
l
;
l
=
l
->
next
)
{
pair
=
(
PurpleKeyValuePair
*
)
l
->
data
;
if
(
g_str_equal
(
pair
->
key
,
language_key
))
{
language_name
=
pair
->
value
;
break
;
}
}
return
language_name
;
}
void
google_translate_cb
(
PurpleUtilFetchUrlData
*
url_data
,
gpointer
user_data
,
const
gchar
*
url_text
,
gsize
len
,
const
gchar
*
error_message
)
{
struct
_TranslateStore
*
store
=
user_data
;
const
gchar
*
trans_start
=
"
\"
translatedText
\"
:
\"
"
;
const
gchar
*
lang_start
=
"
\"
detectedSourceLanguage
\"
:
\"
"
;
gchar
*
strstart
=
NULL
;
gchar
*
translated
=
NULL
;
gchar
*
lang
=
NULL
;
purple_debug_info
(
"translate"
,
"Got response: %s
\n
"
,
url_text
);
strstart
=
g_strstr_len
(
url_text
,
len
,
trans_start
);
if
(
strstart
)
{
strstart
=
strstart
+
strlen
(
trans_start
);
translated
=
g_strndup
(
strstart
,
strchr
(
strstart
,
'"'
)
-
strstart
);
strstart
=
convert_unicode
(
translated
);
g_free
(
translated
);
translated
=
strstart
;
}
strstart
=
g_strstr_len
(
url_text
,
len
,
lang_start
);
if
(
strstart
)
{
strstart
=
strstart
+
strlen
(
lang_start
);
lang
=
g_strndup
(
strstart
,
strchr
(
strstart
,
'"'
)
-
strstart
);
}
store
->
callback
(
store
->
original_phrase
,
translated
,
lang
,
store
->
userdata
);
g_free
(
translated
);
g_free
(
lang
);
g_free
(
store
->
original_phrase
);
g_free
(
store
);
}
void
google_translate
(
const
gchar
*
plain_phrase
,
const
gchar
*
from_lang
,
const
gchar
*
to_lang
,
TranslateCallback
callback
,
gpointer
userdata
)
{
gchar
*
encoded_phrase
;
gchar
*
url
;
struct
_TranslateStore
*
store
;
encoded_phrase
=
g_strdup
(
purple_url_encode
(
plain_phrase
));
if
(
!
from_lang
||
g_str_equal
(
from_lang
,
"auto"
))
from_lang
=
""
;
url
=
g_strdup_printf
(
GOOGLE_TRANSLATE_URL
,
from_lang
,
to_lang
,
encoded_phrase
);
store
=
g_new0
(
struct
_TranslateStore
,
1
);
store
->
original_phrase
=
g_strdup
(
plain_phrase
);
store
->
callback
=
callback
;
store
->
userdata
=
userdata
;
purple_debug_info
(
"translate"
,
"Fetching %s
\n
"
,
url
);
purple_util_fetch_url_request
(
url
,
TRUE
,
"libpurple"
,
FALSE
,
NULL
,
FALSE
,
google_translate_cb
,
store
);
g_free
(
encoded_phrase
);
g_free
(
url
);
}
void
bing_translate_cb
(
PurpleUtilFetchUrlData
*
url_data
,
gpointer
user_data
,
const
gchar
*
url_text
,
gsize
len
,
const
gchar
*
error_message
)
{
struct
_TranslateStore
*
store
=
user_data
;
gchar
*
translated
=
NULL
;
gchar
*
temp
;
purple_debug_info
(
"translate"
,
"Got response: %s
\n
"
,
url_text
);
temp
=
strchr
(
url_text
,
'"'
)
+
1
;
temp
=
g_strndup
(
temp
,
len
-
(
temp
-
url_text
)
-
1
);
translated
=
convert_unicode
(
temp
);
g_free
(
temp
);
store
->
callback
(
store
->
original_phrase
,
translated
,
store
->
detected_language
,
store
->
userdata
);
g_free
(
translated
);
g_free
(
store
->
detected_language
);
g_free
(
store
->
original_phrase
);
g_free
(
store
);
}
void
bing_translate_autodetect_cb
(
PurpleUtilFetchUrlData
*
url_data
,
gpointer
user_data
,
const
gchar
*
url_text
,
gsize
len
,
const
gchar
*
error_message
)
{
struct
_TranslateStore
*
store
=
user_data
;
gchar
*
from_lang
=
NULL
;
gchar
*
to_lang
;
gchar
*
encoded_phrase
;
gchar
*
url
;
purple_debug_info
(
"translate"
,
"Got response: %s
\n
"
,
url_text
);
if
(
!
url_text
||
!
len
||
g_strstr_len
(
url_text
,
len
,
"
\"\"
"
))
{
// Unknown language
store
->
callback
(
store
->
original_phrase
,
store
->
original_phrase
,
NULL
,
store
->
userdata
);
g_free
(
store
->
detected_language
);
g_free
(
store
->
original_phrase
);
g_free
(
store
);
}
else
{
from_lang
=
strchr
(
url_text
,
'"'
)
+
1
;
from_lang
=
g_strndup
(
from_lang
,
len
-
(
from_lang
-
url_text
)
-
1
);
to_lang
=
store
->
detected_language
;
store
->
detected_language
=
from_lang
;
// Same as bing_translate() but we've already made the _TranslateStore
encoded_phrase
=
g_strescape
(
purple_url_encode
(
store
->
original_phrase
),
NULL
);
url
=
g_strdup_printf
(
BING_TRANSLATE_URL
,
encoded_phrase
,
from_lang
,
to_lang
);
purple_debug_info
(
"translate"
,
"Fetching %s
\n
"
,
url
);
purple_util_fetch_url_request
(
url
,
TRUE
,
"libpurple"
,
FALSE
,
NULL
,
FALSE
,
bing_translate_cb
,
store
);
g_free
(
to_lang
);
g_free
(
encoded_phrase
);
g_free
(
url
);
}
}
void
bing_translate
(
const
gchar
*
plain_phrase
,
const
gchar
*
from_lang
,
const
gchar
*
to_lang
,
TranslateCallback
callback
,
gpointer
userdata
)
{
gchar
*
encoded_phrase
;
gchar
*
url
;
struct
_TranslateStore
*
store
;
PurpleUtilFetchUrlCallback
urlcallback
;
encoded_phrase
=
g_strescape
(
purple_url_encode
(
plain_phrase
),
NULL
);
store
=
g_new0
(
struct
_TranslateStore
,
1
);
store
->
original_phrase
=
g_strdup
(
plain_phrase
);
store
->
callback
=
callback
;
store
->
userdata
=
userdata
;
if
(
!
from_lang
||
!
(
*
from_lang
)
||
g_str_equal
(
from_lang
,
"auto"
))
{
url
=
g_strdup_printf
(
BING_DETECT_URL
,
encoded_phrase
);
store
->
detected_language
=
g_strdup
(
to_lang
);
urlcallback
=
bing_translate_autodetect_cb
;
}
else
{
url
=
g_strdup_printf
(
BING_TRANSLATE_URL
,
encoded_phrase
,
from_lang
,
to_lang
);
urlcallback
=
bing_translate_cb
;
}
purple_debug_info
(
"translate"
,
"Fetching %s
\n
"
,
url
);
purple_util_fetch_url_request
(
url
,
TRUE
,
"libpurple"
,
FALSE
,
NULL
,
FALSE
,
urlcallback
,
store
);
g_free
(
encoded_phrase
);
g_free
(
url
);
}
struct
TranslateConvMessage
{
PurpleAccount
*
account
;
gchar
*
sender
;
PurpleConversation
*
conv
;
PurpleMessageFlags
flags
;
};
void
translate_receiving_message_cb
(
const
gchar
*
original_phrase
,
const
gchar
*
translated_phrase
,
const
gchar
*
detected_language
,
gpointer
userdata
)
{
struct
TranslateConvMessage
*
convmsg
=
userdata
;
PurpleBuddy
*
buddy
;
gchar
*
html_text
;
const
gchar
*
language_name
=
NULL
;
gchar
*
message
;
if
(
detected_language
)
{
buddy
=
purple_find_buddy
(
convmsg
->
account
,
convmsg
->
sender
);
purple_blist_node_set_string
((
PurpleBlistNode
*
)
buddy
,
DEST_LANG_SETTING
,
detected_language
);
language_name
=
get_language_name
(
detected_language
);
if
(
language_name
!=
NULL
)
{
message
=
g_strdup_printf
(
"Now translating to %s (auto-detected)"
,
language_name
);
purple_conversation_write
(
convmsg
->
conv
,
NULL
,
message
,
PURPLE_MESSAGE_SYSTEM
|
PURPLE_MESSAGE_NO_LOG
,
time
(
NULL
));
g_free
(
message
);
}
}
html_text
=
purple_strdup_withhtml
(
translated_phrase
);
purple_conversation_write
(
convmsg
->
conv
,
convmsg
->
sender
,
html_text
,
convmsg
->
flags
,
time
(
NULL
));
g_free
(
html_text
);
g_free
(
convmsg
->
sender
);
g_free
(
convmsg
);
}
gboolean
translate_receiving_im_msg
(
PurpleAccount
*
account
,
char
**
sender
,
char
**
message
,
PurpleConversation
*
conv
,
PurpleMessageFlags
*
flags
)
{
struct
TranslateConvMessage
*
convmsg
;
const
gchar
*
stored_lang
=
"auto"
;
gchar
*
stripped
;
const
gchar
*
to_lang
;
PurpleBuddy
*
buddy
;
const
gchar
*
service_to_use
=
""
;
buddy
=
purple_find_buddy
(
account
,
*
sender
);
service_to_use
=
purple_prefs_get_string
(
SERVICE_PREF
);
to_lang
=
purple_prefs_get_string
(
LOCALE_PREF
);
if
(
buddy
)
stored_lang
=
purple_blist_node_get_string
((
PurpleBlistNode
*
)
buddy
,
DEST_LANG_SETTING
);
if
(
!
stored_lang
)
stored_lang
=
"auto"
;
if
(
!
buddy
||
!
service_to_use
||
g_str_equal
(
stored_lang
,
"none"
)
||
g_str_equal
(
stored_lang
,
to_lang
))
{
//Allow the message to go through as per normal
return
FALSE
;
}
if
(
conv
==
NULL
)
conv
=
purple_conversation_new
(
PURPLE_CONV_TYPE_IM
,
account
,
*
sender
);
stripped
=
purple_markup_strip_html
(
*
message
);
convmsg
=
g_new0
(
struct
TranslateConvMessage
,
1
);
convmsg
->
account
=
account
;
convmsg
->
sender
=
*
sender
;
convmsg
->
conv
=
conv
;
convmsg
->
flags
=
*
flags
;
if
(
g_str_equal
(
service_to_use
,
"google"
))
{
google_translate
(
stripped
,
stored_lang
,
to_lang
,
translate_receiving_message_cb
,
convmsg
);
}
else
if
(
g_str_equal
(
service_to_use
,
"bing"
))
{
bing_translate
(
stripped
,
stored_lang
,
to_lang
,
translate_receiving_message_cb
,
convmsg
);
}
g_free
(
stripped
);
g_free
(
*
message
);
*
message
=
NULL
;
*
sender
=
NULL
;
//Cancel the message
return
TRUE
;
}
void
translate_receiving_chat_msg_cb
(
const
gchar
*
original_phrase
,
const
gchar
*
translated_phrase
,
const
gchar
*
detected_language
,
gpointer
userdata
)
{
struct
TranslateConvMessage
*
convmsg
=
userdata
;
PurpleChat
*
chat
;
gchar
*
html_text
;
const
gchar
*
language_name
=
NULL
;
gchar
*
message
;
if
(
detected_language
)
{
chat
=
purple_blist_find_chat
(
convmsg
->
account
,
convmsg
->
conv
->
name
);
purple_blist_node_set_string
((
PurpleBlistNode
*
)
chat
,
DEST_LANG_SETTING
,
detected_language
);
language_name
=
get_language_name
(
detected_language
);
if
(
language_name
!=
NULL
)
{
message
=
g_strdup_printf
(
"Now translating to %s (auto-detected)"
,
language_name
);
purple_conversation_write
(
convmsg
->
conv
,
NULL
,
message
,
PURPLE_MESSAGE_SYSTEM
|
PURPLE_MESSAGE_NO_LOG
,
time
(
NULL
));
g_free
(
message
);
}
}
html_text
=
purple_strdup_withhtml
(
translated_phrase
);
purple_conversation_write
(
convmsg
->
conv
,
convmsg
->
sender
,
html_text
,
convmsg
->
flags
,
time
(
NULL
));
g_free
(
html_text
);
g_free
(
convmsg
->
sender
);
g_free
(
convmsg
);
}
gboolean
translate_receiving_chat_msg
(
PurpleAccount
*
account
,
char
**
sender
,
char
**
message
,
PurpleConversation
*
conv
,
PurpleMessageFlags
*
flags
)
{
struct
TranslateConvMessage
*
convmsg
;
const
gchar
*
stored_lang
=
"auto"
;
gchar
*
stripped
;
const
gchar
*
to_lang
;
PurpleChat
*
chat
;
const
gchar
*
service_to_use
=
""
;
chat
=
purple_blist_find_chat
(
account
,
conv
->
name
);
service_to_use
=
purple_prefs_get_string
(
SERVICE_PREF
);
to_lang
=
purple_prefs_get_string
(
LOCALE_PREF
);
if
(
chat
)
stored_lang
=
purple_blist_node_get_string
((
PurpleBlistNode
*
)
chat
,
DEST_LANG_SETTING
);
if
(
!
stored_lang
)
stored_lang
=
"auto"
;
if
(
!
chat
||
!
service_to_use
||
g_str_equal
(
stored_lang
,
"none"
)
||
g_str_equal
(
stored_lang
,
to_lang
))
{
//Allow the message to go through as per normal
return
FALSE
;
}
stripped
=
purple_markup_strip_html
(
*
message
);
convmsg
=
g_new0
(
struct
TranslateConvMessage
,
1
);
convmsg
->
account
=
account
;
convmsg
->
sender
=
*
sender
;
convmsg
->
conv
=
conv
;
convmsg
->
flags
=
*
flags
;
if
(
g_str_equal
(
service_to_use
,
"google"
))
{
google_translate
(
stripped
,
stored_lang
,
to_lang
,
translate_receiving_chat_msg_cb
,
convmsg
);
}
else
if
(
g_str_equal
(
service_to_use
,
"bing"
))
{
bing_translate
(
stripped
,
stored_lang
,
to_lang
,
translate_receiving_chat_msg_cb
,
convmsg
);
}
g_free
(
stripped
);
g_free
(
*
message
);
*
message
=
NULL
;
*
sender
=
NULL
;
if
(
conv
==
NULL
)
{
// Fake receiving a message to open the conversation window
*
message
=
g_strdup
(
" "
);
*
flags
|=
PURPLE_MESSAGE_INVISIBLE
|
PURPLE_MESSAGE_NO_LOG
;
return
FALSE
;
}
//Cancel the message
return
TRUE
;
}
void
translate_sending_message_cb
(
const
gchar
*
original_phrase
,
const
gchar
*
translated_phrase
,
const
gchar
*
detected_language
,
gpointer
userdata
)
{
struct
TranslateConvMessage
*
convmsg
=
userdata
;
gchar
*
html_text
;
int
err
=
0
;
html_text
=
purple_strdup_withhtml
(
translated_phrase
);
err
=
serv_send_im
(
purple_account_get_connection
(
convmsg
->
account
),
convmsg
->
sender
,
html_text
,
convmsg
->
flags
);
g_free
(
html_text
);
html_text
=
purple_strdup_withhtml
(
original_phrase
);
if
(
err
>
0
)
{
purple_conversation_write
(
convmsg
->
conv
,
convmsg
->
sender
,
html_text
,
convmsg
->
flags
,
time
(
NULL
));
}
purple_signal_emit
(
purple_conversations_get_handle
(),
"sent-im-msg"
,
convmsg
->
account
,
convmsg
->
sender
,
html_text
);
g_free
(
html_text
);
g_free
(
convmsg
->
sender
);
g_free
(
convmsg
);
}
void
translate_sending_im_msg
(
PurpleAccount
*
account
,
const
char
*
receiver
,
char
**
message
)
{
const
gchar
*
from_lang
=
""
;
const
gchar
*
service_to_use
=
""
;
const
gchar
*
to_lang
=
""
;
PurpleBuddy
*
buddy
;
struct
TranslateConvMessage
*
convmsg
;
gchar
*
stripped
;
from_lang
=
purple_prefs_get_string
(
LOCALE_PREF
);
service_to_use
=
purple_prefs_get_string
(
SERVICE_PREF
);
buddy
=
purple_find_buddy
(
account
,
receiver
);
if
(
buddy
)
to_lang
=
purple_blist_node_get_string
((
PurpleBlistNode
*
)
buddy
,
DEST_LANG_SETTING
);
if
(
!
buddy
||
!
service_to_use
||
!
to_lang
||
g_str_equal
(
from_lang
,
to_lang
)
||
g_str_equal
(
to_lang
,
"auto"
))
{
// Don't translate this message
return
;
}
stripped
=
purple_markup_strip_html
(
*
message
);
convmsg
=
g_new0
(
struct
TranslateConvMessage
,
1
);
convmsg
->
account
=
account
;
convmsg
->
sender
=
g_strdup
(
receiver
);
convmsg
->
conv
=
purple_find_conversation_with_account
(
PURPLE_CONV_TYPE_IM
,
receiver
,
account
);
convmsg
->
flags
=
PURPLE_MESSAGE_SEND
;
if
(
g_str_equal
(
service_to_use
,
"google"
))
{
google_translate
(
stripped
,
from_lang
,
to_lang
,
translate_sending_message_cb
,
convmsg
);
}
else
if
(
g_str_equal
(
service_to_use
,
"bing"
))
{
bing_translate
(
stripped
,
from_lang
,
to_lang
,
translate_sending_message_cb
,
convmsg
);
}
g_free
(
stripped
);
g_free
(
*
message
);
*
message
=
NULL
;
}
void
translate_sending_chat_message_cb
(
const
gchar
*
original_phrase
,
const
gchar
*
translated_phrase
,
const
gchar
*
detected_language
,
gpointer
userdata
)
{
struct
TranslateConvMessage
*
convmsg
=
userdata
;
gchar
*
html_text
;
html_text
=
purple_strdup_withhtml
(
translated_phrase
);
serv_chat_send
(
purple_account_get_connection
(
convmsg
->
account
),
purple_conv_chat_get_id
(
PURPLE_CONV_CHAT
(
convmsg
->
conv
)),
html_text
,
convmsg
->
flags
);
g_free
(
html_text
);
html_text
=
purple_strdup_withhtml
(
original_phrase
);
purple_signal_emit
(
purple_conversations_get_handle
(),
"sent-chat-msg"
,
convmsg
->
account
,
html_text
,
purple_conv_chat_get_id
(
PURPLE_CONV_CHAT
(
convmsg
->
conv
)));
g_free
(
html_text
);
g_free
(
convmsg
->
sender
);
g_free
(
convmsg
);
}
void
translate_sending_chat_msg
(
PurpleAccount
*
account
,
char
**
message
,
int
chat_id
)
{
const
gchar
*
from_lang
=
""
;
const
gchar
*
service_to_use
=
""
;
const
gchar
*
to_lang
=
""
;
PurpleChat
*
chat
=
NULL
;
PurpleConversation
*
conv
;
struct
TranslateConvMessage
*
convmsg
;
gchar
*
stripped
;
from_lang
=
purple_prefs_get_string
(
LOCALE_PREF
);
service_to_use
=
purple_prefs_get_string
(
SERVICE_PREF
);
conv
=
purple_find_chat
(
purple_account_get_connection
(
account
),
chat_id
);
if
(
conv
)
chat
=
purple_blist_find_chat
(
account
,
conv
->
name
);
if
(
chat
)
to_lang
=
purple_blist_node_get_string
((
PurpleBlistNode
*
)
chat
,
DEST_LANG_SETTING
);
if
(
!
chat
||
!
service_to_use
||
!
to_lang
||
g_str_equal
(
from_lang
,
to_lang
)
||
g_str_equal
(
to_lang
,
"auto"
))
{
// Don't translate this message
return
;
}
stripped
=
purple_markup_strip_html
(
*
message
);
convmsg
=
g_new0
(
struct
TranslateConvMessage
,
1
);
convmsg
->
account
=
account
;
convmsg
->
conv
=
conv
;
convmsg
->
flags
=
PURPLE_MESSAGE_SEND
;
if
(
g_str_equal
(
service_to_use
,
"google"
))
{
google_translate
(
stripped
,
from_lang
,
to_lang
,
translate_sending_chat_message_cb
,
convmsg
);
}
else
if
(
g_str_equal
(
service_to_use
,
"bing"
))
{
bing_translate
(
stripped
,
from_lang
,
to_lang
,
translate_sending_chat_message_cb
,
convmsg
);
}
g_free
(
stripped
);
g_free
(
*
message
);
*
message
=
NULL
;
}
static
void
translate_action_blist_cb
(
PurpleBlistNode
*
node
,
PurpleKeyValuePair
*
pair
)
{
PurpleConversation
*
conv
=
NULL
;
gchar
*
message
;
PurpleChat
*
chat
;
PurpleContact
*
contact
;
PurpleBuddy
*
buddy
;
if
(
pair
==
NULL
)
purple_blist_node_set_string
(
node
,
DEST_LANG_SETTING
,
NULL
);
else
purple_blist_node_set_string
(
node
,
DEST_LANG_SETTING
,
pair
->
key
);
switch
(
node
->
type
)
{
case
PURPLE_BLIST_CHAT_NODE
:
chat
=
(
PurpleChat
*
)
node
;
conv
=
purple_find_conversation_with_account
(
PURPLE_CONV_TYPE_CHAT
,
purple_chat_get_name
(
chat
),
chat
->
account
);
break
;
case
PURPLE_BLIST_CONTACT_NODE
:
contact
=
(
PurpleContact
*
)
node
;
node
=
(
PurpleBlistNode
*
)
purple_contact_get_priority_buddy
(
contact
);
//fallthrough intentional
case
PURPLE_BLIST_BUDDY_NODE
:
buddy
=
(
PurpleBuddy
*
)
node
;
conv
=
purple_find_conversation_with_account
(
PURPLE_CONV_TYPE_IM
,
purple_buddy_get_name
(
buddy
),
purple_buddy_get_account
(
buddy
));
break
;
default
:
break
;
}
if
(
conv
!=
NULL
&&
pair
!=
NULL
)
{
message
=
g_strdup_printf
(
"Now translating to %s"
,
(
const
gchar
*
)
pair
->
value
);
purple_conversation_write
(
conv
,
NULL
,
message
,
PURPLE_MESSAGE_SYSTEM
|
PURPLE_MESSAGE_NO_LOG
,
time
(
NULL
));
g_free
(
message
);
}
}
static
void
translate_extended_menu
(
PurpleBlistNode
*
node
,
GList
**
menu
,
PurpleCallback
callback
)
{
const
gchar
*
stored_lang
;
GList
*
menu_children
=
NULL
;
PurpleMenuAction
*
action
;
PurpleKeyValuePair
*
pair
;
GList
*
l
;
if
(
!
node
)
return
;
stored_lang
=
purple_blist_node_get_string
(
node
,
DEST_LANG_SETTING
);
if
(
!
stored_lang
)
stored_lang
=
"auto"
;
action
=
purple_menu_action_new
(
_
(
"Auto"
),
callback
,
NULL
,
NULL
);
menu_children
=
g_list_append
(
menu_children
,
action
);
// Spacer
menu_children
=
g_list_append
(
menu_children
,
NULL
);
for
(
l
=
supported_languages
;
l
;
l
=
l
->
next
)
{
pair
=
(
PurpleKeyValuePair
*
)
l
->
data
;
action
=
purple_menu_action_new
(
pair
->
value
,
callback
,
pair
,
NULL
);
menu_children
=
g_list_append
(
menu_children
,
action
);
}
// Create the menu for the languages
action
=
purple_menu_action_new
(
_
(
"Translate to..."
),
NULL
,
NULL
,
menu_children
);
*
menu
=
g_list_append
(
*
menu
,
action
);
}
static
void
translate_blist_extended_menu
(
PurpleBlistNode
*
node
,
GList
**
menu
)
{
translate_extended_menu
(
node
,
menu
,
(
PurpleCallback
)
translate_action_blist_cb
);
}
static
void
translate_action_conv_cb
(
PurpleConversation
*
conv
,
PurpleKeyValuePair
*
pair
)
{
PurpleBlistNode
*
node
=
NULL
;
gchar
*
message
;
if
(
conv
->
type
==
PURPLE_CONV_TYPE_IM
)
node
=
(
PurpleBlistNode
*
)
purple_find_buddy
(
conv
->
account
,
conv
->
name
);
else
if
(
conv
->
type
==
PURPLE_CONV_TYPE_CHAT
)
node
=
(
PurpleBlistNode
*
)
purple_blist_find_chat
(
conv
->
account
,
conv
->
name
);
if
(
node
!=
NULL
)
{
translate_action_blist_cb
(
node
,
pair
);
if
(
pair
!=
NULL
)
{
message
=
g_strdup_printf
(
"Now translating to %s"
,
(
const
gchar
*
)
pair
->
value
);
purple_conversation_write
(
conv
,
NULL
,
message
,
PURPLE_MESSAGE_SYSTEM
|
PURPLE_MESSAGE_NO_LOG
,
time
(
NULL
));
g_free
(
message
);
}
}
}
static
void
translate_conversation_created
(
PurpleConversation
*
conv
)
{
PurpleBlistNode
*
node
=
NULL
;
gchar
*
message
;
const
gchar
*
language_key
;
const
gchar
*
language_name
;
if
(
conv
->
type
==
PURPLE_CONV_TYPE_IM
)
node
=
(
PurpleBlistNode
*
)
purple_find_buddy
(
conv
->
account
,
conv
->
name
);
else
if
(
conv
->
type
==
PURPLE_CONV_TYPE_CHAT
)
node
=
(
PurpleBlistNode
*
)
purple_blist_find_chat
(
conv
->
account
,
conv
->
name
);
if
(
node
!=
NULL
)
{
language_key
=
purple_blist_node_get_string
(
node
,
DEST_LANG_SETTING
);
if
(
language_key
!=
NULL
)
{
language_name
=
get_language_name
(
language_key
);
message
=
g_strdup_printf
(
_
(
"Now translating to %s"
),
language_name
);
purple_conversation_write
(
conv
,
NULL
,
message
,
PURPLE_MESSAGE_SYSTEM
|
PURPLE_MESSAGE_NO_LOG
,
time
(
NULL
));
g_free
(
message
);
}
}
}
static
void
translate_conv_extended_menu
(
PurpleConversation
*
conv
,
GList
**
menu
)
{
PurpleBlistNode
*
node
=
NULL
;
if
(
conv
->
type
==
PURPLE_CONV_TYPE_IM
)
node
=
(
PurpleBlistNode
*
)
purple_find_buddy
(
conv
->
account
,
conv
->
name
);
else
if
(
conv
->
type
==
PURPLE_CONV_TYPE_CHAT
)
node
=
(
PurpleBlistNode
*
)
purple_blist_find_chat
(
conv
->
account
,
conv
->
name
);
if
(
node
!=
NULL
)
translate_extended_menu
(
node
,
menu
,
(
PurpleCallback
)
translate_action_conv_cb
);
}
static
PurplePluginPrefFrame
*
plugin_config_frame
(
PurplePlugin
*
plugin
)
{
PurplePluginPrefFrame
*
frame
;
PurplePluginPref
*
ppref
;
GList
*
l
=
NULL
;
PurpleKeyValuePair
*
pair
;
frame
=
purple_plugin_pref_frame_new
();
ppref
=
purple_plugin_pref_new_with_name_and_label
(
LOCALE_PREF
,
_
(
"My language:"
));
purple_plugin_pref_set_type
(
ppref
,
PURPLE_PLUGIN_PREF_CHOICE
);
for
(
l
=
supported_languages
;
l
;
l
=
l
->
next
)
{
pair
=
(
PurpleKeyValuePair
*
)
l
->
data
;
purple_plugin_pref_add_choice
(
ppref
,
pair
->
value
,
pair
->
key
);
}
purple_plugin_pref_frame_add
(
frame
,
ppref
);
ppref
=
purple_plugin_pref_new_with_name_and_label
(
SERVICE_PREF
,
_
(
"Use service:"
));
purple_plugin_pref_set_type
(
ppref
,
PURPLE_PLUGIN_PREF_CHOICE
);
purple_plugin_pref_add_choice
(
ppref
,
_
(
"Google Translate"
),
"google"
);
purple_plugin_pref_add_choice
(
ppref
,
_
(
"Microsoft Translator"
),
"bing"
);
purple_plugin_pref_frame_add
(
frame
,
ppref
);
return
frame
;
}
static
gboolean
plugin_load
(
PurplePlugin
*
plugin
)
{
purple_signal_connect
(
purple_conversations_get_handle
(),
"receiving-im-msg"
,
plugin
,
PURPLE_CALLBACK
(
translate_receiving_im_msg
),
NULL
);
purple_signal_connect
(
purple_conversations_get_handle
(),
"sending-im-msg"
,
plugin
,
PURPLE_CALLBACK
(
translate_sending_im_msg
),
NULL
);
purple_signal_connect
(
purple_blist_get_handle
(),
"blist-node-extended-menu"
,
plugin
,
PURPLE_CALLBACK
(
translate_blist_extended_menu
),
NULL
);
purple_signal_connect
(
purple_conversations_get_handle
(),
"blist-node-extended-menu"
,
plugin
,
PURPLE_CALLBACK
(
translate_conv_extended_menu
),
NULL
);
purple_signal_connect
(
purple_conversations_get_handle
(),
"conversation-created"
,
plugin
,
PURPLE_CALLBACK
(
translate_conversation_created
),
NULL
);
purple_signal_connect
(
purple_conversations_get_handle
(),
"receiving-chat-msg"
,
plugin
,
PURPLE_CALLBACK
(
translate_receiving_chat_msg
),
NULL
);
purple_signal_connect
(
purple_conversations_get_handle
(),
"sending-chat-msg"
,
plugin
,
PURPLE_CALLBACK
(
translate_sending_chat_msg
),
NULL
);
return
TRUE
;
}
static
gboolean
plugin_unload
(
PurplePlugin
*
plugin
)
{
purple_signal_disconnect
(
purple_conversations_get_handle
(),
"receiving-im-msg"
,
plugin
,
PURPLE_CALLBACK
(
translate_receiving_im_msg
));
purple_signal_disconnect
(
purple_conversations_get_handle
(),
"sending-im-msg"
,
plugin
,
PURPLE_CALLBACK
(
translate_sending_im_msg
));
purple_signal_disconnect
(
purple_blist_get_handle
(),
"blist-node-extended-menu"
,
plugin
,
PURPLE_CALLBACK
(
translate_blist_extended_menu
));
purple_signal_disconnect
(
purple_conversations_get_handle
(),
"blist-node-extended-menu"
,
plugin
,
PURPLE_CALLBACK
(
translate_conv_extended_menu
));
purple_signal_disconnect
(
purple_conversations_get_handle
(),
"conversation-created"
,
plugin
,
PURPLE_CALLBACK
(
translate_conversation_created
));
purple_signal_disconnect
(
purple_conversations_get_handle
(),
"receiving-chat-msg"
,
plugin
,
PURPLE_CALLBACK
(
translate_receiving_chat_msg
));
purple_signal_disconnect
(
purple_conversations_get_handle
(),
"sending-chat-msg"
,
plugin
,
PURPLE_CALLBACK
(
translate_sending_chat_msg
));
return
TRUE
;
}
static
PurplePluginUiInfo
prefs_info
=
{
plugin_config_frame
,
0
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
};
static
PurplePluginInfo
info
=
{
PURPLE_PLUGIN_MAGIC
,
2
,
3
,
PURPLE_PLUGIN_STANDARD
,
NULL
,
0
,
NULL
,
PURPLE_PRIORITY_DEFAULT
,
"eionrobb-libpurple-translate"
,
NULL
,
PP_VERSION
,
NULL
,
""
,
"Eion Robb <eionrobb@gmail.com>"
,
PP_WEBSITE
,
/* URL */
plugin_load
,
/* load */
plugin_unload
,
/* unload */
NULL
,
/* destroy */
NULL
,
NULL
,
&
prefs_info
,
NULL
,
/* reserved */
NULL
,
NULL
,
NULL
,
NULL
};
static
void
init_plugin
(
PurplePlugin
*
plugin
)
{
const
gchar
*
const
*
languages
=
g_get_language_names
();
const
gchar
*
language
;
guint
i
=
0
;
PurpleKeyValuePair
*
pair
;
info
.
name
=
_
(
"Auto Translate"
);
info
.
summary
=
_
(
"Translate incoming/outgoing messages"
);
while
((
language
=
languages
[
i
++
]))
if
(
language
&&
strlen
(
language
)
==
2
)
break
;
if
(
!
language
||
strlen
(
language
)
!=
2
)
language
=
"en"
;
purple_prefs_add_none
(
"/plugins/core/eionrobb-libpurple-translate"
);
purple_prefs_add_string
(
LOCALE_PREF
,
language
);
purple_prefs_add_string
(
SERVICE_PREF
,
"google"
);
#define add_language(label, code) \
pair = g_new0(PurpleKeyValuePair, 1); \
pair->key = g_strdup(code); \
pair->value = g_strdup(label); \
supported_languages = g_list_append(supported_languages, pair);
add_language
(
_
(
"Afrikaans"
),
"af"
);
add_language
(
_
(
"Albanian"
),
"sq"
);
add_language
(
_
(
"Arabic"
),
"ar"
);
add_language
(
_
(
"Armenian"
),
"hy"
);
add_language
(
_
(
"Azerbaijani"
),
"az"
);
add_language
(
_
(
"Basque"
),
"eu"
);
add_language
(
_
(
"Belarusian"
),
"be"
);
add_language
(
_
(
"Bulgarian"
),
"bg"
);
add_language
(
_
(
"Catalan"
),
"ca"
);
add_language
(
_
(
"Chinese (Simplified)"
),
"zh-CN"
);
add_language
(
_
(
"Chinese (Traditional)"
),
"zh-TW"
);
add_language
(
_
(
"Croatian"
),
"hr"
);
add_language
(
_
(
"Czech"
),
"cs"
);
add_language
(
_
(
"Danish"
),
"da"
);
add_language
(
_
(
"Dutch"
),
"nl"
);
add_language
(
_
(
"English"
),
"en"
);
add_language
(
_
(
"Estonian"
),
"et"
);
add_language
(
_
(
"Filipino"
),
"tl"
);
add_language
(
_
(
"Finnish"
),
"fi"
);
add_language
(
_
(
"French"
),
"fr"
);
add_language
(
_
(
"Galician"
),
"gl"
);
add_language
(
_
(
"Georgian"
),
"ka"
);
add_language
(
_
(
"German"
),
"de"
);
add_language
(
_
(
"Greek"
),
"el"
);
add_language
(
_
(
"Haitian Creole"
),
"ht"
);
add_language
(
_
(
"Hebrew"
),
"iw"
);
add_language
(
_
(
"Hindi"
),
"hi"
);
add_language
(
_
(
"Hungarian"
),
"hu"
);
add_language
(
_
(
"Icelandic"
),
"is"
);
add_language
(
_
(
"Indonesian"
),
"id"
);
add_language
(
_
(
"Irish"
),
"ga"
);
add_language
(
_
(
"Italian"
),
"it"
);
add_language
(
_
(
"Japanese"
),
"ja"
);
add_language
(
_
(
"Korean"
),
"ko"
);
add_language
(
_
(
"Latin"
),
"la"
);
add_language
(
_
(
"Latvian"
),
"lv"
);
add_language
(
_
(
"Lithuanian"
),
"lt"
);
add_language
(
_
(
"Macedonian"
),
"mk"
);
add_language
(
_
(
"Malay"
),
"ms"
);
add_language
(
_
(
"Maltese"
),
"mt"
);
add_language
(
_
(
"Norwegian"
),
"no"
);
add_language
(
_
(
"Persian"
),
"fa"
);
add_language
(
_
(
"Polish"
),
"pl"
);
add_language
(
_
(
"Portuguese"
),
"pt"
);
add_language
(
_
(
"Romanian"
),
"ro"
);
add_language
(
_
(
"Russian"
),
"ru"
);
add_language
(
_
(
"Serbian"
),
"sr"
);
add_language
(
_
(
"Slovak"
),
"sk"
);
add_language
(
_
(
"Slovenian"
),
"sl"
);
add_language
(
_
(
"Spanish"
),
"es"
);
add_language
(
_
(
"Swahili"
),
"sw"
);
add_language
(
_
(
"Swedish"
),
"sv"
);
add_language
(
_
(
"Thai"
),
"th"
);
add_language
(
_
(
"Turkish"
),
"tr"
);
add_language
(
_
(
"Ukrainian"
),
"uk"
);
add_language
(
_
(
"Urdu"
),
"ur"
);
add_language
(
_
(
"Vietnamese"
),
"vi"
);
add_language
(
_
(
"Welsh"
),
"cy"
);
add_language
(
_
(
"Yiddish"
),
"yi"
);
}
PURPLE_INIT_PLUGIN
(
translate
,
init_plugin
,
info
);