telegram-purple/tgp-2prpl.c

440 lines
13 KiB
C
Raw Permalink Normal View History

2014-11-16 20:41:03 +01:00
/*
This file is part of telegram-purple
2014-11-16 20:41:03 +01:00
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
Copyright Matthias Jentsch 2014
*/
#include "telegram-purple.h"
#include "tgp-2prpl.h"
#include "tgp-structs.h"
2015-01-21 23:49:42 +01:00
#include "telegram-purple.h"
#include "tgp-utils.h"
#include "telegram-base.h"
#include <server.h>
#include <tgl.h>
2014-11-16 17:56:55 +01:00
#include <msglog.h>
2014-11-17 16:27:01 +03:00
#include <assert.h>
PurpleAccount *tg_get_acc (struct tgl_state *TLS) {
return (PurpleAccount *) ((connection_data *)TLS->ev_base)->pa;
}
PurpleConnection *tg_get_conn (struct tgl_state *TLS) {
return (PurpleConnection *) ((connection_data *)TLS->ev_base)->gc;
}
2015-03-13 18:40:28 +01:00
char *p2tgl_strdup_id (tgl_peer_id_t user) {
2014-11-16 17:56:55 +01:00
return g_strdup_printf("%d", tgl_get_peer_id(user));
}
gchar *p2tgl_strdup_alias (tgl_peer_t *user) {
return g_strdup (user->print_name);
}
int p2tgl_status_is_present (PurpleStatus *status)
{
const char *name = purple_status_get_id (status);
return !(strcmp (name, "unavailable") == 0 || strcmp (name, "away") == 0);
}
2015-02-23 19:42:48 +01:00
/*
Disclaimer: I stole this function from davidgfnet's whatsapp plugin, all
credit for it goes to him
@see: https://github.com/davidgfnet/whatsapp-purple
*/
2015-01-25 22:49:46 +01:00
static PurpleChat *blist_find_chat_by_hasht_cond (PurpleConnection *gc,
2014-11-16 17:56:55 +01:00
int (*fn)(GHashTable *hasht, void *data), void *data) {
PurpleAccount *account = purple_connection_get_account(gc);
PurpleBlistNode *node = purple_blist_get_root();
GHashTable *hasht;
while (node) {
if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
PurpleChat *ch = PURPLE_CHAT(node);
if (purple_chat_get_account(ch) == account) {
hasht = purple_chat_get_components(ch);
if (fn(hasht, data))
return ch;
}
}
2014-11-16 17:56:55 +01:00
node = purple_blist_node_next(node, 0);
}
return NULL;
}
static int hasht_cmp_id(GHashTable *hasht, void *data) {
gpointer id = g_hash_table_lookup(hasht, "id");
if (!id || !data) {
return 0;
}
return !strcmp(id, ((char *)data));
}
PurpleConversation *p2tgl_got_joined_chat (struct tgl_state *TLS, struct tgl_chat *chat) {
connection_data *conn = TLS->ev_base;
gchar *alias = p2tgl_strdup_alias ((tgl_peer_t *)chat);
2014-11-16 17:56:55 +01:00
PurpleConversation *conv = serv_got_joined_chat (conn->gc, tgl_get_peer_id(chat->id), alias);
2014-11-16 17:56:55 +01:00
g_free(alias);
return conv;
}
void p2tgl_got_chat_left (struct tgl_state *TLS, tgl_peer_id_t chat) {
2014-11-16 17:56:55 +01:00
serv_got_chat_left(tg_get_conn(TLS), tgl_get_peer_id(chat));
}
2015-03-12 01:47:57 +01:00
void p2tgl_got_chat_in (struct tgl_state *TLS, tgl_peer_id_t chat, tgl_peer_id_t who,
const char *message, int flags, time_t when) {
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id (who);
2014-11-16 17:56:55 +01:00
serv_got_chat_in (tg_get_conn(TLS), tgl_get_peer_id (chat), name, flags, message, when);
2014-11-16 17:56:55 +01:00
g_free (name);
}
void p2tgl_got_alias (struct tgl_state *TLS, tgl_peer_id_t who, const char *alias) {
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id(who);
2014-11-16 17:56:55 +01:00
serv_got_alias(tg_get_conn(TLS), name, alias);
g_free (name);
}
void p2tgl_got_im (struct tgl_state *TLS, tgl_peer_id_t who, const char *msg, int flags, time_t when) {
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id(who);
2014-11-16 17:56:55 +01:00
serv_got_im(tg_get_conn(TLS), name, msg,flags, when);
g_free (name);
}
2015-03-21 00:56:32 +01:00
void p2tgl_conversation_write (PurpleConversation *conv, tgl_peer_id_t who, const char *message, int flags, int date) {
char *name = p2tgl_strdup_id (who);
purple_conversation_write (conv, name, message, flags, date);
g_free (name);
}
void p2tgl_conv_im_write (PurpleConversation *conv, tgl_peer_id_t who, const char *message, int flags, int date) {
char *name = p2tgl_strdup_id (who);
purple_conv_im_write(purple_conversation_get_im_data(conv), name, message, flags, date);
g_free (name);
}
void p2tgl_got_im_combo (struct tgl_state *TLS, tgl_peer_id_t who, const char *msg, int flags, time_t when) {
/*
Outgoing messages are not well supported in different libpurple clients,
p2tgl_conv_im_write should have the best among different versions. Unfortunately
this causes buggy formatting in Adium, so we don't use this workaround in that case.
NOTE: Outgoing messages will not work in Adium <= 1.6.0, there is no way to print outgoing
messages in those versions at all.
*/
#ifndef __ADIUM_
if (flags & PURPLE_MESSAGE_SEND) {
PurpleConversation *conv = p2tgl_find_conversation_with_account (TLS, who);
if (!conv) {
conv = p2tgl_conversation_new(TLS, who);
}
p2tgl_conv_im_write (conv, who, msg, PURPLE_MESSAGE_SEND, when);
return;
}
#endif
p2tgl_got_im (TLS, who, msg, flags, when);
}
void p2tgl_got_typing (struct tgl_state *TLS, tgl_peer_id_t user, int timeout) {
2014-11-16 17:56:55 +01:00
char *who = g_strdup_printf("%d", tgl_get_peer_id(user));
serv_got_typing(tg_get_conn(TLS), who, timeout, PURPLE_TYPING);
g_free(who);
}
PurpleBuddy *p2tgl_buddy_find (struct tgl_state *TLS, tgl_peer_id_t user) {
2015-03-13 18:40:28 +01:00
gchar *name = p2tgl_strdup_id(user);
2014-11-16 17:56:55 +01:00
PurpleBuddy *b = purple_find_buddy (tg_get_acc(TLS), name);
g_free (name);
return b;
}
PurpleConversation *p2tgl_find_conversation_with_account (struct tgl_state *TLS, tgl_peer_id_t peer) {
int type = PURPLE_CONV_TYPE_IM;
if (tgl_get_peer_type (peer) == TGL_PEER_CHAT) {
type = PURPLE_CONV_TYPE_CHAT;
}
char *who = g_strdup_printf("%d", tgl_get_peer_id(peer));
PurpleConversation *conv = purple_find_conversation_with_account (type, who, tg_get_acc(TLS));
g_free (who);
return conv;
}
PurpleConversation *p2tgl_conversation_new (struct tgl_state *TLS, tgl_peer_id_t who) {
int type = tgl_get_peer_type (who) == TGL_PEER_CHAT ? PURPLE_CONV_TYPE_CHAT : PURPLE_CONV_TYPE_IM;
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id (who);
PurpleConversation *conv = purple_conversation_new(type, tg_get_acc(TLS), name);
g_free (name);
return conv;
}
PurpleBuddy *p2tgl_buddy_new (struct tgl_state *TLS, tgl_peer_t *user) {
2014-11-16 17:56:55 +01:00
char *alias = p2tgl_strdup_alias (user);
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id (user->id);
2014-11-16 17:56:55 +01:00
PurpleBuddy *b = purple_buddy_new (tg_get_acc(TLS), name, alias);
2014-11-16 17:56:55 +01:00
g_free (alias);
g_free (name);
return b;
}
2014-11-17 16:27:01 +03:00
PurpleBuddy *p2tgl_buddy_update (struct tgl_state *TLS, tgl_peer_t *user, unsigned flags) {
PurpleBuddy *b = p2tgl_buddy_find (TLS, user->id);
if (!b) {
b = p2tgl_buddy_new (TLS, user);
}
if (flags & (TGL_UPDATE_NAME | TGL_UPDATE_REAL_NAME | TGL_UPDATE_USERNAME)) {
2015-01-30 00:43:40 +01:00
debug ("Update username for id%d (name %s %s)", tgl_get_peer_id (user->id), user->user.first_name, user->user.last_name);
2014-11-17 16:27:01 +03:00
char *alias = p2tgl_strdup_alias (user);
purple_blist_alias_buddy(b, alias);
g_free (alias);
}
return b;
}
void p2tgl_prpl_got_set_status_mobile (struct tgl_state *TLS, tgl_peer_id_t user) {
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id (user);
purple_prpl_got_user_status (tg_get_acc(TLS), name, "mobile", NULL);
g_free (name);
}
2015-01-07 16:54:35 +01:00
void p2tgl_prpl_got_set_status_offline (struct tgl_state *TLS, tgl_peer_id_t user) {
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id (user);
2015-01-07 16:54:35 +01:00
purple_prpl_got_user_status (tg_get_acc(TLS), name, "offline", NULL);
g_free (name);
}
void p2tgl_prpl_got_set_status_online (struct tgl_state *TLS, tgl_peer_id_t user) {
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id (user);
purple_prpl_got_user_status (tg_get_acc(TLS), name, "available", NULL);
g_free (name);
}
void p2tgl_prpl_got_user_status (struct tgl_state *TLS, tgl_peer_id_t user, struct tgl_user_status *status) {
connection_data *data = TLS->ev_base;
2014-11-17 16:27:01 +03:00
if (status->online == 1) {
p2tgl_prpl_got_set_status_online (TLS, user);
2014-11-17 16:27:01 +03:00
} else {
debug ("%d: when=%d", user.id, status->when);
if (tgp_time_n_days_ago (purple_account_get_int (data->pa, "inactive-days-offline", TGP_DEFAULT_INACTIVE_DAYS_OFFLINE)) > status->when && status->when) {
debug ("offline");
p2tgl_prpl_got_set_status_offline (TLS, user);
}
else {
debug ("mobile");
p2tgl_prpl_got_set_status_mobile (TLS, user);
}
2014-11-17 16:27:01 +03:00
}
}
PurpleChat *p2tgl_blist_find_chat(struct tgl_state *TLS, tgl_peer_id_t chat) {
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id(chat);
2014-11-16 17:56:55 +01:00
PurpleChat *c = purple_blist_find_chat(tg_get_acc(TLS), name);
g_free (name);
return c;
}
PurpleChat *p2tgl_chat_new (struct tgl_state *TLS, struct tgl_chat *chat) {
2014-11-16 17:56:55 +01:00
gchar *admin = g_strdup_printf("%d", chat->admin_id);
gchar *title = g_strdup(chat->print_title);
2015-03-13 18:40:28 +01:00
gchar *name = p2tgl_strdup_id (chat->id);
2014-11-16 17:56:55 +01:00
GHashTable *ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
g_hash_table_insert(ht, g_strdup("subject"), title);
g_hash_table_insert(ht, g_strdup("id"), name);
g_hash_table_insert(ht, g_strdup("owner"), admin);
2015-02-23 19:42:48 +01:00
PurpleChat *C = purple_chat_new(tg_get_acc(TLS), chat->title, ht);
return C;
}
PurpleChat *p2tgl_chat_find (struct tgl_state *TLS, tgl_peer_id_t id) {
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id(id);
PurpleChat *c = blist_find_chat_by_hasht_cond(tg_get_conn(TLS), hasht_cmp_id, name);
2014-11-16 17:56:55 +01:00
g_free(name);
return c;
}
void p2tgl_conv_add_user (PurpleConversation *conv, struct tgl_chat_user user, char *message, int flags, int new_arrival) {
2014-11-16 17:56:55 +01:00
PurpleConvChat *cdata = purple_conversation_get_chat_data(conv);
char *name = g_strdup_printf("%d", user.user_id);
purple_conv_chat_add_user(cdata, name, message, flags, new_arrival);
g_free(name);
}
void p2tgl_connection_set_display_name(struct tgl_state *TLS, tgl_peer_t *user) {
2014-11-16 17:56:55 +01:00
char *name = p2tgl_strdup_alias(user);
purple_connection_set_display_name(tg_get_conn(TLS), name);
g_free(name);
}
void *p2tgl_notify_userinfo(struct tgl_state *TLS, tgl_peer_id_t user, PurpleNotifyUserInfo *user_info, PurpleNotifyCloseCallback cb, gpointer user_data) {
2015-03-13 18:40:28 +01:00
char *name = p2tgl_strdup_id(user);
2014-11-16 17:56:55 +01:00
void *handle = 0;
handle = purple_notify_userinfo(tg_get_conn(TLS), name, user_info, cb, user_data);
g_free(name);
2015-01-23 20:47:23 +01:00
g_free(user_info);
2014-11-16 17:56:55 +01:00
return handle;
}
void p2tgl_blist_alias_buddy (PurpleBuddy *buddy, struct tgl_user *user) {
char *name = p2tgl_strdup_alias ((tgl_peer_t *) user);
purple_blist_alias_buddy (buddy, name);
g_free(name);
}
2015-01-21 23:49:42 +01:00
PurpleNotifyUserInfo *p2tgl_notify_user_info_new (struct tgl_user *U) {
PurpleNotifyUserInfo *info = purple_notify_user_info_new();
if (str_not_empty(U->first_name) && str_not_empty(U->last_name)) {
purple_notify_user_info_add_pair (info, "First name", U->first_name);
purple_notify_user_info_add_pair (info, "Last name", U->last_name);
} else {
purple_notify_user_info_add_pair (info, "Name", U->print_name);
}
if (str_not_empty (U->username)) {
purple_notify_user_info_add_pair (info, "Username", U->username);
}
char *status = tgp_format_user_status (&U->status);
2015-01-21 23:49:42 +01:00
purple_notify_user_info_add_pair (info, "Last seen", status);
g_free (status);
if (str_not_empty (U->phone)) {
char *phone = g_strdup_printf("+%s", U->phone);
purple_notify_user_info_add_pair (info, "Phone", phone);
g_free (phone);
}
return info;
}
PurpleNotifyUserInfo *p2tgl_notify_encrypted_chat_info_new (struct tgl_state *TLS,
struct tgl_secret_chat *secret, struct tgl_user *U) {
PurpleNotifyUserInfo *info = p2tgl_notify_user_info_new (U);
if (secret->state == sc_waiting) {
purple_notify_user_info_add_pair (info, "", "Waiting for user to get online ...");
return info;
}
const char *ttl_key = "Self destructiom timer";
if (secret->ttl) {
char *ttl = g_strdup_printf ("%d", secret->ttl);
purple_notify_user_info_add_pair (info, ttl_key, ttl);
g_free (ttl);
} else {
purple_notify_user_info_add_pair (info, ttl_key, "Off");
}
if (secret->first_key_sha[0]) {
int sha1key_store_id = generate_ident_icon (TLS, secret->first_key_sha);
if (sha1key_store_id != -1) {
char *ident_icon = format_img_full (sha1key_store_id);
purple_notify_user_info_add_pair (info, "Secret key", ident_icon);
g_free(ident_icon);
}
}
return info;
}
PurpleNotifyUserInfo *p2tgl_notify_peer_info_new (struct tgl_state *TLS, tgl_peer_t *P) {
switch (tgl_get_peer_type (P->id)) {
case TGL_PEER_ENCR_CHAT: {
struct tgl_secret_chat *chat = &P->encr_chat;
tgl_peer_t *partner = tgp_encr_chat_get_partner (TLS, chat);
return p2tgl_notify_encrypted_chat_info_new (TLS, chat, &partner->user);
break;
}
case TGL_PEER_USER:
return p2tgl_notify_user_info_new (&P->user);
break;
default:
return purple_notify_user_info_new ();
}
}
int p2tgl_imgstore_add_with_id (const char* filename) {
2015-01-21 23:49:42 +01:00
gchar *data = NULL;
size_t len;
GError *err = NULL;
g_file_get_contents (filename, &data, &len, &err);
int id = purple_imgstore_add_with_id (data, len, NULL);
return id;
}
void p2tgl_buddy_icons_set_for_user (PurpleAccount *pa, tgl_peer_id_t *id, const char* filename) {
2015-01-21 23:49:42 +01:00
char *who = g_strdup_printf("%d", tgl_get_peer_id(*id));
gchar *data = NULL;
size_t len;
GError *err = NULL;
g_file_get_contents (filename, &data, &len, &err);
purple_buddy_icons_set_for_user (pa, who, data, len, NULL);
g_free (who);
}