#include "skypeweb_messages.h"
#include "skypeweb_util.h"
#include "skypeweb_connection.h"
#include "skypeweb_contacts.h"
static gchar *
skypeweb_meify(const gchar *message, gint skypeemoteoffset)
{
guint len;
len = strlen(message);
if (skypeemoteoffset <= 0 || skypeemoteoffset >= len)
return g_strdup(message);
return g_strconcat("/me ", message + skypeemoteoffset, NULL);
}
static void
process_userpresence_resource(SkypeWebAccount *sa, JsonObject *resource)
{
const gchar *selfLink = json_object_get_string_member(resource, "selfLink");
const gchar *status = json_object_get_string_member(resource, "status");
const gchar *from;
from = skypeweb_contact_url_to_name(selfLink);
g_return_if_fail(from);
//TODO not need me
if (!purple_find_buddy(sa->account, from))
{
PurpleGroup *group = purple_find_group("Skype");
if (!group)
{
group = purple_group_new("Skype");
purple_blist_add_group(group, NULL);
}
purple_blist_add_buddy(purple_buddy_new(sa->account, from, NULL), NULL, group, NULL);
}
purple_prpl_got_user_status(sa->account, from, status, NULL);
purple_prpl_got_user_idle(sa->account, from, g_str_equal(status, "Idle"), 0);
}
static void
process_message_resource(SkypeWebAccount *sa, JsonObject *resource)
{
const gchar *clientmessageid = json_object_get_string_member(resource, "clientmessageid");
const gchar *messagetype = json_object_get_string_member(resource, "messagetype");
const gchar *from = json_object_get_string_member(resource, "from");
const gchar *content = json_object_get_string_member(resource, "content");
const gchar *composetime = json_object_get_string_member(resource, "composetime");
const gchar *conversationLink = json_object_get_string_member(resource, "conversationLink");
time_t composetimestamp = purple_str_to_time(composetime, TRUE, NULL, NULL, NULL);
gchar **messagetype_parts;
PurpleConversation *conv;
gchar *convname;
messagetype_parts = g_strsplit(messagetype, "/", -1);
if (clientmessageid && *clientmessageid && g_hash_table_remove(sa->sent_messages_hash, clientmessageid)) {
// We sent this message from here already
return;
}
from = skypeweb_contact_url_to_name(from);
g_return_if_fail(from);
if (strstr(conversationLink, "/19:")) {
// This is a Thread/Group chat message
const gchar *chatname, *topic;
chatname = skypeweb_thread_url_to_name(conversationLink);
convname = g_strdup(chatname);
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, chatname, sa->account);
if (!conv) {
conv = serv_got_joined_chat(sa->pc, g_str_hash(chatname), chatname);
purple_conversation_set_data(conv, "chatname", g_strdup(chatname));
topic = json_object_get_string_member(resource, "threadtopic");
purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), NULL, topic);
//TODO get buddies and history
}
if (g_str_equal(messagetype, "RichText") || g_str_equal(messagetype, "Text")) {
gchar *html;
gint64 skypeemoteoffset = 0;
if (json_object_has_member(resource, "skypeemoteoffset"))
skypeemoteoffset = atoi(json_object_get_string_member(resource, "skypeemoteoffset"));
if (g_str_equal(messagetype, "Text")) {
gchar *temp = skypeweb_meify(content, skypeemoteoffset);
html = purple_markup_escape_text(temp, -1);
g_free(temp);
} else {
html = skypeweb_meify(content, skypeemoteoffset);
}
serv_got_chat_in(sa->pc, g_str_hash(chatname), from, g_str_equal(sa->username, from) ? PURPLE_MESSAGE_SEND : PURPLE_MESSAGE_RECV, html, composetimestamp);
g_free(html);
} else if (g_str_equal(messagetype, "ThreadActivity/AddMember")) {
xmlnode *blob = xmlnode_from_str(content, -1);
xmlnode *target;
for(target = xmlnode_get_child(blob, "target"); target;
target = xmlnode_get_next_twin(target))
{
gchar *user = xmlnode_get_data(target);
if (!purple_conv_chat_find_user(PURPLE_CONV_CHAT(conv), &user[2]))
purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv), &user[2], NULL, PURPLE_CBFLAGS_NONE, TRUE);
g_free(user);
}
xmlnode_free(blob);
} else if (g_str_equal(messagetype, "ThreadActivity/DeleteMember")) {
xmlnode *blob = xmlnode_from_str(content, -1);
xmlnode *target;
for(target = xmlnode_get_child(blob, "target"); target;
target = xmlnode_get_next_twin(target))
{
gchar *user = xmlnode_get_data(target);
if (g_str_equal(sa->username, &user[2]))
purple_conv_chat_left(PURPLE_CONV_CHAT(conv));
purple_conv_chat_remove_user(PURPLE_CONV_CHAT(conv), &user[2], NULL);
g_free(user);
}
xmlnode_free(blob);
} else if (g_str_equal(messagetype, "ThreadActivity/TopicUpdate")) {
xmlnode *blob = xmlnode_from_str(content, -1);
gchar *initiator = xmlnode_get_data(xmlnode_get_child(blob, "initiator"));
gchar *value = xmlnode_get_data(xmlnode_get_child(blob, "value"));
purple_conv_chat_set_topic(PURPLE_CONV_CHAT(conv), &initiator[2], value);
purple_conversation_update(conv, PURPLE_CONV_UPDATE_TOPIC);
g_free(initiator);
g_free(value);
xmlnode_free(blob);
} else {
purple_debug_warning("skypeweb", "Unhandled thread message resource messagetype '%s'\n", messagetype);
}
} else {
// This is a One-to-one/IM message
convname = g_strconcat("8:", skypeweb_contact_url_to_name(conversationLink), NULL);
from = skypeweb_contact_url_to_name(json_object_get_string_member(resource, "from")); //regen the from
if (g_str_equal(messagetype_parts[0], "Control")) {
if (g_str_equal(messagetype_parts[1], "ClearTyping")) {
serv_got_typing(sa->pc, from, 7, PURPLE_NOT_TYPING);
} else if (g_str_equal(messagetype_parts[1], "Typing")) {
serv_got_typing(sa->pc, from, 7, PURPLE_TYPING);
}
} else if (g_str_equal(messagetype, "RichText") || g_str_equal(messagetype, "Text")) {
gchar *html;
gint64 skypeemoteoffset = 0;
if (json_object_has_member(resource, "skypeemoteoffset"))
skypeemoteoffset = atoi(json_object_get_string_member(resource, "skypeemoteoffset"));
if (g_str_equal(messagetype, "Text")) {
gchar *temp = skypeweb_meify(content, skypeemoteoffset);
html = purple_markup_escape_text(temp, -1);
g_free(temp);
} else {
html = skypeweb_meify(content, skypeemoteoffset);
}
if (g_str_equal(sa->username, from)) {
from = skypeweb_contact_url_to_name(conversationLink);
if (from != NULL) {
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, sa->account);
if (conv == NULL)
{
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, sa->account, from);
}
purple_conversation_write(conv, from, html, PURPLE_MESSAGE_SEND, composetimestamp);
}
} else {
serv_got_im(sa->pc, from, html, PURPLE_MESSAGE_RECV, composetimestamp);
}
g_free(html);
} else if (g_str_equal(messagetype, "RichText/UriObject")) {
xmlnode *blob = xmlnode_from_str(content, -1);
const gchar *uri = xmlnode_get_attrib(blob, "uri");
if (g_str_equal(sa->username, from)) {
from = skypeweb_contact_url_to_name(conversationLink);
}
if (from != NULL) {
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, sa->account);
if (conv == NULL)
{
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, sa->account, from);
}
skypeweb_download_uri_to_conv(sa, uri, conv);
}
xmlnode_free(blob);
} else if (g_str_equal(messagetype, "Event/SkypeVideoMessage")) {
xmlnode *blob = xmlnode_from_str(content, -1);
const gchar *sid = xmlnode_get_attrib(blob, "sid");
if (g_str_equal(sa->username, from)) {
from = skypeweb_contact_url_to_name(conversationLink);
}
if (from != NULL) {
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, sa->account);
if (conv == NULL)
{
conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, sa->account, from);
}
//skypeweb_download_video_message(sa, sid, conv); //TODO
serv_got_im(sa->pc, from, content, PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_SYSTEM, composetimestamp);
}
xmlnode_free(blob);
} else {
purple_debug_warning("skypeweb", "Unhandled message resource messagetype '%s'\n", messagetype);
}
}
if (clientmessageid && *clientmessageid) {
// Mark message as seen
const gchar *originalarrivaltime = json_object_get_string_member(resource, "originalarrivaltime");
time_t arrivaltimestamp = purple_str_to_time(originalarrivaltime, TRUE, NULL, NULL, NULL);
gchar *post, *url;
url = g_strdup_printf("/v1/users/ME/conversations/%s/properties?name=consumptionhorizon", purple_url_encode(convname));
post = g_strdup_printf("{\"consumptionhorizon\":\"%d000;%" G_GINT64_FORMAT ";%s\"}", arrivaltimestamp, skypeweb_get_js_time(), clientmessageid);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, url, post, NULL, NULL, TRUE);
g_free(post);
g_free(url);
g_free(convname);
}
g_strfreev(messagetype_parts);
if (composetimestamp > purple_account_get_int(sa->account, "last_message_timestamp", 0))
purple_account_set_int(sa->account, "last_message_timestamp", composetimestamp);
}
static void
process_conversation_resource(SkypeWebAccount *sa, JsonObject *resource)
{
const gchar *id = json_object_get_string_member(resource, "id");
JsonObject *threadProperties;
if (json_object_has_member(resource, "threadProperties")) {
threadProperties = json_object_get_object_member(resource, "threadProperties");
}
}
static void
process_thread_resource(SkypeWebAccount *sa, JsonObject *resource)
{
}
static void
process_endpointpresence_resource(SkypeWebAccount *sa, JsonObject *resource)
{
JsonObject *publicInfo = json_object_get_object_member(resource, "publicInfo");
if (publicInfo != NULL) {
const gchar *typ_str = json_object_get_string_member(publicInfo, "typ");
const gchar *skypeNameVersion = json_object_get_string_member(publicInfo, "skypeNameVersion");
if (typ_str && *typ_str) {
if (g_str_equal(typ_str, "website")) {
} else {
gint typ = atoi(typ_str);
switch(typ) {
case 17: //Android
break;
case 16: //iOS
break;
case 12: //WinRT/Metro
break;
case 15: //Winphone
break;
case 13: //OSX
break;
case 11: //Windows
break;
case 14: //Linux
break;
case 10: //XBox ? skypeNameVersion 11/1.8.0.1006
break;
default:
purple_debug_warning("skypeweb", "Unknown typ %d: %s\n", typ, skypeNameVersion);
break;
}
}
}
}
}
gboolean
skypeweb_timeout(gpointer userdata)
{
SkypeWebAccount *sa = userdata;
skypeweb_poll(sa);
// If no response within 3 minutes, assume connection lost and try again
purple_timeout_remove(sa->watchdog_timeout);
sa->watchdog_timeout = purple_timeout_add_seconds(3 * 60, skypeweb_timeout, sa);
return FALSE;
}
static void
skypeweb_poll_cb(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
{
JsonArray *messages = NULL;
gint index, length;
JsonObject *obj;
obj = json_node_get_object(node);
if (json_object_has_member(obj, "eventMessages"))
messages = json_object_get_array_member(obj, "eventMessages");
if (messages != NULL) {
length = json_array_get_length(messages);
for(index = length - 1; index >= 0; index--)
{
JsonObject *message = json_array_get_object_element(messages, index);
const gchar *resourceType = json_object_get_string_member(message, "resourceType");
JsonObject *resource = json_object_get_object_member(message, "resource");
if (g_str_equal(resourceType, "NewMessage"))
{
process_message_resource(sa, resource);
} else if (g_str_equal(resourceType, "UserPresence"))
{
process_userpresence_resource(sa, resource);
} else if (g_str_equal(resourceType, "EndpointPresence"))
{
process_endpointpresence_resource(sa, resource);
} else if (g_str_equal(resourceType, "ConversationUpdate"))
{
process_conversation_resource(sa, resource);
} else if (g_str_equal(resourceType, "ThreadUpdate"))
{
process_thread_resource(sa, resource);
}
}
} else if (json_object_has_member(obj, "errorCode")) {
gint64 errorCode = json_object_get_int_member(obj, "errorCode");
if (errorCode == 729) {
// "You must create an endpoint before performing this operation"
// Dammit, Jim; I'm a programmer, not a surgeon!
skypeweb_get_registration_token(sa);
return;
}
}
//TODO record id of highest recieved id to make sure we dont process the same id twice
sa->poll_timeout = purple_timeout_add_seconds(1, skypeweb_timeout, sa);
}
void
skypeweb_poll(SkypeWebAccount *sa)
{
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, "/v1/users/ME/endpoints/SELF/subscriptions/0/poll", NULL, skypeweb_poll_cb, NULL, TRUE);
}
static void
skypeweb_got_conv_history(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
{
time_t since = GPOINTER_TO_INT(user_data);
JsonObject *obj;
JsonArray *messages;
gint index, length;
obj = json_node_get_object(node);
messages = json_object_get_array_member(obj, "messages");
length = json_array_get_length(messages);
for(index = length - 1; index >= 0; index--)
{
JsonObject *message = json_array_get_object_element(messages, index);
const gchar *composetime = json_object_get_string_member(message, "composetime");
time_t composetimestamp = purple_str_to_time(composetime, TRUE, NULL, NULL, NULL);
if (composetimestamp > since) {
process_message_resource(sa, message);
}
}
}
void
skypeweb_get_conversation_history_since(SkypeWebAccount *sa, const gchar *convname, time_t since)
{
gchar *url;
url = g_strdup_printf("/v1/users/ME/conversations/%s/messages?startTime=%d000&pageSize=30&view=msnp24Equivalent&targetType=Passport|Skype|Lync|Thread", purple_url_encode(convname), since);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, url, NULL, skypeweb_got_conv_history, GINT_TO_POINTER(since), TRUE);
g_free(url);
}
void
skypeweb_get_conversation_history(SkypeWebAccount *sa, const gchar *convname)
{
skypeweb_get_conversation_history_since(sa, convname, 0);
}
static void
skypeweb_got_all_convs(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
{
time_t since = GPOINTER_TO_INT(user_data);
JsonObject *obj;
JsonArray *conversations;
gint index, length;
obj = json_node_get_object(node);
conversations = json_object_get_array_member(obj, "conversations");
length = json_array_get_length(conversations);
for(index = 0; index < length; index++) {
JsonObject *conversation = json_array_get_object_element(conversations, index);
const gchar *id = json_object_get_string_member(conversation, "id");
JsonObject *lastMessage = json_object_get_object_member(conversation, "lastMessage");
if (lastMessage != NULL) {
const gchar *composetime = json_object_get_string_member(lastMessage, "composetime");
time_t composetimestamp = purple_str_to_time(composetime, TRUE, NULL, NULL, NULL);
if (composetimestamp > since) {
skypeweb_get_conversation_history_since(sa, id, since);
}
}
}
}
void
skypeweb_get_all_conversations_since(SkypeWebAccount *sa, time_t since)
{
gchar *url;
url = g_strdup_printf("/v1/users/ME/conversations?startTime=%d000&pageSize=100&view=msnp24Equivalent&targetType=Passport|Skype|Lync|Thread", since);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, url, NULL, skypeweb_got_all_convs, GINT_TO_POINTER(since), TRUE);
g_free(url);
}
void
skype_web_get_offline_history(SkypeWebAccount *sa)
{
skypeweb_get_all_conversations_since(sa, purple_account_get_int(sa->account, "last_message_timestamp", time(NULL)));
}
void
skypeweb_subscribe_to_contact_status(SkypeWebAccount *sa, GSList *contacts)
{
const gchar *contacts_url = "/v1/users/ME/contacts";
gchar *post;
GSList *cur = contacts;
JsonObject *obj;
JsonArray *contacts_array;
guint count = 0;
if (contacts == NULL)
return;
obj = json_object_new();
contacts_array = json_array_new();
do {
JsonObject *contact = json_object_new();
gchar *id;
id = g_strconcat("8:", cur->data, NULL);
json_object_set_string_member(contact, "id", id);
json_array_add_object_element(contacts_array, contact);
g_free(id);
if (count++ >= 100) {
// Send off the current batch and continue
json_object_set_array_member(obj, "contacts", contacts_array);
post = skypeweb_jsonobj_to_string(obj);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, contacts_url, post, NULL, NULL, TRUE);
g_free(post);
json_object_unref(obj);
obj = json_object_new();
contacts_array = json_array_new();
count = 0;
}
} while((cur = g_slist_next(cur)));
json_object_set_array_member(obj, "contacts", contacts_array);
post = skypeweb_jsonobj_to_string(obj);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, contacts_url, post, NULL, NULL, TRUE);
g_free(post);
json_object_unref(obj);
}
static void
skypeweb_subscribe_cb(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
{
skypeweb_do_all_the_things(sa);
}
static void
skypeweb_subscribe(SkypeWebAccount *sa)
{
JsonObject *obj;
JsonArray *interested;
gchar *post;
interested = json_array_new();
json_array_add_string_element(interested, "/v1/users/ME/conversations/ALL/properties");
json_array_add_string_element(interested, "/v1/users/ME/conversations/ALL/messages");
json_array_add_string_element(interested, "/v1/users/ME/contacts/ALL");
json_array_add_string_element(interested, "/v1/threads/ALL");
obj = json_object_new();
json_object_set_array_member(obj, "interestedResources", interested);
json_object_set_string_member(obj, "template", "raw");
json_object_set_string_member(obj, "channelType", "httpLongPoll");
post = skypeweb_jsonobj_to_string(obj);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, "/v1/users/ME/endpoints/SELF/subscriptions", post, skypeweb_subscribe_cb, NULL, TRUE);
g_free(post);
json_object_unref(obj);
}
static void
skypeweb_got_registration_token(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
{
gchar *registration_token;
gchar *endpointId;
SkypeWebAccount *sa = user_data;
if (url_text == NULL) {
url_text = url_data->webdata;
len = url_data->data_len;
}
registration_token = skypeweb_string_get_chunk(url_text, len, "Set-RegistrationToken: ", ";");
endpointId = skypeweb_string_get_chunk(url_text, len, "endpointId=", "\r\n");
if (registration_token == NULL) {
purple_connection_error (sa->pc,
PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
_("Failed getting Registration Token"));
return;
}
//purple_debug_info("skypeweb", "New RegistrationToken is %s\n", registration_token);
sa->registration_token = registration_token;
sa->endpoint = endpointId;
skypeweb_subscribe(sa);
}
void
skypeweb_get_registration_token(SkypeWebAccount *sa)
{
const gchar *messages_url = "https://" SKYPEWEB_MESSAGES_HOST "/v1/users/ME/endpoints";
gchar *request;
gchar *curtime;
gchar *response;
PurpleUtilFetchUrlData *requestdata;
g_free(sa->registration_token); sa->registration_token = NULL;
g_free(sa->endpoint); sa->endpoint = NULL;
curtime = g_strdup_printf("%d", (int) time(NULL));
response = skypeweb_hmac_sha256(curtime);
request = g_strdup_printf("POST /v1/users/ME/endpoints HTTP/1.0\r\n"
"Connection: close\r\n"
"Accept: */*\r\n"
"BehaviorOverride: redirectAs404\r\n"
"LockAndKey: appId=" SKYPEWEB_LOCKANDKEY_APPID "; time=%s; lockAndKeyResponse=%s\r\n"
"ClientInfo: os=Windows; osVer=8.1; proc=Win32; lcid=en-us; deviceType=1; country=n/a; clientName=" SKYPEWEB_CLIENTINFO_NAME "; clientVer=" SKYPEWEB_CLIENTINFO_VERSION "\r\n"
"Host: " SKYPEWEB_MESSAGES_HOST "\r\n"
"Content-Type: application/json\r\n"
"Authentication: skypetoken=%s\r\n"
"Content-Length: 2\r\n\r\n{}",
curtime, response, sa->skype_token);
//purple_debug_info("skypeweb", "reg token request is %s\n", request);
requestdata = purple_util_fetch_url_request(sa->account, messages_url, TRUE, NULL, FALSE, request, TRUE, 524288, skypeweb_got_registration_token, sa);
requestdata->num_times_redirected = 10; /* Prevent following redirects */
g_free(request);
g_free(curtime);
g_free(response);
}
guint
skypeweb_send_typing(PurpleConnection *pc, const gchar *name, PurpleTypingState state)
{
SkypeWebAccount *sa = pc->proto_data;
gchar *post, *url;
JsonObject *obj;
url = g_strdup_printf("/v1/users/ME/conversations/8:%s/messages", purple_url_encode(name));
obj = json_object_new();
json_object_set_int_member(obj, "clientmessageid", time(NULL));
json_object_set_string_member(obj, "content", "");
json_object_set_string_member(obj, "messagetype", state == PURPLE_TYPING ? "Control/Typing" : "Control/ClearTyping");
json_object_set_string_member(obj, "contenttype", "text");
post = skypeweb_jsonobj_to_string(obj);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, url, post, NULL, NULL, TRUE);
g_free(post);
json_object_unref(obj);
g_free(url);
return 5;
}
static void
skypeweb_set_statusid(SkypeWebAccount *sa, const gchar *status)
{
gchar *post;
g_return_if_fail(status);
post = g_strdup_printf("{\"status\":\"%s\"}", status);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, "/v1/users/ME/presenceDocs/messagingService", post, NULL, NULL, TRUE);
g_free(post);
if (sa->endpoint) {
gchar *url = g_strdup_printf("/v1/users/ME/endpoints/%s/presenceDocs/messagingService", purple_url_encode(sa->endpoint));
post = "{\"id\":\"messagingService\", \"type\":\"EndpointPresenceDoc\", \"selfLink\":\"uri\", \"privateInfo\":{\"epname\":\"skype\"}, \"publicInfo\":{\"capabilities\":\"\", \"type\":1, \"typ\":1, \"skypeNameVersion\":\"" SKYPEWEB_CLIENTINFO_VERSION "/" SKYPEWEB_CLIENTINFO_NAME "\", \"nodeInfo\":\"xx\", \"version\":\"" SKYPEWEB_CLIENTINFO_VERSION "\"}}";
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, url, post, NULL, NULL, TRUE);
}
}
void
skypeweb_set_status(PurpleAccount *account, PurpleStatus *status)
{
PurpleConnection *pc = purple_account_get_connection(account);
SkypeWebAccount *sa = pc->proto_data;
skypeweb_set_statusid(sa, purple_status_get_id(status));
}
void
skypeweb_set_idle(PurpleConnection *pc, int time)
{
SkypeWebAccount *sa = pc->proto_data;
if (time < 30) {
skypeweb_set_statusid(sa, "Online");
} else {
skypeweb_set_statusid(sa, "Idle");
}
}
static void
skypeweb_send_message(SkypeWebAccount *sa, const gchar *convname, const gchar *message)
{
gchar *post, *url;
JsonObject *obj;
gint64 clientmessageid;
gchar *clientmessageid_str;
gchar *stripped;
url = g_strdup_printf("/v1/users/ME/conversations/%s/messages", purple_url_encode(convname));
clientmessageid = skypeweb_get_js_time();
clientmessageid_str = g_strdup_printf("%" G_GINT64_FORMAT "", clientmessageid);
// Some clients don't receive messages with
's in them
stripped = purple_strreplace(message, "
", "\r\n");
obj = json_object_new();
json_object_set_string_member(obj, "clientmessageid", clientmessageid_str);
json_object_set_string_member(obj, "content", message);
json_object_set_string_member(obj, "messagetype", "RichText");
json_object_set_string_member(obj, "contenttype", "text");
if (g_str_has_prefix(message, "/me ")) {
json_object_set_string_member(obj, "skypeemoteoffset", "4"); //Why is this a string :(
}
post = skypeweb_jsonobj_to_string(obj);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, url, post, NULL, NULL, TRUE);
g_free(post);
json_object_unref(obj);
g_free(url);
g_free(stripped);
g_hash_table_insert(sa->sent_messages_hash, clientmessageid_str, clientmessageid_str);
}
gint
skypeweb_chat_send(PurpleConnection *pc, gint id, const gchar *message, PurpleMessageFlags flags)
{
SkypeWebAccount *sa = pc->proto_data;
PurpleConversation *conv;
gchar* chatname;
conv = purple_find_chat(pc, id);
chatname = (gchar *)g_hash_table_lookup(conv->data, "chatname");
if (!chatname)
return -1;
skypeweb_send_message(sa, chatname, message);
serv_got_chat_in(pc, id, sa->username, PURPLE_MESSAGE_SEND, message, time(NULL));
return 1;
}
gint
skypeweb_send_im(PurpleConnection *pc, const gchar *who, const gchar *message, PurpleMessageFlags flags)
{
SkypeWebAccount *sa = pc->proto_data;
gchar *convname;
convname = g_strconcat("8:", who, NULL);
skypeweb_send_message(sa, convname, message);
g_free(convname);
return 1;
}
void
skypeweb_chat_invite(PurpleConnection *pc, int id, const char *message, const char *who)
{
SkypeWebAccount *sa = pc->proto_data;
PurpleConversation *conv;
gchar *chatname;
gchar *post;
GString *url;
conv = purple_find_chat(pc, id);
chatname = (gchar *)g_hash_table_lookup(conv->data, "chatname");
url = g_string_new("/v1/threads/");
g_string_append_printf(url, "%s", purple_url_encode(chatname));
g_string_append(url, "/members/");
g_string_append_printf(url, "8:%s", purple_url_encode(who));
post = "{\"role\":\"User\"}";
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, url->str, post, NULL, NULL, TRUE);
g_string_free(url, TRUE);
}
void
skypeweb_initiate_chat(SkypeWebAccount *sa, const gchar *who)
{
JsonObject *obj, *contact;
JsonArray *members;
gchar *id, *post;
obj = json_object_new();
members = json_array_new();
contact = json_object_new();
id = g_strconcat("8:", who, NULL);
json_object_set_string_member(contact, "id", id);
json_object_set_string_member(contact, "role", "User");
json_array_add_object_element(members, contact);
g_free(id);
contact = json_object_new();
id = g_strconcat("8:", sa->username, NULL);
json_object_set_string_member(contact, "id", id);
json_object_set_string_member(contact, "role", "Admin");
json_array_add_object_element(members, contact);
g_free(id);
json_object_set_array_member(obj, "members", members);
post = skypeweb_jsonobj_to_string(obj);
skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_MESSAGES_HOST, "/v1/threads", post, NULL, NULL, TRUE);
g_free(post);
json_object_unref(obj);
}
void
skypeweb_initiate_chat_from_node(PurpleBlistNode *node, gpointer userdata)
{
if(PURPLE_BLIST_NODE_IS_BUDDY(node))
{
PurpleBuddy *buddy = (PurpleBuddy *) node;
SkypeWebAccount *sa;
if (userdata) {
sa = userdata;
} else {
PurpleConnection *pc = purple_account_get_connection(buddy->account);
sa = pc->proto_data;
}
skypeweb_initiate_chat(sa, buddy->name);
}
}