/soc/2015/igor.gajowiak/chatlog: 38521ffa0033: Implemented skipp...

Igor Gajowiak <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 38521ffa0033c46483d4932827362e97e26cfbeb
Author:	 Igor Gajowiak <[email protected]>
Date:	 2015-08-17 22:42 +0200
Branch:	 default
URL: https://hg.pidgin.im/soc/2015/igor.gajowiak/chatlog/rev/38521ffa0033

Description:

Implemented skipping duplicates when importing messages.

diffstat:

 libpurple/conversation.c          |    4 +-
 libpurple/genericlog.c            |   29 +++++++-
 libpurple/genericlog.h            |   11 ++-
 libpurple/plugins/log/logsqlite.c |  122 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 152 insertions(+), 14 deletions(-)

diffs (truncated from 330 to 300 lines):

diff --git a/libpurple/conversation.c b/libpurple/conversation.c
--- a/libpurple/conversation.c
+++ b/libpurple/conversation.c
@@ -642,7 +642,9 @@ void
 		}
 
 		GError *error;
-		if (!purple_genericlog_log_msg(account, contact, pmsg, &error)) {
+		int seen = (purple_message_get_flags(pmsg) & PURPLE_MESSAGE_SEND)
+			? 1 : 0;
+		if (!purple_genericlog_log_msg(account, contact, pmsg, seen, &error)) {
 			purple_debug_error("conversation", "Logging failed: %s (code=%d)",
 				error->message, error->code);
 			g_error_free(error);
diff --git a/libpurple/genericlog.c b/libpurple/genericlog.c
--- a/libpurple/genericlog.c
+++ b/libpurple/genericlog.c
@@ -261,13 +261,13 @@ purple_genericlog_set_active_log(PurpleG
 
 gboolean
 purple_genericlog_log_msg(PurpleAccount *account, PurpleBlistNode *contact,
-	PurpleMessage *msg, GError **error)
+	PurpleMessage *msg, gboolean seen, GError **error)
 {
 	GENERICLOG_CHECK_CONTACT(contact);
 
 	DEFINE_GENERICLOG_FUNC_WITH_RETURN(log_msg,
 		"%s does not support IM logging",
-		"Failed to log IM in %s", account, contact, msg);
+		"Failed to log IM in %s", account, contact, msg, seen);
 }
 
 gboolean
@@ -349,6 +349,18 @@ purple_genericlog_wipe_log_for_contact(P
 		"Removing messages from %s failed", contact);
 }
 
+static gboolean
+_purple_genericlog_import_msg(PurpleAccount *account, PurpleBlistNode *contact,
+	PurpleMessage *msg, gboolean seen, gboolean *imported, GError **error)
+{
+	GENERICLOG_CHECK_CONTACT(contact);
+
+	DEFINE_GENERICLOG_FUNC_WITH_RETURN(import_msg,
+		"%s does not support importing messages",
+		"Failed to import message into %s",
+		account, contact, msg, seen, imported);
+}
+
 #undef GENERICLOG_CHECK_CONTACT
 #undef DEFINE_GENERICLOG_FUNC_WITH_RETURN
 
@@ -413,9 +425,15 @@ run_import_iteration(gpointer unused)
 		PurpleBlistNode *contact = g_array_index(contacts, PurpleBlistNode*, i);
 		PurpleMessage *message = g_array_index(messages, PurpleMessage*, i);
 
-		/* Should we stop if logging fails? */
-		if (purple_genericlog_log_msg(account, contact, message, NULL))
-			++(import_state->imported_messages_count);
+		gboolean imported;
+
+		/* Should we stop if importing fails? */
+		if (!_purple_genericlog_import_msg(account, contact, message, TRUE,
+			&imported, NULL)) {
+			continue;
+		}
+
+		import_state->imported_messages_count += imported ? 1 : 0;
 	}
 
 	g_array_free(accounts, TRUE);
@@ -581,6 +599,7 @@ purple_genericlog_class_init(PurpleGener
 	klass->init_export = NULL;
 	klass->read_chunk = NULL;
 	klass->finalize_export = NULL;
+	klass->import_msg = NULL;
 
 	klass->reserved1 = NULL;
 	klass->reserved2 = NULL;
diff --git a/libpurple/genericlog.h b/libpurple/genericlog.h
--- a/libpurple/genericlog.h
+++ b/libpurple/genericlog.h
@@ -103,6 +103,9 @@ struct _PurpleGenericLog
  *                   export. Returns %TRUE if operation succeeds,
  *                   %FALSE otherwise.
  * @finalize_export: Finalizes an export procedure.
+ * @import_msg:      Imports a message. Behaves same as log_msg, but
+ *                   additionally skips duplicates. Returns %TRUE if operation
+ *                   succeeds, %FALSE otherwise.
  *
  * The abstract base class for all log implementations. A conforming plugin
  * must implement at least activate and deactivate methods. Not supported
@@ -118,7 +121,7 @@ struct _PurpleGenericLogClass
 	void (*deactivate)(void);
 
 	gboolean (*log_msg) (PurpleAccount *account, PurpleBlistNode* contact,
-		PurpleMessage *message);
+		PurpleMessage *message, gboolean seen);
 
 	gboolean (*mark_as_seen)(PurpleMessage *message);
 
@@ -146,6 +149,9 @@ struct _PurpleGenericLogClass
 
 	void (*finalize_export) (void *export_state);
 
+	gboolean (*import_msg) (PurpleAccount *account, PurpleBlistNode* contact,
+		PurpleMessage *message, gboolean seen, gboolean *imported);
+
 	void (*reserved1)(void);
 	void (*reserved2)(void);
 	void (*reserved3)(void);
@@ -272,6 +278,7 @@ purple_genericlog_set_active_log(PurpleG
  * @account: The account.
  * @contact  The contact, must be PurpleChat or PurpleBuddy.
  * @msg:     The message.
+ * @seen:    %TRUE if message should be marked as seen.
  * @error:   Return location for a #GError or %NULL. If provided, this
  *           will be set to the reason if logging fails.
  *
@@ -281,7 +288,7 @@ purple_genericlog_set_active_log(PurpleG
  */
 gboolean
 purple_genericlog_log_msg(PurpleAccount *account, PurpleBlistNode* contact,
-	PurpleMessage *msg, GError **error);
+	PurpleMessage *msg, gboolean seen, GError **error);
 
 /**
  * purple_genericlog_mark_as_seen:
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
@@ -311,6 +311,23 @@ typedef enum
 	DELETE_CONTACT_QUERY_PARAM_ACCOUNTID   = 2,
 } DeleteContactQueryParam;
 
+static sqlite3_stmt *contains_msg_q = NULL;
+
+static const char *contains_msg_q_str =
+	"SELECT NULL FROM Messages "
+	"WHERE AccountId = ?1 AND ContactId = ?2 AND MsgTime = ?3 "
+	"AND Author IS ?4 AND Recipient IS ?5 AND Contents IS ?6 LIMIT 1;";
+
+typedef enum
+{
+	CONTAINS_MSG_QUERY_PARAM_ACCOUNTID = 1,
+	CONTAINS_MSG_QUERY_PARAM_CONTACTID = 2,
+	CONTAINS_MSG_QUERY_PARAM_MSGTIME   = 3,
+	CONTAINS_MSG_QUERY_PARAM_AUTHOR    = 4,
+	CONTAINS_MSG_QUERY_PARAM_RECIPIENT = 5,
+	CONTAINS_MSG_QUERY_PARAM_CONTENTS  = 6,
+} ContainsMsgQueryParam;
+
 static void
 sqlitelog_finalize_query(sqlite3_stmt **query)
 {
@@ -347,6 +364,7 @@ sqlitelog_finalize_queries()
 	sqlitelog_finalize_query(&get_all_contacts_q);
 	sqlitelog_finalize_query(&get_all_days_q);
 	sqlitelog_finalize_query(&delete_contact_q);
+	sqlitelog_finalize_query(&contains_msg_q);
 }
 
 static gboolean
@@ -396,7 +414,8 @@ sqlitelog_prepare_queries()
 		!sqlitelog_prepare_query(mark_as_seen_q_str, &mark_as_seen_q) ||
 		!sqlitelog_prepare_query(get_all_contacts_q_str, &get_all_contacts_q) ||
 		!sqlitelog_prepare_query(get_all_days_q_str, &get_all_days_q) ||
-		!sqlitelog_prepare_query(delete_contact_q_str, &delete_contact_q)) {
+		!sqlitelog_prepare_query(delete_contact_q_str, &delete_contact_q) ||
+		!sqlitelog_prepare_query(contains_msg_q_str, &contains_msg_q)) {
 
 		sqlitelog_finalize_queries();
 		return FALSE;
@@ -695,7 +714,7 @@ sqlitelog_insert_day(guint64 time, unsig
 static gboolean
 sqlitelog_insert_message(PurpleAccount *account, unsigned account_id,
 	unsigned contact_id, unsigned day_id, const PurpleMessage *msg,
-	unsigned *id)
+	gboolean seen, unsigned *id)
 {
 	g_assert(account);
 	g_assert(account_id != SQLITELOG_DB_ID_NONE);
@@ -714,7 +733,6 @@ sqlitelog_insert_message(PurpleAccount *
 	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;
 
 	if (sqlite3_bind_text(insert_message_q, INSERT_MESSAGE_QUERY_PARAM_AUTHOR,
 			author, -1, SQLITE_STATIC) != SQLITE_OK ||
@@ -731,7 +749,7 @@ sqlitelog_insert_message(PurpleAccount *
 		sqlite3_bind_int(insert_message_q, INSERT_MESSAGE_QUERY_PARAM_FLAGS,
 			msg_flags) != SQLITE_OK ||
 		sqlite3_bind_int(insert_message_q, INSERT_MESSAGE_QUERY_PARAM_SEEN,
-			seen) != SQLITE_OK ||
+			seen ? 1 : 0) != SQLITE_OK ||
 		sqlite3_bind_int64(insert_message_q,
 			INSERT_MESSAGE_QUERY_PARAM_ACCOUNTID, account_id) != SQLITE_OK ||
 		sqlite3_bind_int64(insert_message_q,
@@ -1168,6 +1186,73 @@ sqlitelog_delete_contact_impl(PurpleBlis
 	return rc == SQLITE_DONE;
 }
 
+static gboolean
+sqlitelog_contains_msg(PurpleAccount *account, PurpleBlistNode* contact,
+	PurpleMessage *message, gboolean *result)
+{
+	g_assert(account);
+	g_assert(contact);
+	g_assert(message);
+	g_assert(result);
+
+	unsigned account_id;
+	if (!sqlitelog_get_account_id(account, &account_id))
+		return FALSE;
+
+	if (account_id == SQLITELOG_DB_ID_NONE) {
+		*result = FALSE;
+		return TRUE;
+	}
+
+	const char *contact_name = PURPLE_IS_CHAT(contact) ?
+		purple_chat_get_name_only(PURPLE_CHAT(contact)) :
+		purple_buddy_get_name(PURPLE_BUDDY(contact));
+
+	if (!contact_name)
+		return FALSE;
+
+	unsigned contact_id;
+	if (!sqlitelog_get_contact_id(account_id, contact_name, &contact_id))
+		return FALSE;
+
+	if (contact_id == SQLITELOG_DB_ID_NONE) {
+		*result = FALSE;
+		return TRUE;
+	}
+
+	if (sqlite3_bind_int64(contains_msg_q, CONTAINS_MSG_QUERY_PARAM_ACCOUNTID,
+			account_id) != SQLITE_OK ||
+		sqlite3_bind_int64(contains_msg_q, CONTAINS_MSG_QUERY_PARAM_CONTACTID,
+			contact_id) != SQLITE_OK ||
+		sqlite3_bind_int64(contains_msg_q, CONTAINS_MSG_QUERY_PARAM_MSGTIME,
+			purple_message_get_time(message)) != SQLITE_OK ||
+		sqlite3_bind_text(contains_msg_q, CONTAINS_MSG_QUERY_PARAM_AUTHOR,
+			purple_message_get_author(message), -1, SQLITE_STATIC)
+		!= SQLITE_OK ||
+		sqlite3_bind_text(contains_msg_q, CONTAINS_MSG_QUERY_PARAM_RECIPIENT,
+			purple_message_get_recipient(message), -1, SQLITE_STATIC)
+		!= SQLITE_OK ||
+		sqlite3_bind_text(contains_msg_q, CONTAINS_MSG_QUERY_PARAM_CONTENTS,
+			purple_message_get_contents(message), -1, SQLITE_STATIC)
+		!= SQLITE_OK) {
+		return FALSE;
+	}
+
+	gboolean msg_found = FALSE;
+
+	int rc;
+	while ((rc = sqlite3_step(contains_msg_q)) == SQLITE_ROW)
+		msg_found |= TRUE;
+
+	sqlite3_reset(contains_msg_q);
+
+	if (rc != SQLITE_DONE)
+		return FALSE;
+
+	*result = msg_found;
+	return TRUE;
+}
+
 /**************************************************************************/
 /* PurpleGenericLog API implementation                                    */
 /**************************************************************************/
@@ -1235,7 +1320,7 @@ guint64 truncate_to_days(guint64 timesta
 
 static gboolean
 sqlitelog_log_msg(PurpleAccount *account, PurpleBlistNode *contact,
-	PurpleMessage *message)
+	PurpleMessage *message, gboolean seen)
 {
 	g_return_val_if_fail(account != NULL, FALSE);
 	g_return_val_if_fail(contact != NULL, FALSE);
@@ -1299,7 +1384,7 @@ sqlitelog_log_msg(PurpleAccount *account
 
 	unsigned message_id;
 	if (!sqlitelog_insert_message(account, account_id, contact_id, day_id,
-		message, &message_id)) {
+		message, seen, &message_id)) {
 		sqlite3_step(rollback_transation_q);
 		return FALSE;
 	}
@@ -1442,6 +1527,30 @@ sqlitelog_wipe_log_for_contact(PurpleBli
 	return sqlitelog_delete_contact_impl(contact);
 }
 
+gboolean sqlitelog_import_msg(PurpleAccount *account, PurpleBlistNode* contact,
+	PurpleMessage *message, gboolean seen, gboolean *imported)
+{
+	g_return_val_if_fail(account != NULL, FALSE);
+	g_return_val_if_fail(contact != NULL, FALSE);

_______________________________________________
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.