/soc/2015/igor.gajowiak/chatlog: 2867d33d0158: Implemented getti...

Igor Gajowiak <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 2867d33d01586124e4b989cfcc0defae72873ebc
Author:	 Igor Gajowiak <[email protected]>
Date:	 2015-07-23 23:49 +0200
Branch:	 default
URL: https://hg.pidgin.im/soc/2015/igor.gajowiak/chatlog/rev/2867d33d0158

Description:

Implemented getting all buddies from the generic log.

diffstat:

 libpurple/genericlog.c            |  37 ++++++++++++++
 libpurple/genericlog.h            |  24 +++++++++
 libpurple/plugins/log/logsqlite.c |  98 ++++++++++++++++++++++++++++++++++++--
 pidgin/gtkgenericlog.c            |  79 ++++++++++++++++++++++++++----
 4 files changed, 219 insertions(+), 19 deletions(-)

diffs (truncated from 424 to 300 lines):

diff --git a/libpurple/genericlog.c b/libpurple/genericlog.c
--- a/libpurple/genericlog.c
+++ b/libpurple/genericlog.c
@@ -297,6 +297,43 @@ purple_genericlog_get_unseen_msgs(Purple
 	return TRUE;
 }
 
+gboolean
+purple_genericlog_get_all_buddies(GList** result, GError** error)
+{
+	if (!purple_genericlog_inuse) {
+		if (!error) return FALSE;
+
+		*error = g_error_new(purple_genericlog_error_domain(),
+			PURPLE_GENERICLOG_ERROR_NOLOG, "No active log");
+		return FALSE;
+	}
+
+	PurpleGenericLogClass *klass =
+		PURPLE_GENERICLOG_GET_CLASS(purple_genericlog_inuse);
+
+	if (!klass->get_all_buddies) {
+		if (!error) return FALSE;
+
+		*error = g_error_new(purple_genericlog_error_domain(),
+			PURPLE_GENERICLOG_ERROR_OPERATIONNOTSUPPORTED,
+			"%s does not support getting buddies from log",
+			purple_genericlog_get_id(purple_genericlog_inuse));
+		return FALSE;
+	}
+
+	if (!klass->get_all_buddies(result)) {
+		if (!error) return FALSE;
+
+		*error = g_error_new(purple_genericlog_error_domain(),
+			PURPLE_GENERICLOG_ERROR_BACKENDFAIL,
+			"Getting buddies from %s failed",
+			purple_genericlog_get_id(purple_genericlog_inuse));
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 /**************************************************************************/
 /* Error Codes                                                            */
 /**************************************************************************/
diff --git a/libpurple/genericlog.h b/libpurple/genericlog.h
--- a/libpurple/genericlog.h
+++ b/libpurple/genericlog.h
@@ -61,6 +61,10 @@ struct _PurpleGenericLog
  *                   In case of any error the result is not set.
  *                   The client is responsible for freeing the result with
  *                   g_list_free_full(result, g_object_unref).
+ * @get_all_buddies: Gets a list of all #PurpleBuddy objects with at least one
+ *                   message in the log. Returns %TRUE if operation succeeds,
+ *                   %FALSE otherwise. The client is responsible for freeing
+ *                   the result with g_list_free_full(result, g_object_unref).
  *
  * The abstract base class for all log implementations. A conforming plugin
  * must implement at least activate and deactivate methods. Not supported
@@ -81,6 +85,8 @@ struct _PurpleGenericLogClass
 
 	gboolean (*get_unseen_msgs)(PurpleAccount *account, GList **result);
 
+	gboolean (*get_all_buddies)(GList **result);
+
 	void (*reserved1)(void);
 	void (*reserved2)(void);
 	void (*reserved3)(void);
@@ -229,6 +235,24 @@ gboolean
 purple_genericlog_get_unseen_msgs(PurpleAccount *account, GList **result,
 	GError **error);
 
+/**
+ * purple_genericlog_get_all_buddies:
+ * @result[out]: Return location for a #GList containing a list of #PurpleBuddy
+ *               objects. This will not be set in case of any errors.
+ * @error:       Return location for a #GError or %NULL. If provided, this
+ *               will be set to the reason if getting messages fails.
+ *
+ * Gets a list of all #PurpleBuddy objects with at least one message in the
+ * active log.
+ *
+ * The caller is responsible for freeing the result with
+ * g_list_free_full(result, g_object_unref).
+ *
+ * Returns: %TRUE if succeeds, %FALSE otherwise.
+ */
+gboolean
+purple_genericlog_get_all_buddies(GList **result, GError **error);
+
 /**************************************************************************/
 /* Error Codes                                                            */
 /**************************************************************************/
diff --git a/libpurple/plugins/log/logsqlite.c b/libpurple/plugins/log/logsqlite.c
--- a/libpurple/plugins/log/logsqlite.c
+++ b/libpurple/plugins/log/logsqlite.c
@@ -80,8 +80,8 @@ static sqlite3_stmt *insert_message_q = 
 
 static const char *insert_message_q_str =
 	"INSERT INTO Messages (Author, AuthorAlias, Recipient, "
-	"Contents, MsgTime, Flags, Seen, AccountId) "
-	"VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8);";
+	"Contents, MsgTime, Flags, Seen, Send, AccountId) "
+	"VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9);";
 
 typedef enum
 {
@@ -92,7 +92,8 @@ typedef enum
 	INSERT_MESSAGE_QUERY_PARAM_MSGTIME     = 5,
 	INSERT_MESSAGE_QUERY_PARAM_FLAGS       = 6,
 	INSERT_MESSAGE_QUERY_PARAM_SEEN        = 7,
-	INSERT_MESSAGE_QUERY_PARAM_ACCOUNTID   = 8,
+	INSERT_MESSAGE_QUERY_PARAM_SEND        = 8,
+	INSERT_MESSAGE_QUERY_PARAM_ACCOUNTID   = 9,
 } InsertMessageQueryParam;
 
 static sqlite3_stmt *get_unseen_msgs_q = NULL;
@@ -132,6 +133,26 @@ typedef enum
 	MARK_AS_SEEN_QUERY_PARAM_ID = 1
 } MarkAsSeenQueryParam;
 
+static sqlite3_stmt *get_all_buddies_q = NULL;
+
+static const char *get_all_buddies_q_str =
+	"SELECT Username, ProtocolId, Author Buddy FROM "
+	"Messages JOIN Accounts on Accounts.Id = AccountId "
+	"WHERE Send = 0 "
+	"GROUP BY Username, ProtocolId, Buddy "
+	"UNION "
+	"SELECT Username, ProtocolId, Recipient Buddy FROM "
+	"Messages JOIN Accounts on Accounts.Id = AccountId "
+	"WHERE Send = 1 "
+	"GROUP BY Username, ProtocolId, Buddy;";
+
+typedef enum
+{
+	GET_ALL_BUDDIES_QUERY_COL_USERNAME = 0,
+	GET_ALL_BUDDIES_QUERY_COL_PROTOCOL = 1,
+	GET_ALL_BUDDIES_QUERY_COL_BUDDY    = 2,
+} GetAllBuddiesQueryCol;
+
 static void
 sqlitelog_finalize_query(sqlite3_stmt **query)
 {
@@ -153,6 +174,7 @@ sqlitelog_finalize_queries()
 	sqlitelog_finalize_query(&insert_message_q);
 	sqlitelog_finalize_query(&get_unseen_msgs_q);
 	sqlitelog_finalize_query(&mark_as_seen_q);
+	sqlitelog_finalize_query(&get_all_buddies_q);
 }
 
 static gboolean
@@ -184,7 +206,8 @@ sqlitelog_prepare_queries()
 	    !sqlitelog_prepare_query(insert_account_q_str, &insert_account_q) ||
 		!sqlitelog_prepare_query(insert_message_q_str, &insert_message_q) ||
 		!sqlitelog_prepare_query(get_unseen_msgs_q_str, &get_unseen_msgs_q) ||
-		!sqlitelog_prepare_query(mark_as_seen_q_str, &mark_as_seen_q)) {
+		!sqlitelog_prepare_query(mark_as_seen_q_str, &mark_as_seen_q) ||
+		!sqlitelog_prepare_query(get_all_buddies_q_str, &get_all_buddies_q)) {
 
 		sqlitelog_finalize_queries();
 		return FALSE;
@@ -219,10 +242,12 @@ sqlitelog_create_tables(sqlite3 *db_hand
 		"MsgTime INTEGER NOT NULL,"
 		"Flags INTEGER NOT NULL,"
 		"Seen BOOLEAN DEFAULT 0,"
+		"Send BOOLEAN NOT NULL,"
 		"AccountId INTEGER NOT NULL,"
 		"FOREIGN KEY(AccountId) REFERENCES Accounts(Id)); "
 
 		"CREATE INDEX SeenIndex ON Messages (Seen); "
+		"CREATE INDEX SendIndex ON Messages (Send); "
 
 		"CREATE TRIGGER AccountDeleted AFTER DELETE ON Accounts "
 		"BEGIN "
@@ -339,9 +364,10 @@ sqlitelog_insert_account(const PurpleAcc
 }
 
 static gboolean
-sqlitelog_insert_message(unsigned account_id, const PurpleMessage *msg,
-	unsigned *id)
+sqlitelog_insert_message(PurpleAccount *account, unsigned account_id,
+	const PurpleMessage *msg, unsigned *id)
 {
+	g_assert(account);
 	g_assert(account_id != SQLITELOG_DB_ID_NONE);
 	g_assert(msg);
 	g_assert(id);
@@ -349,12 +375,15 @@ sqlitelog_insert_message(unsigned accoun
 	g_assert(insert_message_q);
 
 	const char *author = purple_message_get_author(msg);
+	author = author ? purple_normalize(account, author) : NULL;
 	const char *author_alias = purple_message_get_author_alias(msg);
 	const char *recipient = purple_message_get_recipient(msg);
+	recipient = recipient ? purple_normalize(account, recipient) : NULL;
 	const char *contents = purple_message_get_contents(msg);
 	guint64 msg_time = purple_message_get_time(msg);
 	PurpleMessageFlags msg_flags = purple_message_get_flags(msg);
 	int seen = (msg_flags & PURPLE_MESSAGE_SEND) ? 1 : 0;
+	int send = (msg_flags & PURPLE_MESSAGE_SEND) ? 1 : 0;
 
 	if (sqlite3_bind_text(insert_message_q, INSERT_MESSAGE_QUERY_PARAM_AUTHOR,
 			author, -1, SQLITE_STATIC) != SQLITE_OK ||
@@ -372,6 +401,8 @@ sqlitelog_insert_message(unsigned accoun
 			msg_flags) != SQLITE_OK ||
 		sqlite3_bind_int(insert_message_q, INSERT_MESSAGE_QUERY_PARAM_SEEN,
 			seen) != SQLITE_OK ||
+		sqlite3_bind_int(insert_message_q, INSERT_MESSAGE_QUERY_PARAM_SEND,
+			send) != SQLITE_OK ||
 		sqlite3_bind_int(insert_message_q, INSERT_MESSAGE_QUERY_PARAM_ACCOUNTID,
 			account_id) != SQLITE_OK) {
 		return FALSE;
@@ -465,6 +496,44 @@ sqlitelog_mark_as_seen_impl(unsigned msg
 	return rc == SQLITE_DONE;
 }
 
+static gboolean
+sqlitelog_get_all_buddies_impl(GList **result)
+{
+	g_assert(result);
+
+	g_assert(get_all_buddies_q);
+
+	GList *buddies = NULL;
+	int rc;
+	while ((rc = sqlite3_step(get_all_buddies_q)) == SQLITE_ROW) {
+		const char *username = (const char*) sqlite3_column_text(
+			get_all_buddies_q, GET_ALL_BUDDIES_QUERY_COL_USERNAME);
+		const char *protocol = (const char*) sqlite3_column_text(
+			get_all_buddies_q, GET_ALL_BUDDIES_QUERY_COL_PROTOCOL);
+		const char *buddy = (const char*) sqlite3_column_text(
+			get_all_buddies_q, GET_ALL_BUDDIES_QUERY_COL_BUDDY);
+
+		PurpleAccount *account = purple_accounts_find(username, protocol);
+		if (!account)
+			continue;
+
+		PurpleBuddy *prpl_buddy = purple_blist_find_buddy(account, buddy);
+		if (!prpl_buddy)
+			continue;
+
+		buddies = g_list_prepend(buddies, prpl_buddy);
+		g_object_ref(prpl_buddy);
+	}
+
+	if (rc != SQLITE_DONE) {
+		g_list_free_full(buddies, g_object_unref);
+		return FALSE;
+	}
+
+	*result = buddies;
+	return TRUE;
+}
+
 /**************************************************************************/
 /* PurpleGenericLog API implementation                                    */
 /**************************************************************************/
@@ -540,7 +609,7 @@ sqlitelog_log_im(PurpleAccount *account,
 	}
 
 	unsigned message_id;
-	if (!sqlitelog_insert_message(account_id, message, &message_id))
+	if (!sqlitelog_insert_message(account, account_id, message, &message_id))
 		return FALSE;
 
 	g_object_set_data(G_OBJECT(message), SQLITELOG_MESSAGE_ID_ATTR,
@@ -583,6 +652,20 @@ sqlitelog_get_unseen_msgs(PurpleAccount 
 	return sqlitelog_get_unseen_msgs_impl(account, result);
 }
 
+static gboolean
+sqlitelog_get_all_buddies(GList **result)
+{
+	g_return_val_if_fail(result != NULL, FALSE);
+
+	if (!sqlitelog_db_handle) {
+		purple_debug_error(SQLITELOG_DEBUG_CATEGORY,
+			"Log is not active");
+		return FALSE;
+	}
+
+	return sqlitelog_get_all_buddies_impl(result);
+}
+
 /**************************************************************************/
 /* GObject stuff                                                          */
 /**************************************************************************/
@@ -627,6 +710,7 @@ purple_sqlitelog_class_init (PurpleSqlit
 	klass->parent_class.log_im = sqlitelog_log_im;
 	klass->parent_class.mark_as_seen = sqlitelog_mark_as_seen;
 	klass->parent_class.get_unseen_msgs = sqlitelog_get_unseen_msgs;
+	klass->parent_class.get_all_buddies = sqlitelog_get_all_buddies;
 }
 
 static GType
diff --git a/pidgin/gtkgenericlog.c b/pidgin/gtkgenericlog.c
--- a/pidgin/gtkgenericlog.c

_______________________________________________
Commits mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/commits
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.