/soc/2015/igor.gajowiak/chatlog: 2867d33d0158: Implemented getti...
Igor Gajowiak
igor.gajowiak at gmail.com
Thu Jul 23 17:49:23 EDT 2015
Changeset: 2867d33d01586124e4b989cfcc0defae72873ebc
Author: Igor Gajowiak <igor.gajowiak at gmail.com>
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
More information about the Commits
mailing list