Implement sender realname/avatarurl storage
authorJanne Koschinski <janne@kuschku.de>
Tue, 8 May 2018 20:17:38 +0000 (15:17 -0500)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 23 May 2018 22:33:28 +0000 (00:33 +0200)
- Store sender realname and avatarurl in database
- Guard protocol changes behind feature flag 'RichMessages'
- Avatar URLs are not actually stored yet, as we do not implement
  METADATA yet.

This is not yet used in Quassel itself, but third-party clients
including QuasselDroid use this to provide more context in messages
and allow for realname-based fallback avatar fetching to work in the
chat message backlog.

Incorporates suggestions from @mamarley.

Closes GH-351.

38 files changed:
src/common/message.cpp
src/common/message.h
src/common/quassel.h
src/core/SQL/PostgreSQL/insert_sender.sql
src/core/SQL/PostgreSQL/migrate_write_sender.sql
src/core/SQL/PostgreSQL/select_messagesAll.sql
src/core/SQL/PostgreSQL/select_messagesAllNew.sql
src/core/SQL/PostgreSQL/select_messagesNewerThan.sql
src/core/SQL/PostgreSQL/select_messagesNewestK.sql
src/core/SQL/PostgreSQL/select_messagesRange.sql
src/core/SQL/PostgreSQL/select_senderid.sql
src/core/SQL/PostgreSQL/setup_010_sender.sql
src/core/SQL/PostgreSQL/setup_140_sender_idx.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/version/27/upgrade_000_update_sender_add_realname.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/version/27/upgrade_010_update_sender_add_avatarurl.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/version/27/upgrade_020_update_sender_add_new_constraint.sql [new file with mode: 0644]
src/core/SQL/PostgreSQL/version/27/upgrade_030_upgrade_sender_drop_old_constraint.sql [new file with mode: 0644]
src/core/SQL/SQLite/insert_sender.sql
src/core/SQL/SQLite/migrate_read_sender.sql
src/core/SQL/SQLite/select_messagesAll.sql
src/core/SQL/SQLite/select_messagesAllNew.sql
src/core/SQL/SQLite/select_messagesNewerThan.sql
src/core/SQL/SQLite/select_messagesNewestK.sql
src/core/SQL/SQLite/select_messagesRange.sql
src/core/SQL/SQLite/setup_010_sender.sql
src/core/SQL/SQLite/setup_150_sender_idx.sql [new file with mode: 0644]
src/core/SQL/SQLite/version/29/upgrade_000_create_sender_tmp.sql [new file with mode: 0644]
src/core/SQL/SQLite/version/29/upgrade_010_copy_sender_sender_tmp.sql [new file with mode: 0644]
src/core/SQL/SQLite/version/29/upgrade_020_drop_sender.sql [new file with mode: 0644]
src/core/SQL/SQLite/version/29/upgrade_030_rename_sender_tmp_sender.sql [new file with mode: 0644]
src/core/SQL/SQLite/version/29/upgrade_040_update_sender_add_realname_avatarurl.sql [new file with mode: 0644]
src/core/abstractsqlstorage.cpp
src/core/abstractsqlstorage.h
src/core/coresession.cpp
src/core/coresession.h
src/core/postgresqlstorage.cpp
src/core/sql.qrc
src/core/sqlitestorage.cpp

index 34990c6..061f16e 100644 (file)
 
 #include <QDataStream>
 
-Message::Message(const BufferInfo &bufferInfo, Type type, const QString &contents, const QString &sender, const QString &senderPrefixes, Flags flags)
+Message::Message(const BufferInfo &bufferInfo, Type type, const QString &contents, const QString &sender,
+                 const QString &senderPrefixes, const QString &realName, const QString &avatarUrl, Flags flags)
     : _timestamp(QDateTime::currentDateTime().toUTC()),
     _bufferInfo(bufferInfo),
     _contents(contents),
     _sender(sender),
     _senderPrefixes(senderPrefixes),
+    _realName(realName),
+    _avatarUrl(avatarUrl),
     _type(type),
     _flags(flags)
 {
 }
 
 
-Message::Message(const QDateTime &ts, const BufferInfo &bufferInfo, Type type, const QString &contents, const QString &sender, const QString &senderPrefixes, Flags flags)
+Message::Message(const QDateTime &ts, const BufferInfo &bufferInfo, Type type, const QString &contents,
+                 const QString &sender, const QString &senderPrefixes, const QString &realName,
+                 const QString &avatarUrl, Flags flags)
     : _timestamp(ts),
     _bufferInfo(bufferInfo),
     _contents(contents),
     _sender(sender),
     _senderPrefixes(senderPrefixes),
+    _realName(realName),
+    _avatarUrl(avatarUrl),
     _type(type),
     _flags(flags)
 {
@@ -72,6 +79,11 @@ QDataStream &operator<<(QDataStream &out, const Message &msg)
     if (SignalProxy::current()->targetPeer()->hasFeature(Quassel::Feature::SenderPrefixes))
         out << msg.senderPrefixes().toUtf8();
 
+    if (SignalProxy::current()->targetPeer()->hasFeature(Quassel::Feature::RichMessages)) {
+        out << msg.realName().toUtf8();
+        out << msg.avatarUrl().toUtf8();
+    }
+
     out << msg.contents().toUtf8();
     return out;
 }
@@ -113,6 +125,15 @@ QDataStream &operator>>(QDataStream &in, Message &msg)
         in >> senderPrefixes;
     msg._senderPrefixes = QString::fromUtf8(senderPrefixes);
 
+    QByteArray realName;
+    QByteArray avatarUrl;
+    if (SignalProxy::current()->sourcePeer()->hasFeature(Quassel::Feature::RichMessages)) {
+        in >> realName;
+        in >> avatarUrl;
+    }
+    msg._realName = QString::fromUtf8(realName);
+    msg._avatarUrl = QString::fromUtf8(avatarUrl);
+
     QByteArray contents;
     in >> contents;
     msg._contents = QString::fromUtf8(contents);
@@ -126,7 +147,9 @@ QDebug operator<<(QDebug dbg, const Message &msg)
     dbg.nospace() << qPrintable(QString("Message(MsgId:")) << msg.msgId()
     << qPrintable(QString(",")) << msg.timestamp()
     << qPrintable(QString(", Type:")) << msg.type()
+    << qPrintable(QString(", RealName:")) << msg.realName()
+    << qPrintable(QString(", AvatarURL:")) << msg.avatarUrl()
     << qPrintable(QString(", Flags:")) << msg.flags() << qPrintable(QString(")"))
-    << msg.sender() << ":" << msg.contents();
+    << msg.senderPrefixes() << msg.sender() << ":" << msg.contents();
     return dbg;
 }
index 79e25cf..45a8286 100644 (file)
@@ -68,10 +68,11 @@ public:
     Q_DECLARE_FLAGS(Flags, Flag)
 
     Message(const BufferInfo &bufferInfo = BufferInfo(), Type type = Plain, const QString &contents = {},
-            const QString &sender = {}, const QString &senderPrefixes = {}, Flags flags = None);
+            const QString &sender = {}, const QString &senderPrefixes = {}, const QString &realName = {},
+            const QString &avatarUrl = {}, Flags flags = None);
     Message(const QDateTime &ts, const BufferInfo &buffer = BufferInfo(), Type type = Plain,
             const QString &contents = {}, const QString &sender = {}, const QString &senderPrefixes = {},
-            Flags flags = None);
+            const QString &realName = {}, const QString &avatarUrl = {}, Flags flags = None);
 
     inline static Message ChangeOfDay(const QDateTime &day) { return Message(day, BufferInfo(), DayChange); }
     inline const MsgId &msgId() const { return _msgId; }
@@ -83,6 +84,8 @@ public:
     inline const QString &contents() const { return _contents; }
     inline const QString &sender() const { return _sender; }
     inline const QString &senderPrefixes() const { return _senderPrefixes; }
+    inline const QString &realName() const { return _realName; }
+    inline const QString &avatarUrl() const { return _avatarUrl; }
     inline Type type() const { return _type; }
     inline Flags flags() const { return _flags; }
     inline void setFlags(Flags flags) { _flags = flags; }
@@ -99,6 +102,8 @@ private:
     QString _contents;
     QString _sender;
     QString _senderPrefixes;
+    QString _realName;
+    QString _avatarUrl;
     Type _type;
     Flags _flags;
 
index aa155e8..fd91f9a 100644 (file)
@@ -132,6 +132,7 @@ public:
         RemoteDisconnect,         ///< Allow this peer to be remotely disconnected
         ExtendedFeatures,         ///< Extended features
         LongMessageTime,          ///< Serialize message time as 64-bit
+        RichMessages,             ///< Real Name and Avatar URL in backlog
 #if QT_VERSION >= 0x050500
         EcdsaCertfpKeys,          ///< ECDSA keys for CertFP in identities
 #endif
index f7d89ad..bb385db 100644 (file)
@@ -1,3 +1,3 @@
-INSERT INTO sender (sender)
-VALUES ($1)
+INSERT INTO sender (sender, realname, avatarurl)
+VALUES ($1, $2, $3)
 RETURNING senderid
index bf953cd..f1ac46b 100644 (file)
@@ -1,2 +1,2 @@
-INSERT INTO sender (senderid, sender)
-VALUES (?, ?)
+INSERT INTO sender (senderid, sender, realname, avatarurl)
+VALUES (?, ?, ?, ?)
index 0ee372a..5109f68 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, bufferid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, bufferid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE backlog.bufferid IN (SELECT bufferid FROM buffer WHERE userid = :userid)
index 9f81545..827a94e 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, bufferid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, bufferid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE backlog.bufferid IN (SELECT bufferid FROM buffer WHERE userid = :userid)
index 621fd0a..7736daf 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE backlog.messageid >= $1
index e705928..7faba9b 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE bufferid = $1
index a95c23c..4b7de10 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE backlog.messageid >= $1
index b0b3ed3..63b124c 100644 (file)
@@ -1,3 +1,3 @@
 SELECT senderid
 FROM sender
-WHERE sender = $1
+WHERE sender = $1 AND realname = $2 AND avatarurl = $3
index 0e9cdf1..0854291 100644 (file)
@@ -1,4 +1,6 @@
 CREATE TABLE sender ( -- THE SENDER OF IRC MESSAGES
        senderid serial NOT NULL PRIMARY KEY,
-       sender varchar(128) UNIQUE NOT NULL
-)
+       sender varchar(128) NOT NULL,
+       realname TEXT,
+       avatarurl TEXT
+);
diff --git a/src/core/SQL/PostgreSQL/setup_140_sender_idx.sql b/src/core/SQL/PostgreSQL/setup_140_sender_idx.sql
new file mode 100644 (file)
index 0000000..3aa66a1
--- /dev/null
@@ -0,0 +1 @@
+CREATE UNIQUE INDEX sender_sender_realname_avatarurl_uindex ON sender(sender, realname, avatarurl);
diff --git a/src/core/SQL/PostgreSQL/version/27/upgrade_000_update_sender_add_realname.sql b/src/core/SQL/PostgreSQL/version/27/upgrade_000_update_sender_add_realname.sql
new file mode 100644 (file)
index 0000000..c95ca27
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE sender ADD realname TEXT NULL;
diff --git a/src/core/SQL/PostgreSQL/version/27/upgrade_010_update_sender_add_avatarurl.sql b/src/core/SQL/PostgreSQL/version/27/upgrade_010_update_sender_add_avatarurl.sql
new file mode 100644 (file)
index 0000000..4fb6e43
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE sender ADD avatarurl TEXT NULL;
diff --git a/src/core/SQL/PostgreSQL/version/27/upgrade_020_update_sender_add_new_constraint.sql b/src/core/SQL/PostgreSQL/version/27/upgrade_020_update_sender_add_new_constraint.sql
new file mode 100644 (file)
index 0000000..3aa66a1
--- /dev/null
@@ -0,0 +1 @@
+CREATE UNIQUE INDEX sender_sender_realname_avatarurl_uindex ON sender(sender, realname, avatarurl);
diff --git a/src/core/SQL/PostgreSQL/version/27/upgrade_030_upgrade_sender_drop_old_constraint.sql b/src/core/SQL/PostgreSQL/version/27/upgrade_030_upgrade_sender_drop_old_constraint.sql
new file mode 100644 (file)
index 0000000..0f63c9e
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE sender DROP CONSTRAINT sender_sender_key;
index 0e84f63..63633c4 100644 (file)
@@ -1,2 +1,2 @@
-INSERT INTO sender (sender)
-VALUES (:sender)
\ No newline at end of file
+INSERT INTO sender (sender, realname, avatarurl)
+VALUES (:sender, :realname, :avatarurl)
index 9cd5ce1..53f0381 100644 (file)
@@ -1,5 +1,4 @@
-SELECT senderid, sender
+SELECT senderid, sender, realname, avatarurl
 FROM sender
 WHERE senderid > ? AND senderid <= ?
 ORDER BY senderid ASC
-
index 2fb1cdb..60957d5 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, bufferid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, bufferid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE backlog.bufferid IN (SELECT bufferid FROM buffer WHERE userid = :userid)
index f6a5471..098b4fe 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, bufferid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, bufferid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE backlog.bufferid IN (SELECT bufferid FROM buffer WHERE userid = :userid)
index 8129c44..5040b9e 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE backlog.messageid >= :firstmsg
index 18105db..eb4af1f 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE bufferid = :bufferid
index dc6e617..f78cf8d 100644 (file)
@@ -1,4 +1,4 @@
-SELECT messageid, time,  type, flags, sender, senderprefixes, message
+SELECT messageid, time,  type, flags, sender, senderprefixes, realname, avatarurl, message
 FROM backlog
 JOIN sender ON backlog.senderid = sender.senderid
 WHERE bufferid = :bufferid
index 4e7251e..c35041d 100644 (file)
@@ -1,6 +1,6 @@
 CREATE TABLE sender ( -- THE SENDER OF IRC MESSAGES
        senderid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
-       sender TEXT UNIQUE NOT NULL
-)
-
-         
+       sender TEXT NOT NULL,
+       realname TEXT,
+       avatarurl TEXT
+);
diff --git a/src/core/SQL/SQLite/setup_150_sender_idx.sql b/src/core/SQL/SQLite/setup_150_sender_idx.sql
new file mode 100644 (file)
index 0000000..fec1fec
--- /dev/null
@@ -0,0 +1 @@
+CREATE UNIQUE INDEX sender_index ON sender(sender, realname, avatarurl);
diff --git a/src/core/SQL/SQLite/version/29/upgrade_000_create_sender_tmp.sql b/src/core/SQL/SQLite/version/29/upgrade_000_create_sender_tmp.sql
new file mode 100644 (file)
index 0000000..25c1df2
--- /dev/null
@@ -0,0 +1 @@
+CREATE TABLE sender_tmp (senderid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, sender TEXT NOT NULL, realname TEXT, avatarurl TEXT);
diff --git a/src/core/SQL/SQLite/version/29/upgrade_010_copy_sender_sender_tmp.sql b/src/core/SQL/SQLite/version/29/upgrade_010_copy_sender_sender_tmp.sql
new file mode 100644 (file)
index 0000000..5400092
--- /dev/null
@@ -0,0 +1 @@
+INSERT INTO sender_tmp SELECT senderid, sender, NULL as realname, NULL as avatarurl FROM sender;
diff --git a/src/core/SQL/SQLite/version/29/upgrade_020_drop_sender.sql b/src/core/SQL/SQLite/version/29/upgrade_020_drop_sender.sql
new file mode 100644 (file)
index 0000000..7e89301
--- /dev/null
@@ -0,0 +1 @@
+DROP TABLE sender;
diff --git a/src/core/SQL/SQLite/version/29/upgrade_030_rename_sender_tmp_sender.sql b/src/core/SQL/SQLite/version/29/upgrade_030_rename_sender_tmp_sender.sql
new file mode 100644 (file)
index 0000000..e03b21e
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE sender_tmp RENAME TO sender;
diff --git a/src/core/SQL/SQLite/version/29/upgrade_040_update_sender_add_realname_avatarurl.sql b/src/core/SQL/SQLite/version/29/upgrade_040_update_sender_add_realname_avatarurl.sql
new file mode 100644 (file)
index 0000000..fec1fec
--- /dev/null
@@ -0,0 +1 @@
+CREATE UNIQUE INDEX sender_index ON sender(sender, realname, avatarurl);
index 947c1ba..4ecf623 100644 (file)
@@ -584,3 +584,13 @@ bool AbstractSqlMigrationReader::transferMo(MigrationObject moType, T &mo)
     qDebug() << "Done.";
     return true;
 }
+
+uint qHash(const SenderData &key) {
+    return qHash(QString(key.sender + "\n" + key.realname + "\n" + key.avatarurl));
+}
+
+bool operator==(const SenderData &a, const SenderData &b) {
+    return a.sender == b.sender &&
+        a.realname == b.realname &&
+        a.avatarurl == b.avatarurl;
+}
index 2a59fbf..2e57230 100644 (file)
@@ -118,6 +118,14 @@ private:
     QHash<QThread *, Connection *> _connectionPool;
 };
 
+struct SenderData {
+    QString sender;
+    QString realname;
+    QString avatarurl;
+
+    friend uint qHash(const SenderData &key);
+    friend bool operator==(const SenderData &a, const SenderData &b);
+};
 
 // ========================================
 //  AbstractSqlStorage::Connection
@@ -155,6 +163,8 @@ public:
     struct SenderMO {
         int senderId;
         QString sender;
+        QString realname;
+        QString avatarurl;
         SenderMO() : senderId(0) {}
     };
 
index 249690c..df9061d 100644 (file)
@@ -385,8 +385,9 @@ void CoreSession::processMessages()
             Q_ASSERT(!createBuffer);
             bufferInfo = Core::bufferInfo(user(), rawMsg.networkId, BufferInfo::StatusBuffer, "");
         }
-        Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender,
-                    senderPrefixes(rawMsg.sender, bufferInfo), rawMsg.flags);
+        Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender, senderPrefixes(rawMsg.sender, bufferInfo),
+                    realName(rawMsg.sender, rawMsg.networkId),  avatarUrl(rawMsg.sender, rawMsg.networkId),
+                    rawMsg.flags);
         if(Core::storeMessage(msg))
             emit displayMsg(msg);
     }
@@ -410,8 +411,9 @@ void CoreSession::processMessages()
                 }
                 bufferInfoCache[rawMsg.networkId][rawMsg.target] = bufferInfo;
             }
-            Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender,
-                        senderPrefixes(rawMsg.sender, bufferInfo), rawMsg.flags);
+            Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender, senderPrefixes(rawMsg.sender, bufferInfo),
+                        realName(rawMsg.sender, rawMsg.networkId),  avatarUrl(rawMsg.sender, rawMsg.networkId),
+                        rawMsg.flags);
             messages << msg;
         }
 
@@ -427,8 +429,9 @@ void CoreSession::processMessages()
                 // add the StatusBuffer to the Cache in case there are more Messages for the original target
                 bufferInfoCache[rawMsg.networkId][rawMsg.target] = bufferInfo;
             }
-            Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender,
-                        senderPrefixes(rawMsg.sender, bufferInfo), rawMsg.flags);
+            Message msg(bufferInfo, rawMsg.type, rawMsg.text, rawMsg.sender, senderPrefixes(rawMsg.sender, bufferInfo),
+                        realName(rawMsg.sender, rawMsg.networkId),  avatarUrl(rawMsg.sender, rawMsg.networkId),
+                        rawMsg.flags);
             messages << msg;
         }
 
@@ -463,6 +466,33 @@ QString CoreSession::senderPrefixes(const QString &sender, const BufferInfo &buf
     return currentNetwork->modesToPrefixes(modes);
 }
 
+QString CoreSession::realName(const QString &sender, NetworkId networkId) const
+{
+    CoreNetwork *currentNetwork = network(networkId);
+    if (!currentNetwork) {
+        return {};
+    }
+
+    IrcUser *currentUser = currentNetwork->ircUser(nickFromMask(sender));
+    if (!currentUser) {
+        return {};
+    }
+
+    return currentUser->realName();
+}
+
+QString CoreSession::avatarUrl(const QString &sender, NetworkId networkId) const
+{
+    Q_UNUSED(sender);
+    Q_UNUSED(networkId);
+    // Currently we do not have a way to retrieve this value yet.
+    //
+    // This likely will require implementing IRCv3's METADATA spec.
+    // See https://ircv3.net/irc/
+    // And https://blog.irccloud.com/avatars/
+    return "";
+}
+
 Protocol::SessionState CoreSession::sessionState() const
 {
     QVariantList bufferInfos;
index 9967f80..72843a5 100644 (file)
@@ -241,6 +241,20 @@ private:
      * @param bufferInfo The BufferInfo object of the buffer
      */
     QString senderPrefixes(const QString &sender, const BufferInfo &bufferInfo) const;
+
+    /**
+     * This method obtains the realname of the message's sender.
+     * @param sender The hostmask of the sender
+     * @param networkId The network the user is on
+     */
+    QString realName(const QString &sender, NetworkId networkId) const;
+
+    /**
+     * This method obtains the avatar of the message's sender.
+     * @param sender The hostmask of the sender
+     * @param networkId The network the user is on
+     */
+    QString avatarUrl(const QString &sender, NetworkId networkId) const;
     QList<RawMessage> _messageQueue;
     bool _processMessages;
     CoreIgnoreListManager _ignoreListManager;
index 7377149..3c15b2c 100644 (file)
@@ -1542,7 +1542,11 @@ bool PostgreSqlStorage::logMessage(Message &msg)
         return false;
     }
 
-    QSqlQuery getSenderIdQuery = executePreparedQuery("select_senderid", msg.sender(), db);
+    QVariantList senderParams;
+    senderParams << msg.sender()
+                 << msg.realName()
+                 << msg.avatarUrl();
+    QSqlQuery getSenderIdQuery = executePreparedQuery("select_senderid", senderParams, db);
     int senderId;
     if (getSenderIdQuery.first()) {
         senderId = getSenderIdQuery.value(0).toInt();
@@ -1551,11 +1555,11 @@ bool PostgreSqlStorage::logMessage(Message &msg)
         // it's possible that the sender was already added by another thread
         // since the insert might fail we're setting a savepoint
         savePoint("sender_sp1", db);
-        QSqlQuery addSenderQuery = executePreparedQuery("insert_sender", msg.sender(), db);
+        QSqlQuery addSenderQuery = executePreparedQuery("insert_sender", senderParams, db);
 
         if (addSenderQuery.lastError().isValid()) {
             rollbackSavePoint("sender_sp1", db);
-            getSenderIdQuery = executePreparedQuery("select_senderid", msg.sender(), db);
+            getSenderIdQuery = executePreparedQuery("select_senderid", senderParams, db);
             watchQuery(getSenderIdQuery);
             getSenderIdQuery.first();
             senderId = getSenderIdQuery.value(0).toInt();
@@ -1605,28 +1609,34 @@ bool PostgreSqlStorage::logMessages(MessageList &msgs)
     }
 
     QList<int> senderIdList;
-    QHash<QString, int> senderIds;
+    QHash<SenderData, int> senderIds;
     QSqlQuery addSenderQuery;
     QSqlQuery selectSenderQuery;;
     for (int i = 0; i < msgs.count(); i++) {
-        const QString &sender = msgs.at(i).sender();
+        auto &msg = msgs.at(i);
+        SenderData sender = { msg.sender(), msg.realName(), msg.avatarUrl() };
         if (senderIds.contains(sender)) {
             senderIdList << senderIds[sender];
             continue;
         }
 
-        selectSenderQuery = executePreparedQuery("select_senderid", sender, db);
+        QVariantList senderParams;
+        senderParams << sender.sender
+                     << sender.realname
+                     << sender.avatarurl;
+
+        selectSenderQuery = executePreparedQuery("select_senderid", senderParams, db);
         if (selectSenderQuery.first()) {
             senderIdList << selectSenderQuery.value(0).toInt();
             senderIds[sender] = selectSenderQuery.value(0).toInt();
         }
         else {
             savePoint("sender_sp", db);
-            addSenderQuery = executePreparedQuery("insert_sender", sender, db);
+            addSenderQuery = executePreparedQuery("insert_sender", senderParams, db);
             if (addSenderQuery.lastError().isValid()) {
                 // seems it was inserted meanwhile... by a different thread
                 rollbackSavePoint("sender_sp", db);
-                selectSenderQuery = executePreparedQuery("select_senderid", sender, db);
+                selectSenderQuery = executePreparedQuery("select_senderid", senderParams, db);
                 watchQuery(selectSenderQuery);
                 selectSenderQuery.first();
                 senderIdList << selectSenderQuery.value(0).toInt();
@@ -1730,9 +1740,11 @@ QList<Message> PostgreSqlStorage::requestMsgs(UserId user, BufferId bufferId, Ms
         Message msg(timestamp,
             bufferInfo,
             (Message::Type)query.value(2).toUInt(),
-            query.value(6).toString(),
+            query.value(8).toString(),
             query.value(4).toString(),
             query.value(5).toString(),
+            query.value(6).toString(),
+            query.value(7).toString(),
             (Message::Flags)query.value(3).toUInt());
         msg.setMsgId(query.value(0).toInt());
         messagelist << msg;
@@ -1783,9 +1795,11 @@ QList<Message> PostgreSqlStorage::requestAllMsgs(UserId user, MsgId first, MsgId
         Message msg(timestamp,
             bufferInfoHash[query.value(1).toInt()],
             (Message::Type)query.value(3).toUInt(),
-            query.value(7).toString(),
+            query.value(9).toString(),
             query.value(5).toString(),
             query.value(6).toString(),
+            query.value(7).toString(),
+            query.value(8).toString(),
             (Message::Flags)query.value(4).toUInt());
         msg.setMsgId(query.value(0).toInt());
         messagelist << msg;
@@ -2060,6 +2074,8 @@ bool PostgreSqlMigrationWriter::writeMo(const SenderMO &sender)
 {
     bindValue(0, sender.senderId);
     bindValue(1, sender.sender);
+    bindValue(2, sender.realname);
+    bindValue(3, sender.avatarurl);
     return exec();
 }
 
index b8fc95e..96de7f6 100644 (file)
@@ -81,6 +81,7 @@
     <file>./SQL/PostgreSQL/setup_110_alter_sender_seq.sql</file>
     <file>./SQL/PostgreSQL/setup_120_alter_messageid_seq.sql</file>
     <file>./SQL/PostgreSQL/setup_130_function_lastmsgid.sql</file>
+    <file>./SQL/PostgreSQL/setup_140_sender_idx.sql</file>
     <file>./SQL/PostgreSQL/update_backlog_bufferid.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_bufferactivity.sql</file>
     <file>./SQL/PostgreSQL/update_buffer_cipher.sql</file>
     <file>./SQL/PostgreSQL/version/24/upgrade_000_alter_buffer_add_bufferactivity.sql</file>
     <file>./SQL/PostgreSQL/version/25/upgrade_000_alter_buffer_add_cipher.sql</file>
     <file>./SQL/PostgreSQL/version/26/upgrade_000_alter_buffer_add_highlightcount.sql</file>
+    <file>./SQL/PostgreSQL/version/27/upgrade_000_update_sender_add_realname.sql</file>
+    <file>./SQL/PostgreSQL/version/27/upgrade_010_update_sender_add_avatarurl.sql</file>
+    <file>./SQL/PostgreSQL/version/27/upgrade_020_update_sender_add_new_constraint.sql</file>
+    <file>./SQL/PostgreSQL/version/27/upgrade_030_upgrade_sender_drop_old_constraint.sql</file>
     <file>./SQL/SQLite/delete_backlog_by_uid.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_buffer.sql</file>
     <file>./SQL/SQLite/delete_backlog_for_network.sql</file>
     <file>./SQL/SQLite/setup_120_user_setting.sql</file>
     <file>./SQL/SQLite/setup_130_identity.sql</file>
     <file>./SQL/SQLite/setup_140_identity_nick.sql</file>
+    <file>./SQL/SQLite/setup_150_sender_idx.sql</file>
     <file>./SQL/SQLite/update_backlog_bufferid.sql</file>
     <file>./SQL/SQLite/update_buffer_bufferactivity.sql</file>
     <file>./SQL/SQLite/update_buffer_cipher.sql</file>
     <file>./SQL/SQLite/version/26/upgrade_000_create_buffer_idx.sql</file>
     <file>./SQL/SQLite/version/27/upgrade_000_alter_buffer_add_cipher.sql</file>
     <file>./SQL/SQLite/version/28/upgrade_000_alter_buffer_add_highlightcount.sql</file>
+    <file>./SQL/SQLite/version/29/upgrade_000_create_sender_tmp.sql</file>
+    <file>./SQL/SQLite/version/29/upgrade_010_copy_sender_sender_tmp.sql</file>
+    <file>./SQL/SQLite/version/29/upgrade_020_drop_sender.sql</file>
+    <file>./SQL/SQLite/version/29/upgrade_030_rename_sender_tmp_sender.sql</file>
+    <file>./SQL/SQLite/version/29/upgrade_040_update_sender_add_realname_avatarurl.sql</file>
 </qresource>
 </RCC>
index d71dd3c..7666679 100644 (file)
@@ -1720,6 +1720,8 @@ bool SqliteStorage::logMessage(Message &msg)
                 QSqlQuery addSenderQuery(db);
                 addSenderQuery.prepare(queryString("insert_sender"));
                 addSenderQuery.bindValue(":sender", msg.sender());
+                addSenderQuery.bindValue(":realname", msg.realName());
+                addSenderQuery.bindValue(":avatarurl", msg.avatarUrl());
                 safeExec(addSenderQuery);
                 safeExec(logMessageQuery);
                 error = !watchQuery(logMessageQuery);
@@ -1757,17 +1759,20 @@ bool SqliteStorage::logMessages(MessageList &msgs)
     db.transaction();
 
     {
-        QSet<QString> senders;
+        QSet<SenderData> senders;
         QSqlQuery addSenderQuery(db);
         addSenderQuery.prepare(queryString("insert_sender"));
         lockForWrite();
         for (int i = 0; i < msgs.count(); i++) {
-            const QString &sender = msgs.at(i).sender();
+            auto &msg = msgs.at(i);
+            SenderData sender = { msg.sender(), msg.realName(), msg.avatarUrl() };
             if (senders.contains(sender))
                 continue;
             senders << sender;
 
-            addSenderQuery.bindValue(":sender", sender);
+            addSenderQuery.bindValue(":sender", sender.sender);
+            addSenderQuery.bindValue(":realname", sender.realname);
+            addSenderQuery.bindValue(":avatarurl", sender.avatarurl);
             safeExec(addSenderQuery);
         }
     }
@@ -1869,9 +1874,11 @@ QList<Message> SqliteStorage::requestMsgs(UserId user, BufferId bufferId, MsgId
             Message msg(QDateTime::fromTime_t(query.value(1).toInt()),
                 bufferInfo,
                 (Message::Type)query.value(2).toUInt(),
-                query.value(6).toString(),
+                query.value(8).toString(),
                 query.value(4).toString(),
                 query.value(5).toString(),
+                query.value(6).toString(),
+                query.value(7).toString(),
                 (Message::Flags)query.value(3).toUInt());
             msg.setMsgId(query.value(0).toInt());
             messagelist << msg;
@@ -1924,9 +1931,11 @@ QList<Message> SqliteStorage::requestAllMsgs(UserId user, MsgId first, MsgId las
             Message msg(QDateTime::fromTime_t(query.value(2).toInt()),
                 bufferInfoHash[query.value(1).toInt()],
                 (Message::Type)query.value(3).toUInt(),
-                query.value(7).toString(),
+                query.value(9).toString(),
                 query.value(5).toString(),
                 query.value(6).toString(),
+                query.value(7).toString(),
+                query.value(8).toString(),
                 (Message::Flags)query.value(4).toUInt());
             msg.setMsgId(query.value(0).toInt());
             messagelist << msg;
@@ -2215,6 +2224,8 @@ bool SqliteMigrationReader::readMo(SenderMO &sender)
 
     sender.senderId = value(0).toInt();
     sender.sender = value(1).toString();
+    sender.realname = value(2).toString();
+    sender.avatarurl = value(3).toString();
     return true;
 }