Overhaul username handling

Use print names instead of ids as usernames, to fix problems with "useless" user ids showing up for unknown users and in group chats. Remove workarounds like "Telegram Foreign" needed to temporarily store user names for alias resolution.
This commit is contained in:
mjentsch 2015-10-11 14:17:24 +02:00
parent 7f3cf7c58f
commit 4eeb7f73c9
15 changed files with 416 additions and 482 deletions

View file

@ -18,7 +18,7 @@ OBJ=objs
LIB=libs
DIR_LIST=${DEP} ${EXE} ${OBJ} ${LIB} ${DEP}/lodepng ${OBJ}/lodepng
PLUGIN_OBJECTS=${OBJ}/tgp-net.o ${OBJ}/tgp-timers.o ${OBJ}/msglog.o ${OBJ}/telegram-base.o ${OBJ}/telegram-purple.o ${OBJ}/tgp-2prpl.o ${OBJ}/tgp-structs.o ${OBJ}/tgp-utils.o ${OBJ}/tgp-chat.o ${OBJ}/tgp-ft.o ${OBJ}/tgp-msg.o ${OBJ}/tgp-request.o ${OBJ}/lodepng/lodepng.o
PLUGIN_OBJECTS=${OBJ}/tgp-net.o ${OBJ}/tgp-timers.o ${OBJ}/msglog.o ${OBJ}/telegram-base.o ${OBJ}/telegram-purple.o ${OBJ}/tgp-2prpl.o ${OBJ}/tgp-structs.o ${OBJ}/tgp-utils.o ${OBJ}/tgp-chat.o ${OBJ}/tgp-ft.o ${OBJ}/tgp-msg.o ${OBJ}/tgp-request.o ${OBJ}/tgp-blist.o ${OBJ}/lodepng/lodepng.o
ALL_OBJS=${PLUGIN_OBJECTS}
LOCALES=$(patsubst %.po, %.mo, $(wildcard po/*.po))

View file

@ -56,7 +56,6 @@
#include "msglog.h"
#include "telegram-base.h"
#include "tgp-structs.h"
#include "tgp-2prpl.h"
#include "tgp-net.h"
#include "tgp-timers.h"
@ -65,6 +64,7 @@
#include "tgp-ft.h"
#include "tgp-msg.h"
#include "tgp-request.h"
#include "tgp-blist.h"
static void get_password (struct tgl_state *TLS, enum tgl_value_type type, const char *prompt, int num_values,
void (*callback)(struct tgl_state *TLS, const char *string[], void *arg), void *arg);
@ -97,15 +97,15 @@ struct tgl_update_callback tgp_callback = {
};
static void _update_buddy (struct tgl_state *TLS, tgl_peer_t *user, unsigned flags) {
PurpleBuddy *buddy = p2tgl_buddy_find (TLS, user->id);
PurpleBuddy *buddy = tgp_blist_buddy_find (TLS, user->id);
if (buddy) {
if (flags & TGL_UPDATE_DELETED) {
purple_blist_remove_buddy (buddy);
} else {
if (flags & (TGL_UPDATE_NAME | TGL_UPDATE_REAL_NAME | TGL_UPDATE_USERNAME)) {
char *alias = p2tgl_strdup_alias (user);
purple_blist_alias_buddy (buddy, alias);
g_free (alias);
// TODO: test this, renaming MUST NOT fail
purple_blist_rename_buddy (buddy, tgp_blist_peer_get_name (TLS, user->id));
}
if (flags & TGL_UPDATE_PHOTO) {
tgl_do_get_user_info (TLS, user->id, 0, on_user_get_info, get_user_info_data_new (0, user->id));
@ -115,8 +115,15 @@ static void _update_buddy (struct tgl_state *TLS, tgl_peer_t *user, unsigned fla
}
static void update_user_handler (struct tgl_state *TLS, struct tgl_user *user, unsigned flags) {
debug ("update_user_handler(id=%d, print_name=%s)", user->id.peer_id, user->print_name);
if (flags & TGL_UPDATE_CREATED) {
tgp_blist_peer_add (TLS, (tgl_peer_t *)user);
}
// set own name
if (tgl_get_peer_id (TLS->our_id) == tgl_get_peer_id (user->id) && flags & TGL_UPDATE_NAME) {
p2tgl_connection_set_display_name (TLS, (tgl_peer_t *)user);
purple_connection_set_display_name (tg_get_conn (TLS), user->print_name);
return;
}
@ -124,14 +131,31 @@ static void update_user_handler (struct tgl_state *TLS, struct tgl_user *user, u
// buddy was altered, update it
_update_buddy (TLS, (tgl_peer_t *)user, flags);
} else {
// new buddy was fetched, just update the status for all buddies in the contact list
if (p2tgl_buddy_find (TLS, user->id)) {
PurpleBuddy *buddy = tgp_blist_buddy_find (TLS, user->id);
// migrate buddies that are still stored in the old naming scheme
if (! buddy) {
char *id = g_strdup_printf ("%d", tgl_get_peer_id (user->id));
buddy = purple_find_buddy (tg_get_acc (TLS), id);
if (buddy) {
/*
purple_blist_rename_buddy (buddy, user->print_name);
tgp_blist_buddy_set_id (buddy, user->id);
*/
tgp_blist_buddy_update_name (TLS, buddy, user);
}
g_free (id);
}
// user that is also in buddy list created, initialize the buddy by upating the user status
if (buddy) {
p2tgl_prpl_got_user_status (TLS, user->id, &user->status);
}
}
}
static void update_message_handler (struct tgl_state *TLS, struct tgl_message *M) {
debug ("update_message_handler(id=%d)", M->permanent_id.id);
write_files_schedule (TLS);
tgp_msg_recv (TLS, M);
}
@ -141,16 +165,21 @@ static void update_user_status_handler (struct tgl_state *TLS, struct tgl_user *
}
static void update_secret_chat_handler (struct tgl_state *TLS, struct tgl_secret_chat *U, unsigned flags) {
PurpleBuddy *buddy = p2tgl_buddy_find (TLS, U->id);
PurpleBuddy *buddy = tgp_blist_buddy_find (TLS, U->id);
connection_data *conn = TLS->ev_base;
debug ("update_secret_chat_handler: state=%d", U->state);
if (flags & TGL_UPDATE_CREATED) {
tgp_blist_peer_add (TLS, (tgl_peer_t *)U);
}
if (!(flags & TGL_UPDATE_DELETED)) {
if (! buddy) {
buddy = p2tgl_buddy_new (TLS, (tgl_peer_t *)U);
purple_blist_add_buddy (buddy, NULL, tggroup, NULL);
buddy = tgp_blist_buddy_new (TLS, (tgl_peer_t *)U);
purple_blist_add_buddy (buddy, NULL, tgp_blist_group_init ("Telegram"), NULL);
purple_blist_alias_buddy (buddy, U->print_name);
}
p2tgl_prpl_got_set_status_mobile (TLS, U->id);
purple_prpl_got_user_status (tg_get_acc (TLS), tgp_blist_peer_get_name (TLS, U->id), "mobile", NULL);
}
if (flags & TGL_UPDATE_WORKING || flags & TGL_UPDATE_DELETED) {
@ -158,7 +187,6 @@ static void update_secret_chat_handler (struct tgl_state *TLS, struct tgl_secret
}
if (flags & TGL_UPDATE_REQUESTED) {
connection_data *conn = TLS->ev_base;
const char* choice = purple_account_get_string (conn->pa, "accept-secret-chats", "ask");
if (! strcmp (choice, "always")) {
tgl_do_accept_encr_chat_request (TLS, U, write_secret_chat_gw, 0);
@ -169,8 +197,11 @@ static void update_secret_chat_handler (struct tgl_state *TLS, struct tgl_secret
if (!(flags & TGL_UPDATE_CREATED) && buddy) {
if (flags & TGL_UPDATE_DELETED) {
p2tgl_got_im (TLS, U->id, _("Secret chat terminated."), PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_WHISPER, time (0));
p2tgl_prpl_got_set_status_offline (TLS, U->id);
// TODO: Broken in Adium, message not displayed as system message
serv_got_im (conn->gc, tgp_blist_peer_get_name (TLS, U->id), _("Secret chat terminated."),
PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_WHISPER, time (0));
purple_prpl_got_user_status (tg_get_acc (TLS), tgp_blist_peer_get_name (TLS, U->id), "offline", NULL);
} else {
_update_buddy (TLS, (tgl_peer_t *)U, flags);
}
@ -178,8 +209,12 @@ static void update_secret_chat_handler (struct tgl_state *TLS, struct tgl_secret
}
static void update_chat_handler (struct tgl_state *TLS, struct tgl_chat *chat, unsigned flags) {
if (flags & TGL_UPDATE_CREATED) {
tgp_blist_peer_add (TLS, (tgl_peer_t *)chat);
}
if (! (flags & TGL_UPDATE_CREATED)) {
PurpleChat *ch = p2tgl_chat_find (TLS, chat->id);
PurpleChat *ch = tgp_blist_chat_find (TLS, chat->id);
if (flags & TGL_UPDATE_TITLE && ch) {
purple_blist_alias_chat (ch, chat->print_title);
@ -192,7 +227,7 @@ static void update_chat_handler (struct tgl_state *TLS, struct tgl_chat *chat, u
static void update_user_typing (struct tgl_state *TLS, struct tgl_user *U, enum tgl_typing_status status) {
if (status == tgl_typing_typing) {
p2tgl_got_typing (TLS, U->id, 2);
serv_got_typing (tg_get_conn(TLS), tgp_blist_peer_get_name (TLS, U->id), 2, PURPLE_TYPING);
}
}
@ -300,13 +335,12 @@ static void on_userpic_loaded (struct tgl_state *TLS, void *extra, int success,
if (imgStoreId > 0) {
used_images_add (conn, imgStoreId);
p2tgl_buddy_icons_set_for_user (conn->pa, &P->id, filename);
p2tgl_buddy_icons_set_for_user (conn->pa, P->id, filename);
if (dld->get_user_info_data->show_info == 1) {
PurpleNotifyUserInfo *info = p2tgl_notify_peer_info_new (TLS, P);
p2tgl_notify_userinfo (TLS, P->id, info, NULL, NULL);
purple_notify_userinfo (tg_get_conn (TLS), tgp_blist_peer_get_name (TLS, P->id),
p2tgl_notify_peer_info_new (TLS, P), NULL, NULL);
}
}
free (dld->get_user_info_data);
free (dld);
}
@ -324,15 +358,15 @@ static void on_get_dialog_list_done (struct tgl_state *TLS, void *callback_extra
case TGL_PEER_USER:
assert (UC);
if (tgl_get_peer_id (UC->id) == tgl_get_peer_id (TLS->our_id)) {
p2tgl_connection_set_display_name (TLS, UC);
purple_connection_set_display_name (tg_get_conn (TLS), UC->print_name);
continue;
}
if (! (UC->user.flags & TGLUF_DELETED)) {
PurpleBuddy *buddy = p2tgl_buddy_find (TLS, UC->id);
PurpleBuddy *buddy = tgp_blist_buddy_find (TLS, UC->id);
if (! buddy) {
buddy = p2tgl_buddy_new (TLS, UC);
purple_blist_add_buddy (buddy, NULL, tggroup, NULL);
buddy = tgp_blist_buddy_new (TLS, UC);
purple_blist_add_buddy (buddy, NULL, tgp_blist_group_init ("Telegram"), NULL);
if (UC->user.photo_id) {
debug ("tgl_do_get_user_info(%s)", UC->print_name);
@ -347,7 +381,7 @@ static void on_get_dialog_list_done (struct tgl_state *TLS, void *callback_extra
case TGL_PEER_CHAT:
assert (UC);
if (UC->chat.users_num > 0 && purple_account_get_bool (conn->pa, TGP_KEY_JOIN_GROUP_CHATS, TGP_DEFAULT_JOIN_GROUP_CHATS)) {
PurpleChat *PC = p2tgl_chat_find (TLS, UC->id);
PurpleChat *PC = tgp_blist_chat_find (TLS, UC->id);
if (!PC) {
PC = p2tgl_chat_new (TLS, &UC->chat);
purple_blist_add_chat (PC, NULL, NULL);
@ -370,8 +404,7 @@ void on_user_get_info (struct tgl_state *TLS, void *info_data, int success, stru
if (!U->photo || U->photo->sizes_num == 0) {
// No profile pic to load, display it right away
if (user_info_data->show_info) {
PurpleNotifyUserInfo *info = p2tgl_notify_peer_info_new (TLS, P);
p2tgl_notify_userinfo (TLS, P->id, info, NULL, NULL);
purple_notify_userinfo (tg_get_conn (TLS), tgp_blist_peer_get_name (TLS, P->id), p2tgl_notify_peer_info_new (TLS, P), NULL, NULL);
}
g_free (user_info_data);
} else {
@ -410,9 +443,9 @@ static void tgprpl_tooltip_text (PurpleBuddy *buddy, PurpleNotifyUserInfo *info,
debug ("tgprpl_tooltip_text()");
assert (buddy->name);
tgl_peer_t *P = find_peer_by_name (get_conn_from_buddy (buddy)->TLS, buddy->name);
tgl_peer_t *P = tgl_peer_get_by_name (pbn_get_conn (&buddy->node)->TLS, buddy->name);
if (!P) {
warning ("Peer %s not found in tree.", buddy->name);
failure ("Peer %s not found in tree.", buddy->name);
return;
}
gchar *status = tgp_format_user_status (&P->user.status);
@ -458,10 +491,13 @@ static void create_secret_chat_done (struct tgl_state *TLS, void *callback_extra
static void start_secret_chat (PurpleBlistNode *node, gpointer data) {
PurpleBuddy *buddy = data;
connection_data *conn = get_conn_from_buddy (buddy);
const char *name = purple_buddy_get_name (buddy);
tgl_do_create_secret_chat (conn->TLS, TGL_MK_USER(atoi (name)), create_secret_chat_done, 0);
tgl_peer_t *P = tgl_peer_get_by_name (pbn_get_conn (node)->TLS, purple_buddy_get_name (buddy));
if (P) {
tgl_do_create_secret_chat (pbn_get_conn (node)->TLS, P->id, create_secret_chat_done, NULL);
return;
}
failure ("Peer \"%s\" not found, not creating secret chat.", purple_buddy_get_name (buddy));
}
static void create_chat_link_done (struct tgl_state *TLS, void *extra, int success, const char *url) {
@ -473,8 +509,7 @@ static void create_chat_link_done (struct tgl_state *TLS, void *extra, int succe
tgp_chat_show (TLS, &C->chat);
char *msg = g_strdup_printf (_("Invite link: %s"), url);
serv_got_chat_in (conn->gc, tgl_get_peer_id(C->id), "WebPage", PURPLE_MESSAGE_SYSTEM,
msg, time(NULL));
serv_got_chat_in (conn->gc, tgl_get_peer_id (C->id), "WebPage", PURPLE_MESSAGE_SYSTEM, msg, time(NULL));
g_free (msg);
} else {
tgp_notify_on_error_gw (TLS, NULL, success);
@ -483,9 +518,7 @@ static void create_chat_link_done (struct tgl_state *TLS, void *extra, int succe
static void create_chat_link (PurpleBlistNode *node, gpointer data) {
PurpleChat *chat = (PurpleChat*)node;
connection_data *conn = purple_connection_get_protocol_data (
purple_account_get_connection (purple_chat_get_account (chat)));
export_chat_link_checked (conn->TLS, purple_chat_get_name (chat));
export_chat_link_checked (pbn_get_conn (node)->TLS, purple_chat_get_name (chat));
}
void export_chat_link_checked (struct tgl_state *TLS, const char *name) {
@ -504,16 +537,12 @@ void export_chat_link_checked (struct tgl_state *TLS, const char *name) {
void leave_and_delete_chat (PurpleBlistNode *node, gpointer data) {
PurpleChat *PC = (PurpleChat*)node;
connection_data *conn = purple_connection_get_protocol_data (
purple_account_get_connection (purple_chat_get_account (PC)));
tgl_peer_t *P = tgl_peer_get (conn->TLS, p2tgl_chat_get_id (PC));
tgl_peer_t *P = tgl_peer_get (pbn_get_conn (node)->TLS, p2tgl_chat_get_id (PC));
if (P && P->chat.users_num) {
tgl_do_del_user_from_chat (conn->TLS, P->id, conn->TLS->our_id,
tgp_notify_on_error_gw, NULL);
serv_got_chat_left (conn->gc, tgl_get_peer_id (P->id));
tgl_do_del_user_from_chat (pbn_get_conn (node)->TLS, P->id, pbn_get_conn (node)->TLS->our_id, tgp_notify_on_error_gw, NULL);
serv_got_chat_left (pbn_get_conn (node)->gc, tgl_get_peer_id (P->id));
}
purple_blist_remove_chat (PC);
}
@ -620,7 +649,7 @@ static void tgprpl_close (PurpleConnection * gc) {
static int tgprpl_send_im (PurpleConnection * gc, const char *who, const char *message, PurpleMessageFlags flags) {
debug ("tgprpl_send_im()");
connection_data *conn = purple_connection_get_protocol_data(gc);
connection_data *conn = purple_connection_get_protocol_data (gc);
// this is part of a workaround to support clients without
// the request API (request.h), see telegram-base.c:request_code()
@ -641,7 +670,7 @@ static int tgprpl_send_im (PurpleConnection * gc, const char *who, const char *m
searching it in the peer tree. This allows us to give immediate feedback
by returning an error-code in case the peer doesn't exist
*/
tgl_peer_t *peer = find_peer_by_name (conn->TLS, who);
tgl_peer_t *peer = tgl_peer_get_by_name (conn->TLS, who);
if (peer) {
if (tgl_get_peer_type (peer->id) == TGL_PEER_ENCR_CHAT && peer->encr_chat.state != sc_ok) {
warning ("secret chat not ready for sending messages or deleted");
@ -654,66 +683,57 @@ static int tgprpl_send_im (PurpleConnection * gc, const char *who, const char *m
return -1;
}
static unsigned int tgprpl_send_typing (PurpleConnection * gc, const char *who, PurpleTypingState typing) {
static unsigned int tgprpl_send_typing (PurpleConnection *gc, const char *who, PurpleTypingState typing) {
debug ("tgprpl_send_typing()");
int id = atoi (who);
connection_data *conn = purple_connection_get_protocol_data(gc);
tgl_peer_t *U = tgl_peer_get (conn->TLS, TGL_MK_USER (id));
tgl_peer_t *U = tgl_peer_get_by_name (gc_get_conn (gc)->TLS, who);
if (U) {
if (typing == PURPLE_TYPING) {
tgl_do_send_typing (conn->TLS, U->id, tgl_typing_typing, 0, 0);
tgl_do_send_typing (gc_get_conn (gc)->TLS, U->id, tgl_typing_typing, 0, 0);
} else {
tgl_do_send_typing (conn->TLS, U->id, tgl_typing_cancel, 0, 0);
tgl_do_send_typing (gc_get_conn (gc)->TLS, U->id, tgl_typing_cancel, 0, 0);
}
}
return 0;
}
static void tgprpl_get_info (PurpleConnection * gc, const char *who) {
static void tgprpl_get_info (PurpleConnection *gc, const char *who) {
debug ("tgprpl_get_info()");
connection_data *conn = purple_connection_get_protocol_data(gc);
tgl_peer_t *peer = find_peer_by_name (conn->TLS, who);
if (! peer) { return; }
get_user_info_data* info_data = get_user_info_data_new (1, peer->id);
switch (tgl_get_peer_type (peer->id)) {
case TGL_PEER_USER:
case TGL_PEER_CHAT:
tgl_do_get_user_info (conn->TLS, peer->id, 0, on_user_get_info, info_data);
break;
case TGL_PEER_ENCR_CHAT: {
tgl_peer_t *parent_peer = tgp_encr_chat_get_partner(conn->TLS, &peer->encr_chat);
if (parent_peer) {
tgl_do_get_user_info (conn->TLS, parent_peer->id, 0, on_user_get_info, info_data);
tgl_peer_t *peer = tgl_peer_get_by_name (gc_get_conn (gc)->TLS, who);
if (peer) {
get_user_info_data* info_data = get_user_info_data_new (1, peer->id);
switch (tgl_get_peer_type (peer->id)) {
case TGL_PEER_USER:
case TGL_PEER_CHAT:
tgl_do_get_user_info (gc_get_conn (gc)->TLS, peer->id, 0, on_user_get_info, info_data);
break;
case TGL_PEER_ENCR_CHAT: {
tgl_peer_t *parent_peer = tgp_encr_chat_get_partner (gc_get_conn (gc)->TLS, &peer->encr_chat);
if (parent_peer) {
tgl_do_get_user_info (gc_get_conn (gc)->TLS, parent_peer->id, 0, on_user_get_info, info_data);
}
break;
}
break;
}
}
}
static void tgprpl_set_status (PurpleAccount * acct, PurpleStatus * status) {
static void tgprpl_set_status (PurpleAccount *acct, PurpleStatus *status) {
debug ("tgprpl_set_status(%s)", purple_status_get_name (status));
debug ("tgprpl_set_status(currstatus=%s)", purple_status_get_name(purple_account_get_active_status(acct)));
PurpleConnection *gc = purple_account_get_connection(acct);
if (!gc) { return; }
connection_data *conn = purple_connection_get_protocol_data (gc);
debug ("tgprpl_set_status(currstatus=%s)", purple_status_get_name (purple_account_get_active_status (acct)));
int present = p2tgl_status_is_present (status);
if (present && p2tgl_send_notifications (acct)) {
pending_reads_send_all (conn->pending_reads, conn->TLS);
pending_reads_send_all (pa_get_conn (acct)->pending_reads, pa_get_conn (acct)->TLS);
}
}
static void tgprpl_add_buddy (PurpleConnection * gc, PurpleBuddy * buddy, PurpleGroup * group) {
connection_data *conn = purple_connection_get_protocol_data(gc);
tgl_peer_t *peer = tgl_peer_get (conn->TLS, TGL_MK_USER (atoi (buddy->name)));
static void tgprpl_add_buddy (PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) {
tgl_peer_t *peer = tgl_peer_get_by_name (gc_get_conn (gc)->TLS, purple_buddy_get_name (buddy));
if (peer) {
_update_buddy (conn->TLS, peer, TGL_UPDATE_NAME | TGL_UPDATE_PHOTO);
_update_buddy (gc_get_conn (gc)->TLS, peer, TGL_UPDATE_NAME | TGL_UPDATE_PHOTO);
}
}
@ -723,33 +743,30 @@ static void tgprpl_remove_buddy (PurpleConnection *gc, PurpleBuddy *buddy, Purpl
return;
}
connection_data *conn = purple_connection_get_protocol_data (gc);
tgl_peer_t *peer = find_peer_by_name (conn->TLS, buddy->name);
tgl_peer_t *peer = tgl_peer_get_by_name (gc_get_conn (gc)->TLS, buddy->name);
if (!peer) {
return;
}
if (tgl_get_peer_type(peer->id) == TGL_PEER_ENCR_CHAT) {
if (tgl_get_peer_type (peer->id) == TGL_PEER_ENCR_CHAT) {
/* TODO: implement the api call cancel secret chats. Currently the chat will only be marked as
deleted on our side so that it won't be added on startup
(when the secret chat file is loaded) */
bl_do_peer_delete (conn->TLS, peer->encr_chat.id);
bl_do_peer_delete (gc_get_conn (gc)->TLS, peer->encr_chat.id);
}
}
static void tgprpl_chat_invite (PurpleConnection * gc, int id, const char *message, const char *name) {
static void tgprpl_chat_invite (PurpleConnection *gc, int id, const char *message, const char *name) {
debug ("tgprpl_chat_invite()");
connection_data *conn = purple_connection_get_protocol_data (gc);
tgl_peer_t *chat = tgl_peer_get(conn->TLS, TGL_MK_CHAT (id));
tgl_peer_t *user = tgl_peer_get(conn->TLS, TGL_MK_USER (atoi(name)));
tgl_peer_t *chat = tgl_peer_get (gc_get_conn (gc)->TLS, TGL_MK_CHAT (id));
tgl_peer_t *user = tgl_peer_get_by_name (gc_get_conn (gc)->TLS, name);
if (! chat || ! user) {
purple_notify_error (_telegram_protocol, _("Not found"), _("Cannot invite buddy to chat."), _("Specified user is not existing."));
return;
}
tgl_do_add_user_to_chat (conn->TLS, chat->id, user->id, 0, tgp_notify_on_error_gw, chat);
tgl_do_add_user_to_chat (gc_get_conn (gc)->TLS, chat->id, user->id, 0, tgp_notify_on_error_gw, chat);
}
static int tgprpl_send_chat (PurpleConnection * gc, int id, const char *message, PurpleMessageFlags flags) {

View file

@ -35,11 +35,15 @@
#include <tgl.h>
#include <purple.h>
#include <notify.h>
#include <server.h>
#include <plugin.h>
#include <version.h>
#include <account.h>
#include <connection.h>
#include "tgp-blist.h"
#include "tgp-structs.h"
#define PLUGIN_ID "prpl-telegram"
#define TG_AUTHOR "Matthias Jentsch <mtthsjntsch@gmail.com>, Vitaly Valtman, Christopher Althaus <althaus.christopher@gmail.com>, Markus Endres <endresma45241@th-nuernberg.de>. Based on libtgl by Vitaly Valtman."
#define TG_DESCRIPTION "Telegram protocol."

View file

@ -36,20 +36,35 @@
#include "msglog.h"
#include <assert.h>
PurpleAccount *tg_get_acc (struct tgl_state *TLS) {
return (PurpleAccount *) ((connection_data *)TLS->ev_base)->pa;
return tg_get_data(TLS)->pa;
}
PurpleConnection *tg_get_conn (struct tgl_state *TLS) {
return (PurpleConnection *) ((connection_data *)TLS->ev_base)->gc;
return tg_get_data (TLS)->gc;
}
char *p2tgl_strdup_id (tgl_peer_id_t user) {
return g_strdup_printf ("%d", tgl_get_peer_id(user));
connection_data *tg_get_data (struct tgl_state *TLS) {
return TLS->ev_base;
}
gchar *p2tgl_strdup_alias (tgl_peer_t *user) {
return g_strdup (user->print_name);
connection_data *gc_get_conn (PurpleConnection *gc) {
return purple_connection_get_protocol_data (gc);
}
connection_data *pa_get_conn (PurpleAccount *pa) {
return purple_connection_get_protocol_data (purple_account_get_connection (pa));
}
connection_data *pbn_get_conn (PurpleBlistNode *node) {
if (PURPLE_BLIST_NODE_IS_CHAT (node)) {
return pa_get_conn (purple_chat_get_account ((PurpleChat *)node));
}
if (PURPLE_BLIST_NODE_IS_BUDDY (node)) {
return pa_get_conn (purple_buddy_get_account ((PurpleBuddy *)node));
}
return NULL;
}
int p2tgl_status_is_present (PurpleStatus *status) {
@ -63,115 +78,22 @@ int p2tgl_send_notifications (PurpleAccount *acct) {
return ret;
}
/*
Disclaimer: I stole this function from davidgfnet's whatsapp plugin, all
credit for it goes to him
@see: https://github.com/davidgfnet/whatsapp-purple
*/
static PurpleChat *blist_find_chat_by_hasht_cond (PurpleConnection *gc,
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;
}
}
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);
PurpleConversation *conv = serv_got_joined_chat (conn->gc, tgl_get_peer_id (chat->id), alias);
g_free(alias);
return conv;
}
void p2tgl_got_chat_left (struct tgl_state *TLS, tgl_peer_id_t chat) {
serv_got_chat_left(tg_get_conn(TLS), tgl_get_peer_id(chat));
serv_got_chat_left (tg_get_conn(TLS), tgl_get_peer_id(chat));
}
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) {
char *name = p2tgl_strdup_id (who);
// Make sure that the participant exists in the blist, so that the correct print name of
// the chat is being displayed by libpurple
connection_data *conn = TLS->ev_base;
PurpleBuddy *buddy = buddy = purple_find_buddy (conn->pa, name);
if (! buddy) {
buddy = purple_buddy_new (conn->pa, name, tgl_peer_get(TLS, who)->print_name);
PurpleGroup *group = purple_find_group ("Telegram Foreign");
if (!group) {
group = purple_group_new ("Telegram Foreign");
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);
}
const char *name = tgp_blist_peer_get_name (TLS, who);
serv_got_chat_in (tg_get_conn(TLS), tgl_get_peer_id (chat), name, flags, message, when);
g_free (name);
}
void p2tgl_got_alias (struct tgl_state *TLS, tgl_peer_id_t who, const char *alias) {
char *name = p2tgl_strdup_id(who);
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) {
char *name = p2tgl_strdup_id(who);
serv_got_im(tg_get_conn(TLS), name, msg, flags, when);
g_free (name);
}
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) {
connection_data *conn = TLS->ev_base;
/*
Outgoing messages are not well supported in different libpurple clients,
p2tgl_conv_im_write should have the best among different versions. Unfortunately
purple_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
@ -181,31 +103,15 @@ void p2tgl_got_im_combo (struct tgl_state *TLS, tgl_peer_id_t who, const char *m
if (flags & PURPLE_MESSAGE_SEND) {
PurpleConversation *conv = p2tgl_find_conversation_with_account (TLS, who);
if (!conv) {
conv = p2tgl_conversation_new(TLS, who);
conv = purple_conversation_new (PURPLE_CONV_TYPE_IM, tg_get_acc (TLS),
tgp_blist_peer_get_name (TLS, who));
}
p2tgl_conv_im_write (conv, who, msg, PURPLE_MESSAGE_SEND, when);
purple_conv_im_write (purple_conversation_get_im_data (conv), tgp_blist_peer_get_name (TLS, 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) {
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) {
gchar *name = p2tgl_strdup_id(user);
PurpleBuddy *b = purple_find_buddy (tg_get_acc(TLS), name);
g_free (name);
return b;
serv_got_im (conn->gc, tgp_blist_peer_get_name (TLS, who), msg, flags, when);
}
PurpleConversation *p2tgl_find_conversation_with_account (struct tgl_state *TLS, tgl_peer_id_t peer) {
@ -213,86 +119,28 @@ PurpleConversation *p2tgl_find_conversation_with_account (struct tgl_state *TLS,
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);
PurpleConversation *conv = purple_find_conversation_with_account (type,
tgp_blist_peer_get_name (TLS, peer), tg_get_acc (TLS));
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;
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) {
char *alias = p2tgl_strdup_alias (user);
char *name = p2tgl_strdup_id (user->id);
PurpleBuddy *b = purple_buddy_new (tg_get_acc(TLS), name, alias);
g_free (alias);
g_free (name);
return b;
}
void p2tgl_prpl_got_set_status_mobile (struct tgl_state *TLS, tgl_peer_id_t user) {
char *name = p2tgl_strdup_id (user);
purple_prpl_got_user_status (tg_get_acc(TLS), name, "mobile", NULL);
g_free (name);
}
void p2tgl_prpl_got_set_status_offline (struct tgl_state *TLS, tgl_peer_id_t user) {
char *name = p2tgl_strdup_id (user);
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) {
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;
if (status->online == 1) {
p2tgl_prpl_got_set_status_online (TLS, user);
purple_prpl_got_user_status (tg_get_acc (TLS), tgp_blist_peer_get_name (TLS, user), "available", NULL);
} else {
debug ("%d: when=%d", tgl_get_peer_id (user), 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 {
purple_prpl_got_user_status (tg_get_acc (TLS), tgp_blist_peer_get_name (TLS, user), "offline", NULL);
} else {
debug ("mobile");
p2tgl_prpl_got_set_status_mobile (TLS, user);
purple_prpl_got_user_status (tg_get_acc (TLS), tgp_blist_peer_get_name (TLS, user), "mobile", NULL);
}
}
}
PurpleChat *p2tgl_blist_find_chat(struct tgl_state *TLS, tgl_peer_id_t chat) {
char *name = p2tgl_strdup_id(chat);
PurpleChat *c = purple_blist_find_chat(tg_get_acc(TLS), name);
g_free (name);
return c;
}
tgl_chat_id_t p2tgl_chat_get_id (PurpleChat *PC) {
char *name = g_hash_table_lookup (purple_chat_get_components (PC), "id");
if (! name || ! atoi (name)) {
@ -302,87 +150,15 @@ tgl_chat_id_t p2tgl_chat_get_id (PurpleChat *PC) {
return TGL_MK_CHAT(atoi (name));
}
PurpleChat *p2tgl_chat_find (struct tgl_state *TLS, tgl_peer_id_t id) {
char *name = p2tgl_strdup_id(id);
PurpleChat *c = blist_find_chat_by_hasht_cond(tg_get_conn(TLS), hasht_cmp_id, name);
g_free(name);
return c;
}
void p2tgl_conv_add_user_rename (tgl_peer_t *U, PurpleConversation *conv) {
// inject print_name into chat buddies to display a human-readable name
// for buddies not in the buddy list instead of the user id
if (U) {
char *name = g_strdup_printf("%d", tgl_get_peer_id (U->id));
PurpleConvChatBuddy *cbuddy = purple_conv_chat_cb_find (PURPLE_CONV_CHAT(conv), name);
PurpleConversationUiOps *uiops = purple_conversation_get_ui_ops (conv);
if (cbuddy && cbuddy->alias) {
g_free (cbuddy->alias);
cbuddy->alias = g_strdup (U->print_name);
}
if (uiops && uiops->chat_rename_user) {
debug ("try rename user %s to %s\n", name, U->print_name);
uiops->chat_rename_user (conv, name, name, U->print_name);
} else if (uiops && uiops->chat_update_user) {
debug ("try update user %s\n", name);
uiops->chat_update_user (conv, name);
}
g_free (name);
}
}
void p2tgl_conv_add_user (struct tgl_state *TLS, PurpleConversation *conv,
int user, char *message, int flags, int new_arrival) {
PurpleConvChat *cdata = purple_conversation_get_chat_data(conv);
char *name = g_strdup_printf ("%d", user);
purple_conv_chat_add_user (cdata, name, message, flags, new_arrival);
p2tgl_conv_add_user_rename (tgl_peer_get (TLS, TGL_MK_USER(user)), conv);
g_free(name);
}
void p2tgl_conv_del_user (struct tgl_state *TLS, PurpleConversation *conv, const char *message, int userid) {
char *name = g_strdup_printf("%d", userid);
purple_conv_chat_remove_user (purple_conversation_get_chat_data (conv), name, message);
g_free (name);
}
void p2tgl_connection_set_display_name(struct tgl_state *TLS, tgl_peer_t *user) {
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) {
char *name = p2tgl_strdup_id(user);
void *handle = 0;
handle = purple_notify_userinfo(tg_get_conn(TLS), name, user_info, cb, user_data);
g_free(name);
g_free(user_info);
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);
purple_conv_chat_add_user (purple_conversation_get_chat_data (conv), tgp_blist_peer_get_name (TLS, TGL_MK_USER (user)), message, flags, new_arrival);
}
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)) {
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 {
@ -400,7 +176,7 @@ PurpleNotifyUserInfo *p2tgl_notify_user_info_new (struct tgl_user *U) {
g_free (status);
if (str_not_empty (U->phone)) {
char *phone = g_strdup_printf("+%s", U->phone);
char *phone = g_strdup_printf ("+%s", U->phone);
purple_notify_user_info_add_pair (info, _("Phone"), phone);
g_free (phone);
}
@ -408,9 +184,8 @@ PurpleNotifyUserInfo *p2tgl_notify_user_info_new (struct tgl_user *U) {
return info;
}
PurpleNotifyUserInfo *p2tgl_notify_encrypted_chat_info_new (struct tgl_state *TLS,
struct tgl_secret_chat *secret, struct tgl_user *U) {
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) {
@ -521,16 +296,13 @@ int p2tgl_imgstore_add_with_id_webp (const char *filename) {
}
#endif
void p2tgl_buddy_icons_set_for_user (PurpleAccount *pa, tgl_peer_id_t *id, const char* filename) {
char *who = g_strdup_printf("%d", tgl_get_peer_id(*id));
void p2tgl_buddy_icons_set_for_user (PurpleAccount *pa, tgl_peer_id_t id, const char* filename) {
connection_data *conn = purple_connection_get_protocol_data (purple_account_get_connection (pa));
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);
purple_buddy_icons_set_for_user (conn->pa, tgp_blist_peer_get_name (conn->TLS, id), data, len, NULL);
}

View file

@ -22,63 +22,43 @@
#include <stdio.h>
#include "telegram-purple.h"
#include "account.h"
#include "conversation.h"
#include "prpl.h"
#include <tgl.h>
#include <tgl-layout.h>
PurpleAccount *tg_get_acc (struct tgl_state *TLS);
PurpleConnection *tg_get_conn (struct tgl_state *TLS);
connection_data *tg_get_data (struct tgl_state *TLS);
connection_data *gc_get_conn (PurpleConnection *gc);
connection_data *pa_get_conn (PurpleAccount *pa);
connection_data *pbn_get_conn (PurpleBlistNode *node);
tgl_peer_t *p2tgl_get_peer (tgl_peer_id_t peer);
tgl_peer_t *p2tgl_get_peer_by_id (int id);
char *p2tgl_strdup_id (tgl_peer_id_t user);
char *p2tgl_strdup_alias(tgl_peer_t *user);
int p2tgl_status_is_present (PurpleStatus *status);
int p2tgl_send_notifications (PurpleAccount *acct);
PurpleConversation *p2tgl_got_joined_chat (struct tgl_state *TLS, struct tgl_chat *chat);
void p2tgl_got_chat_invite (PurpleConnection *gc, tgl_peer_t *chat, tgl_peer_id_t inviter, const char *message);
void p2tgl_got_chat_left (struct tgl_state *TLS, tgl_peer_id_t chat);
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);
void p2tgl_got_alias (struct tgl_state *TLS, tgl_peer_id_t who, const char *alias);
void p2tgl_got_im (struct tgl_state *TLS, tgl_peer_id_t who, const char *msg, int flags, time_t when);
void p2tgl_got_im_combo (struct tgl_state *TLS, tgl_peer_id_t who, const char *msg, int flags, time_t when);
void p2tgl_got_typing (struct tgl_state *TLS, tgl_peer_id_t name, int timeout);
PurpleBuddy *p2tgl_buddy_find (struct tgl_state *TLS, tgl_peer_id_t user);
PurpleBuddy *p2tgl_buddy_new (struct tgl_state *TLS, tgl_peer_t *user);
tgl_chat_id_t p2tgl_chat_get_id (PurpleChat *PC);
void p2tgl_buddy_add_data (struct tgl_state *TLS, tgl_peer_id_t user, void *data);
void p2tgl_buddy_add_data (struct tgl_state *TLS, tgl_peer_id_t user, void *data);
void p2tgl_prpl_got_user_status (struct tgl_state *TLS, tgl_peer_id_t user, struct tgl_user_status *status);
void p2tgl_prpl_got_set_status_mobile (struct tgl_state *TLS, tgl_peer_id_t user);
void p2tgl_prpl_got_set_status_offline (struct tgl_state *TLS, tgl_peer_id_t user);
void p2tgl_connection_set_display_name (struct tgl_state *TLS, tgl_peer_t *user);
void p2tgl_conv_del_user (struct tgl_state *TLS, PurpleConversation *conv, const char *message, int userid);
void p2tgl_conv_add_user_rename (tgl_peer_t *U, PurpleConversation *conv);
void p2tgl_conv_add_users (PurpleConversation *conv, struct tgl_chat_user *list);
void p2tgl_conv_add_user (struct tgl_state *TLS, PurpleConversation *conv, int user, char *message, int flags, int new_arrival);
PurpleConversation *p2tgl_find_conversation_with_account (struct tgl_state *TLS, tgl_peer_id_t peer);
void p2tgl_conversation_write (PurpleConversation *conv, tgl_peer_id_t who, const char *message, int flags, int date);
PurpleConversation *p2tgl_conversation_new (struct tgl_state *TLS, tgl_peer_id_t who);
PurpleChat *p2tgl_chat_find (struct tgl_state *TLS, tgl_peer_id_t chat);
void *p2tgl_notify_userinfo (struct tgl_state *TLS, tgl_peer_id_t user, PurpleNotifyUserInfo *user_info,
PurpleNotifyCloseCallback cb, gpointer user_data);
PurpleNotifyUserInfo *p2tgl_notify_peer_info_new (struct tgl_state *TLS, tgl_peer_t *P);
PurpleNotifyUserInfo *p2tgl_notify_user_info_new (struct tgl_user *U);
PurpleNotifyUserInfo *p2tgl_notify_encrypted_chat_info_new (struct tgl_state *TLS, struct tgl_secret_chat *secret, struct tgl_user *U);
void p2tgl_blist_alias_buddy (PurpleBuddy *buddy, struct tgl_user *user);
int p2tgl_imgstore_add_with_id (const char* filename);
int p2tgl_imgstore_add_with_id_webp (const char *filename);
void p2tgl_buddy_icons_set_for_user (PurpleAccount *pa, tgl_peer_id_t *id, const char* filename);
void p2tgl_buddy_icons_set_for_user (PurpleAccount *pa, tgl_peer_id_t id, const char* filename);
#endif

148
tgp-blist.c Normal file
View file

@ -0,0 +1,148 @@
/* This file is part of telegram-purple
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 2015
*/
#include "tgp-blist.h"
#include "tgp-structs.h"
#include "tgp-2prpl.h"
#include <glib.h>
#include <blist.h>
#include <assert.h>
/*
Functions for handling telegram users in the buddy list
Purple prefers human-readable names for buddy usernames, while Telegram uses numerical user ids.
In older versions of this plugin, the user id was used as username and the print name as the users
alias. This means that getting a useful username in the interface relied on the alias resolution,
which unfortunately doesn't work when a user isn't in the buddy list, or in Adium group chats.
Because of that, this plugin now uses the unique print names provided by libtgl as username instead.
*/
tgl_peer_t *tgp_blist_peer_get (struct tgl_state *TLS, tgl_peer_id_t id) {
connection_data *conn = TLS->ev_base;
return g_hash_table_lookup (conn->id_to_tgl_peer, GINT_TO_POINTER(tgl_get_peer_id (id)));
}
const char *tgp_blist_peer_get_name (struct tgl_state *TLS, tgl_peer_id_t id) {
tgl_peer_t *P = tgp_blist_peer_get (TLS, id);
if (! P) {
assert (0);
return NULL;
}
return P->print_name;
}
int tgp_blist_peer_exists (struct tgl_state *TLS, tgl_peer_id_t id) {
return tgp_blist_peer_get (TLS, id) != NULL;
}
void tgp_blist_peer_add (struct tgl_state *TLS, tgl_peer_t *peer) {
g_hash_table_insert (tg_get_data (TLS)->id_to_tgl_peer, GINT_TO_POINTER(tgl_get_peer_id (peer->id)), peer);
}
/*
To make this new approach robust to names changes, it is necessarry to store the user ID in each
blist node to allow reliable buddy list lookups by user ids. Since users should be able to just
upgrade to this version without having to drop their history or buddy list, it is also necessary
to migrate all old buddy list nodes to the new format while preserving existing history.
*/
PurpleBuddy *tgp_blist_buddy_new (struct tgl_state *TLS, tgl_peer_t *user) {
PurpleBuddy *buddy = purple_buddy_new (tg_get_acc (TLS), tgp_blist_peer_get_name (TLS, user->id), NULL);
tgp_blist_buddy_set_id (buddy, user->id);
return buddy;
}
void tgp_blist_buddy_update_name (struct tgl_state *TLS, PurpleBuddy *buddy, struct tgl_user *user) {
PurpleBuddyIcon *icon = purple_buddy_get_icon (buddy);
purple_buddy_icon_ref (icon);
purple_blist_remove_buddy (buddy);
buddy = purple_buddy_new (tg_get_acc (TLS), user->print_name, NULL);
tgp_blist_buddy_set_id (buddy, user->id);
purple_buddy_set_icon (buddy, icon);
purple_blist_add_buddy (buddy, NULL, tgp_blist_group_init ("Telegram"), NULL);
purple_buddy_icon_unref (icon);
}
void tgp_blist_buddy_set_id (PurpleBuddy *buddy, tgl_peer_id_t id) {
int uid = tgl_get_peer_id (id),
type = tgl_get_peer_type (id);
assert (uid == TGL_PEER_ENCR_CHAT || type == TGL_PEER_USER);
purple_blist_node_set_int (&buddy->node, TGP_BUDDY_KEY_PEER_ID, uid);
purple_blist_node_set_int (&buddy->node, TGP_BUDDY_KEY_PEER_TYPE, type);
}
tgl_peer_id_t tgp_blist_buddy_get_id (PurpleBuddy *buddy) {
int id = purple_blist_node_get_int (&buddy->node, TGP_BUDDY_KEY_PEER_ID),
type = purple_blist_node_get_int (&buddy->node, TGP_BUDDY_KEY_PEER_TYPE);
if (type == TGL_PEER_USER) {
return TGL_MK_USER (id);
} else if (type == TGL_PEER_ENCR_CHAT) {
return TGL_MK_ENCR_CHAT (id);
} else {
assert (FALSE);
}
}
PurpleBuddy *tgp_blist_buddy_find (struct tgl_state *TLS, tgl_peer_id_t user) {
PurpleBlistNode *node = purple_blist_get_root ();
while (node) {
if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
PurpleBuddy *buddy = PURPLE_BUDDY(node);
if (purple_buddy_get_account (buddy) == tg_get_acc (TLS)) {
if (purple_blist_node_get_int (node, TGP_BUDDY_KEY_PEER_ID) == tgl_get_peer_id (user)) {
assert (tgl_get_peer_type (user) == purple_blist_node_get_int (node, TGP_BUDDY_KEY_PEER_TYPE));
return buddy;
}
}
}
node = purple_blist_node_next (node, FALSE);
}
return NULL;
}
PurpleChat *tgp_blist_chat_find (struct tgl_state *TLS, tgl_peer_id_t user) {
PurpleBlistNode *node = purple_blist_get_root ();
while (node) {
if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
PurpleChat *chat = PURPLE_CHAT(node);
if (purple_chat_get_account (chat) == tg_get_acc (TLS)) {
const char *id = g_hash_table_lookup (purple_chat_get_components (chat), "id");
if (id && *id && atoi (id) == tgl_get_peer_id (user)) {
return chat;
}
}
}
node = purple_blist_node_next (node, FALSE);
}
return NULL;
}
PurpleGroup *tgp_blist_group_init (const char *name) {
PurpleGroup *grp = purple_find_group (name);
if (grp == NULL) {
grp = purple_group_new (name);
purple_blist_add_group (grp, NULL);
}
return grp;
}

43
tgp-blist.h Normal file
View file

@ -0,0 +1,43 @@
/*
This file is part of telegram-purple
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 2015
*/
#ifndef tgp_blist_h
#define tgp_blist_h
#include <tgl.h>
#include <purple.h>
#define TGP_BUDDY_KEY_PEER_ID "user_id"
#define TGP_BUDDY_KEY_PEER_TYPE "peer_type"
tgl_peer_t *tgp_blist_peer_get (struct tgl_state *TLS, tgl_peer_id_t id);
const char *tgp_blist_peer_get_name (struct tgl_state *TLS, tgl_peer_id_t id);
int tgp_blist_peer_exists (struct tgl_state *TLS, tgl_peer_id_t id);
void tgp_blist_buddy_set_id (PurpleBuddy *buddy, tgl_peer_id_t id);
tgl_peer_id_t tgp_blist_buddy_get_id (PurpleBuddy *buddy);
PurpleBuddy *tgp_blist_buddy_new (struct tgl_state *TLS, tgl_peer_t *user);
void tgp_blist_buddy_update_name (struct tgl_state *TLS, PurpleBuddy *buddy, struct tgl_user *user);
PurpleBuddy *tgp_blist_buddy_find (struct tgl_state *TLS, tgl_peer_id_t user);
PurpleChat *tgp_blist_chat_find (struct tgl_state *TLS, tgl_peer_id_t user);
void tgp_blist_peer_add (struct tgl_state *TLS, tgl_peer_t *peer);
PurpleGroup *tgp_blist_group_init (const char *name);
#endif

View file

@ -30,14 +30,12 @@
#include <assert.h>
GHashTable *tgp_chat_info_new (struct tgl_state *TLS, struct tgl_chat *chat) {
gchar *admin = g_strdup_printf ("%d", chat->admin_id);
gchar *title = g_strdup (chat->print_title);
gchar *name = p2tgl_strdup_id (chat->id);
GHashTable *ht = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
g_hash_table_insert (ht, "subject", title);
g_hash_table_insert (ht, "id", name);
g_hash_table_insert (ht, "owner", admin);
g_hash_table_insert (ht, "id", g_strdup_printf ("%d", tgl_get_peer_id (chat->id)));
return ht;
}
@ -46,7 +44,7 @@ PurpleChat *p2tgl_chat_new (struct tgl_state *TLS, struct tgl_chat *chat) {
return purple_chat_new (tg_get_acc(TLS), chat->title, tgp_chat_info_new (TLS, chat));
}
void p2tgl_chat_update (PurpleChat *chat, tgl_peer_id_t id, int admin_id, const char *subject) {
void p2tgl_chat_update (struct tgl_state *TLS, PurpleChat *chat, tgl_peer_id_t id, int admin_id, const char *subject) {
GHashTable *ht = purple_chat_get_components (chat);
g_hash_table_replace (ht, g_strdup ("id"), g_strdup_printf ("%d", tgl_get_peer_id (id)));
@ -57,14 +55,14 @@ void p2tgl_chat_update (PurpleChat *chat, tgl_peer_id_t id, int admin_id, const
void tgp_chat_on_loaded_chat_full (struct tgl_state *TLS, struct tgl_chat *C) {
connection_data *conn = TLS->ev_base;
PurpleChat *PC = p2tgl_chat_find (TLS, C->id);
PurpleChat *PC = tgp_blist_chat_find (TLS, C->id);
if (!PC) {
PC = p2tgl_chat_new (TLS, C);
if (purple_account_get_bool (conn->pa, TGP_KEY_JOIN_GROUP_CHATS, TGP_DEFAULT_JOIN_GROUP_CHATS)) {
purple_blist_add_chat (PC, NULL, NULL);
purple_blist_add_chat (PC, tgp_blist_group_init ("Telegram Chats"), NULL);
}
}
p2tgl_chat_update (PC, C->id, C->admin_id, C->print_title);
p2tgl_chat_update (TLS, PC, C->id, C->admin_id, C->print_title);
}
static void tgp_chat_on_loaded_chat_full_joining (struct tgl_state *TLS, void *_,
@ -92,16 +90,10 @@ static void tgp_chat_add_all_users (struct tgl_state *TLS, PurpleConversation *c
int i = 0;
for (; i < C->user_list_size; i++) {
struct tgl_chat_user *uid = (C->user_list + i);
users = g_list_append (users, g_strdup_printf ("%d", uid->user_id));
users = g_list_append (users, g_strdup (tgp_blist_peer_get_name (TLS, TGL_MK_USER(uid->user_id))));
flags = g_list_append (flags, GINT_TO_POINTER(C->admin_id == uid->user_id ? PURPLE_CBFLAGS_FOUNDER : PURPLE_CBFLAGS_NONE));
}
purple_conv_chat_add_users (PURPLE_CONV_CHAT(conv), users, NULL, flags, FALSE);
while (users) {
p2tgl_conv_add_user_rename (tgl_peer_get (TLS, TGL_MK_USER(atoi (users->data))), conv);
users = g_list_next (users);
}
g_list_free_full (users, g_free);
g_list_free (flags);
}
@ -116,12 +108,11 @@ void tgp_chat_users_update (struct tgl_state *TLS, struct tgl_chat *C) {
PurpleConversation *tgp_chat_show (struct tgl_state *TLS, struct tgl_chat *C) {
connection_data *conn = TLS->ev_base;
PurpleConversation *convo = purple_find_chat (conn->gc, tgl_get_peer_id (C->id));
PurpleConvChat *chat = purple_conversation_get_chat_data (convo);
if (! convo || (chat && purple_conv_chat_has_left (chat))) {
convo = p2tgl_got_joined_chat (conn->TLS, C);
convo = serv_got_joined_chat (conn->gc, tgl_get_peer_id (C->id), C->print_title);
tgp_chat_users_update (conn->TLS, C);
}
return convo;
@ -216,14 +207,14 @@ static void tgp_chat_roomlist_it (tgl_peer_t *P, void *extra) {
connection_data *conn = extra;
if (tgl_get_peer_type (P->id) == TGL_PEER_CHAT && P->chat.users_num) {
char *name = g_strdup_printf ("%d", tgl_get_peer_id (P->id));
char *id = g_strdup_printf ("%d", tgl_get_peer_id (P->id));
PurpleRoomlistRoom *room = purple_roomlist_room_new (PURPLE_ROOMLIST_ROOMTYPE_ROOM, P->chat.print_title, NULL);
purple_roomlist_room_add_field (conn->roomlist, room, name);
purple_roomlist_room_add_field (conn->roomlist, room, id);
purple_roomlist_room_add_field (conn->roomlist, room, GINT_TO_POINTER(P->chat.users_num));
purple_roomlist_room_add (conn->roomlist, room);
g_free (name);
g_free (id);
}
}

View file

@ -166,7 +166,7 @@ static void tgprpl_xfer_recv_init (PurpleXfer *X) {
purple_xfer_start (X, -1, NULL, 0);
const char *who = purple_xfer_get_remote_user (X);
P = find_peer_by_name (TLS, who);
P = tgl_peer_get_by_name (TLS, who);
if (P) {
switch (M->media.type) {
case tgl_message_media_document:
@ -206,7 +206,7 @@ static void tgprpl_xfer_send_init (PurpleXfer *X) {
const char *who = purple_xfer_get_remote_user (X);
debug ("xfer_on_init (file=%s, local=%s, who=%s)", file, localfile, who);
tgl_peer_t *P = find_peer_by_name (data->conn->TLS, who);
tgl_peer_t *P = tgl_peer_get_by_name (data->conn->TLS, who);
if (P) {
tgl_do_send_document (data->conn->TLS, P->id, (char*) localfile, NULL,
0, TGL_SEND_MSG_FLAG_DOCUMENT_AUTO, tgprpl_xfer_on_finished, data);

View file

@ -42,7 +42,7 @@ static void tgp_msg_err_out (struct tgl_state *TLS, const char *error, tgl_peer_
static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) {
assert (M && M->flags & TGLMF_SERVICE);
connection_data *conn = TLS->ev_base;
char *txt_user = NULL;
const char *txt_user = NULL;
char *txt_action = NULL;
char *txt = NULL;
@ -50,7 +50,7 @@ static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) {
if (! peer) {
return NULL;
}
txt_user = p2tgl_strdup_alias (peer);
txt_user = peer->print_name;
switch (M->action.type) {
case tgl_message_action_chat_create:
@ -68,16 +68,11 @@ static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) {
case tgl_message_action_chat_add_user_by_link: {
tgl_peer_t *actionPeer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user));
if (actionPeer) {
char *alias = p2tgl_strdup_alias (actionPeer);
PurpleConversation *conv = purple_find_chat (conn->gc, tgl_get_peer_id (M->to_id));
txt_action = g_strdup_printf (_("%s added user %s by link"), alias, txt_user);
txt_action = g_strdup_printf (_("%s added user %s by link"), actionPeer->print_name, txt_user);
if (conv) {
p2tgl_conv_add_user (TLS, conv, tgl_get_peer_id (peer->id), NULL, 0, FALSE);
}
g_free (alias);
g_free (txt_user);
return txt_action;
}
break;
@ -85,14 +80,12 @@ static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) {
case tgl_message_action_chat_add_user: {
tgl_peer_t *peer = tgl_peer_get (TLS, TGL_MK_USER (M->action.user));
if (peer) {
char *alias = p2tgl_strdup_alias (peer);
txt_action = g_strdup_printf (_("added user %s."), alias);
txt_action = g_strdup_printf (_("added user %s."), peer->print_name);
PurpleConversation *conv = purple_find_chat (conn->gc, tgl_get_peer_id (M->to_id));
if (conv) {
p2tgl_conv_add_user (TLS, conv, M->action.user, NULL, 0, FALSE);
}
g_free (alias);
}
break;
}
@ -108,25 +101,21 @@ static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) {
// the deleted user
PurpleConversation *conv = tgp_chat_show (TLS, &chatPeer->chat);
if (conv) {
char *alias = p2tgl_strdup_alias (peer);
txt_action = g_strdup_printf (_("%s deleted user %s."), txt_user, alias);
g_free (alias);
txt_action = g_strdup_printf (_("%s deleted user %s."), txt_user, peer->print_name);
purple_conv_chat_remove_user (purple_conversation_get_chat_data (conv),
tgp_blist_peer_get_name (TLS, TGL_MK_USER (M->action.user)), txt_action);
p2tgl_conv_del_user (TLS, conv, txt_action, M->action.user);
if (M->action.user == tgl_get_peer_id (TLS->our_id)) {
purple_conv_chat_left (purple_conversation_get_chat_data (conv));
}
// conv_del_user already printed a message, prevent a redundant message
// from being printed by returning NULL
g_free (txt_user);
g_free (txt_action);
return NULL;
}
char *alias = p2tgl_strdup_alias (peer);
txt_action = g_strdup_printf (_("deleted user %s"), alias);
g_free (alias);
txt_action = g_strdup_printf (_("deleted user %s"), peer->print_name);
}
break;
}
@ -165,7 +154,6 @@ static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) {
txt = g_strdup_printf ("%s %s.", txt_user, txt_action);
g_free (txt_action);
}
g_free (txt_user);
return txt;
}
@ -363,10 +351,8 @@ static char *tgp_msg_sticker_display (struct tgl_state *TLS, tgl_peer_id_t from,
text = tgp_format_img (img);
*flags |= PURPLE_MESSAGE_IMAGES;
#else
char *txt_user = p2tgl_strdup_alias (tgl_peer_get (TLS, from));
text = g_strdup_printf (_("%s sent a sticker"), txt_user);
text = g_strdup_printf (_("%s sent a sticker"), tgp_blist_peer_get_name (TLS, from));
*flags |= PURPLE_MESSAGE_SYSTEM;
g_free (txt_user);
#endif
return text;
}
@ -407,13 +393,15 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
switch (M->media.type) {
case tgl_message_media_photo: {
assert (C->data);
text = tgp_msg_photo_display (TLS, C->data, &flags);
if (str_not_empty (text)) {
if (str_not_empty (M->media.caption)) {
char *old = text;
text = g_strdup_printf ("%s<br>%s", old, M->media.caption);
g_free (old);
if (M->media.photo) {
assert (C->data);
text = tgp_msg_photo_display (TLS, C->data, &flags);
if (str_not_empty (text)) {
if (str_not_empty (M->media.caption)) {
char *old = text;
text = g_strdup_printf ("%s<br>%s", old, M->media.caption);
g_free (old);
}
}
}
break;
@ -427,9 +415,8 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
assert (C->data);
text = tgp_msg_photo_display (TLS, C->data, &flags);
} else {
char *who = p2tgl_strdup_id (M->from_id);
if (! tgp_our_msg(TLS, M)) {
tgprpl_recv_file (conn->gc, who, M);
tgprpl_recv_file (conn->gc, tgp_blist_peer_get_name (TLS, M->from_id), M);
}
return;
}
@ -437,9 +424,8 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
case tgl_message_media_video:
case tgl_message_media_audio: {
char *who = p2tgl_strdup_id (M->from_id);
if (! tgp_our_msg(TLS, M)) {
tgprpl_recv_file (conn->gc, who, M);
tgprpl_recv_file (conn->gc, tgp_blist_peer_get_name (TLS, M->from_id), M);
}
}
break;
@ -452,9 +438,8 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
assert (C->data);
text = tgp_msg_photo_display (TLS, C->data, &flags);
} else {
char *who = p2tgl_strdup_id (M->to_id);
if (! tgp_our_msg(TLS, M)) {
tgprpl_recv_file (conn->gc, who, M);
tgprpl_recv_file (conn->gc, tgp_blist_peer_get_name (TLS, M->to_id), M);
}
return;
}
@ -524,7 +509,7 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
break;
}
case TGL_PEER_ENCR_CHAT: {
p2tgl_got_im (TLS, M->to_id, text, flags, M->date);
serv_got_im (tg_get_conn (TLS), tgp_blist_peer_get_name (TLS, M->to_id), text, flags, M->date);
pending_reads_add (conn->pending_reads, M->to_id);
break;
}
@ -534,7 +519,7 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
flags &= ~PURPLE_MESSAGE_RECV;
p2tgl_got_im_combo (TLS, M->to_id, text, flags, M->date);
} else {
p2tgl_got_im (TLS, M->from_id, text, flags, M->date);
serv_got_im (tg_get_conn (TLS), tgp_blist_peer_get_name (TLS, M->from_id), text, flags, M->date);
pending_reads_add (conn->pending_reads, M->from_id);
}
break;
@ -613,10 +598,16 @@ void tgp_msg_recv (struct tgl_state *TLS, struct tgl_message *M) {
// handle all messages that need to load content before they can be displayed
if (M->media.type != tgl_message_media_none) {
switch (M->media.type) {
case tgl_message_media_photo:
++ C->pending;
tgl_do_load_photo (TLS, M->media.photo, tgp_msg_on_loaded_document, C);
case tgl_message_media_photo: {
// include the "bad photo" check from telegram-cli interface.c:3287 to avoid crashes when fetching history
// TODO: find out the reason for this behavior
if (M->media.photo) {
++ C->pending;
tgl_do_load_photo (TLS, M->media.photo, tgp_msg_on_loaded_document, C);
}
break;
}
// documents that are stickers or images will be displayed just like regular photo messages
// and need to be lodaed beforehand
@ -651,8 +642,9 @@ void tgp_msg_recv (struct tgl_state *TLS, struct tgl_message *M) {
assert (peer);
if (! peer->chat.user_list_size) {
// we receive messages even though the user list is empty, this means that we still
// haven't fetched the full chat information
// To display a chat the full name of every single user is needed, but the updates received from the server only
// contain the names of users mentioned in the events. In order to display a messages we always need to fetch the
// full chat info first. If the user list is empty, this means that we still haven't fetched the full chat information.
// assure that there is only one chat info request for every
// chat to avoid causing FLOOD_WAIT_X errors that will lead to delays or dropped messages

View file

@ -192,14 +192,14 @@ static void decline_secret_chat_cb (gpointer _data, const gchar *code) {
struct accept_secret_chat_data *data = _data;
bl_do_peer_delete (data->TLS, data->U->id);
purple_blist_remove_buddy (p2tgl_buddy_find(data->TLS, data->U->id));
purple_blist_remove_buddy (tgp_blist_buddy_find (data->TLS, data->U->id));
g_free (data);
}
void request_accept_secret_chat (struct tgl_state *TLS, struct tgl_secret_chat *U) {
connection_data *conn = TLS->ev_base;
PurpleBuddy *who = p2tgl_buddy_find (TLS, TGL_MK_USER (U->user_id));
PurpleBuddy *who = tgp_blist_buddy_find (TLS, TGL_MK_USER (U->user_id));
struct accept_secret_chat_data *data = g_new (struct accept_secret_chat_data, 1);
data->TLS = TLS;
data->U = U;

View file

@ -101,6 +101,7 @@ connection_data *connection_data_init (struct tgl_state *TLS, PurpleConnection *
conn->out_messages = g_queue_new ();
conn->pending_reads = g_queue_new ();
conn->pending_chat_info = g_hash_table_new (g_direct_hash, g_direct_equal);
conn->id_to_tgl_peer = g_hash_table_new (g_direct_hash, g_direct_equal);
return conn;
}
@ -114,6 +115,7 @@ void *connection_data_free (connection_data *conn) {
tgp_g_queue_free_full (conn->out_messages, tgp_msg_sending_free);
tgp_g_list_free_full (conn->used_images, used_image_free);
g_hash_table_destroy (conn->pending_chat_info);
g_hash_table_destroy (conn->id_to_tgl_peer);
tgprpl_xfer_free_all (conn);
tgl_free_all (conn->TLS);
g_free(conn->TLS->base_path);
@ -129,3 +131,4 @@ get_user_info_data* get_user_info_data_new (int show_info, tgl_peer_id_t peer) {
info_data->peer = peer;
return info_data;
}

View file

@ -43,6 +43,7 @@ typedef struct {
int password_retries;
PurpleRoomlist *roomlist;
GHashTable *pending_chat_info;
GHashTable *id_to_tgl_peer;
} connection_data;
typedef struct {
@ -88,3 +89,4 @@ struct tgp_msg_sending *tgp_msg_sending_init (struct tgl_state *TLS, char *M, tg
void tgp_msg_loading_free (gpointer data);
void tgp_msg_sending_free (gpointer data);
#endif

View file

@ -26,12 +26,6 @@
#include <purple.h>
connection_data *get_conn_from_buddy (PurpleBuddy *buddy) {
connection_data *c = purple_connection_get_protocol_data (
purple_account_get_connection (purple_buddy_get_account (buddy)));
return c;
}
const char *format_time (time_t date) {
struct tm *datetime = localtime(&date);
return purple_utf8_strftime ("%d.%m.%Y %H:%M", datetime);
@ -81,16 +75,6 @@ int tgp_our_msg (struct tgl_state *TLS, struct tgl_message *M) {
return tgl_get_peer_id (TLS->our_id) == tgl_get_peer_id (M->from_id);
}
tgl_peer_t *find_peer_by_name (struct tgl_state *TLS, const char *who) {
tgl_peer_t *peer = tgl_peer_get (TLS, TGL_MK_USER(atoi (who)));
if (peer) { return peer; }
peer = tgl_peer_get (TLS, TGL_MK_CHAT(atoi(who)));
if (peer) { return peer; }
peer = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT(atoi(who)));
if (peer) { return peer; }
return NULL;
}
tgl_peer_t *tgp_encr_chat_get_partner (struct tgl_state *TLS, struct tgl_secret_chat *chat) {
return tgl_peer_get (TLS, TGL_MK_USER(chat->admin_id == tgl_get_peer_id (TLS->our_id) ? chat->user_id : chat->admin_id));
}

View file

@ -27,9 +27,7 @@
#include <tgl.h>
#include <glib.h>
connection_data *get_conn_from_buddy (PurpleBuddy *buddy);
tgl_peer_t *tgp_encr_chat_get_partner (struct tgl_state *TLS, struct tgl_secret_chat *chat);
tgl_peer_t *find_peer_by_name (struct tgl_state *TLS, const char *who);
/**
* Return whether this message was created by our client in this session