Commit 4f22ec0a authored by Ronan's avatar Ronan

feat(EventsDb): import content text from legacy messages

parent 7b59cd6e
......@@ -38,6 +38,7 @@ public:
// -----------------------------------------------------------------------------
const ContentType ContentType::Cpim("message/cpim");
const ContentType ContentType::ExternalBody("message/external-body");
const ContentType ContentType::FileTransfer("application/vnd.gsma.rcs-ft-http+xml");
const ContentType ContentType::Imdn("message/imdn+xml");
const ContentType ContentType::ImIsComposing("application/im-iscomposing+xml");
......
......@@ -55,6 +55,7 @@ public:
std::string asString () const;
static const ContentType Cpim;
static const ContentType ExternalBody;
static const ContentType FileTransfer;
static const ContentType Imdn;
static const ContentType ImIsComposing;
......
......@@ -28,6 +28,7 @@
#include "abstract/abstract-db-p.h"
#include "chat/chat-message.h"
#include "content/content.h"
#include "db/provider/db-session-provider.h"
#include "event-log/call-event.h"
#include "event-log/chat-message-event.h"
......@@ -35,6 +36,9 @@
#include "events-db.h"
#define MESSAGE_CONTENT_TYPE_TEXT 0
#define MESSAGE_CONTENT_TYPE_FILE 1
// =============================================================================
using namespace std;
......@@ -47,7 +51,6 @@ struct MessageEventReferences {
long localSipAddressId;
long remoteSipAddressId;
long chatRoomId;
long contentTypeId;
#endif
};
......@@ -55,6 +58,7 @@ class EventsDbPrivate : public AbstractDbPrivate {
#ifdef SOCI_ENABLED
public:
long insertSipAddress (const string &sipAddress);
void insertContent (const Content &content, long messageEventId);
long insertContentType (const string &contentType);
long insertEvent (EventLog::Type type, const tm &date);
long insertChatRoom (long sipAddressId, const tm &date);
......@@ -64,7 +68,7 @@ public:
ChatMessage::Direction direction,
const string &imdnMessageId,
bool isSecured,
const string *text = nullptr
const list<Content> &contents
);
void importLegacyMessages (const soci::rowset<soci::row> &messages);
......@@ -154,6 +158,34 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
return q->getLastInsertId();
}
void EventsDbPrivate::insertContent (const Content &content, long messageEventId) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
const ContentType &contentType = content.getContentType();
int type;
if (contentType == ContentType::PlainText)
type = MESSAGE_CONTENT_TYPE_TEXT;
else if (contentType == ContentType::FileTransfer)
type = MESSAGE_CONTENT_TYPE_FILE;
else {
lWarning() << "Unable to insert in database unsupported content: `" << contentType.asString() << "`.";
return;
}
long contentTypeId = insertContentType(contentType.asString());
*session << "INSERT INTO message_content (message_event_id, content_type_id, type) VALUES"
" (:messageEventId, :contentTypeId, :type)", soci::use(messageEventId), soci::use(contentTypeId), soci::use(type);
if (type == MESSAGE_CONTENT_TYPE_TEXT) {
*session << "INSERT INTO message_content_text (message_content_id, text) VALUES"
" (:messageContentId, :text)", soci::use(q->getLastInsertId()), soci::use(content.getBodyAsString());
return;
}
// TODO: MESSAGE_CONTENT_TYPE_FILE
}
long EventsDbPrivate::insertContentType (const string &contentType) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
......@@ -198,23 +230,27 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
ChatMessage::Direction direction,
const string &imdnMessageId,
bool isSecured,
const string *text
const list<Content> &contents
) {
L_Q();
soci::session *session = dbSession.getBackendSession<soci::session>();
soci::indicator textIndicator = text ? soci::i_ok : soci::i_null;
*session << "INSERT INTO message_event ("
" event_id, chat_room_id, local_sip_address_id, remote_sip_address_id,"
" state, direction, imdn_message_id, is_secured, text"
" state, direction, imdn_message_id, is_secured"
") VALUES ("
" :eventId, :chatRoomId, :localSipaddressId, :remoteSipaddressId,"
" :state, :direction, :imdnMessageId, :isSecured, :text"
" :state, :direction, :imdnMessageId, :isSecured"
")", soci::use(references.eventId), soci::use(references.chatRoomId), soci::use(references.localSipAddressId),
soci::use(references.remoteSipAddressId), soci::use(static_cast<int>(state)),
soci::use(static_cast<int>(direction)), soci::use(imdnMessageId), soci::use(isSecured ? 1 : 0),
soci::use(text ? *text : string(), textIndicator);
return q->getLastInsertId();
soci::use(static_cast<int>(direction)), soci::use(imdnMessageId), soci::use(isSecured ? 1 : 0);
long messageEventId = q->getLastInsertId();
for (const auto &content : contents)
insertContent(content, messageEventId);
return messageEventId;
}
// -----------------------------------------------------------------------------
......@@ -248,25 +284,39 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
const tm date = Utils::getLongAsTm(message.get<int>(9, 0));
const bool noUrl = false;
const string url = getValueFromLegacyMessage<string>(message, 8, const_cast<bool &>(noUrl));
const string contentType = message.get<string>(
13,
message.get<int>(11, -1) != -1
? "application/vnd.gsma.rcs-ft-http+xml"
: (noUrl ? "text/plain" : "message/external-body")
);
bool isNull;
const string url = getValueFromLegacyMessage<string>(message, 8, isNull);
const int contentId = message.get<int>(11, -1);
ContentType contentType(message.get<string>(13, ""));
if (!contentType.isValid())
contentType = contentId != -1
? ContentType::FileTransfer
: (isNull ? ContentType::PlainText : ContentType::ExternalBody);
if (contentType == ContentType::ExternalBody) {
lInfo() << "Import of external body content is skipped.";
continue;
}
const bool noText = false;
const string text = getValueFromLegacyMessage<string>(message, 4, const_cast<bool &>(noText));
const string text = getValueFromLegacyMessage<string>(message, 4, isNull);
Content content;
content.setContentType(contentType);
if (contentType == ContentType::PlainText) {
if (isNull) {
lWarning() << "Unable to import legacy message with no text.";
continue;
}
content.setBody(text);
} else {
continue;
}
struct MessageEventReferences references;
references.eventId = insertEvent(EventLog::Type::ChatMessage, date);
references.localSipAddressId = insertSipAddress(message.get<string>(1));
references.remoteSipAddressId = insertSipAddress(message.get<string>(2));
references.chatRoomId = insertChatRoom(references.remoteSipAddressId, date);
references.contentTypeId = insertContentType(contentType);
insertMessageEvent (
references,
......@@ -274,7 +324,7 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
static_cast<ChatMessage::Direction>(direction),
message.get<string>(12, ""),
!!message.get<int>(14, 0),
noText ? nullptr : &text
{ content }
);
const bool noAppData = false;
......@@ -336,7 +386,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
" chat_room_id INT UNSIGNED NOT NULL,"
" local_sip_address_id INT UNSIGNED NOT NULL,"
" remote_sip_address_id INT UNSIGNED NOT NULL,"
" content_type_id INT UNSIGNED NOT NULL,"
// See: https://tools.ietf.org/html/rfc5438#section-6.3
" imdn_message_id VARCHAR(255) NOT NULL,"
......@@ -345,8 +394,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
" direction TINYINT UNSIGNED NOT NULL,"
" is_secured BOOLEAN NOT NULL,"
" text TEXT,"
" FOREIGN KEY (event_id)"
" REFERENCES event(id)"
" ON DELETE CASCADE,"
......@@ -358,38 +405,53 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
" ON DELETE CASCADE,"
" FOREIGN KEY (remote_sip_address_id)"
" REFERENCES sip_address(id)"
" ON DELETE CASCADE,"
" FOREIGN KEY (content_type_id)"
" REFERENCES content_type(id)"
" ON DELETE CASCADE"
")";
*session <<
"CREATE TABLE IF NOT EXISTS message_crypto_data ("
"CREATE TABLE IF NOT EXISTS message_content ("
" id" + primaryKeyAutoIncrementStr() + ","
" message_event_id INT UNSIGNED NOT NULL,"
" data BLOB,"
" content_type_id INT UNSIGNED NOT NULL,"
" type TINYINT UNSIGNED NOT NULL,"
" FOREIGN KEY (message_event_id)"
" REFERENCES message_event(id)"
" ON DELETE CASCADE,"
" FOREIGN KEY (content_type_id)"
" REFERENCES content_type(id)"
" ON DELETE CASCADE"
")";
*session <<
"CREATE TABLE IF NOT EXISTS message_file_info ("
"CREATE TABLE IF NOT EXISTS message_content_text ("
" id" + primaryKeyAutoIncrementStr() + ","
" message_id INT UNSIGNED NOT NULL,"
" content_type_id INT UNSIGNED NOT NULL,"
" message_content_id INT UNSIGNED NOT NULL,"
" text TEXT NOT NULL,"
" FOREIGN KEY (message_content_id)"
" REFERENCES message_content(id)"
" ON DELETE CASCADE"
")";
*session <<
"CREATE TABLE IF NOT EXISTS message_content_file ("
" id" + primaryKeyAutoIncrementStr() + ","
" message_content_id INT UNSIGNED NOT NULL,"
" name VARCHAR(255) NOT NULL,"
" size INT UNSIGNED NOT NULL,"
" url VARCHAR(255) NOT NULL,"
" FOREIGN KEY (message_id)"
" REFERENCES message(id)"
" FOREIGN KEY (message_content_id)"
" REFERENCES message_content(id)"
" ON DELETE CASCADE"
" FOREIGN KEY (content_type_id)"
" REFERENCES content_type(id)"
")";
*session <<
"CREATE TABLE IF NOT EXISTS message_crypto_data ("
" id" + primaryKeyAutoIncrementStr() + ","
" message_event_id INT UNSIGNED NOT NULL,"
" data BLOB,"
" FOREIGN KEY (message_event_id)"
" REFERENCES message_event(id)"
" ON DELETE CASCADE"
")";
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment