diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aab7db7d..7a7e91af9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Bugfix: Handle symlinks properly when saving commands & settings (#1856, #1908) - Bugfix: Starting Chatterino in a minimized state after an update will no longer cause a crash - Bugfix: Modify the emote parsing to handle some edge-cases with dots and stuff (#1704, #1714) +- Bugfix: Fixed timestamps being incorrect on some messages loaded from the recent-messages service on startup (#1286, #2020) ## 2.2.0 diff --git a/src/messages/MessageBuilder.cpp b/src/messages/MessageBuilder.cpp index 545d8735f..43abc5c27 100644 --- a/src/messages/MessageBuilder.cpp +++ b/src/messages/MessageBuilder.cpp @@ -127,7 +127,8 @@ MessageBuilder::MessageBuilder(SystemMessageTag, const QString &text, } MessageBuilder::MessageBuilder(TimeoutMessageTag, - const QString &systemMessageText, int times) + const QString &systemMessageText, int times, + const QTime &time) : MessageBuilder() { QString username = systemMessageText.split(" ").at(0); @@ -135,7 +136,7 @@ MessageBuilder::MessageBuilder(TimeoutMessageTag, QString text; - this->emplace(); + this->emplace(time); this->emplaceSystemTextAndUpdate(username, text) ->setLink({Link::UserInfo, username}); this->emplaceSystemTextAndUpdate( @@ -147,13 +148,14 @@ MessageBuilder::MessageBuilder(TimeoutMessageTag, MessageBuilder::MessageBuilder(TimeoutMessageTag, const QString &username, const QString &durationInSeconds, - const QString &reason, bool multipleTimes) + const QString &reason, bool multipleTimes, + const QTime &time) : MessageBuilder() { QString fullText; QString text; - this->emplace(); + this->emplace(time); this->emplaceSystemTextAndUpdate(username, fullText) ->setLink({Link::UserInfo, username}); diff --git a/src/messages/MessageBuilder.hpp b/src/messages/MessageBuilder.hpp index a8e04b628..8a9468f0d 100644 --- a/src/messages/MessageBuilder.hpp +++ b/src/messages/MessageBuilder.hpp @@ -42,10 +42,11 @@ public: MessageBuilder(SystemMessageTag, const QString &text, const QTime &time = QTime::currentTime()); MessageBuilder(TimeoutMessageTag, const QString &systemMessageText, - int times); + int times, const QTime &time = QTime::currentTime()); MessageBuilder(TimeoutMessageTag, const QString &username, const QString &durationInSeconds, const QString &reason, - bool multipleTimes); + bool multipleTimes, + const QTime &time = QTime::currentTime()); MessageBuilder(const BanAction &action, uint32_t count = 1); MessageBuilder(const UnbanAction &action); MessageBuilder(const AutomodUserAction &action); diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index 5853d02fc..a0a5cd6ff 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -370,7 +370,8 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) { chan->disableAllMessages(); chan->addMessage( - makeSystemMessage("Chat has been cleared by a moderator.")); + makeSystemMessage("Chat has been cleared by a moderator.", + calculateMessageTimestamp(message))); return; } @@ -390,9 +391,10 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message) reason = v.toString(); } - auto timeoutMsg = MessageBuilder(timeoutMessage, username, - durationInSeconds, reason, false) - .release(); + auto timeoutMsg = + MessageBuilder(timeoutMessage, username, durationInSeconds, reason, + false, calculateMessageTimestamp(message)) + .release(); chan->addOrReplaceTimeout(timeoutMsg); // refresh all @@ -556,8 +558,9 @@ std::vector IrcMessageHandler::parseUserNoticeMessage( if (it != tags.end()) { - auto b = MessageBuilder(systemMessage, - parseTagString(it.value().toString())); + auto b = + MessageBuilder(systemMessage, parseTagString(it.value().toString()), + calculateMessageTimestamp(message)); b->flags.set(MessageFlag::Subscription); auto newMessage = b.release(); @@ -597,8 +600,9 @@ void IrcMessageHandler::handleUserNoticeMessage(Communi::IrcMessage *message, if (it != tags.end()) { - auto b = MessageBuilder(systemMessage, - parseTagString(it.value().toString())); + auto b = + MessageBuilder(systemMessage, parseTagString(it.value().toString()), + calculateMessageTimestamp(message)); b->flags.set(MessageFlag::Subscription); auto newMessage = b.release(); @@ -659,25 +663,8 @@ std::vector IrcMessageHandler::parseNoticeMessage( { std::vector builtMessages; - if (message->tags().contains("historical")) - { - bool customReceived = false; - qint64 ts = message->tags() - .value("rm-received-ts") - .toLongLong(&customReceived); - if (!customReceived) - { - ts = message->tags().value("tmi-sent-ts").toLongLong(); - } - - QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(ts); - builtMessages.emplace_back( - makeSystemMessage(message->content(), dateTime.time())); - } - else - { - builtMessages.emplace_back(makeSystemMessage(message->content())); - } + builtMessages.emplace_back(makeSystemMessage( + message->content(), calculateMessageTimestamp(message))); return builtMessages; } diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 57e22600e..f8becd25a 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -71,11 +71,15 @@ namespace { // rebuild the raw irc message so we can convert it back to an ircmessage again! // this could probably be done in a smarter way + auto s = QString(":tmi.twitch.tv NOTICE %1 :%2") .arg(channelName) .arg(noticeMessage); - return Communi::IrcMessage::fromData(s.toUtf8(), nullptr); + auto newMessage = Communi::IrcMessage::fromData(s.toUtf8(), nullptr); + newMessage->setTags(message->tags()); + + return newMessage; } // parseRecentMessages takes a json object and returns a vector of diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 9eca8ad4c..42bf4096e 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -220,24 +220,8 @@ MessagePtr TwitchMessageBuilder::build() } // timestamp - if (this->historicalMessage_) - { - // This may be architecture dependent(datatype) - bool customReceived = false; - qint64 ts = - this->tags.value("rm-received-ts").toLongLong(&customReceived); - if (!customReceived) - { - ts = this->tags.value("tmi-sent-ts").toLongLong(); - } - - QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(ts); - this->emplace(dateTime.time()); - } - else - { - this->emplace(); - } + this->emplace( + calculateMessageTimestamp(this->ircMessage)); bool addModerationElement = true; if (this->senderIsBroadcaster) diff --git a/src/util/IrcHelpers.hpp b/src/util/IrcHelpers.hpp index 9fb8ce2b4..821bee2fd 100644 --- a/src/util/IrcHelpers.hpp +++ b/src/util/IrcHelpers.hpp @@ -58,4 +58,25 @@ inline QString parseTagString(const QString &input) return output; } +inline QTime calculateMessageTimestamp(const Communi::IrcMessage *message) +{ + // Check if message is from recent-messages API + if (message->tags().contains("historical")) + { + bool customReceived = false; + qint64 ts = + message->tags().value("rm-received-ts").toLongLong(&customReceived); + if (!customReceived) + { + ts = message->tags().value("tmi-sent-ts").toLongLong(); + } + + return QDateTime::fromMSecsSinceEpoch(ts).time(); + } + else + { + return QTime::currentTime(); + } +} + } // namespace chatterino