Support supergroups and displaying channel members
Change all channels to be chats instead of regular buddies and implement fetching channel memberships. Remove some unneeded code scraps from old channel handling.
This commit is contained in:
parent
4ef719cd3a
commit
fbe3a7fbba
10 changed files with 382 additions and 215 deletions
|
@ -112,7 +112,6 @@
|
|||
C4B57BE51B109E6D006997F4 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
|
||||
C4B57BE81B10D814006997F4 /* configure.ac */ = {isa = PBXFileReference; lastKnownFileType = text; name = configure.ac; path = ../configure.ac; sourceTree = "<group>"; };
|
||||
C4B57BE91B10D822006997F4 /* Makefile.in */ = {isa = PBXFileReference; lastKnownFileType = text; name = Makefile.in; path = ../Makefile.in; sourceTree = "<group>"; };
|
||||
C4B57BEC1B13B2C4006997F4 /* auto-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "auto-types.h"; path = "../auto/auto-types.h"; sourceTree = "<group>"; };
|
||||
C4B57BED1B1598BE006997F4 /* telegram-purple */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "telegram-purple"; path = ..; sourceTree = "<group>"; };
|
||||
C4B57BEF1B1598D4006997F4 /* libtgl.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtgl.a; path = ../libs/libtgl.a; sourceTree = "<group>"; };
|
||||
C4D12DEE1BC534CF00C0F6E1 /* tgp-blist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tgp-blist.h"; path = "../tgp-blist.h"; sourceTree = "<group>"; };
|
||||
|
@ -268,7 +267,6 @@
|
|||
C431EB7B1A76C737006521CB /* tgp-chat.c */,
|
||||
C431EB7C1A76C737006521CB /* tgp-chat.h */,
|
||||
C4E5280F1A8A907200C4B915 /* tgp-ft.c */,
|
||||
C4B57BEC1B13B2C4006997F4 /* auto-types.h */,
|
||||
C4E528101A8A907200C4B915 /* tgp-ft.h */,
|
||||
C479A8001BB69C2100C153DF /* tgp-request.c */,
|
||||
C479A8011BB69C2100C153DF /* tgp-request.h */,
|
||||
|
|
|
@ -34,8 +34,6 @@ static void update_secret_chat_typing (struct tgl_state *TLS, struct tgl_secret_
|
|||
static void update_user_status_handler (struct tgl_state *TLS, struct tgl_user *U);
|
||||
static void update_user_handler (struct tgl_state *TLS, struct tgl_user *U, unsigned flags);
|
||||
static void update_secret_chat_handler (struct tgl_state *TLS, struct tgl_secret_chat *C, unsigned flags);
|
||||
static void update_chat_handler (struct tgl_state *TLS, struct tgl_chat *C, unsigned flags);
|
||||
static void update_channel_handler (struct tgl_state *TLS, struct tgl_channel *C, unsigned flags);
|
||||
static void update_on_failed_login (struct tgl_state *TLS);
|
||||
|
||||
const char *config_dir = "telegram-purple";
|
||||
|
@ -154,37 +152,6 @@ static void update_user_handler (struct tgl_state *TLS, struct tgl_user *user, u
|
|||
}
|
||||
}
|
||||
|
||||
static void update_channel_handler (struct tgl_state *TLS, struct tgl_channel *C, unsigned flags) {
|
||||
debug ("update_channel_handler() (%s)", print_flags_update (flags));
|
||||
|
||||
PurpleBuddy *buddy = tgp_blist_buddy_find (TLS, C->id);
|
||||
|
||||
if (flags & TGL_UPDATE_CREATED) {
|
||||
debug ("channel allocated '%s' (%s)", C->title, print_flags_channel (C->flags));
|
||||
if (buddy) {
|
||||
tgp_blist_lookup_add (TLS, C->id, purple_buddy_get_name (buddy));
|
||||
if (C->title && strcmp (C->title, purple_buddy_get_name (buddy))) {
|
||||
purple_blist_alias_buddy (buddy, C->title);
|
||||
}
|
||||
purple_prpl_got_user_status (tls_get_pa (TLS), purple_buddy_get_name (buddy), "available", NULL);
|
||||
} else {
|
||||
tgp_blist_lookup_add (TLS, C->id, C->title);
|
||||
}
|
||||
} else {
|
||||
if (buddy) {
|
||||
if (flags & TGL_UPDATE_FLAGS) {
|
||||
debug ("channel updated flags '%s' to (%s)", C->title, print_flags_channel (C->flags));
|
||||
if (C->flags & TGLCHF_LEFT) {
|
||||
purple_blist_remove_buddy (buddy);
|
||||
}
|
||||
}
|
||||
if (flags & TGL_UPDATE_PHOTO) {
|
||||
tgp_info_update_photo (buddy, tgl_peer_get (TLS, C->id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_secret_chat_handler (struct tgl_state *TLS, struct tgl_secret_chat *U, unsigned flags) {
|
||||
debug ("update_secret_chat_handler() (%s)", print_flags_update (flags));
|
||||
PurpleBuddy *buddy = tgp_blist_buddy_find (TLS, U->id);
|
||||
|
@ -231,23 +198,6 @@ 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) {
|
||||
debug ("update_chat_handler() (%s)", print_flags_update(flags));
|
||||
|
||||
if (flags & TGL_UPDATE_CREATED) {
|
||||
debug ("new chat '%s' allocated (%s)", chat->title, print_flags_peer (chat->flags));
|
||||
tgp_blist_lookup_add (TLS, chat->id, chat->print_title);
|
||||
} else {
|
||||
PurpleChat *ch = tgp_blist_chat_find (TLS, chat->id);
|
||||
if (flags & TGL_UPDATE_TITLE && ch) {
|
||||
purple_blist_alias_chat (ch, chat->print_title);
|
||||
}
|
||||
if (flags & TGL_UPDATE_DELETED && ch) {
|
||||
purple_blist_remove_chat (ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_user_status_handler (struct tgl_state *TLS, struct tgl_user *U) {
|
||||
p2tgl_prpl_got_user_status (TLS, U->id, &U->status);
|
||||
}
|
||||
|
@ -300,40 +250,16 @@ static void on_get_dialog_list_done (struct tgl_state *TLS, void *extra, int suc
|
|||
g_warn_if_reached ();
|
||||
continue;
|
||||
}
|
||||
|
||||
// our own contact shouldn't show up in our buddy list
|
||||
if (tgl_get_peer_id (UC->id) == tgl_get_peer_id (TLS->our_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tgl_get_peer_type (UC->id) == TGL_PEER_USER) {
|
||||
if (! (UC->user.flags & TGLUF_DELETED)) {
|
||||
tgp_blist_contact_add (TLS, &UC->user);
|
||||
}
|
||||
} else if (tgl_get_peer_type (UC->id) == TGL_PEER_CHAT) {
|
||||
if (purple_account_get_bool (tls_get_data (TLS)->pa, TGP_KEY_JOIN_GROUP_CHATS, TGP_DEFAULT_JOIN_GROUP_CHATS)) {
|
||||
|
||||
PurpleChat *PC = tgp_blist_chat_find (TLS, UC->id);
|
||||
if (! (UC->chat.flags & TGLCF_LEFT)) {
|
||||
if (!PC) {
|
||||
PC = p2tgl_chat_new (TLS, &UC->chat);
|
||||
purple_blist_add_chat (PC, tgp_blist_group_init ("Telegram Chats"), NULL);
|
||||
}
|
||||
} else {
|
||||
if (PC) {
|
||||
purple_blist_remove_chat (PC);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (tgl_get_peer_type (UC->id) == TGL_PEER_CHANNEL) {
|
||||
// unlike the other peer types, deleted and left channels will not show up in the dialogue list
|
||||
PurpleBuddy *buddy = tgp_blist_buddy_find (TLS, UC->id);
|
||||
if (! buddy) {
|
||||
info ("%s is in the dialogue list but not in the buddy list, add the channel", UC->print_name);
|
||||
buddy = tgp_blist_buddy_new (TLS, UC);
|
||||
purple_blist_add_buddy (buddy, NULL, tgp_blist_group_init (_("Telegram Channels")), NULL);
|
||||
tgp_info_update_photo (buddy, UC);
|
||||
}
|
||||
purple_prpl_got_user_status (tls_get_pa (TLS), tgp_blist_lookup_purple_name (TLS, UC->id), "available",
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,14 +329,18 @@ static void start_secret_chat (PurpleBlistNode *node, gpointer data) {
|
|||
}
|
||||
|
||||
static void create_chat_link_done (struct tgl_state *TLS, void *extra, int success, const char *url) {
|
||||
tgl_peer_t *C = extra;
|
||||
tgl_peer_t *P = extra;
|
||||
|
||||
if (success) {
|
||||
assert (tgl_get_peer_type (C->id) == TGL_PEER_CHAT);
|
||||
tgp_chat_show (TLS, &C->chat);
|
||||
assert (tgl_get_peer_type (P->id) == TGL_PEER_CHAT);
|
||||
/*
|
||||
tgp_chat_show (TLS, P);
|
||||
serv_got_chat_in (tls_get_conn (TLS), tgl_get_peer_id (P->id), "WebPage", PURPLE_MESSAGE_SYSTEM, msg, time(NULL));
|
||||
*/
|
||||
|
||||
char *msg = g_strdup_printf (_("Invite link: %s"), url);
|
||||
serv_got_chat_in (tls_get_conn (TLS), tgl_get_peer_id (C->id), "WebPage", PURPLE_MESSAGE_SYSTEM, msg, time(NULL));
|
||||
|
||||
tgp_chat_got_in (TLS, P, P->id, msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
|
||||
g_free (msg);
|
||||
} else {
|
||||
tgp_notify_on_error_gw (TLS, NULL, success);
|
||||
|
@ -535,6 +465,7 @@ static void update_on_ready (struct tgl_state *TLS) {
|
|||
}
|
||||
|
||||
tgl_do_get_dialog_list (TLS, 200, 0, on_get_dialog_list_done, NULL);
|
||||
tgl_do_get_channels_dialog_list (TLS, 50, 0, NULL, NULL);
|
||||
tgl_do_update_contact_list (TLS, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -729,16 +660,6 @@ static void tgprpl_chat_invite (PurpleConnection *gc, int id, const char *messag
|
|||
tgl_do_add_user_to_chat (gc_get_tls (gc), 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) {
|
||||
debug ("tgprpl_send_chat()");
|
||||
int ret = tgp_msg_send (gc_get_tls (gc), message, TGL_MK_CHAT(id));
|
||||
if (ret != 0) {
|
||||
p2tgl_got_chat_in (gc_get_tls (gc), TGL_MK_CHAT(id), gc_get_tls (gc)->our_id, message, PURPLE_MESSAGE_RECV,
|
||||
time (NULL));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean tgprpl_can_receive_file (PurpleConnection *gc, const char *who) {
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,9 @@
|
|||
#define TGP_DEFAULT_SEND_READ_NOTIFICATIONS TRUE
|
||||
#define TGP_KEY_SEND_READ_NOTIFICATIONS "send-read-notifications"
|
||||
|
||||
#define TGP_DEFAULT_CHANNEL_MEMBERS 500
|
||||
#define TGP_KEY_CHANNEL_MEMBERS "channel-member-count"
|
||||
|
||||
#define TGP_KEY_RESET_AUTH "reset-authorization"
|
||||
|
||||
extern const char *pk_path;
|
||||
|
|
25
tgp-2prpl.c
25
tgp-2prpl.c
|
@ -63,10 +63,21 @@ int p2tgl_status_is_present (PurpleStatus *status) {
|
|||
return !(strcmp (name, "unavailable") == 0 || strcmp (name, "away") == 0);
|
||||
}
|
||||
|
||||
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) {
|
||||
serv_got_chat_in (tls_get_conn (TLS), tgl_get_peer_id (chat), tgp_blist_lookup_purple_name (TLS, who), flags,
|
||||
message, when);
|
||||
void tgp_chat_got_in (struct tgl_state *TLS, tgl_peer_t *chat, tgl_peer_id_t from, const char *message,
|
||||
int flags, time_t when) {
|
||||
g_return_if_fail(chat);
|
||||
if (tgp_chat_show (TLS, chat)) {
|
||||
|
||||
// channel messages in non-megagroups are always sent by the channel itself
|
||||
if (tgl_get_peer_type (chat->id) == TGL_PEER_CHANNEL && !(chat->channel.flags & TGLCHF_MEGAGROUP)) {
|
||||
from = chat->id;
|
||||
}
|
||||
|
||||
serv_got_chat_in (tls_get_conn (TLS), tgl_get_peer_id (chat->id), tgp_blist_lookup_purple_name (TLS, from),
|
||||
flags, message, when);
|
||||
} else {
|
||||
g_warn_if_reached();
|
||||
}
|
||||
}
|
||||
|
||||
void p2tgl_got_im_combo (struct tgl_state *TLS, tgl_peer_id_t who, const char *msg, int flags, time_t when) {
|
||||
|
@ -102,11 +113,11 @@ void p2tgl_got_im_combo (struct tgl_state *TLS, tgl_peer_id_t who, const char *m
|
|||
|
||||
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) {
|
||||
if (tgl_get_peer_type (peer) == TGL_PEER_CHAT || tgl_get_peer_type (peer) == TGL_PEER_CHANNEL) {
|
||||
type = PURPLE_CONV_TYPE_CHAT;
|
||||
}
|
||||
PurpleConversation *conv = purple_find_conversation_with_account (type, tgp_blist_lookup_purple_name (TLS, peer),
|
||||
tls_get_pa (TLS));
|
||||
PurpleConversation *conv = purple_find_conversation_with_account (type,
|
||||
tgp_blist_lookup_purple_name (TLS, peer), tls_get_pa (TLS));
|
||||
return conv;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ struct tgl_state *gc_get_tls (PurpleConnection *gc);
|
|||
|
||||
int p2tgl_status_is_present (PurpleStatus *status);
|
||||
|
||||
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 tgp_chat_got_in (struct tgl_state *TLS, tgl_peer_t *chat, tgl_peer_id_t who, const char *message, 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_prpl_got_user_status (struct tgl_state *TLS, tgl_peer_id_t user, struct tgl_user_status *status);
|
||||
void p2tgl_conv_add_user (struct tgl_state *TLS, PurpleConversation *conv, int user, char *message, int flags, int new_arrival);
|
||||
|
|
312
tgp-chat.c
312
tgp-chat.c
|
@ -20,25 +20,21 @@
|
|||
|
||||
#include "tgp-chat.h"
|
||||
|
||||
GHashTable *tgp_chat_info_new (struct tgl_state *TLS, struct tgl_chat *chat) {
|
||||
gchar *title = g_strdup (chat->print_title);
|
||||
GHashTable *tgp_chat_info_new (struct tgl_state *TLS, tgl_peer_t *P) {
|
||||
|
||||
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", g_strdup_printf ("%d", tgl_get_peer_id (chat->id)));
|
||||
g_hash_table_insert (ht, "subject", g_strdup (P->print_name));
|
||||
g_hash_table_insert (ht, "id", g_strdup_printf ("%d", tgl_get_peer_id (P->chat.id)));
|
||||
|
||||
if (tgl_get_peer_type (P->id) == TGL_PEER_CHANNEL) {
|
||||
g_hash_table_insert (ht, "last_server_id", g_strdup_printf ("%d", 0));
|
||||
}
|
||||
|
||||
return ht;
|
||||
}
|
||||
|
||||
PurpleChat *p2tgl_chat_new (struct tgl_state *TLS, struct tgl_chat *chat) {
|
||||
return purple_chat_new (tls_get_pa (TLS), chat->title, tgp_chat_info_new (TLS, chat));
|
||||
}
|
||||
|
||||
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)));
|
||||
g_hash_table_replace (ht, g_strdup ("subject"), g_strdup (subject));
|
||||
PurpleChat *tgp_chat_new (struct tgl_state *TLS, tgl_peer_t *P) {
|
||||
return purple_chat_new (tls_get_pa (TLS), P->chat.print_title, tgp_chat_info_new (TLS, P));
|
||||
}
|
||||
|
||||
int tgp_chat_has_id (PurpleChat *C) {
|
||||
|
@ -52,15 +48,30 @@ tgl_peer_id_t tgp_chat_get_id (PurpleChat *C) {
|
|||
return TGL_MK_CHAT(atoi (id));
|
||||
}
|
||||
|
||||
void tgp_chat_on_loaded_chat_full (struct tgl_state *TLS, struct tgl_chat *C) {
|
||||
PurpleChat *PC = tgp_blist_chat_find (TLS, C->id);
|
||||
if (!PC) {
|
||||
PC = p2tgl_chat_new (TLS, C);
|
||||
if (purple_account_get_bool (tls_get_pa (TLS), TGP_KEY_JOIN_GROUP_CHATS, TGP_DEFAULT_JOIN_GROUP_CHATS)) {
|
||||
purple_blist_add_chat (PC, tgp_blist_group_init (_("Telegram Chats")), NULL);
|
||||
static void tgp_chat_blist_store (struct tgl_state *TLS, tgl_peer_t *P, const char *group) {
|
||||
g_return_if_fail(tgl_get_peer_type (P->id) == TGL_PEER_CHAT || tgl_get_peer_type (P->id) == TGL_PEER_CHANNEL);
|
||||
|
||||
PurpleChat *PC = tgp_blist_chat_find (TLS, P->id);
|
||||
if (! (P->flags & TGLCF_LEFT)) {
|
||||
if (! PC) {
|
||||
PC = tgp_chat_new (TLS, tgl_peer_get (TLS, P->id));
|
||||
if (purple_account_get_bool (tls_get_pa (TLS), TGP_KEY_JOIN_GROUP_CHATS, TGP_DEFAULT_JOIN_GROUP_CHATS)) {
|
||||
purple_blist_add_chat (PC, tgp_blist_group_init (group), NULL);
|
||||
tgp_info_update_photo (&PC->node, tgl_peer_get (TLS, P->id));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (PC) {
|
||||
purple_blist_remove_chat (PC);
|
||||
}
|
||||
}
|
||||
p2tgl_chat_update (TLS, PC, C->id, C->admin_id, C->print_title);
|
||||
|
||||
if (PC) {
|
||||
g_hash_table_replace (purple_chat_get_components (PC), g_strdup ("id"),
|
||||
g_strdup_printf ("%d", tgl_get_peer_id (P->id)));
|
||||
g_hash_table_replace (purple_chat_get_components (PC), g_strdup ("subject"),
|
||||
g_strdup (tgl_get_peer_type (P->id) == TGL_PEER_CHANNEL ? P->channel.title : P->chat.title));
|
||||
}
|
||||
}
|
||||
|
||||
static void tgp_chat_on_loaded_chat_full_joining (struct tgl_state *TLS, void *_, int success, struct tgl_chat *C) {
|
||||
|
@ -70,58 +81,117 @@ static void tgp_chat_on_loaded_chat_full_joining (struct tgl_state *TLS, void *_
|
|||
return;
|
||||
}
|
||||
|
||||
tgp_chat_on_loaded_chat_full (TLS, C);
|
||||
tgp_chat_show (TLS, C);
|
||||
|
||||
tgp_chat_blist_store (TLS, tgl_peer_get (TLS, C->id), _("Telegram Chats"));
|
||||
tgp_chat_show (TLS, tgl_peer_get (TLS, C->id));
|
||||
|
||||
// Check if the users attempts to join an empty chat
|
||||
if (! C->user_list_size) {
|
||||
p2tgl_got_chat_in (TLS, C->id, C->id, _("You have already left this chat."), PURPLE_MESSAGE_SYSTEM, time (NULL));
|
||||
if (C->flags & TGLCF_LEFT) {
|
||||
tgp_chat_got_in (TLS, tgl_peer_get (TLS, C->id), C->id, _("You have already left this chat."), PURPLE_MESSAGE_SYSTEM,
|
||||
time (NULL));
|
||||
}
|
||||
}
|
||||
|
||||
static void tgp_chat_add_all_users (struct tgl_state *TLS, PurpleConversation *conv, struct tgl_chat *C) {
|
||||
static void tgp_chat_on_loaded_channel_full_joining (struct tgl_state *TLS, int success, tgl_peer_t *P, void *extra) {
|
||||
debug ("tgp_chat_on_loaded_channel_full_joining()");
|
||||
if (! success) {
|
||||
tgp_notify_on_error_gw (TLS, NULL, success);
|
||||
return;
|
||||
}
|
||||
|
||||
tgp_chat_blist_store (TLS, P, _("Telegram Channels"));
|
||||
tgp_chat_show (TLS, P);
|
||||
}
|
||||
|
||||
static void tgp_chat_add_all_users (struct tgl_state *TLS, PurpleConversation *conv, tgl_peer_t *P) {
|
||||
debug ("tgp_chat_add_all_users()");
|
||||
|
||||
GList *users = NULL,
|
||||
*flags = NULL;
|
||||
debug ("tgp_chat_add_all_users()");
|
||||
|
||||
int i = 0;
|
||||
for (; i < C->user_list_size; i++) {
|
||||
struct tgl_chat_user *uid = (C->user_list + i);
|
||||
const char *name = tgp_blist_lookup_purple_name (TLS, TGL_MK_USER(uid->user_id));
|
||||
if (! name) {
|
||||
g_warn_if_reached();
|
||||
continue;
|
||||
|
||||
switch (tgl_get_peer_type (P->id)) {
|
||||
case TGL_PEER_CHAT: {
|
||||
struct tgl_chat *C = &P->chat;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < C->user_list_size; i ++) {
|
||||
struct tgl_chat_user *uid = (C->user_list + i);
|
||||
const char *name = tgp_blist_lookup_purple_name (TLS, TGL_MK_USER(uid->user_id));
|
||||
if (name) {
|
||||
users = g_list_append (users, g_strdup (name));
|
||||
flags = g_list_append (flags, GINT_TO_POINTER(C->admin_id == uid->user_id ? PURPLE_CBFLAGS_FOUNDER : PURPLE_CBFLAGS_NONE));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
users = g_list_append (users, g_strdup (name));
|
||||
flags = g_list_append (flags, GINT_TO_POINTER(C->admin_id == uid->user_id ? PURPLE_CBFLAGS_FOUNDER : PURPLE_CBFLAGS_NONE));
|
||||
|
||||
case TGL_PEER_CHANNEL: {
|
||||
// fetch users
|
||||
GList *MS = g_hash_table_lookup (tls_get_data (TLS)->channel_members, GINT_TO_POINTER(tgl_get_peer_id (P->id)));
|
||||
|
||||
while (MS) {
|
||||
struct tgp_channel_member *M = MS->data;
|
||||
const char *name = tgp_blist_lookup_purple_name (TLS, M->id);
|
||||
if (name) {
|
||||
users = g_list_append (users, g_strdup (name));
|
||||
flags = g_list_append (flags, GINT_TO_POINTER(M->flags));
|
||||
}
|
||||
MS = g_list_next (MS);
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
g_return_if_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
purple_conv_chat_add_users (PURPLE_CONV_CHAT(conv), users, NULL, flags, FALSE);
|
||||
g_list_free_full (users, g_free);
|
||||
g_list_free (flags);
|
||||
}
|
||||
|
||||
PurpleConversation *tgp_chat_show (struct tgl_state *TLS, struct tgl_chat *C) {
|
||||
PurpleConversation *tgp_chat_show (struct tgl_state *TLS, tgl_peer_t *P) {
|
||||
PurpleConvChat *chat = NULL;
|
||||
|
||||
// check if chat is already shown
|
||||
PurpleConversation *conv = purple_find_chat (tls_get_conn (TLS), tgl_get_peer_id (C->id));
|
||||
PurpleConversation *conv = purple_find_chat (tls_get_conn (TLS), tgl_get_peer_id (P->id));
|
||||
if (conv) {
|
||||
chat = purple_conversation_get_chat_data (conv);
|
||||
if (chat && ! purple_conv_chat_has_left (chat)) {
|
||||
return conv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// join the chat now
|
||||
conv = serv_got_joined_chat (tls_get_conn (TLS), tgl_get_peer_id (C->id), C->print_title);
|
||||
const char *name = NULL;
|
||||
if (tgl_get_peer_type (P->id) == TGL_PEER_CHAT) {
|
||||
name = P->chat.print_title;
|
||||
} else if (tgl_get_peer_type (P->id) == TGL_PEER_CHANNEL) {
|
||||
name = P->channel.print_title;
|
||||
}
|
||||
g_return_val_if_fail(name, NULL);
|
||||
|
||||
conv = serv_got_joined_chat (tls_get_conn (TLS), tgl_get_peer_id (P->id), name);
|
||||
g_return_val_if_fail(conv, NULL);
|
||||
|
||||
|
||||
purple_conv_chat_clear_users (purple_conversation_get_chat_data (conv));
|
||||
tgp_chat_add_all_users (TLS, conv, C);
|
||||
|
||||
tgp_chat_add_all_users (TLS, conv, P);
|
||||
|
||||
return conv;
|
||||
}
|
||||
|
||||
int tgprpl_send_chat (PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags) {
|
||||
debug ("tgprpl_send_chat()");
|
||||
|
||||
tgl_peer_t *P = tgl_peer_get (gc_get_tls (gc), TGL_MK_CHAT(id));
|
||||
if (! P) {
|
||||
P = tgl_peer_get (gc_get_tls (gc), TGL_MK_CHANNEL(id));
|
||||
}
|
||||
g_return_val_if_fail(P != NULL, -1);
|
||||
|
||||
return tgp_msg_send (gc_get_tls (gc), message, P->id);
|
||||
}
|
||||
|
||||
GList *tgprpl_chat_join_info (PurpleConnection *gc) {
|
||||
struct proto_chat_entry *pce;
|
||||
pce = g_new0 (struct proto_chat_entry, 1);
|
||||
|
@ -149,8 +219,7 @@ GHashTable *tgprpl_chat_info_defaults (PurpleConnection *gc, const char *chat_na
|
|||
if (chat_name) {
|
||||
tgl_peer_t *P = tgl_peer_get_by_name (gc_get_tls (gc), chat_name);
|
||||
if (P) {
|
||||
debug ("found chat...");
|
||||
return tgp_chat_info_new (gc_get_tls (gc), &P->chat);
|
||||
return tgp_chat_info_new (gc_get_tls (gc), P);
|
||||
}
|
||||
warning ("Chat not found, returning empty defaults...");
|
||||
}
|
||||
|
@ -176,13 +245,24 @@ void tgprpl_chat_join (PurpleConnection *gc, GHashTable *data) {
|
|||
// join existing chat by id when the user clicks on a chat in the buddy list
|
||||
void *value = g_hash_table_lookup (data, "id");
|
||||
if (value && atoi (value)) {
|
||||
tgl_peer_id_t cid = TGL_MK_CHAT(atoi (value));
|
||||
tgl_peer_t *P = tgl_peer_get (gc_get_tls (gc), cid);
|
||||
tgl_peer_t *P = tgl_peer_get (gc_get_tls (gc), TGL_MK_CHAT(atoi (value)));
|
||||
|
||||
if (! P) {
|
||||
P = tgl_peer_get (gc_get_tls (gc), TGL_MK_CHANNEL(atoi (value)));
|
||||
}
|
||||
|
||||
if (P) {
|
||||
debug ("joining chat by id %d ...", tgl_get_peer_id (cid));
|
||||
tgl_do_get_chat_info (gc_get_tls (gc), cid, FALSE, tgp_chat_on_loaded_chat_full_joining, NULL);
|
||||
debug ("type=%d", tgl_get_peer_type (P->id));
|
||||
if (tgl_get_peer_type (P->id) == TGL_PEER_CHAT) {
|
||||
debug ("joining chat by id %d ...", tgl_get_peer_id (P->id));
|
||||
tgl_do_get_chat_info (gc_get_tls (gc), P->id, FALSE, tgp_chat_on_loaded_chat_full_joining, NULL);
|
||||
} else {
|
||||
g_return_if_fail(tgl_get_peer_type (P->id) == TGL_PEER_CHANNEL);
|
||||
debug ("joining channel by id %d ...", tgl_get_peer_id (P->id));
|
||||
tgp_chat_load_channel_members (gc_get_tls (gc), P, tgp_chat_on_loaded_channel_full_joining, NULL);
|
||||
}
|
||||
} else {
|
||||
warning ("Cannot join chat %d, peer not found...", tgl_get_peer_id (cid));
|
||||
warning ("Cannot join chat %d, peer not found...", tgl_get_peer_id (P->id));
|
||||
purple_serv_got_join_chat_failed (gc, data);
|
||||
}
|
||||
return;
|
||||
|
@ -199,17 +279,25 @@ void tgprpl_chat_join (PurpleConnection *gc, GHashTable *data) {
|
|||
const char *subject = g_hash_table_lookup (data, "subject");
|
||||
if (str_not_empty (subject)) {
|
||||
tgl_peer_t *P = tgl_peer_get_by_name (gc_get_tls (gc), subject);
|
||||
|
||||
// handle joining chats by print_names as used by the Adium plugin
|
||||
if (P && tgl_get_peer_type (P->id) == TGL_PEER_CHAT) {
|
||||
debug ("joining chat by subject %s ...", subject);
|
||||
|
||||
tgl_do_get_chat_info (gc_get_tls (gc), P->id, FALSE, tgp_chat_on_loaded_chat_full_joining, NULL);
|
||||
if (! P) {
|
||||
// user creates a new chat by providing its subject the chat join window
|
||||
request_create_chat (gc_get_tls (gc), subject);
|
||||
return;
|
||||
}
|
||||
|
||||
// user creates a new chat by providing its subject the chat join window
|
||||
request_create_chat (gc_get_tls (gc), subject);
|
||||
// handle joining chats by print_names as used by the Adium plugin
|
||||
if (tgl_get_peer_type (P->id) == TGL_PEER_CHAT) {
|
||||
debug ("joining chat by subject %s ...", subject);
|
||||
tgl_do_get_chat_info (gc_get_tls (gc), P->id, FALSE, tgp_chat_on_loaded_chat_full_joining, NULL);
|
||||
return;
|
||||
} else if (tgl_get_peer_type (P->id) == TGL_PEER_CHANNEL) {
|
||||
debug ("joining channel by subject %s ...", subject);
|
||||
tgp_chat_load_channel_members (gc_get_tls (gc), P, tgp_chat_on_loaded_channel_full_joining, NULL);
|
||||
return;
|
||||
} else {
|
||||
warning ("Cannot join chat %s, wrong peer type", subject);
|
||||
purple_serv_got_join_chat_failed (gc, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,3 +371,109 @@ void tgp_chat_join_all_pending (struct tgl_state *TLS) {
|
|||
tls_get_data (TLS)->pending_joins = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void tgp_channel_load_admins_done (struct tgl_state *TLS, void *extra, int success, int users_num,
|
||||
struct tgl_user **users) {
|
||||
debug ("tgp_channel_load_admins_done()");
|
||||
|
||||
struct tgp_channel_members_loading *D = extra;
|
||||
|
||||
if (success) {
|
||||
GHashTable *HT = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < users_num; i ++) {
|
||||
g_hash_table_insert (HT, GINT_TO_POINTER(tgl_get_peer_id (users[i]->id)), GINT_TO_POINTER(1));
|
||||
}
|
||||
|
||||
GList *MS = D->members;
|
||||
do {
|
||||
struct tgp_channel_member *M = MS->data;
|
||||
if (g_hash_table_lookup (HT, GINT_TO_POINTER(tgl_get_peer_id (M->id)))) {
|
||||
M->flags |= PURPLE_CBFLAGS_OP;
|
||||
}
|
||||
} while ((MS = g_list_next (MS)));
|
||||
g_hash_table_insert (tls_get_data (TLS)->channel_members, GINT_TO_POINTER(tgl_get_peer_id (D->P->id)), MS);
|
||||
|
||||
g_hash_table_destroy (HT);
|
||||
}
|
||||
|
||||
D->callback (TLS, success, D->P, D->extra);
|
||||
free (D);
|
||||
}
|
||||
|
||||
static void tgp_channel_load_members_done (struct tgl_state *TLS, void *extra, int success, int users_num,
|
||||
struct tgl_user **users) {
|
||||
debug ("tgp_channel_load_members_done()");
|
||||
|
||||
struct tgp_channel_members_loading *D = extra;
|
||||
|
||||
if (! success) {
|
||||
D->callback (TLS, FALSE, D->P, NULL);
|
||||
free (D);
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < users_num; i ++) {
|
||||
struct tgp_channel_member *M = talloc0 (sizeof(struct tgp_channel_member));
|
||||
M->id = users[i]->id;
|
||||
D->members = g_list_append (D->members, M);
|
||||
}
|
||||
|
||||
if (D->P->flags & TGLCHF_ADMIN) {
|
||||
tgl_do_channel_get_members (TLS, D->P->id,
|
||||
purple_account_get_int (tls_get_pa (TLS), TGP_KEY_CHANNEL_MEMBERS, TGP_DEFAULT_CHANNEL_MEMBERS),
|
||||
0, 1, tgp_channel_load_admins_done, D);
|
||||
} else {
|
||||
g_hash_table_insert (tls_get_data (TLS)->channel_members, GINT_TO_POINTER(tgl_get_peer_id (D->P->id)),
|
||||
D->members);
|
||||
D->callback (TLS, success, D->P, D->extra);
|
||||
free (D);
|
||||
}
|
||||
}
|
||||
|
||||
void tgp_chat_load_channel_members (struct tgl_state *TLS, tgl_peer_t *P,
|
||||
void (*callback) (struct tgl_state *TLS, int success, tgl_peer_t *P, void *extra), void *extra) {
|
||||
|
||||
struct tgp_channel_members_loading *D = talloc0 (sizeof(struct tgp_channel_members_loading));
|
||||
D->P = P;
|
||||
D->callback = callback;
|
||||
D->remaining = 2;
|
||||
D->extra = extra;
|
||||
|
||||
tgl_do_channel_get_members (TLS, P->id,
|
||||
purple_account_get_int (tls_get_pa (TLS), TGP_KEY_CHANNEL_MEMBERS, TGP_DEFAULT_CHANNEL_MEMBERS),
|
||||
0, 0, tgp_channel_load_members_done, D);
|
||||
}
|
||||
|
||||
static void update_chat (struct tgl_state *TLS, tgl_peer_t *C, unsigned flags, const char *group) {
|
||||
if (flags & TGL_UPDATE_CREATED) {
|
||||
tgp_blist_lookup_add (TLS, C->id, C->print_name);
|
||||
tgp_chat_blist_store (TLS, tgl_peer_get (TLS, C->id), group);
|
||||
|
||||
} else {
|
||||
PurpleChat *PC = tgp_blist_chat_find (TLS, C->id);
|
||||
if (PC) {
|
||||
if (flags & TGL_UPDATE_TITLE) {
|
||||
purple_blist_alias_chat (PC, C->print_name);
|
||||
}
|
||||
if (flags & TGL_UPDATE_DELETED) { // TODO: test if this is actually executed on deletion
|
||||
purple_blist_remove_chat (PC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_channel_handler (struct tgl_state *TLS, struct tgl_channel *C, unsigned flags) {
|
||||
debug ("update_channel_handler() (%s)", print_flags_update (flags));
|
||||
|
||||
update_chat (TLS, tgl_peer_get (TLS, C->id), flags, _("Telegram Channels"));
|
||||
}
|
||||
|
||||
void update_chat_handler (struct tgl_state *TLS, struct tgl_chat *C, unsigned flags) {
|
||||
debug ("update_chat_handler() (%s)", print_flags_update (flags));
|
||||
|
||||
update_chat (TLS, tgl_peer_get (TLS, C->id), flags, _("Telegram Chats"));
|
||||
}
|
||||
|
||||
|
|
26
tgp-chat.h
26
tgp-chat.h
|
@ -23,14 +23,26 @@
|
|||
|
||||
#include "telegram-purple.h"
|
||||
|
||||
PurpleChat *p2tgl_chat_new (struct tgl_state *TLS, struct tgl_chat *chat);
|
||||
struct tgp_channel_member {
|
||||
tgl_peer_id_t id;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct tgp_channel_members_loading {
|
||||
tgl_peer_t *P;
|
||||
GList *members;
|
||||
void (*callback) (struct tgl_state *TLS, int success, tgl_peer_t *P, void *extra);
|
||||
void *extra;
|
||||
int remaining;
|
||||
};
|
||||
|
||||
PurpleChat *tgp_chat_new (struct tgl_state *TLS, tgl_peer_t *P);
|
||||
|
||||
tgl_peer_id_t tgp_chat_get_id (PurpleChat *C);
|
||||
int tgp_chat_has_id (PurpleChat *C);
|
||||
|
||||
void tgp_chat_on_loaded_chat_full (struct tgl_state *TLS, struct tgl_chat *C);
|
||||
PurpleConversation *tgp_chat_show (struct tgl_state *TLS, struct tgl_chat *C);
|
||||
|
||||
PurpleConversation *tgp_chat_show (struct tgl_state *TLS, tgl_peer_t *P);
|
||||
int tgprpl_send_chat (PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags);
|
||||
char *tgprpl_get_chat_name (GHashTable *data);
|
||||
void tgprpl_chat_join (PurpleConnection *gc, GHashTable *data);
|
||||
GList *tgprpl_chat_join_info (PurpleConnection *gc);
|
||||
|
@ -38,4 +50,10 @@ PurpleRoomlist *tgprpl_roomlist_get_list (PurpleConnection *gc);
|
|||
void tgprpl_roomlist_cancel (PurpleRoomlist *list);
|
||||
GHashTable *tgprpl_chat_info_defaults (PurpleConnection *gc, const char *chat_name);
|
||||
void tgp_chat_join_all_pending (struct tgl_state *TLS);
|
||||
|
||||
void tgp_chat_load_channel_members (struct tgl_state *TLS, tgl_peer_t *P,
|
||||
void (*callback) (struct tgl_state *TLS, int success, tgl_peer_t *P, void *extra), void *extra);
|
||||
void update_channel_handler (struct tgl_state *TLS, struct tgl_channel *C, unsigned flags);
|
||||
void update_chat_handler (struct tgl_state *TLS, struct tgl_chat *C, unsigned flags);
|
||||
|
||||
#endif
|
||||
|
|
121
tgp-msg.c
121
tgp-msg.c
|
@ -105,7 +105,7 @@ static char *format_service_msg (struct tgl_state *TLS, struct tgl_message *M) {
|
|||
|
||||
// make sure that the chat is showing before deleting the user, otherwise the chat will be
|
||||
// initialised after removing the chat and the chat will still contain the deleted user
|
||||
PurpleConversation *conv = tgp_chat_show (TLS, &chatPeer->chat);
|
||||
PurpleConversation *conv = tgp_chat_show (TLS, chatPeer);
|
||||
if (conv) {
|
||||
char *alias = peer->print_name;
|
||||
const char *aliasLeft = tgp_blist_lookup_purple_name (TLS, TGL_MK_USER (M->action.user));
|
||||
|
@ -214,7 +214,8 @@ static gboolean tgp_msg_send_schedule_cb (gpointer data) {
|
|||
g_queue_pop_head (conn->out_messages);
|
||||
|
||||
unsigned long long flags = 0;
|
||||
if (tgl_get_peer_type (D->to) == TGL_PEER_CHANNEL) {
|
||||
if (tgl_get_peer_type (D->to) == TGL_PEER_CHANNEL
|
||||
&& !(tgl_peer_get (conn->TLS, D->to)->channel.flags & TGLCHF_MEGAGROUP)) {
|
||||
flags |= TGLMF_POST_AS_CHANNEL;
|
||||
}
|
||||
// TODO: option for disable_msg_preview
|
||||
|
@ -248,17 +249,12 @@ static int tgp_msg_send_split (struct tgl_state *TLS, const char *message, tgl_p
|
|||
start = end;
|
||||
}
|
||||
|
||||
// Prevent client from automatically printing the outgoing message. Channel messages are always printed by the
|
||||
// channel user, not by ourselves to emulate behavior similar to the other Telegram clients.
|
||||
if (tgl_get_peer_type (to) == TGL_PEER_CHANNEL) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void tgp_msg_special_out (struct tgl_state *TLS, const char *msg, tgl_peer_id_t to_id, int flags) {
|
||||
if (tgl_get_peer_type (to_id) == TGL_PEER_CHAT) {
|
||||
p2tgl_got_chat_in (TLS, to_id, to_id, msg, flags, time(0));
|
||||
tgp_chat_got_in (TLS, tgl_peer_get (TLS, to_id), to_id, msg, flags, time(0));
|
||||
} else {
|
||||
// Regular IM conversations will not display specialized message flags like PURPLE_MESSAGE_ERROR or
|
||||
// PURPLE_MESSAGE_SYSTEM correctly when using serv_got_in, therefore it is necessary to use the underlying
|
||||
|
@ -419,20 +415,12 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
|
|||
}
|
||||
|
||||
// TODO: return 0 for all messages, so this isn't necessary and rely on this code to display all outgoing messages
|
||||
if (tgp_outgoing_msg (TLS, M) && tgl_get_peer_type (M->to_id) != TGL_PEER_CHANNEL) {
|
||||
if (tgp_outgoing_msg (TLS, M)
|
||||
&& tgl_get_peer_type (M->to_id) != TGL_PEER_CHANNEL
|
||||
&& tgl_get_peer_type (M->to_id) != TGL_PEER_CHAT) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __ADIUM_
|
||||
/* Adium ignores when this plugin returns 0 in prpl_send_im, even though that flag indicates that an outgoing
|
||||
message shouldn't be printed to the conversation. This will still look messy, cause some posts will show up
|
||||
with the current user's name, while external post will show up with the actual channel name, but there is no
|
||||
way to prevent outgoing messages in Adium. */
|
||||
if (tgp_outgoing_msg (TLS, M)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// filter empty or messages with invalid recipients
|
||||
if (! M->message || !tgl_get_peer_type (M->to_id)) {
|
||||
return;
|
||||
|
@ -562,17 +550,11 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
|
|||
flags |= PURPLE_MESSAGE_RECV;
|
||||
}
|
||||
|
||||
if (tgl_get_peer_type (M->to_id) != TGL_PEER_ENCR_CHAT && ! (M->flags & TGLMF_UNREAD)) {
|
||||
if (tgl_get_peer_type (M->to_id) != TGL_PEER_ENCR_CHAT
|
||||
&& tgl_get_peer_type (M->to_id) != TGL_PEER_CHANNEL
|
||||
&& ! (M->flags & TGLMF_UNREAD)) {
|
||||
flags |= PURPLE_MESSAGE_DELAYED;
|
||||
}
|
||||
|
||||
#ifdef __ADIUM_
|
||||
/* (oh boy, here we go again...) Adium will print DELAYED messages with a custom layout, which causes the
|
||||
already fucked-up layout (see ifdef __ADIUM_ above) to be even more confusing. */
|
||||
if (! (M->flags & TGLMF_UNREAD) && tgl_get_peer_type (M->to_id) == TGL_PEER_CHANNEL) {
|
||||
flags ^= PURPLE_MESSAGE_DELAYED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// some service messages (like removing/adding users from chats) might print the message
|
||||
// text through other means and leave the text empty
|
||||
|
@ -619,15 +601,26 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
|
|||
|
||||
// display the message to the user
|
||||
switch (tgl_get_peer_type (M->to_id)) {
|
||||
case TGL_PEER_CHAT: {
|
||||
case TGL_PEER_CHANNEL: {
|
||||
tgl_peer_t *P = tgl_peer_get (TLS, M->to_id);
|
||||
g_return_if_fail(P != NULL);
|
||||
|
||||
if (tgp_chat_show (TLS, &P->chat)) {
|
||||
p2tgl_got_chat_in (TLS, M->to_id, M->from_id, text, flags, M->date);
|
||||
if (P->channel.flags & TGLCHF_MEGAGROUP) {
|
||||
// sender is the group
|
||||
tgp_chat_got_in (TLS, P, M->from_id, text, flags, M->date);
|
||||
} else {
|
||||
|
||||
// sender is the channel itself
|
||||
tgp_chat_got_in (TLS, P, P->id, text, flags, M->date);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TGL_PEER_CHAT: {
|
||||
tgl_peer_t *P = tgl_peer_get (TLS, M->to_id);
|
||||
g_return_if_fail(P != NULL);
|
||||
tgp_chat_got_in (TLS, P, M->from_id, text, flags, M->date);
|
||||
break;
|
||||
}
|
||||
case TGL_PEER_ENCR_CHAT: {
|
||||
p2tgl_got_im_combo (TLS, M->to_id, text, flags, M->date);
|
||||
break;
|
||||
|
@ -642,9 +635,6 @@ static void tgp_msg_display (struct tgl_state *TLS, struct tgp_msg_loading *C) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TGL_PEER_CHANNEL:
|
||||
p2tgl_got_im_combo (TLS, M->to_id, text, flags, M->date);
|
||||
break;
|
||||
}
|
||||
g_free (text);
|
||||
}
|
||||
|
@ -701,19 +691,33 @@ static void tgp_msg_on_loaded_document (struct tgl_state *TLS, void *extra, int
|
|||
|
||||
static void tgp_msg_on_loaded_chat_full (struct tgl_state *TLS, void *extra, int success, struct tgl_chat *chat) {
|
||||
debug ("tgp_msg_on_loaded_chat_full()");
|
||||
|
||||
tgp_chat_on_loaded_chat_full (TLS, chat);
|
||||
struct tgp_msg_loading *C = extra;
|
||||
|
||||
|
||||
if (! success) {
|
||||
// foreign user's names won't be displayed in the user list
|
||||
g_warn_if_reached();
|
||||
}
|
||||
|
||||
|
||||
struct tgp_msg_loading *C = extra;
|
||||
-- C->pending;
|
||||
|
||||
tgp_msg_process_in_ready (TLS);
|
||||
}
|
||||
|
||||
static void tgp_msg_on_loaded_channel_members (struct tgl_state *TLS, int success, tgl_peer_t *P, void *extra) {
|
||||
debug ("tgp_msg_on_loaded_channel_members()");
|
||||
|
||||
if (! success) {
|
||||
// user names won't be available in the channel
|
||||
g_warn_if_reached();
|
||||
}
|
||||
|
||||
struct tgp_msg_loading *C = extra;
|
||||
-- C->pending;
|
||||
|
||||
tgp_msg_process_in_ready (TLS);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static void tgp_msg_on_loaded_user_full (struct tgl_state *TLS, void *extra, int success, struct tgl_user *U) {
|
||||
debug ("tgp_msg_on_loaded_user_full()");
|
||||
|
@ -796,26 +800,39 @@ void tgp_msg_recv (struct tgl_state *TLS, struct tgl_message *M) {
|
|||
}
|
||||
*/
|
||||
|
||||
if (tgl_get_peer_type (M->to_id) == TGL_PEER_CHAT) {
|
||||
|
||||
tgl_peer_t *P = tgl_peer_get (TLS, M->to_id);
|
||||
g_warn_if_fail(P);
|
||||
if (P && ! P->chat.user_list_size) {
|
||||
// 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.
|
||||
// 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
|
||||
gpointer to_ptr = GINT_TO_POINTER(tgl_get_peer_id (M->to_id));
|
||||
|
||||
if (! g_hash_table_lookup (conn->pending_chat_info, to_ptr)) {
|
||||
|
||||
if (tgl_get_peer_type (M->to_id) == TGL_PEER_CHAT) {
|
||||
tgl_peer_t *P = tgl_peer_get (TLS, M->to_id);
|
||||
g_warn_if_fail(P);
|
||||
|
||||
// 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
|
||||
gpointer to_ptr = GINT_TO_POINTER(tgl_get_peer_id (M->to_id));
|
||||
|
||||
if (! g_hash_table_lookup (conn->pending_chat_info, to_ptr)) {
|
||||
if (P && ! P->chat.user_list_size) {
|
||||
++ C->pending;
|
||||
|
||||
tgl_do_get_chat_info (TLS, M->to_id, FALSE, tgp_msg_on_loaded_chat_full, C);
|
||||
g_hash_table_replace (conn->pending_chat_info, to_ptr, to_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (tgl_get_peer_type (M->to_id) == TGL_PEER_CHANNEL) {
|
||||
tgl_peer_t *P = tgl_peer_get (TLS, M->to_id);
|
||||
g_warn_if_fail(P);
|
||||
|
||||
// FIXME: check if the types are actually valid
|
||||
if (P && ((P->channel.flags & (TGLCHF_ADMIN | TGLCHF_CREATOR)) || (P->channel.flags & TGLCHF_MEGAGROUP))) {
|
||||
++ C->pending;
|
||||
|
||||
tgp_chat_load_channel_members (TLS, P, tgp_msg_on_loaded_channel_members, C);
|
||||
g_hash_table_replace (conn->pending_chat_info, to_ptr, to_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_queue_push_tail (conn->new_messages, C);
|
||||
|
|
|
@ -104,6 +104,8 @@ connection_data *connection_data_init (struct tgl_state *TLS, PurpleConnection *
|
|||
conn->pending_chat_info = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
conn->id_to_purple_name = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
|
||||
conn->purple_name_to_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||
conn->channel_members = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (void (*) (gpointer)) g_list_free);
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
@ -120,6 +122,8 @@ void *connection_data_free (connection_data *conn) {
|
|||
g_hash_table_destroy (conn->pending_chat_info);
|
||||
g_hash_table_destroy (conn->id_to_purple_name);
|
||||
g_hash_table_destroy (conn->purple_name_to_id);
|
||||
g_hash_table_destroy (conn->channel_members);
|
||||
|
||||
tgprpl_xfer_free_all (conn);
|
||||
g_free (conn->TLS->base_path);
|
||||
tgl_free_all (conn->TLS);
|
||||
|
|
|
@ -46,6 +46,7 @@ typedef struct {
|
|||
GHashTable *pending_chat_info;
|
||||
GHashTable *id_to_purple_name;
|
||||
GHashTable *purple_name_to_id;
|
||||
GHashTable *channel_members;
|
||||
GList *pending_joins;
|
||||
int dialogues_ready;
|
||||
} connection_data;
|
||||
|
|
Loading…
Add table
Reference in a new issue