Commit 1d4016db authored by Mohammed Sadiq's avatar Mohammed Sadiq
Browse files

various: Handle message content type

pass message content type when creating new message and
use this to handle message when showing the message row

Also get the content type from message when saving to
history and handle media and file types separately
while saving to history
parent 93c3c910
......@@ -128,5 +128,12 @@ typedef enum
CHATTY_MESSAGE_FILE,
CHATTY_MESSAGE_IMAGE,
CHATTY_MESSAGE_VIDEO,
chatty_message_AUDIO,
CHATTY_MESSAGE_AUDIO,
} ChattyMsgType;
typedef enum
{
CHATTY_FILE_DOWNLOADED = 1,
CHATTY_FILE_MISSING,
CHATTY_FILE_DECRYPT_FAILED,
} ChattyFileStatus;
This diff is collapsed.
......@@ -812,6 +812,8 @@ chatty_conv_write_conversation (PurpleConversation *conv,
NULL};
g_autoptr(GError) err = NULL;
g_autoptr(LfbEvent) event = NULL;
ChattyProtocol protocol;
ChattyMsgType msg_type;
if ((flags & PURPLE_MESSAGE_SYSTEM) && !(flags & PURPLE_MESSAGE_NOTIFY)) {
flags &= ~(PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV);
......@@ -820,6 +822,12 @@ chatty_conv_write_conversation (PurpleConversation *conv,
node = chatty_utils_get_conv_blist_node (conv);
chat = conv->ui_data;
self = chatty_manager_get_default ();
protocol = chatty_item_get_protocols (CHATTY_ITEM (chat));
if (protocol == CHATTY_PROTOCOL_SMS)
msg_type = CHATTY_MESSAGE_TEXT;
else
msg_type = CHATTY_MESSAGE_HTML_ESCAPED;
account = purple_conversation_get_account (conv);
g_return_if_fail (account != NULL);
......@@ -838,10 +846,6 @@ chatty_conv_write_conversation (PurpleConversation *conv,
pcm.who = chatty_utils_jabber_id_strip(who);
} else {
ChattyProtocol protocol;
protocol = chatty_item_get_protocols (CHATTY_ITEM (chat));
if (protocol == CHATTY_PROTOCOL_MATRIX ||
protocol == CHATTY_PROTOCOL_XMPP)
pcm.who = chatty_pp_chat_get_buddy_name (CHATTY_PP_CHAT (chat), who);
......@@ -882,7 +886,7 @@ chatty_conv_write_conversation (PurpleConversation *conv,
if (pcm.flags & (PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_ERROR)) {
// System is usually also RECV so should be first to catch
chat_message = chatty_message_new (NULL, NULL, message, uuid, 0, CHATTY_DIRECTION_SYSTEM, 0);
chat_message = chatty_message_new (NULL, NULL, message, uuid, 0, msg_type, CHATTY_DIRECTION_SYSTEM, 0);
chatty_pp_chat_append_message (CHATTY_PP_CHAT (chat), chat_message);
} else if (pcm.flags & PURPLE_MESSAGE_RECV) {
ChattyChat *active_chat;
......@@ -911,11 +915,11 @@ chatty_conv_write_conversation (PurpleConversation *conv,
g_free (titel);
}
chat_message = chatty_message_new (NULL, who, message, uuid, mtime, CHATTY_DIRECTION_IN, 0);
chat_message = chatty_message_new (NULL, who, message, uuid, mtime, msg_type, CHATTY_DIRECTION_IN, 0);
chatty_pp_chat_append_message (CHATTY_PP_CHAT (chat), chat_message);
} else if (flags & PURPLE_MESSAGE_SEND && pcm.flags & PURPLE_MESSAGE_SEND) {
// normal send
chat_message = chatty_message_new (NULL, NULL, message, uuid, 0, CHATTY_DIRECTION_OUT, 0);
chat_message = chatty_message_new (NULL, NULL, message, uuid, 0, msg_type, CHATTY_DIRECTION_OUT, 0);
chatty_message_set_status (chat_message, CHATTY_STATUS_SENT, 0);
chatty_pp_chat_append_message (CHATTY_PP_CHAT (chat), chat_message);
} else if (pcm.flags & PURPLE_MESSAGE_SEND) {
......@@ -923,7 +927,7 @@ chatty_conv_write_conversation (PurpleConversation *conv,
// FIXME: current list_box does not allow ordering rows by timestamp
// TODO: Needs proper sort function and timestamp as user_data for rows
// FIXME: Alternatively may need to reload history to re-populate rows
chat_message = chatty_message_new (NULL, NULL, message, uuid, mtime, CHATTY_DIRECTION_OUT, 0);
chat_message = chatty_message_new (NULL, NULL, message, uuid, mtime, msg_type, CHATTY_DIRECTION_OUT, 0);
chatty_message_set_status (chat_message, CHATTY_STATUS_SENT, 0);
chatty_pp_chat_append_message (CHATTY_PP_CHAT (chat), chat_message);
}
......
......@@ -53,10 +53,7 @@ chatty_msg_list_escape_message (ChattyMessageRow *self,
char *result;
nl_2_br = purple_strdup_withhtml (message);
if (self->protocol == CHATTY_PROTOCOL_SMS)
striped = g_strdup (message);
else
striped = purple_markup_strip_html (nl_2_br);
striped = purple_markup_strip_html (nl_2_br);
escaped = purple_markup_escape_text (striped, -1);
linkified = purple_markup_linkify (escaped);
// convert all tags to lowercase for GtkLabel markup parser
......@@ -119,6 +116,7 @@ message_row_update_message (ChattyMessageRow *self)
g_autofree char *footer = NULL;
const char *status_str = "";
ChattyMsgStatus status;
ChattyMsgType type;
g_assert (CHATTY_IS_MESSAGE_ROW (self));
g_assert (self->message);
......@@ -132,7 +130,7 @@ message_row_update_message (ChattyMessageRow *self)
else if (status == CHATTY_STATUS_DELIVERED)
status_str = "<span color='#6cba3d'> ✓</span>";
if (self->is_im) {
if (self->is_im && self->protocol != CHATTY_PROTOCOL_MATRIX) {
g_autofree char *time_str = NULL;
time_t time_stamp;
......@@ -156,8 +154,39 @@ message_row_update_message (ChattyMessageRow *self)
NULL);
}
message = chatty_msg_list_escape_message (self, chatty_message_get_text (self->message));
gtk_label_set_markup (GTK_LABEL (self->message_label), message);
type = chatty_message_get_msg_type (self->message);
if (type == CHATTY_MESSAGE_IMAGE ||
type == CHATTY_MESSAGE_VIDEO ||
type == CHATTY_MESSAGE_AUDIO ||
type == CHATTY_MESSAGE_FILE) {
ChattyFileInfo *file;
const char *name;
file = chatty_message_get_file (self->message);
if (file)
name = file->file_name ? file->file_name : chatty_message_get_text (self->message);
if (file && file->url) {
if (file->status == CHATTY_FILE_DOWNLOADED) {
const char *end = strrchr (file->url, '/');
if (end)
message = g_strconcat ("<a href='file://", g_get_user_cache_dir (), "/",
"chatty", "/", "files", end, "'>", name, "</a>", NULL);
}
if (!message)
message = g_strconcat ("<a href='", file->url, "'>", name, "</a>", NULL);
} else
message = g_strdup (name);
} else {
message = chatty_msg_list_escape_message (self, chatty_message_get_text (self->message));
}
if (type == CHATTY_MESSAGE_TEXT)
gtk_label_set_text (GTK_LABEL (self->message_label),
chatty_message_get_text (self->message));
else
gtk_label_set_markup (GTK_LABEL (self->message_label), message);
gtk_label_set_markup (GTK_LABEL (self->footer_label), footer);
gtk_widget_set_visible (self->footer_label, footer && *footer);
}
......@@ -260,7 +289,7 @@ chatty_message_row_new (ChattyMessage *message,
gtk_label_set_xalign (GTK_LABEL (self->footer_label), 0);
}
if (is_im || direction == CHATTY_DIRECTION_SYSTEM ||
if ((is_im && protocol != CHATTY_PROTOCOL_MATRIX) || direction == CHATTY_DIRECTION_SYSTEM ||
direction == CHATTY_DIRECTION_OUT)
gtk_widget_hide (self->avatar_image);
else
......
......@@ -35,9 +35,16 @@ struct _ChattyMessage
char *message;
char *uid;
char *id;
ChattyFileInfo *file;
ChattyFileInfo *preview;
ChattyMsgType type;
ChattyMsgStatus status;
ChattyMsgDirection direction;
time_t time;
gboolean encrypted;
};
G_DEFINE_TYPE (ChattyMessage, chatty_message, G_TYPE_OBJECT)
......@@ -98,6 +105,7 @@ chatty_message_new (ChattyItem *user,
const char *message,
const char *uid,
time_t timestamp,
ChattyMsgType type,
ChattyMsgDirection direction,
ChattyMsgStatus status)
{
......@@ -114,10 +122,64 @@ chatty_message_new (ChattyItem *user,
self->status = status;
self->direction = direction;
self->time = timestamp;
self->type = type;
return self;
}
gboolean
chatty_message_get_encrypted (ChattyMessage *self)
{
g_return_val_if_fail (CHATTY_IS_MESSAGE (self), FALSE);
return self->encrypted;
}
void
chatty_message_set_encrypted (ChattyMessage *self,
gboolean is_encrypted)
{
g_return_if_fail (CHATTY_IS_MESSAGE (self));
self->encrypted = !!is_encrypted;
}
ChattyFileInfo *
chatty_message_get_file (ChattyMessage *self)
{
g_return_val_if_fail (CHATTY_IS_MESSAGE (self), NULL);
return self->file;
}
void
chatty_message_set_file (ChattyMessage *self,
ChattyFileInfo *file)
{
g_return_if_fail (CHATTY_IS_MESSAGE (self));
g_return_if_fail (!self->file);
self->file = file;
}
ChattyFileInfo *
chatty_message_get_preview (ChattyMessage *self)
{
g_return_val_if_fail (CHATTY_IS_MESSAGE (self), NULL);
return self->preview;
}
void
chatty_message_set_preview (ChattyMessage *self,
ChattyFileInfo *preview)
{
g_return_if_fail (CHATTY_IS_MESSAGE (self));
g_return_if_fail (!self->preview);
self->preview = preview;
}
const char *
chatty_message_get_uid (ChattyMessage *self)
{
......@@ -126,6 +188,16 @@ chatty_message_get_uid (ChattyMessage *self)
return self->uid;
}
void
chatty_message_set_uid (ChattyMessage *self,
const char *uid)
{
g_return_if_fail (CHATTY_IS_MESSAGE (self));
g_return_if_fail (!self->uid);
self->uid = g_strdup (uid);
}
const char *
chatty_message_get_id (ChattyMessage *self)
{
......@@ -155,7 +227,6 @@ chatty_message_get_text (ChattyMessage *self)
return self->message;
}
ChattyItem *
chatty_message_get_user (ChattyMessage *self)
{
......@@ -196,9 +267,20 @@ chatty_message_set_user_name (ChattyMessage *self,
const char *
chatty_message_get_user_alias (ChattyMessage *self)
{
const char *name = NULL;
g_return_val_if_fail (CHATTY_IS_MESSAGE (self), NULL);
return self->user_alias;
if (self->user_alias)
return self->user_alias;
if (self->user)
name = chatty_item_get_name (self->user);
if (name && *name)
return name;
return NULL;
}
time_t
......@@ -231,6 +313,14 @@ chatty_message_set_status (ChattyMessage *self,
g_signal_emit (self, signals[UPDATED], 0);
}
ChattyMsgType
chatty_message_get_msg_type (ChattyMessage *self)
{
g_return_val_if_fail (CHATTY_IS_MESSAGE (self), CHATTY_MESSAGE_UNKNOWN);
return self->type;
}
ChattyMsgDirection
chatty_message_get_msg_direction (ChattyMessage *self)
{
......@@ -238,3 +328,16 @@ chatty_message_get_msg_direction (ChattyMessage *self)
return self->direction;
}
void
chatty_file_info_free (ChattyFileInfo *file_info)
{
if (!file_info)
return;
g_free (file_info->file_name);
g_free (file_info->url);
g_free (file_info->path);
g_free (file_info->mime_type);
g_free (file_info);
}
......@@ -18,6 +18,22 @@
G_BEGIN_DECLS
typedef struct _ChattyFileInfo ChattyFileInfo;
struct _ChattyFileInfo {
char *file_name;
char *url;
char *path;
char *mime_type;
gpointer user_data;
gsize width;
gsize height;
gsize size;
/* For audio files */
gsize duration;
int status;
};
#define CHATTY_TYPE_MESSAGE (chatty_message_get_type ())
G_DECLARE_FINAL_TYPE (ChattyMessage, chatty_message, CHATTY, MESSAGE, GObject)
......@@ -27,11 +43,26 @@ ChattyMessage *chatty_message_new (ChattyItem *user,
const char *message,
const char *uid,
time_t time,
ChattyMsgType type,
ChattyMsgDirection direction,
ChattyMsgStatus status);
ChattyMessage *chatty_message_new_purple (ChattyPpBuddy *buddy,
PurpleConvMessage *message);
gboolean chatty_message_get_encrypted (ChattyMessage *self);
void chatty_message_set_encrypted (ChattyMessage *self,
gboolean is_encrypted);
ChattyFileInfo *chatty_message_get_file (ChattyMessage *self);
void chatty_message_set_file (ChattyMessage *self,
ChattyFileInfo *file);
ChattyFileInfo *chatty_message_get_preview (ChattyMessage *self);
void chatty_message_set_preview (ChattyMessage *self,
ChattyFileInfo *info);
const char *chatty_message_get_uid (ChattyMessage *self);
void chatty_message_set_uid (ChattyMessage *self,
const char *uid);
const char *chatty_message_get_id (ChattyMessage *self);
void chatty_message_set_id (ChattyMessage *self,
const char *id);
......@@ -46,6 +77,8 @@ ChattyMsgStatus chatty_message_get_status (ChattyMessage *self);
void chatty_message_set_status (ChattyMessage *self,
ChattyMsgStatus status,
time_t mtime);
ChattyMsgType chatty_message_get_msg_type (ChattyMessage *self);
ChattyMsgDirection chatty_message_get_msg_direction (ChattyMessage *self);
void chatty_file_info_free (ChattyFileInfo *file_info);
G_END_DECLS
......@@ -800,7 +800,8 @@ cb_chatty_mam_msg_received (PurpleConnection *pc,
if (!stanza_id)
stanza_id = g_uuid_string_random ();
chat_message = chatty_message_new (NULL, NULL, pcm->what, stanza_id, pcm->when,
chat_message = chatty_message_new (NULL, NULL, pcm->what, stanza_id,
pcm->when, CHATTY_MESSAGE_HTML_ESCAPED,
chatty_utils_direction_from_flag (pcm->flags), 0);
if (chat_message && pcm->who && !(flags & PURPLE_MESSAGE_SEND))
chatty_message_set_user_name (chat_message, who ? who : pcm->who);
......
BEGIN TRANSACTION;
PRAGMA user_version = 2;
PRAGMA foreign_keys = ON;
CREATE TABLE mime_type (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE
);
CREATE TABLE files (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT,
url TEXT NOT NULL UNIQUE,
path TEXT,
mime_type_id INTEGER REFERENCES mime_type(id),
status INT,
size INTEGER
);
CREATE TABLE audio (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
file_id INTEGER NOT NULL UNIQUE,
duration INTEGER,
FOREIGN KEY(file_id) REFERENCES files(id)
);
CREATE TABLE image (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
file_id INTEGER NOT NULL UNIQUE,
width INTEGER,
height INTEGER,
FOREIGN KEY(file_id) REFERENCES files(id)
);
CREATE TABLE video (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
file_id INTEGER NOT NULL UNIQUE,
width INTEGER,
height INTEGER,
duration INTEGER,
FOREIGN KEY(file_id) REFERENCES files(id)
);
CREATE TABLE users (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
alias TEXT,
avatar_id INTEGER REFERENCES files(id),
type INTEGER NOT NULL,
UNIQUE (username, type)
);
INSERT INTO users VALUES(1,'SMS',NULL,NULL,1);
INSERT INTO users VALUES(2,'MMS',NULL,NULL,1);
CREATE TABLE accounts (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id),
password TEXT,
enabled INTEGER DEFAULT 0,
protocol INTEGER NOT NULL,
UNIQUE (user_id, protocol)
);
INSERT INTO accounts VALUES(1,1,NULL,0,1);
INSERT INTO accounts VALUES(2,2,NULL,0,2);
CREATE TABLE threads (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
alias TEXT,
avatar_id INTEGER REFERENCES files(id),
account_id INTEGER NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
type INTEGER NOT NULL,
encrypted INTEGER DEFAULT 0,
UNIQUE (name, account_id, type)
);
CREATE TABLE thread_members (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
thread_id INTEGER NOT NULL REFERENCES threads(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id),
UNIQUE (thread_id, user_id)
);
CREATE TABLE messages (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
uid TEXT NOT NULL,
thread_id INTEGER NOT NULL REFERENCES threads(id) ON DELETE CASCADE,
sender_id INTEGER REFERENCES users(id),
user_alias TEXT,
body TEXT NOT NULL,
body_type INTEGER NOT NULL,
direction INTEGER NOT NULL,
time INTEGER NOT NULL,
status INTEGER,
encrypted INTEGER DEFAULT 0,
preview_id INTEGER REFERENCES files(id),
UNIQUE (uid, thread_id, body, time)
);
ALTER TABLE threads ADD COLUMN last_read_id INTEGER REFERENCES messages(id);
COMMIT;
BEGIN TRANSACTION;
PRAGMA user_version = 2;
PRAGMA foreign_keys = ON;
CREATE TABLE mime_type (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE
);
CREATE TABLE files (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT,
url TEXT NOT NULL UNIQUE,
path TEXT,
mime_type_id INTEGER REFERENCES mime_type(id),
status INT,
size INTEGER
);
CREATE TABLE audio (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
file_id INTEGER NOT NULL UNIQUE,
duration INTEGER,
FOREIGN KEY(file_id) REFERENCES files(id)
);
CREATE TABLE image (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
file_id INTEGER NOT NULL UNIQUE,
width INTEGER,
height INTEGER,
FOREIGN KEY(file_id) REFERENCES files(id)
);
CREATE TABLE video (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
file_id INTEGER NOT NULL UNIQUE,
width INTEGER,
height INTEGER,
duration INTEGER,
FOREIGN KEY(file_id) REFERENCES files(id)
);
CREATE TABLE users (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
alias TEXT,
avatar_id INTEGER REFERENCES files(id),
type INTEGER NOT NULL,
UNIQUE (username, type)
);
INSERT INTO users VALUES(1,'SMS',NULL,NULL,1);
INSERT INTO users VALUES(2,'MMS',NULL,NULL,1);
CREATE TABLE accounts (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id),
password TEXT,
enabled INTEGER DEFAULT 0,
protocol INTEGER NOT NULL,
UNIQUE (user_id, protocol)
);
INSERT INTO accounts VALUES(1,1,NULL,0,1);
INSERT INTO accounts VALUES(2,2,NULL,0,2);
CREATE TABLE threads (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
alias TEXT,
avatar_id INTEGER REFERENCES files(id),
account_id INTEGER NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
type INTEGER NOT NULL,
encrypted INTEGER DEFAULT 0,
UNIQUE (name, account_id, type)
);
CREATE TABLE thread_members (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
thread_id INTEGER NOT NULL REFERENCES threads(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id),
UNIQUE (thread_id, user_id)
);
CREATE TABLE messages (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
uid TEXT NOT NULL,
thread_id INTEGER NOT NULL REFERENCES threads(id) ON DELETE CASCADE,
sender_id INTEGER REFERENCES users(id),
user_alias TEXT,
body TEXT NOT NULL,
body_type INTEGER NOT NULL,
direction INTEGER NOT NULL,
time INTEGER NOT NULL,
status INTEGER,
encrypted INTEGER DEFAULT 0,
preview_id INTEGER REFERENCES files(id),
UNIQUE (uid, thread_id, body, time)
);
ALTER TABLE threads ADD COLUMN last_read_id INTEGER REFERENCES messages(id);
INSERT INTO users VALUES(3,'alice',NULL,NULL,4);
INSERT INTO users VALUES(4,'@charlie:example.com',NULL,NULL,4);
INSERT INTO users VALUES(5,'@_freenode_hunter2:example.com',NULL,NULL,4);
INSERT INTO users VALUES(7,'@bob:example.com',NULL,NULL,4);
INSERT INTO users VALUES(8,'@bob:example.org',NULL,NULL,4);
INSERT INTO users VALUES(9,'@alice:example.com',NULL,NULL,4);
INSERT INTO accounts VALUES(3,3,NULL,0,4);
INSERT INTO accounts VALUES(4,8,NULL,0,4);
INSERT INTO accounts VALUES(5,9,NULL,0,4);
INSERT INTO threads VALUES(1,'!CDFTfyJgtVMvsXDEi:example.com',NULL,NULL,4,1,0,NULL);
INSERT INTO threads VALUES(2,'!CDFTfyJgtVMvsXDEi:example.com',NULL,NULL,5,1,0,NULL);
INSERT INTO threads VALUES(3,'!VPWUCfyJyeVMxiHYGi:example.com',NULL,NULL,5,1,0,NULL);
INSERT INTO threads VALUES(4,'!VPWUCfyJyeVMxiHYGi:example.com',NULL,NULL,3,1,0,NULL);
INSERT INTO thread_members VALUES(1,1,4);
INSERT INTO thread_members VALUES(2,1,9);
INSERT INTO thread_members VALUES(3,2,5);
INSERT INTO thread_members VALUES(4,3,7);
INSERT INTO thread_members VALUES(5,3,9);
INSERT INTO thread_members VALUES(6,4,9);
INSERT INTO messages VALUES(NULL,'10600c18-ecc1-4d42-8f0a-5c5e563b1b3d',1,NULL,NULL,'Another empty author message',2,1,1586447320,NULL,0,NULL);
INSERT INTO messages VALUES(NULL,'1dc29876-0f92-11eb-aeb4-d7486be58053',1,4,NULL,'Failed',2,1,1586448432,NULL,0,NULL);
INSERT INTO messages VALUES(NULL,'c73bbcbc-0f91-11eb-aab2-8b95affe5e24',1,9,NULL,'Test',2,1,1586448429,NULL,0,NULL);
INSERT INTO messages VALUES(NULL,'414d35fa-e50f-441f-a382-3cb8acd7a510',2,5,NULL,'Weird. All I see is *',2,1,1586448435,NULL,0,NULL);
INSERT INTO messages VALUES(NULL,'f86768a5-d0fb-423c-9430-3d3b66d74a67',2,NULL,NULL,'A message with no author',2,1,1586448438,NULL,0,NULL);
INSERT INTO messages VALUES(NULL,'12107bfc-0f91-11eb-8501-2314b53187d5',3,7,NULL,'Hi',2,1,1586447316,NULL,0,NULL);
INSERT INTO messages VALUES(NULL,'2a5f6c4a-0f91-11eb-af2c-27e3777f4483',3,7,NULL,'Are you there?',2,1,1586447319,NULL,0,NULL);
INSERT INTO messages VALUES(NULL,'6b67fa36-0f91-11eb-9714-af849160d937',3,9,NULL,'Hi',2,-1,1586447419,NULL,0,NULL);