pidgin/purple-plugin-pack

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/
/*
* ning_chat.c
* pidgin-ning
*
* Created by MyMacSpace on 6/08/09.
* Copyright 2009 __MyCompanyName__. All rights reserved.
*
*/
#include "ning_chat.h"
//list buddies
//send message to chat
//send whisper
//poll for messages
//fetch chat history
//join chat
/*
void (*chat_leave)(PurpleConnection *, int id);
void (*chat_whisper)(PurpleConnection *, int id, const char *who, const char *message);
int (*chat_send)(PurpleConnection *, int id, const char *message, PurpleMessageFlags flags);
void (*join_chat)(PurpleConnection *, GHashTable *components);
PurpleConversation* purple_find_chat(const PurpleConnection *gc, int id);
*/
gint64 ning_time_kludge(gint initial_time)
{
if (sizeof(gint) >= sizeof(gint64))
return initial_time;
gint64 now_millis = (gint64) time(NULL);
now_millis *= 1000;
now_millis &= 0xFFFFFFFF00000000LL;
gint64 final_time = now_millis | ((guint)initial_time);
return final_time;
}
void
ning_chat_messages_cb(NingAccount *na, gchar *response, gsize len, gpointer userdata)
{
NingChat *chat;
JsonObject *obj;
JsonArray *array;
JsonObject *msgobj;
const gchar *type;
const gchar *body;
gint date;
JsonObject *sender;
const gchar *senderId;
PurpleBuddy *buddy;
PurpleGroup *group;
guint i;
guint64 time_kludge;
chat = userdata;
purple_debug_info("ning", "ning_chat_messages_cb: %s\n", response?response:"(null)");
obj = ning_json_parse(response, len);
if (json_object_has_member(obj, "hash"))
{
g_free(chat->ning_hash);
chat->ning_hash = g_strdup(json_node_get_string(json_object_get_member(obj, "hash")));
}
array = json_node_get_array(json_object_get_member(obj, "messages"));
for(i = 0; i < json_array_get_length(array); i++)
{
msgobj = json_node_get_object(json_array_get_element(array, i));
//type (message or private)
//body, date, roomId, targetId, sender(obj)
type = json_node_get_string(json_object_get_member(msgobj, "type"));
body = json_node_get_string(json_object_get_member(msgobj, "body"));
date = json_node_get_int(json_object_get_member(msgobj, "date"));
sender = json_node_get_object(json_object_get_member(msgobj, "sender"));
senderId = json_node_get_string(json_object_get_member(sender, "ningId"));
//Check that they're on the buddy list
buddy = purple_find_buddy(na->account, senderId);
if (!buddy)
{
//They aren't, so lets fake it
buddy = purple_buddy_new(na->account, senderId,
json_node_get_string(json_object_get_member(sender, "name")));
group = purple_find_group(NING_TEMP_GROUP_NAME);
if (!group)
{
group = purple_group_new(NING_TEMP_GROUP_NAME);
purple_blist_add_group(group, NULL);
purple_blist_node_set_flags(&group->node, PURPLE_BLIST_NODE_FLAG_NO_SAVE);
}
purple_blist_add_buddy(buddy, NULL, group, NULL);
purple_blist_node_set_flags(&buddy->node, PURPLE_BLIST_NODE_FLAG_NO_SAVE);
}
time_kludge = ning_time_kludge(date);
if (g_str_equal(type, "message"))
{
serv_got_chat_in(na->pc, chat->purple_id, senderId, PURPLE_MESSAGE_RECV, body, time_kludge);
} else if (g_str_equal(type, "private"))
{
serv_got_chat_in(na->pc, chat->purple_id, senderId,
PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_WHISPER, body, time_kludge);
} else {
purple_debug_info("ning", "unknown message type: %s\n", type);
}
}
json_object_unref(obj);
}
gboolean
ning_chat_get_history(NingChat *chat)
{
NingAccount *na;
gchar *url;
gchar *encoded_hash;
gchar *encoded_app;
gchar *encoded_id;
gchar *encoded_token;
gchar *encoded_room;
na = chat->na;
encoded_hash = g_strdup(purple_url_encode(chat->ning_hash));
encoded_app = g_strdup(purple_url_encode(na->ning_app));
encoded_id = g_strdup(purple_url_encode(na->ning_id));
encoded_token = g_strdup(purple_url_encode(na->chat_token));
encoded_room = g_strdup(purple_url_encode(chat->roomId));
url = g_strdup_printf("/xn/groupchat/list?h=%s&a=%s&i=%s&t=%s&r=%s", encoded_hash, encoded_app,
encoded_id, encoded_token, encoded_room);
ning_post_or_get(na, NING_METHOD_GET, na->chat_domain,
url, NULL,
ning_chat_messages_cb, chat, FALSE);
g_free(url);
g_free(encoded_room);
g_free(encoded_token);
g_free(encoded_id);
g_free(encoded_app);
g_free(encoded_hash);
return FALSE;
}
void
ning_chat_get_users_cb(NingAccount *na, gchar *response, gsize len, gpointer userdata)
{
NingChat *chat;
JsonObject *obj;
JsonArray *array;
JsonObject *userobj;
int i;
const gchar *ningId;
const gchar *name;
//const gchar *iconUrl;
gboolean isAdmin;
PurpleConversation *conv;
// PurpleBuddy *buddy;
PurpleConvChatBuddy *cbuddy;
PurpleConversationUiOps *uiops;
purple_debug_info("ning", "chat users: %s\n", response?response:"(null)");
chat = userdata;
obj = ning_json_parse(response, len);
if (json_object_has_member(obj, "hash"))
{
g_free(chat->ning_hash);
chat->ning_hash = g_strdup(json_node_get_string(json_object_get_member(obj, "hash")));
}
conv = purple_find_chat(na->pc, chat->purple_id);
uiops = purple_conversation_get_ui_ops(conv);
array = json_node_get_array(json_object_get_member(obj, "expired"));
for(i = 0; i < json_array_get_length(array); i++)
{
ningId = json_node_get_string(json_array_get_element(array, i));
purple_conv_chat_remove_user(PURPLE_CONV_CHAT(conv), ningId, NULL);
}
array = json_node_get_array(json_object_get_member(obj, "users"));
if (array && json_array_get_length(array) > 0)
{
purple_conv_chat_clear_users(PURPLE_CONV_CHAT(conv));
}
for(i = 0; i < json_array_get_length(array); i++)
{
userobj = json_node_get_object(json_array_get_element(array, i));
//isNC, iconUrl, name, ningId, isAdmin
ningId = json_node_get_string(json_object_get_member(userobj, "ningId"));
name = json_node_get_string(json_object_get_member(userobj, "name"));
isAdmin = json_node_get_boolean(json_object_get_member(userobj, "isAdmin"));
if (!purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), ningId))
{
purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv), ningId,
NULL, isAdmin?PURPLE_CBFLAGS_OP:PURPLE_CBFLAGS_NONE,
FALSE);
}
cbuddy = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), ningId);
if (cbuddy)
{
g_free(cbuddy->alias);
cbuddy->alias = g_strdup(name);
}
//Refresh the buddy
if (uiops && uiops->chat_rename_user)
{
purple_debug_info("ning", "try rename user %s to %s\n", ningId, name);
uiops->chat_rename_user(conv, ningId, ningId, name);
}
else if (uiops && uiops->chat_update_user)
{
purple_debug_info("ning", "try update user %s\n", ningId);
uiops->chat_update_user(conv, ningId);
}
}
json_object_unref(obj);
}
gboolean
ning_chat_get_users(NingChat *chat)
{
NingAccount *na;
gchar *url;
gchar *encoded_hash;
gchar *encoded_app;
gchar *encoded_id;
gchar *encoded_token;
gchar *encoded_room;
na = chat->na;
encoded_hash = g_strdup(purple_url_encode(chat->ning_hash));
encoded_app = g_strdup(purple_url_encode(na->ning_app));
encoded_id = g_strdup(purple_url_encode(na->ning_id));
encoded_token = g_strdup(purple_url_encode(na->chat_token));
encoded_room = g_strdup(purple_url_encode(chat->roomId));
url = g_strdup_printf("/xn/presence/list?h=%s&a=%s&i=%s&t=%s&r=%s", encoded_hash, encoded_app,
encoded_id, encoded_token, encoded_room);
ning_post_or_get(na, NING_METHOD_GET, na->chat_domain,
url, NULL,
ning_chat_get_users_cb, chat, FALSE);
g_free(url);
g_free(encoded_room);
g_free(encoded_token);
g_free(encoded_id);
g_free(encoded_app);
g_free(encoded_hash);
return TRUE;
}
gboolean
ning_chat_poll_messages(NingChat *chat)
{
NingAccount *na;
gchar *url;
gchar *encoded_app;
gchar *encoded_id;
gchar *encoded_token;
gchar *encoded_room;
na = chat->na;
encoded_app = g_strdup(purple_url_encode(na->ning_app));
encoded_id = g_strdup(purple_url_encode(na->ning_id));
encoded_token = g_strdup(purple_url_encode(na->chat_token));
encoded_room = g_strdup(purple_url_encode(chat->roomId));
url = g_strdup_printf("/xn/groupchat/poll?a=%s&i=%s&t=%s&r=%s", encoded_app,
encoded_id, encoded_token, encoded_room);
ning_post_or_get(na, NING_METHOD_GET, na->chat_domain,
url, NULL,
ning_chat_messages_cb, chat, FALSE);
g_free(url);
g_free(encoded_room);
g_free(encoded_token);
g_free(encoded_id);
g_free(encoded_app);
return TRUE;
}
void
ning_chat_cb(NingAccount *na, gchar *response, gsize len, gpointer userdata)
{
purple_debug_info("ning", "ning_chat_cb: %s\n", response?response:"(null)");
}
void
ning_chat_whisper(PurpleConnection *pc, int id, const char *who, const char *message)
{
NingAccount *na;
gchar *stripped;
PurpleConversation *conv;
gchar *postdata;
gchar *message_json;
gchar *sender;
gchar *message_escaped;
gchar *ning_id_escaped;
gchar *token_escaped;
gchar *room_escaped;
gchar *app_escaped;
purple_debug_info("ning", "chat whisper %s %s\n", who, message);
na = pc->proto_data;
conv = purple_find_chat(pc, id);
app_escaped = g_strdup(purple_url_encode(na->ning_app));
token_escaped = g_strdup(purple_url_encode(na->xg_token));
room_escaped = g_strdup(purple_url_encode(conv->name));
ning_id_escaped = g_strdup(purple_url_encode(na->ning_id));
sender = build_user_json(na);
stripped = purple_markup_strip_html(message);
if (who != NULL)
{
message_json = g_strdup_printf("{ \"roomId\":\"%s\", \"type\":\"private\", \"targetId\":\"%s\", \"body\":\"%s\", \"sender\":%s }",
conv->name, who, stripped,
sender);
} else {
message_json = g_strdup_printf("{ \"roomId\":\"%s\", \"type\":\"message\", \"targetId\":null, \"body\":\"%s\", \"sender\":%s }",
conv->name, stripped,
sender);
}
message_escaped = g_strdup(purple_url_encode(message_json));
postdata = g_strdup_printf("a=%s&i=%s&t=%s&r=%s&message=%s",
app_escaped, ning_id_escaped,
token_escaped, room_escaped,
message_escaped);
ning_post_or_get(na, NING_METHOD_POST, na->chat_domain,
"/xn/groupchat/publish", postdata,
ning_chat_cb, conv, FALSE);
g_free(sender);
g_free(postdata);
g_free(message_escaped);
g_free(message_json);
g_free(stripped);
g_free(app_escaped);
g_free(ning_id_escaped);
g_free(token_escaped);
g_free(room_escaped);
}
int
ning_send_im(PurpleConnection *pc, const char *who, const char *message, PurpleMessageFlags flags)
{
PurpleConversation *conv;
GList *chats;
PurpleConvChat *chat;
gint chat_id;
if (flags != PURPLE_MESSAGE_SEND)
return -1;
chats = purple_get_chats();
for (;chats;chats = chats->next)
{
conv = chats->data;
chat = PURPLE_CONV_CHAT(conv);
if (purple_conv_chat_find_user(chat, who))
{
chat_id = purple_conv_chat_get_id(chat);
ning_chat_whisper(pc, chat_id, who, message);
return 1;
}
}
return -1;
}
int
ning_chat_send(PurpleConnection *pc, int id, const char *message, PurpleMessageFlags flags)
{
if (flags != PURPLE_MESSAGE_SEND)
return -1;
ning_chat_whisper(pc, id, NULL, message);
return 1;
}
void
ning_join_chat_by_name(NingAccount *na, const gchar *roomId)
{
NingChat *chat;
if (na == NULL || roomId == NULL)
return;
chat = g_new0(NingChat, 1);
chat->na = na;
chat->roomId = g_strdup(roomId);
chat->purple_id = g_str_hash(roomId);
chat->ning_hash = g_strdup("null");
serv_got_joined_chat(na->pc, g_str_hash(roomId), roomId);
//get history
ning_chat_get_history(chat);
//get user list
ning_chat_get_users(chat);
chat->userlist_timer = purple_timeout_add_seconds(60, (GSourceFunc) ning_chat_get_users, chat);
//start message poll
ning_chat_poll_messages(chat);
chat->message_poll_timer = purple_timeout_add_seconds(180, (GSourceFunc) ning_chat_poll_messages, chat);
na->chats = g_list_append(na->chats, chat);
}
void
ning_join_chat(PurpleConnection *pc, GHashTable *components)
{
NingAccount *na;
if (pc == NULL || pc->proto_data == NULL || components == NULL)
return;
na = pc->proto_data;
ning_join_chat_by_name(na, g_hash_table_lookup(components, "name"));
}