summaryrefslogtreecommitdiff
path: root/libpurple/protocols/qq/group_internal.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpurple/protocols/qq/group_internal.c')
-rw-r--r--libpurple/protocols/qq/group_internal.c519
1 files changed, 348 insertions, 171 deletions
diff --git a/libpurple/protocols/qq/group_internal.c b/libpurple/protocols/qq/group_internal.c
index 1853fd2999..002e19b875 100644
--- a/libpurple/protocols/qq/group_internal.c
+++ b/libpurple/protocols/qq/group_internal.c
@@ -27,219 +27,396 @@
#include "debug.h"
#include "buddy_opt.h"
-#include "group_free.h"
#include "group_internal.h"
#include "utils.h"
-static gchar *get_role_desc(qq_group *group)
+static qq_room_data *room_data_new(guint32 id, guint32 ext_id, gchar *title)
{
- const char *role_desc;
- g_return_val_if_fail(group != NULL, g_strdup(""));
+ qq_room_data *rmd;
- switch (group->my_role) {
- case QQ_ROOM_ROLE_NO:
- role_desc = _("I am not a member");
- break;
- case QQ_ROOM_ROLE_YES:
- role_desc = _("I am a member");
- break;
- case QQ_ROOM_ROLE_REQUESTING:
- role_desc = _("I am requesting");
- break;
- case QQ_ROOM_ROLE_ADMIN:
- role_desc = _("I am the admin");
- break;
- default:
- role_desc = _("Unknown status");
+ purple_debug_info("QQ", "Created room data: %s, ext id %d, id %d\n",
+ title, ext_id, id);
+ rmd = g_new0(qq_room_data, 1);
+ rmd->my_role = QQ_ROOM_ROLE_NO;
+ rmd->id = id;
+ rmd->ext_id = ext_id;
+ rmd->type8 = 0x01; /* assume permanent Qun */
+ rmd->creator_uid = 10000; /* assume by QQ admin */
+ rmd->category = 0x01;
+ rmd->auth_type = 0x02; /* assume need auth */
+ rmd->title_utf8 = g_strdup(title == NULL ? "" : title);
+ rmd->desc_utf8 = g_strdup("");
+ rmd->notice_utf8 = g_strdup("");
+ rmd->members = NULL;
+ rmd->is_got_buddies = FALSE;
+ return rmd;
+}
+
+/* create a qq_room_data from hashtable */
+static qq_room_data *room_data_new_by_hashtable(PurpleConnection *gc, GHashTable *data)
+{
+ qq_room_data *rmd;
+ guint32 id, ext_id;
+ gchar *value;
+
+ value = g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID);
+ id = value ? strtol(value, NULL, 10) : 0;
+ value= g_hash_table_lookup(data, QQ_ROOM_KEY_EXTERNAL_ID);
+ ext_id = value ? strtol(value, NULL, 10) : 0;
+ value = g_strdup(g_hash_table_lookup(data, QQ_ROOM_KEY_TITLE_UTF8));
+
+ rmd = room_data_new(id, ext_id, value);
+ rmd->my_role = QQ_ROOM_ROLE_YES;
+ return rmd;
+}
+
+/* gracefully free all members in a room */
+static void room_buddies_free(qq_room_data *rmd)
+{
+ gint i;
+ GList *list;
+ qq_buddy_data *bd;
+
+ g_return_if_fail(rmd != NULL);
+ i = 0;
+ while (NULL != (list = rmd->members)) {
+ bd = (qq_buddy_data *) list->data;
+ i++;
+ rmd->members = g_list_remove(rmd->members, bd);
+ qq_buddy_data_free(bd);
}
- return g_strdup(role_desc);
+ rmd->members = NULL;
}
-static void add_room_to_blist(PurpleConnection *gc, qq_group *group)
+/* gracefully free the memory for one qq_room_data */
+static void room_data_free(qq_room_data *rmd)
+{
+ g_return_if_fail(rmd != NULL);
+ room_buddies_free(rmd);
+ g_free(rmd->title_utf8);
+ g_free(rmd->desc_utf8);
+ g_free(rmd->notice_utf8);
+ g_free(rmd);
+}
+
+void qq_room_update_chat_info(PurpleChat *chat, qq_room_data *rmd)
+{
+ if (rmd->title_utf8 != NULL && strlen(rmd->title_utf8) > 0) {
+ purple_blist_alias_chat(chat, rmd->title_utf8);
+ }
+ g_hash_table_replace(chat->components,
+ g_strdup(QQ_ROOM_KEY_INTERNAL_ID),
+ g_strdup_printf("%d", rmd->id));
+ g_hash_table_replace(chat->components,
+ g_strdup(QQ_ROOM_KEY_EXTERNAL_ID),
+ g_strdup_printf("%d", rmd->ext_id));
+ g_hash_table_replace(chat->components,
+ g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(rmd->title_utf8));
+}
+
+static PurpleChat *chat_new(PurpleConnection *gc, qq_room_data *rmd)
{
GHashTable *components;
PurpleGroup *g;
PurpleChat *chat;
- components = qq_group_to_hashtable(group);
- chat = purple_chat_new(purple_connection_get_account(gc), group->title_utf8, components);
- g = qq_get_purple_group(PURPLE_GROUP_QQ_QUN);
+
+ purple_debug_info("QQ", "Add new chat: id %d, ext id %d, title %s\n",
+ rmd->id, rmd->ext_id, rmd->title_utf8);
+
+ components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ g_hash_table_insert(components,
+ g_strdup(QQ_ROOM_KEY_INTERNAL_ID), g_strdup_printf("%d", rmd->id));
+ g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_EXTERNAL_ID),
+ g_strdup_printf("%d", rmd->ext_id));
+ g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(rmd->title_utf8));
+
+ chat = purple_chat_new(purple_connection_get_account(gc), rmd->title_utf8, components);
+ g = qq_group_find_or_new(PURPLE_GROUP_QQ_QUN);
purple_blist_add_chat(chat, g, NULL);
- purple_debug_info("QQ", "You have added group \"%s\" to blist locally\n", group->title_utf8);
+
+ return chat;
}
-/* Create a dummy qq_group, which includes only internal_id, ext_id,
- * and potentially title_utf8, in case we need to call group_conv_show_window
- * right after creation. All other attributes are set to empty.
- * We need to send a get_group_info to the QQ server to update it right away */
-qq_group *qq_group_create_internal_record(PurpleConnection *gc,
- guint32 internal_id, guint32 ext_id, gchar *title_utf8)
+PurpleChat *qq_room_find_or_new(PurpleConnection *gc, guint32 id, guint32 ext_id)
{
- qq_group *group;
- qq_data *qd;
+ qq_data *qd;
+ qq_room_data *rmd;
+ PurpleChat *chat;
+ gchar *num_str;
- g_return_val_if_fail(internal_id > 0, NULL);
- qd = (qq_data *) gc->proto_data;
+ g_return_val_if_fail (gc != NULL && gc->proto_data != NULL, NULL);
+ qd = (qq_data *) gc->proto_data;
+
+ g_return_val_if_fail(id != 0 && ext_id != 0, NULL);
+
+ purple_debug_info("QQ", "Find or add new room: id %d, ext id %d\n", id, ext_id);
+
+ rmd = qq_room_data_find(gc, id);
+ if (rmd == NULL) {
+ rmd = room_data_new(id, ext_id, NULL);
+ g_return_val_if_fail(rmd != NULL, NULL);
+ rmd->my_role = QQ_ROOM_ROLE_YES;
+ qd->groups = g_list_append(qd->groups, rmd);
+ }
+
+ num_str = g_strdup_printf("%d", ext_id);
+ chat = purple_blist_find_chat(purple_connection_get_account(gc), num_str);
+ g_free(num_str);
+ if (chat) {
+ return chat;
+ }
+
+ return chat_new(gc, rmd);
+}
+
+void qq_room_remove(PurpleConnection *gc, guint32 id)
+{
+ qq_data *qd;
+ PurpleChat *chat;
+ qq_room_data *rmd;
+ gchar *num_str;
+ guint32 ext_id;
- group = g_new0(qq_group, 1);
- group->my_role = QQ_ROOM_ROLE_NO;
- group->my_role_desc = get_role_desc(group);
- group->id = internal_id;
- group->ext_id = ext_id;
- group->type8 = 0x01; /* assume permanent Qun */
- group->creator_uid = 10000; /* assume by QQ admin */
- group->category = 0x01;
- group->auth_type = 0x02; /* assume need auth */
- group->title_utf8 = g_strdup(title_utf8 == NULL ? "" : title_utf8);
- group->desc_utf8 = g_strdup("");
- group->notice_utf8 = g_strdup("");
- group->members = NULL;
+ g_return_if_fail (gc != NULL && gc->proto_data != NULL);
+ qd = (qq_data *) gc->proto_data;
+
+ purple_debug_info("QQ", "Find and remove room data, id %d", id);
+ rmd = qq_room_data_find(gc, id);
+ g_return_if_fail (rmd != NULL);
+
+ ext_id = rmd->ext_id;
+ qd->groups = g_list_remove(qd->groups, rmd);
+ room_data_free(rmd);
+
+ purple_debug_info("QQ", "Find and remove chat, ext_id %d", ext_id);
+ num_str = g_strdup_printf("%d", ext_id);
+ chat = purple_blist_find_chat(purple_connection_get_account(gc), num_str);
+ g_free(num_str);
- qd->groups = g_list_append(qd->groups, group);
- add_room_to_blist(gc, group);
+ g_return_if_fail (chat != NULL);
- return group;
+ purple_blist_remove_chat(chat);
}
-void qq_group_delete_internal_record(qq_data *qd, guint32 id)
+/* find a qq_buddy_data by uid, called by im.c */
+qq_buddy_data *qq_room_buddy_find(qq_room_data *rmd, guint32 uid)
{
- qq_group *group;
- GList *list;
+ GList *list;
+ qq_buddy_data *bd;
+ g_return_val_if_fail(rmd != NULL && uid > 0, NULL);
- list = qd->groups;
- while (list != NULL) {
- group = (qq_group *) qd->groups->data;
- if (id == group->id) {
- qd->groups = g_list_remove(qd->groups, group);
- qq_group_free(group);
- break;
- } else {
- list = list->next;
- }
- }
+ list = rmd->members;
+ while (list != NULL) {
+ bd = (qq_buddy_data *) list->data;
+ if (bd->uid == uid)
+ return bd;
+ else
+ list = list->next;
+ }
+
+ return NULL;
}
-/* convert a qq_group to hash-table, which could be component of PurpleChat */
-GHashTable *qq_group_to_hashtable(qq_group *group)
+/* remove a qq_buddy_data by uid, called by qq_group_opt.c */
+void qq_room_buddy_remove(qq_room_data *rmd, guint32 uid)
{
- GHashTable *components;
- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_ROLE), g_strdup_printf("%d", group->my_role));
- group->my_role_desc = get_role_desc(group);
+ GList *list;
+ qq_buddy_data *bd;
+ g_return_if_fail(rmd != NULL && uid > 0);
- g_hash_table_insert(components,
- g_strdup(QQ_ROOM_KEY_INTERNAL_ID), g_strdup_printf("%d", group->id));
- g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_EXTERNAL_ID),
- g_strdup_printf("%d", group->ext_id));
- g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_TYPE), g_strdup_printf("%d", group->type8));
- g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_CREATOR_UID), g_strdup_printf("%d", group->creator_uid));
- g_hash_table_insert(components,
- g_strdup(QQ_ROOM_KEY_CATEGORY), g_strdup_printf("%d", group->category));
- g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type));
- g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_ROLE_DESC), g_strdup(group->my_role_desc));
- g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(group->title_utf8));
- g_hash_table_insert(components, g_strdup(QQ_ROOM_KEY_DESC_UTF8), g_strdup(group->desc_utf8));
- return components;
+ list = rmd->members;
+ while (list != NULL) {
+ bd = (qq_buddy_data *) list->data;
+ if (bd->uid == uid) {
+ rmd->members = g_list_remove(rmd->members, bd);
+ return;
+ } else {
+ list = list->next;
+ }
+ }
+}
+
+qq_buddy_data *qq_room_buddy_find_or_new(PurpleConnection *gc, qq_room_data *rmd, guint32 member_uid)
+{
+ qq_buddy_data *member, *bd;
+ PurpleBuddy *buddy;
+ g_return_val_if_fail(rmd != NULL && member_uid > 0, NULL);
+
+ member = qq_room_buddy_find(rmd, member_uid);
+ if (member == NULL) { /* first appear during my session */
+ member = g_new0(qq_buddy_data, 1);
+ member->uid = member_uid;
+ buddy = purple_find_buddy(purple_connection_get_account(gc), uid_to_purple_name(member_uid));
+ if (buddy != NULL) {
+ bd = (qq_buddy_data *) buddy->proto_data;
+ if (bd != NULL && bd->nickname != NULL)
+ member->nickname = g_strdup(bd->nickname);
+ else if (buddy->alias != NULL)
+ member->nickname = g_strdup(buddy->alias);
+ }
+ rmd->members = g_list_append(rmd->members, member);
+ }
+
+ return member;
}
-/* create a qq_group from hashtable */
-qq_group *qq_room_create_by_hashtable(PurpleConnection *gc, GHashTable *data)
+qq_room_data *qq_room_data_find(PurpleConnection *gc, guint32 room_id)
{
+ GList *list;
+ qq_room_data *rmd;
qq_data *qd;
- qq_group *group;
- g_return_val_if_fail(data != NULL, NULL);
qd = (qq_data *) gc->proto_data;
- group = g_new0(qq_group, 1);
- group->my_role =
- qq_string_to_dec_value
- (NULL ==
- g_hash_table_lookup(data,
- QQ_ROOM_KEY_ROLE) ?
- g_strdup_printf("%d", QQ_ROOM_ROLE_NO) :
- g_hash_table_lookup(data, QQ_ROOM_KEY_ROLE));
- group->id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_INTERNAL_ID));
- group->ext_id = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_EXTERNAL_ID));
- group->type8 = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_TYPE));
- group->creator_uid = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_CREATOR_UID));
- group->category = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_CATEGORY));
- group->auth_type = qq_string_to_dec_value(g_hash_table_lookup(data, QQ_ROOM_KEY_AUTH_TYPE));
- group->title_utf8 = g_strdup(g_hash_table_lookup(data, QQ_ROOM_KEY_TITLE_UTF8));
- group->desc_utf8 = g_strdup(g_hash_table_lookup(data, QQ_ROOM_KEY_DESC_UTF8));
- group->my_role_desc = get_role_desc(group);
- group->is_got_info = FALSE;
-
- qd->groups = g_list_append(qd->groups, group);
- return group;
-}
-
-/* refresh group local subscription */
-void qq_group_refresh(PurpleConnection *gc, qq_group *group)
+ if (qd->groups == NULL || room_id <= 0)
+ return 0;
+
+ list = qd->groups;
+ while (list != NULL) {
+ rmd = (qq_room_data *) list->data;
+ if (rmd->id == room_id) {
+ return rmd;
+ }
+ list = list->next;
+ }
+
+ return NULL;
+}
+
+guint32 qq_room_get_next(PurpleConnection *gc, guint32 room_id)
{
+ GList *list;
+ qq_room_data *rmd;
+ qq_data *qd;
+ gboolean is_find = FALSE;
+
+ qd = (qq_data *) gc->proto_data;
+
+ if (qd->groups == NULL) {
+ return 0;
+ }
+
+ if (room_id <= 0) {
+ rmd = (qq_room_data *) qd->groups->data;
+ return rmd->id;
+ }
+
+ list = qd->groups;
+ while (list != NULL) {
+ rmd = (qq_room_data *) list->data;
+ list = list->next;
+ if (rmd->id == room_id) {
+ is_find = TRUE;
+ break;
+ }
+ }
+
+ g_return_val_if_fail(is_find, 0);
+ if (list == NULL) return 0; /* be the end */
+ rmd = (qq_room_data *) list->data;
+ g_return_val_if_fail(rmd != NULL, 0);
+ return rmd->id;
+}
+
+guint32 qq_room_get_next_conv(PurpleConnection *gc, guint32 room_id)
+{
+ GList *list;
+ qq_room_data *rmd;
+ qq_data *qd;
+ gboolean is_find;
+
+ qd = (qq_data *) gc->proto_data;
+
+ list = qd->groups;
+ if (room_id > 0) {
+ /* search next room */
+ is_find = FALSE;
+ while (list != NULL) {
+ rmd = (qq_room_data *) list->data;
+ list = list->next;
+ if (rmd->id == room_id) {
+ is_find = TRUE;
+ break;
+ }
+ }
+ g_return_val_if_fail(is_find, 0);
+ }
+
+ while (list != NULL) {
+ rmd = (qq_room_data *) list->data;
+ g_return_val_if_fail(rmd != NULL, 0);
+
+ if (rmd->my_role == QQ_ROOM_ROLE_YES || rmd->my_role == QQ_ROOM_ROLE_ADMIN) {
+ if (NULL != purple_find_conversation_with_account(
+ PURPLE_CONV_TYPE_CHAT,rmd->title_utf8, purple_connection_get_account(gc))) {
+ /* In convseration*/
+ return rmd->id;
+ }
+ }
+ list = list->next;
+ }
+
+ return 0;
+}
+
+/* this should be called upon signin, even when we did not open group chat window */
+void qq_room_data_initial(PurpleConnection *gc)
+{
+ PurpleAccount *account;
PurpleChat *chat;
- GHashTable *components;
- gchar *ext_id;
- g_return_if_fail(group != NULL);
-
- ext_id = g_strdup_printf("%d", group->ext_id);
- chat = purple_blist_find_chat(purple_connection_get_account(gc), ext_id);
- g_free(ext_id);
- if (chat == NULL && group->my_role != QQ_ROOM_ROLE_NO) {
- add_room_to_blist(gc, group);
+ PurpleGroup *purple_group;
+ PurpleBlistNode *node;
+ qq_data *qd;
+ qq_room_data *rmd;
+ gint count;
+
+ account = purple_connection_get_account(gc);
+ qd = (qq_data *) gc->proto_data;
+
+ purple_debug_info("QQ", "Initial QQ Qun configurations\n");
+ purple_group = purple_find_group(PURPLE_GROUP_QQ_QUN);
+ if (purple_group == NULL) {
+ purple_debug_info("QQ", "We have no QQ Qun\n");
return;
}
- if (chat == NULL) {
- return;
+ count = 0;
+ for (node = ((PurpleBlistNode *) purple_group)->child; node != NULL; node = node->next) {
+ if ( !PURPLE_BLIST_NODE_IS_CHAT(node)) {
+ continue;
+ }
+ /* got one */
+ chat = (PurpleChat *) node;
+ if (account != chat->account) /* not qq account*/
+ continue;
+
+ rmd = room_data_new_by_hashtable(gc, chat->components);
+ qd->groups = g_list_append(qd->groups, rmd);
+ count++;
}
- components = purple_chat_get_components(chat);
+ purple_debug_info("QQ", "Load %d QQ Qun configurations\n", count);
+}
- /* we have a local record, update its info */
- /* if there is title_utf8, we update the group name */
- if (group->title_utf8 != NULL && strlen(group->title_utf8) > 0)
- purple_blist_alias_chat(chat, group->title_utf8);
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_ROLE), g_strdup_printf("%d", group->my_role));
- group->my_role_desc = get_role_desc(group);
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_ROLE_DESC), g_strdup(group->my_role_desc));
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_INTERNAL_ID),
- g_strdup_printf("%d", group->id));
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_EXTERNAL_ID),
- g_strdup_printf("%d", group->ext_id));
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_TYPE), g_strdup_printf("%d", group->type8));
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_CREATOR_UID), g_strdup_printf("%d", group->creator_uid));
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_CATEGORY),
- g_strdup_printf("%d", group->category));
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_AUTH_TYPE), g_strdup_printf("%d", group->auth_type));
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_TITLE_UTF8), g_strdup(group->title_utf8));
- g_hash_table_replace(components,
- g_strdup(QQ_ROOM_KEY_DESC_UTF8), g_strdup(group->desc_utf8));
-}
-
-/* NOTE: If we knew how to convert between an external and internal group id, as the official
- * client seems to, the following would be unnecessary. That would be ideal. */
-
-/* Use list to specify if id's alternate id is pending discovery. */
-void qq_set_pending_id(GSList **list, guint32 id, gboolean pending)
-{
- if (pending)
- *list = g_slist_prepend(*list, GINT_TO_POINTER(id));
- else
- *list = g_slist_remove(*list, GINT_TO_POINTER(id));
-}
-
-/* Return the location of id in list, or NULL if not found */
-GSList *qq_get_pending_id(GSList *list, guint32 id)
-{
- return g_slist_find(list, GINT_TO_POINTER(id));
+void qq_room_data_free_all(PurpleConnection *gc)
+{
+ qq_data *qd;
+ qq_room_data *rmd;
+ gint count;
+
+ g_return_if_fail (gc != NULL && gc->proto_data != NULL);
+ qd = (qq_data *) gc->proto_data;
+
+ count = 0;
+ while (qd->groups != NULL) {
+ rmd = (qq_room_data *) qd->groups->data;
+ qd->groups = g_list_remove(qd->groups, rmd);
+ room_data_free(rmd);
+ count++;
+ }
+
+ if (count > 0) {
+ purple_debug_info("QQ", "%d rooms are freed\n", count);
+ }
}