common: Port remote nicks to NickHighlightMatcher
[quassel.git] / src / core / coresessioneventprocessor.cpp
index c4c01e5..a461491 100644 (file)
@@ -28,7 +28,7 @@
 #include "ctcpevent.h"
 #include "ircevent.h"
 #include "ircuser.h"
-#include "logger.h"
+#include "logmessage.h"
 #include "messageevent.h"
 #include "netsplit.h"
 #include "quassel.h"
@@ -661,12 +661,46 @@ void CoreSessionEventProcessor::processIrcEventPong(IrcEvent *e)
     // Attempt to parse the timestamp
     QTime sendTime = QTime::fromString(timestamp, "hh:mm:ss.zzz");
     if (sendTime.isValid()) {
+        // Mark IRC server as sending valid ping replies
+        if (!coreNetwork(e)->isPongTimestampValid()) {
+            coreNetwork(e)->setPongTimestampValid(true);
+            // Add a message the first time it happens
+            qDebug().nospace() << "Received PONG with valid timestamp, marking pong replies on "
+                                  "network "
+                               << "\"" << qPrintable(e->network()->networkName()) << "\" (ID: "
+                               << qPrintable(QString::number(e->network()->networkId().toInt()))
+                               << ") as usable for latency measurement";
+        }
+        // Remove pending flag
+        coreNetwork(e)->resetPongReplyPending();
+
+        // Don't show this in the UI
+        e->setFlag(EventManager::Silent);
+        // TODO:  To allow for a user-sent /ping (without arguments, so default timestamp is used),
+        // this could track how many automated PINGs have been sent by the core and subtract one
+        // each time, only marking the PING as silent if there's pending automated pong replies.
+        // However, that's a behavior change which warrants further testing.  For now, take the
+        // simpler, previous approach that errs on the side of silencing too much.
+
         // Calculate latency from time difference, divided by 2 to account for round-trip time
         e->network()->setLatency(sendTime.msecsTo(QTime::currentTime()) / 2);
-    } else {
-        // Just in case it's a wonky server, log a debug message to make this easier to track down
-        qDebug() << "Received valid PONG with invalid timestamp, parameters are" << e->params();
+    } else if (coreNetwork(e)->isPongReplyPending() && !coreNetwork(e)->isPongTimestampValid()) {
+        // There's an auto-PING reply pending and we've not yet received a PONG reply with a valid
+        // timestamp.  It's possible this server will never respond with a valid timestamp, and thus
+        // any automated PINGs will result in unwanted spamming of the server buffer.
+
+        // Don't show this in the UI
+        e->setFlag(EventManager::Silent);
+        // Remove pending flag
+        coreNetwork(e)->resetPongReplyPending();
+
+        // Log a message
+        qDebug().nospace() << "Received PONG with invalid timestamp from network "
+                           << "\"" << qPrintable(e->network()->networkName()) << "\" (ID: "
+                           << qPrintable(QString::number(e->network()->networkId().toInt()))
+                           << "), silencing, parameters are " << e->params();
     }
+    // else: We're not expecting a PONG reply and timestamp is not valid, assume it's from the user
 }
 
 
@@ -1020,13 +1054,13 @@ void CoreSessionEventProcessor::processIrcEvent322(IrcEvent *e)
     switch (e->params().count()) {
     case 3:
         topic = e->params()[2];
-        [[clang::fallthrough]];
+        // fallthrough
     case 2:
         userCount = e->params()[1].toUInt();
-        [[clang::fallthrough]];
+        // fallthrough
     case 1:
         channelName = e->params()[0];
-        [[clang::fallthrough]];
+        // fallthrough
     default:
         break;
     }
@@ -1579,27 +1613,22 @@ void CoreSessionEventProcessor::handleCtcpPing(CtcpEvent *e)
 
 void CoreSessionEventProcessor::handleCtcpTime(CtcpEvent *e)
 {
-    // Explicitly specify the Qt default DateTime format string to allow for modification
-    // Qt::TextDate default roughly corresponds to...
-    // > ddd MMM d yyyy HH:mm:ss
-    //
-    // See https://doc.qt.io/qt-5/qdatetime.html#toString
-    // And https://doc.qt.io/qt-5/qt.html#DateFormat-enum
-#if QT_VERSION > 0x050000
-    // Append the timezone identifier "t", so other other IRC users have a frame of reference for
-    // the current timezone.  This could be figured out before by manually comparing to UTC, so this
-    // is just convenience.
-
-    // Alas, "t" was only added in Qt 5
-    e->setReply(QDateTime::currentDateTime().toString("ddd MMM d yyyy HH:mm:ss t"));
-#else
-    e->setReply(QDateTime::currentDateTime().toString("ddd MMM d yyyy HH:mm:ss"));
-#endif
+    // Use the ISO standard to avoid locale-specific translated names
+    // Include timezone offset data to show which timezone a user's in, otherwise we're providing
+    // NTP-over-IRC with terrible accuracy.
+    e->setReply(formatDateTimeToOffsetISO(QDateTime::currentDateTime()));
 }
 
 
 void CoreSessionEventProcessor::handleCtcpVersion(CtcpEvent *e)
 {
-    e->setReply(QString("Quassel IRC %1 (built on %2) -- https://www.quassel-irc.org")
-        .arg(Quassel::buildInfo().plainVersionString).arg(Quassel::buildInfo().commitDate));
+    // Deliberately do not translate project name
+    // Use the ISO standard to avoid locale-specific translated names
+    // Use UTC time to provide a consistent string regardless of timezone
+    // (Statistics tracking tools usually only group client versions by exact string matching)
+    e->setReply(QString("Quassel IRC %1 (version date %2) -- https://www.quassel-irc.org")
+                .arg(Quassel::buildInfo().plainVersionString)
+                .arg(Quassel::buildInfo().commitDate.isEmpty() ?
+                      "unknown" : tryFormatUnixEpoch(Quassel::buildInfo().commitDate,
+                                                     Qt::DateFormat::ISODate, true)));
 }