/soc/2015/igor.gajowiak/chatlog: 38521ffa0033: Implemented skipp...
Igor Gajowiak
igor.gajowiak at gmail.com
Mon Aug 17 16:43:04 EDT 2015
Changeset: 38521ffa0033c46483d4932827362e97e26cfbeb
Author: Igor Gajowiak <igor.gajowiak at gmail.com>
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);
More information about the Commits
mailing list