# HG changeset patch
# Node ID c5b6a11ee7b7b8889ef2300229ea29b4c7dd2190
# Parent  f0edc907e01842fc59d52965971b2c7329db94ad
diff --git a/libpurple/purpleconversation.c b/libpurple/purpleconversation.c
--- a/libpurple/purpleconversation.c
+++ b/libpurple/purpleconversation.c
@@ -198,6 +198,15 @@
 		if(PURPLE_IS_ACCOUNT(conversation->account)) {
 			PurpleContactInfo *info = NULL;
 			PurpleConversationMember *member = NULL;
+			const char *tag_value = NULL;
+
+			tag_value = purple_account_get_id(conversation->account);
+			purple_tags_add_with_value(conversation->tags, "account-id",
+			                           tag_value);
+
+			tag_value = purple_account_get_protocol_id(conversation->account);
+			purple_tags_add_with_value(conversation->tags, "protocol-id",
+			                           tag_value);
 
 			info = purple_account_get_contact_info(account);
 			member = purple_conversation_members_add_member(conversation->members,
@@ -227,8 +236,30 @@
 	g_return_if_fail(PURPLE_IS_CONVERSATION(conversation));
 
 	if(type != conversation->type) {
+		const char *tag_value = NULL;
+
 		conversation->type = type;
 
+		switch(conversation->type) {
+		case PURPLE_CONVERSATION_TYPE_DM:
+			tag_value = "dm";
+			break;
+		case PURPLE_CONVERSATION_TYPE_GROUP_DM:
+			tag_value = "group-dm";
+			break;
+		case PURPLE_CONVERSATION_TYPE_CHANNEL:
+			tag_value = "channel";
+			break;
+		case PURPLE_CONVERSATION_TYPE_THREAD:
+			tag_value = "thread";
+			break;
+		case PURPLE_CONVERSATION_TYPE_UNSET:
+		default:
+			tag_value = NULL;
+		}
+
+		purple_tags_add_with_value(conversation->tags, "type", tag_value);
+
 		g_object_notify_by_pspec(G_OBJECT(conversation),
 		                         properties[PROP_TYPE]);
 	}
@@ -243,6 +274,10 @@
 	if(conversation->federated != federated) {
 		conversation->federated = federated;
 
+		if(federated) {
+			purple_tags_add(conversation->tags, "federated");
+		}
+
 		g_object_notify_by_pspec(G_OBJECT(conversation),
 		                         properties[PROP_FEDERATED]);
 	}
@@ -605,6 +640,13 @@
 static void
 purple_conversation_init(PurpleConversation *conversation) {
 	conversation->tags = purple_tags_new();
+
+	/* If type provided during construction, the type setter isn't called,
+	 * which means this tag doesn't get created. To work around this, we set it
+	 * here, which will be overridden by the type setter.
+	 */
+	purple_tags_add(conversation->tags, "type");
+
 	conversation->messages = g_list_store_new(PURPLE_TYPE_MESSAGE);
 
 	conversation->members = purple_conversation_members_new();
diff --git a/libpurple/tests/test_conversation.c b/libpurple/tests/test_conversation.c
--- a/libpurple/tests/test_conversation.c
+++ b/libpurple/tests/test_conversation.c
@@ -614,6 +614,196 @@
 }
 
 /******************************************************************************
+ * Tags Tests
+ *****************************************************************************/
+static void
+test_purple_conversation_tags_unset(void) {
+	PurpleAccount *account = NULL;
+	PurpleConversation *conversation = NULL;
+	PurpleTags *actual = NULL;
+	PurpleTags *expected = NULL;
+	const char *account_id = NULL;
+
+	expected = purple_tags_new();
+	purple_tags_add_with_value(expected, "protocol-id", "test");
+	purple_tags_add(expected, "type");
+
+	account = purple_account_new("test", "test");
+	conversation = g_object_new(
+		PURPLE_TYPE_CONVERSATION,
+		"account", account,
+		NULL);
+
+	actual = purple_conversation_get_tags(conversation);
+	g_assert_true(purple_tags_contains(actual, expected));
+
+	/* Account id is randomly generated so we just make sure it's not null. */
+	account_id = purple_tags_get(actual, "account-id");
+	g_assert_nonnull(account_id);
+
+	g_assert_finalize_object(expected);
+	g_assert_finalize_object(conversation);
+	g_assert_finalize_object(account);
+}
+
+static void
+test_purple_conversation_tags_dm(void) {
+	PurpleAccount *account = NULL;
+	PurpleConversation *conversation = NULL;
+	PurpleTags *actual = NULL;
+	PurpleTags *expected = NULL;
+	const char *account_id = NULL;
+
+	expected = purple_tags_new();
+	purple_tags_add_with_value(expected, "protocol-id", "test");
+	purple_tags_add_with_value(expected, "type", "dm");
+
+	account = purple_account_new("test", "test");
+	conversation = g_object_new(
+		PURPLE_TYPE_CONVERSATION,
+		"account", account,
+		"type", PURPLE_CONVERSATION_TYPE_DM,
+		NULL);
+
+	actual = purple_conversation_get_tags(conversation);
+	g_assert_true(purple_tags_contains(actual, expected));
+
+	/* Account id is randomly generated so we just make sure it's not null. */
+	account_id = purple_tags_get(actual, "account-id");
+	g_assert_nonnull(account_id);
+
+	g_assert_finalize_object(expected);
+	g_assert_finalize_object(conversation);
+	g_assert_finalize_object(account);
+}
+
+static void
+test_purple_conversation_tags_group_dm(void) {
+	PurpleAccount *account = NULL;
+	PurpleConversation *conversation = NULL;
+	PurpleTags *actual = NULL;
+	PurpleTags *expected = NULL;
+	const char *account_id = NULL;
+
+	expected = purple_tags_new();
+	purple_tags_add_with_value(expected, "protocol-id", "test");
+	purple_tags_add_with_value(expected, "type", "group-dm");
+
+	account = purple_account_new("test", "test");
+	conversation = g_object_new(
+		PURPLE_TYPE_CONVERSATION,
+		"account", account,
+		"type", PURPLE_CONVERSATION_TYPE_GROUP_DM,
+		NULL);
+
+	actual = purple_conversation_get_tags(conversation);
+	g_assert_true(purple_tags_contains(actual, expected));
+
+	/* Account id is randomly generated so we just make sure it's not null. */
+	account_id = purple_tags_get(actual, "account-id");
+	g_assert_nonnull(account_id);
+
+	g_assert_finalize_object(expected);
+	g_assert_finalize_object(conversation);
+	g_assert_finalize_object(account);
+}
+
+static void
+test_purple_conversation_tags_channel(void) {
+	PurpleAccount *account = NULL;
+	PurpleConversation *conversation = NULL;
+	PurpleTags *actual = NULL;
+	PurpleTags *expected = NULL;
+	const char *account_id = NULL;
+
+	expected = purple_tags_new();
+	purple_tags_add_with_value(expected, "protocol-id", "test");
+	purple_tags_add_with_value(expected, "type", "channel");
+
+	account = purple_account_new("test", "test");
+	conversation = g_object_new(
+		PURPLE_TYPE_CONVERSATION,
+		"account", account,
+		"type", PURPLE_CONVERSATION_TYPE_CHANNEL,
+		NULL);
+
+	actual = purple_conversation_get_tags(conversation);
+	g_assert_true(purple_tags_contains(actual, expected));
+
+	/* Account id is randomly generated so we just make sure it's not null. */
+	account_id = purple_tags_get(actual, "account-id");
+	g_assert_nonnull(account_id);
+
+	g_assert_finalize_object(expected);
+	g_assert_finalize_object(conversation);
+	g_assert_finalize_object(account);
+}
+
+static void
+test_purple_conversation_tags_federated_channel(void) {
+	PurpleAccount *account = NULL;
+	PurpleConversation *conversation = NULL;
+	PurpleTags *actual = NULL;
+	PurpleTags *expected = NULL;
+	const char *account_id = NULL;
+
+	expected = purple_tags_new();
+	purple_tags_add(expected, "federated");
+	purple_tags_add_with_value(expected, "protocol-id", "test");
+	purple_tags_add_with_value(expected, "type", "channel");
+
+	account = purple_account_new("test", "test");
+	conversation = g_object_new(
+		PURPLE_TYPE_CONVERSATION,
+		"account", account,
+		"federated", TRUE,
+		"type", PURPLE_CONVERSATION_TYPE_CHANNEL,
+		NULL);
+
+	actual = purple_conversation_get_tags(conversation);
+	g_assert_true(purple_tags_contains(actual, expected));
+
+	/* Account id is randomly generated so we just make sure it's not null. */
+	account_id = purple_tags_get(actual, "account-id");
+	g_assert_nonnull(account_id);
+
+	g_assert_finalize_object(expected);
+	g_assert_finalize_object(conversation);
+	g_assert_finalize_object(account);
+}
+
+static void
+test_purple_conversation_tags_thread(void) {
+	PurpleAccount *account = NULL;
+	PurpleConversation *conversation = NULL;
+	PurpleTags *actual = NULL;
+	PurpleTags *expected = NULL;
+	const char *account_id = NULL;
+
+	expected = purple_tags_new();
+	purple_tags_add_with_value(expected, "protocol-id", "test");
+	purple_tags_add_with_value(expected, "type", "thread");
+
+	account = purple_account_new("test", "test");
+	conversation = g_object_new(
+		PURPLE_TYPE_CONVERSATION,
+		"account", account,
+		"type", PURPLE_CONVERSATION_TYPE_THREAD,
+		NULL);
+
+	actual = purple_conversation_get_tags(conversation);
+	g_assert_true(purple_tags_contains(actual, expected));
+
+	/* Account id is randomly generated so we just make sure it's not null. */
+	account_id = purple_tags_get(actual, "account-id");
+	g_assert_nonnull(account_id);
+
+	g_assert_finalize_object(expected);
+	g_assert_finalize_object(conversation);
+	g_assert_finalize_object(account);
+}
+
+/******************************************************************************
  * Main
  *****************************************************************************/
 gint
@@ -652,6 +842,19 @@
 	g_test_add_func("/conversation/generate-title/group-dm",
 	                test_purple_conversation_generate_title_group_dm);
 
+	g_test_add_func("/conversation/tags/unset",
+	                test_purple_conversation_tags_unset);
+	g_test_add_func("/conversation/tags/dm",
+	                test_purple_conversation_tags_dm);
+	g_test_add_func("/conversation/tags/group-dm",
+	                test_purple_conversation_tags_group_dm);
+	g_test_add_func("/conversation/tags/channel",
+	                test_purple_conversation_tags_channel);
+	g_test_add_func("/conversation/tags/federated-channel",
+	                test_purple_conversation_tags_federated_channel);
+	g_test_add_func("/conversation/tags/thread",
+	                test_purple_conversation_tags_thread);
+
 	ret = g_test_run();
 
 	test_ui_purple_uninit();
