Browse Source

libtransport: store MUC messages in the database

- You can't get them back out again, yet.
- As you can see in the schema, we'll introduce a way to store where each
  resource has read up to, and then use this information to include
  unseen lines in the initial MUC history sent on join.
master
eta 2 years ago
parent
commit
c8be02c1a4
  1. 5
      include/transport/ConversationManager.h
  2. 2
      include/transport/PQXXBackend.h
  3. 2
      include/transport/SQLite3Backend.h
  4. 3
      include/transport/StorageBackend.h
  5. 4
      include/transport/User.h
  6. 5
      libtransport/Conversation.cpp
  7. 3
      libtransport/ConversationManager.cpp
  8. 60
      libtransport/PQXXBackend.cpp
  9. 4
      libtransport/SQLite3Backend.cpp
  10. 2
      libtransport/User.cpp
  11. 4
      src/frontends/xmpp/XMPPUser.h

5
include/transport/ConversationManager.h

@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
#include <map>
#include <string>
#include "StorageBackend.h"
#include "Swiften/Elements/Message.h"
namespace Transport {
@ -40,7 +41,7 @@ class ConversationManager { @@ -40,7 +41,7 @@ class ConversationManager {
/// \param user User associated with this ConversationManager.
/// \param component Transport instance associated with this
/// ConversationManager.
ConversationManager(User *user, Component *component);
ConversationManager(User *user, Component *component, StorageBackend *storageBackend);
/// Destructor.
virtual ~ConversationManager();
@ -88,6 +89,8 @@ class ConversationManager { @@ -88,6 +89,8 @@ class ConversationManager {
return m_convs;
}
StorageBackend *m_storageBackend;
private:
void handleMessageReceived(Swift::Message::ref message);

2
include/transport/PQXXBackend.h

@ -26,6 +26,7 @@ @@ -26,6 +26,7 @@
#include <pqxx/pqxx>
#include <string>
#include "Swiften/Elements/Delay.h"
#include "transport/Config.h"
#include "transport/StorageBackend.h"
@ -104,6 +105,7 @@ class PQXXBackend : public StorageBackend { @@ -104,6 +105,7 @@ class PQXXBackend : public StorageBackend {
void updateUserSetting(long userId, const std::string &variable, const std::string &value);
void addMucName(long userId, const std::string &mucId, const std::string &mucName);
std::string getMucName(long userId, const std::string &mucId);
void storeMUCHistory(long userid, const std::string &mucId, const Swift::Message &message);
void beginTransaction();
void commitTransaction();

2
include/transport/SQLite3Backend.h

@ -101,6 +101,8 @@ class SQLite3Backend : public StorageBackend { @@ -101,6 +101,8 @@ class SQLite3Backend : public StorageBackend {
void addMucName(long userId, const std::string &mucId, const std::string &mucName);
std::string getMucName(long userId, const std::string &mucId);
void storeMUCHistory(long userid, const std::string &mucId, const Swift::Message &message);
void beginTransaction();
void commitTransaction();

3
include/transport/StorageBackend.h

@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
#pragma once
#include "Swiften/Elements/Message.h"
#include <boost/bind.hpp>
#include <list>
#include <map>
@ -142,6 +143,8 @@ class StorageBackend { @@ -142,6 +143,8 @@ class StorageBackend {
virtual void addMucName(long userId, const std::string &mucId, const std::string &mucName) = 0;
virtual std::string getMucName(long userId, const std::string &mucId) = 0;
virtual void storeMUCHistory(long userid, const std::string &mucId, const Swift::Message &message) = 0;
/// onStorageError
// boost::signal<void (const std::string &statement, const
// std::string &error)> onStorageError;

4
include/transport/User.h

@ -172,6 +172,10 @@ class User { @@ -172,6 +172,10 @@ class User {
void leaveRoom(const std::string &room);
long getUserId() {
return m_userInfo.id;
}
boost::signals2::signal<void()> onReadyToConnect;
boost::signals2::signal<void(Swift::Presence::ref presence)> onPresenceChanged;
boost::signals2::signal<void(Swift::Presence::ref presence)> onRawPresenceReceived;

5
libtransport/Conversation.cpp

@ -161,6 +161,11 @@ void Conversation::handleRawMessage(std::shared_ptr<Swift::Message> &message) { @@ -161,6 +161,11 @@ void Conversation::handleRawMessage(std::shared_ptr<Swift::Message> &message) {
std::string hashId = generateMessageId(message);
if (hashId != "") {
message->setID(hashId);
if (message->getType() == Swift::Message::Groupchat) {
long uid = m_conversationManager->getUser()->getUserId();
std::string mucJid = m_jid.toString();
m_conversationManager->m_storageBackend->storeMUCHistory(uid, mucJid, *message);
}
}
if (message->getType() != Swift::Message::Groupchat) {
m_conversationManager->getComponent()->getFrontend()->sendMessage(message);

3
libtransport/ConversationManager.cpp

@ -34,9 +34,10 @@ namespace Transport { @@ -34,9 +34,10 @@ namespace Transport {
DEFINE_LOGGER(logger, "ConversationManager");
ConversationManager::ConversationManager(User *user, Component *component) {
ConversationManager::ConversationManager(User *user, Component *component, StorageBackend *storageBackend) {
m_user = user;
m_component = component;
m_storageBackend = storageBackend;
}
ConversationManager::~ConversationManager() {

60
libtransport/PQXXBackend.cpp

@ -26,6 +26,9 @@ @@ -26,6 +26,9 @@
#include "log4cxx/logger.h"
#include "transport/Util.h"
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/date_time/posix_time/time_serialize.hpp>
using namespace log4cxx;
@ -133,6 +136,32 @@ bool PQXXBackend::createDatabase() { @@ -133,6 +136,32 @@ bool PQXXBackend::createDatabase() {
"UNIQUE(user_id, muc_id)"
");");
exec("CREATE TABLE IF NOT EXISTS " + m_prefix +
"muc_history ("
"user_id INTEGER NOT NULL,"
"muc_id VARCHAR NOT NULL,"
"message_id VARCHAR NOT NULL,"
"timestamp TIMESTAMP NOT NULL,"
"jid VARCHAR NOT NULL,"
"body VARCHAR NOT NULL"
");");
exec("CREATE INDEX IF NOT EXISTS " + m_prefix +
"muc_history_idx "
"ON " +
m_prefix +
"muc_history"
"(user_id, muc_id, timestamp);");
exec("CREATE TABLE IF NOT EXISTS " + m_prefix +
"muc_history_pointers ("
"user_id INTEGER NOT NULL,"
"muc_id VARCHAR NOT NULL,"
"resource VARCHAR NOT NULL,"
"last_timestamp TIMESTAMP NOT NULL,"
"UNIQUE(user_id, muc_id, resource)"
");");
return true;
}
@ -439,6 +468,37 @@ std::string PQXXBackend::getMucName(long userId, const std::string &mucId) { @@ -439,6 +468,37 @@ std::string PQXXBackend::getMucName(long userId, const std::string &mucId) {
}
}
long epoch(boost::posix_time::ptime ts) {
boost::posix_time::ptime time_t_epoch(boost::gregorian::date(1970, 1, 1));
boost::posix_time::time_duration diff = ts - time_t_epoch;
return diff.total_seconds();
}
void PQXXBackend::storeMUCHistory(long userid, const std::string &mucId, const Swift::Message &message) {
try {
const std::shared_ptr<Swift::Delay> delay = message.getPayload<Swift::Delay>();
const std::string from = message.getFrom().toString();
std::string body = message.getBody().get_value_or("");
std::string messageId = message.getID();
boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time();
if (delay.get() != NULL) {
timestamp = delay.get()->getStamp();
}
if (body == "" || messageId == "") {
LOG4CXX_WARN(logger, "Attempted to store MUC history with incomplete message!");
return;
}
pqxx::nontransaction txn(*m_conn);
txn.exec_params("INSERT INTO " + m_prefix +
"muc_history (user_id, muc_id, message_id, timestamp, jid, body) VALUES ($1, $2, $3, "
"to_timestamp($4), $5, $6)",
userid, mucId, messageId, epoch(timestamp), from, body);
} catch (std::exception &e) {
LOG4CXX_ERROR(logger, e.what());
connect();
}
}
void PQXXBackend::beginTransaction() {
exec("BEGIN;");
}

4
libtransport/SQLite3Backend.cpp

@ -596,6 +596,10 @@ std::string SQLite3Backend::getMucName(long userId, const std::string &mucId) { @@ -596,6 +596,10 @@ std::string SQLite3Backend::getMucName(long userId, const std::string &mucId) {
LOG4CXX_ERROR(logger, "getMucName() not implemented in sqlite3 backend yet");
return "";
}
void SQLite3Backend::storeMUCHistory(long userid, const std::string &mucId, const Swift::Message &message) {
LOG4CXX_ERROR(logger, "storeMUCHistory() not implemented in sqlite3 backend yet");
return;
}
void SQLite3Backend::beginTransaction() {
exec("BEGIN TRANSACTION;");

2
libtransport/User.cpp

@ -68,7 +68,7 @@ User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, User @@ -68,7 +68,7 @@ User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, User
m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this));
m_rosterManager = component->getFrontend()->createRosterManager(this, m_component);
m_conversationManager = new ConversationManager(this, m_component);
m_conversationManager = new ConversationManager(this, m_component, userManager->m_storageBackend);
LOG4CXX_INFO(logger, m_jid.toString() << ": Created");
updateLastActivity();

4
src/frontends/xmpp/XMPPUser.h

@ -84,10 +84,6 @@ class XMPPUser : public User { @@ -84,10 +84,6 @@ class XMPPUser : public User {
}
}
long getUserId() {
return m_userInfo.id;
}
private:
void onConnectingTimeout();
void handleVCardReceived(std::shared_ptr<Swift::VCard> vcard, Swift::ErrorPayload::ref error,

Loading…
Cancel
Save