Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/majn/telegram-purple.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormjentsch <mtthsjntsch@gmail.com>2015-12-28 19:44:49 +0300
committermjentsch <mtthsjntsch@gmail.com>2015-12-28 19:44:49 +0300
commit8fed82cc75a6a3de8d13fcc8ea6a9ae5f7896545 (patch)
treedc106927b7515da75d1d47ddb16d0d04b60b0b99 /tgp-blist.c
parent855e6fc04e43788ffd7ed7ef63749411f7569870 (diff)
Fix writing messages to deleted buddies and cleanup
Do not depend on buddy list entries when looking up the ID from the user name, by maintaining a bi-directional mapping ID <-> username. Rename functions to make them more evident as something that operatos on the lookup. Cleanup blist functions by implementating generic iterator function over account buddies.
Diffstat (limited to 'tgp-blist.c')
-rw-r--r--tgp-blist.c139
1 files changed, 87 insertions, 52 deletions
diff --git a/tgp-blist.c b/tgp-blist.c
index e09f658..27e8572 100644
--- a/tgp-blist.c
+++ b/tgp-blist.c
@@ -18,38 +18,77 @@
#include "telegram-purple.h"
-const char *tgp_blist_peer_get_purple_name (struct tgl_state *TLS, tgl_peer_id_t id) {
- const char *name = g_hash_table_lookup (tls_get_data (TLS)->id_to_purple_name, GINT_TO_POINTER(tgl_get_peer_id (id)));
- if (! name) {
- g_warn_if_reached();
- return NULL;
+// utilities
+
+PurpleBlistNode *tgp_blist_iterate (struct tgl_state *TLS,
+ int (* callback) (PurpleBlistNode *node, void *extra), void *extra) {
+ PurpleBlistNode *node = purple_blist_get_root ();
+ while (node) {
+ if ((PURPLE_BLIST_NODE_IS_BUDDY(node) && purple_buddy_get_account ((PurpleBuddy *)node) == tls_get_pa (TLS))
+ || (PURPLE_BLIST_NODE_IS_CHAT(node) && purple_chat_get_account ((PurpleChat *)node) == tls_get_pa (TLS))) {
+ if (callback (node, extra)) {
+ return node;
+ }
+ }
+ node = purple_blist_node_next (node, FALSE);
}
+ return NULL;
+}
+
+// lookup
+
+const char *tgp_blist_lookup_purple_name (struct tgl_state *TLS, tgl_peer_id_t id) {
+ const char *name = g_hash_table_lookup (tls_get_data (TLS)->id_to_purple_name,
+ GINT_TO_POINTER(tgl_get_peer_id (id)));
+ g_warn_if_fail(name);
return name;
}
-void tgp_blist_peer_add_purple_name (struct tgl_state *TLS, tgl_peer_id_t id, const char *purple_name) {
+void tgp_blist_lookup_add (struct tgl_state *TLS, tgl_peer_id_t id, const char *purple_name) {
+
g_hash_table_replace (tls_get_data (TLS)->id_to_purple_name, GINT_TO_POINTER(tgl_get_peer_id (id)),
- g_strdup (purple_name));
+ g_strdup (name));
+ g_hash_table_replace (tls_get_data (TLS)->purple_name_to_id, g_strdup (name),
+ g_memdup (&id, sizeof(tgl_peer_id_t)));
+}
+
+static tgl_peer_id_t *tgp_blist_lookup_get_id (struct tgl_state *TLS, const char *purple_name) {
+ return g_hash_table_lookup (tls_get_data (TLS)->purple_name_to_id, purple_name);
+}
+
+tgl_peer_t *tgp_blist_lookup_peer_get (struct tgl_state *TLS, const char *purple_name) {
+ tgl_peer_id_t *id = tgp_blist_lookup_get_id (TLS, purple_name);
+ g_return_val_if_fail(id, NULL);
+ return tgl_peer_get (TLS, *id);
}
-tgl_peer_t *tgp_blist_peer_find (struct tgl_state *TLS, const char *purple_name) {
- // buddies will keep the name they had when they were first added to the user list. The print_name of the peer
- // may have changed since then, therefore the ID stored in the buddy is used to fetch the user name.
- PurpleBuddy *buddy = purple_find_buddy (tls_get_pa (TLS), purple_name);
- if (! buddy) {
- // foreign users are not in the buddy list by default, therefore the name used by libpurple and the
- // print name is always identical
- return tgl_peer_get_by_name (TLS, purple_name);
+static int tgp_blist_lookup_init_cb (PurpleBlistNode *node, void *extra) {
+ if (PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+ PurpleBuddy *buddy = (PurpleBuddy *) node;
+ if (tgl_get_peer_type (tgp_blist_buddy_get_id (buddy)) != TGL_PEER_UNKNOWN) {
+ tgp_blist_lookup_add (pbn_get_data (node)->TLS, tgp_blist_buddy_get_id (buddy),
+ purple_buddy_get_name (buddy));
+ }
}
- if (! tgp_blist_buddy_has_id (buddy)) {
- g_warn_if_reached ();
- return NULL;
+ if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
+ PurpleChat *chat = (PurpleChat *) node;
+ if (tgp_chat_has_id (chat)) {
+ tgp_blist_lookup_add (pbn_get_data (node)->TLS, tgp_chat_get_id (chat),
+ purple_chat_get_name (chat));
+ }
}
- return tgl_peer_get (TLS, tgp_blist_buddy_get_id (buddy));
+ return FALSE;
+}
+
+void tgp_blist_lookup_init (struct tgl_state *TLS) {
+ info ("loading known ids from buddy list ...");
+ tgp_blist_iterate (TLS, tgp_blist_lookup_init_cb, 0);
}
+// buddies
+
PurpleBuddy *tgp_blist_buddy_new (struct tgl_state *TLS, tgl_peer_t *user) {
- PurpleBuddy *buddy = purple_buddy_new (tls_get_pa (TLS), tgp_blist_peer_get_purple_name (TLS, user->id), NULL);
+ PurpleBuddy *buddy = purple_buddy_new (tls_get_pa (TLS), tgp_blist_lookup_purple_name (TLS, user->id), NULL);
tgp_blist_buddy_set_id (buddy, user->id);
return buddy;
}
@@ -84,9 +123,7 @@ tgl_peer_id_t tgp_blist_buddy_get_id (PurpleBuddy *buddy) {
} else if (type == TGL_PEER_ENCR_CHAT) {
return TGL_MK_ENCR_CHAT (id);
} else {
- assert (FALSE);
- // avoid compiler errors for missing return value
- return TGL_MK_USER(0);
+ return tgl_set_peer_id (TGL_PEER_UNKNOWN, 0);
}
}
@@ -98,40 +135,34 @@ tgl_peer_t *tgp_blist_buddy_get_peer (PurpleBuddy *buddy) {
return tgl_peer_get (pbn_get_data (&buddy->node)->TLS, tgp_blist_buddy_get_id (buddy));
}
+static int tgp_blist_buddy_find_cb (PurpleBlistNode *node, void *extra) {
+ return PURPLE_BLIST_NODE_IS_BUDDY(node)
+ && purple_blist_node_get_int (node, TGP_BUDDY_KEY_PEER_ID) == GPOINTER_TO_INT(extra);
+}
+
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) == tls_get_pa (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;
- }
- }
+ return (PurpleBuddy *) tgp_blist_iterate (TLS, tgp_blist_buddy_find_cb, GINT_TO_POINTER(tgl_get_peer_id (user)));
+}
+
+// chats
+
+static int tgp_blist_chat_find_cb (PurpleBlistNode *node, void *extra) {
+ if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
+ PurpleChat *chat = PURPLE_CHAT(node);
+ const char *id = g_hash_table_lookup (purple_chat_get_components (chat), "id");
+ if (id && *id && atoi (id) == GPOINTER_TO_INT(extra)) {
+ return TRUE;
}
- node = purple_blist_node_next (node, FALSE);
}
- return NULL;
+ return FALSE;
}
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) == tls_get_pa (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;
+ return (PurpleChat *) tgp_blist_iterate (TLS, tgp_blist_chat_find_cb, GINT_TO_POINTER(tgl_get_peer_id (user)));
}
+// groups
+
PurpleGroup *tgp_blist_group_init (const char *name) {
PurpleGroup *grp = purple_find_group (name);
if (grp == NULL) {
@@ -141,8 +172,11 @@ PurpleGroup *tgp_blist_group_init (const char *name) {
return grp;
}
+// names
+
char *tgp_blist_create_print_name (struct tgl_state *TLS, tgl_peer_id_t id, const char *a1, const char *a2,
const char *a3, const char *a4) {
+
// libtgl passes 0 for all unused strings, therefore the last passed string will always be followed
// by a NULL-termination as expected
gchar *name = g_strjoin (" ", a1, a2, a3, a4, NULL);
@@ -160,13 +194,14 @@ char *tgp_blist_create_print_name (struct tgl_state *TLS, tgl_peer_id_t id, cons
with the old BlistNode. */
int i = 0;
gchar *n = NULL;
- tgl_peer_t *B = tgp_blist_peer_find (TLS, name);
- while (B && tgl_get_peer_id (B->id) != tgl_get_peer_id (id)) {
+ tgl_peer_id_t *id2 = tgp_blist_lookup_get_id (TLS, name);
+ while (id2 && tgl_get_peer_id (*id2) != tgl_get_peer_id (id)) {
if (n) {
g_free (n);
}
n = g_strdup_printf ("%s #%d", name, ++ i);
- B = tgp_blist_peer_find (TLS, n);
+ debug ("resolving duplicate for %s, assigning: %s", name, n);
+ id2 = tgp_blist_lookup_get_id (TLS, n);
}
if (n) {
g_free (name);