delthas: 1 Truncate message times to the second when using the FS message store 4 files changed, 25 insertions(+), 5 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~emersion/soju-dev/patches/36190/mbox | git am -3Learn more about email & git
The FS message store truncates message times to the second. This means that a message sent out as 2020-01-01T00:00:00.123Z could be sent later as part of a CHATHISTORY batch as 2020-01-01T00:00:00.000Z, which could cause issues in clients. One such issue is a client sending a MARKREAD for 2020-01-01T00:00:00.000Z, with another client considering the 2020-01-01T00:00:00.123Z message it has as unread. This fixes the issue by truncating all message times to the second when using the FS message store. --- downstream.go | 6 +++--- msgstore/fs.go | 5 +++++ upstream.go | 8 ++++++-- user.go | 11 +++++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/downstream.go b/downstream.go index 6302a5c..45c8576 100644 --- a/downstream.go +++ b/downstream.go @@ -2280,7 +2280,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc. dc.logger.Printf("broadcasting bouncer-wide %v: %v", msg.Command, text) broadcastTags := tags.Copy() - broadcastTags["time"] = irc.TagValue(xirc.FormatServerTime(time.Now())) + broadcastTags["time"] = irc.TagValue(dc.user.FormatServerTime(time.Now())) broadcastMsg := &irc.Message{ Tags: broadcastTags, Prefix: servicePrefix, @@ -2306,7 +2306,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc. if casemapASCII(name) == serviceNickCM { if dc.caps.IsEnabled("echo-message") { echoTags := tags.Copy() - echoTags["time"] = irc.TagValue(xirc.FormatServerTime(time.Now())) + echoTags["time"] = irc.TagValue(dc.user.FormatServerTime(time.Now())) dc.SendMessage(&irc.Message{ Tags: echoTags, Prefix: dc.prefix(), @@ -2350,7 +2350,7 @@ func (dc *downstreamConn) handleMessageRegistered(ctx context.Context, msg *irc. } echoTags := tags.Copy() - echoTags["time"] = irc.TagValue(xirc.FormatServerTime(time.Now())) + echoTags["time"] = irc.TagValue(dc.user.FormatServerTime(time.Now())) if uc.account != "" { echoTags["account"] = irc.TagValue(uc.account) } diff --git a/msgstore/fs.go b/msgstore/fs.go index 53f9977..65db04e 100644 --- a/msgstore/fs.go +++ b/msgstore/fs.go @@ -96,6 +96,11 @@ var ( _ RenameNetworkStore = (*fsMessageStore)(nil) ) +func IsFSStore(store Store) bool { + _, ok := store.(*fsMessageStore) + return ok +} + func NewFSStore(root string, user *database.User) *fsMessageStore { return &fsMessageStore{ root: filepath.Join(root, escapeFilename(user.Username)), diff --git a/upstream.go b/upstream.go index e1030a2..4aa3ff9 100644 --- a/upstream.go +++ b/upstream.go @@ -485,8 +485,12 @@ func (uc *upstreamConn) handleMessage(ctx context.Context, msg *irc.Message) err msg.Prefix = uc.serverPrefix } - if _, ok := msg.Tags["time"]; !ok && !isNumeric(msg.Command) { - msg.Tags["time"] = irc.TagValue(xirc.FormatServerTime(time.Now())) + if !isNumeric(msg.Command) { + t, err := time.Parse(xirc.ServerTimeLayout, string(msg.Tags["time"])) + if err != nil { + t = time.Now() + } + msg.Tags["time"] = irc.TagValue(uc.user.FormatServerTime(t)) } switch msg.Command { diff --git a/user.go b/user.go index 7468483..43ea79a 100644 --- a/user.go +++ b/user.go @@ -13,6 +13,8 @@ import ( "strings" "time" + "git.sr.ht/~emersion/soju/xirc" + "github.com/SherClockHolmes/webpush-go" "gopkg.in/irc.v3" @@ -1114,6 +1116,15 @@ func (u *user) hasPersistentMsgStore() bool { return !msgstore.IsMemoryStore(u.msgStore) } +func (u *user) FormatServerTime(t time.Time) string { + if u.msgStore != nil && msgstore.IsFSStore(u.msgStore) { + // The FS message store truncates message timestamps to the second, + // so truncate them here to get consistent timestamps. + t = t.Truncate(time.Second) + } + return xirc.FormatServerTime(t) +} + // localAddrForHost returns the local address to use when connecting to host. // A nil address is returned when the OS should automatically pick one. func (u *user) localTCPAddrForHost(ctx context.Context, host string) (*net.TCPAddr, error) { base-commit: 90be9a8ab95a06d7e622852bf312116c7e199d48 -- 2.17.1
Pushed, thanks!