From 60b0acb45afee95823691b14105f8398754fee46 Mon Sep 17 00:00:00 2001 From: Dima Krasner Date: Thu, 17 Oct 2024 15:51:58 +0300 Subject: [PATCH] be more user-friendly when posting or editing is throttled --- front/edit.go | 5 +++-- front/post.go | 11 ++++++----- test/edit_test.go | 4 ++-- test/poll_test.go | 2 +- test/say_test.go | 2 +- test/upload_edit_test.go | 2 +- test/whisper_test.go | 2 +- 7 files changed, 15 insertions(+), 13 deletions(-) diff --git a/front/edit.go b/front/edit.go index aa13ee0d..9062c491 100644 --- a/front/edit.go +++ b/front/edit.go @@ -63,9 +63,10 @@ func (h *Handler) doEdit(w text.Writer, r *Request, args []string, readInput inp } canEdit := lastEditTime.Add(h.Config.EditThrottleUnit * time.Duration(math.Pow(h.Config.EditThrottleFactor, float64(edits)))) - if time.Now().Before(canEdit) { + until := time.Until(canEdit) + if until > 0 { r.Log.Warn("Throttled request to edit post", "note", note.ID, "can", canEdit) - w.Status(40, "Please try again later") + w.Statusf(40, "Please wait for %s", until.Truncate(time.Second).String()) return } diff --git a/front/post.go b/front/post.go index 1578995b..fe303610 100644 --- a/front/post.go +++ b/front/post.go @@ -60,16 +60,17 @@ func (h *Handler) post(w text.Writer, r *Request, oldNote *ap.Object, inReplyTo if today.Valid && today.Int64 >= h.Config.MaxPostsPerDay { r.Log.Warn("User has exceeded the daily posts quota", "posts", today.Int64) - w.Status(40, "Please wait before posting again") + w.Status(40, "Reached daily posts quota") return } if today.Valid && last.Valid { t := time.Unix(last.Int64, 0) - interval := max(1, time.Duration(today.Int64/h.Config.PostThrottleFactor)) * h.Config.PostThrottleUnit - if now.Sub(t) < interval { - r.Log.Warn("User is posting too frequently", "last", t, "can", t.Add(interval)) - w.Status(40, "Please wait before posting again") + can := t.Add(max(1, time.Duration(today.Int64/h.Config.PostThrottleFactor)) * h.Config.PostThrottleUnit) + until := time.Until(can) + if until > 0 { + r.Log.Warn("User is posting too frequently", "last", t, "can", can) + w.Statusf(40, "Please wait for %s", until.Truncate(time.Second).String()) return } } diff --git a/test/edit_test.go b/test/edit_test.go index 288982ca..11e13558 100644 --- a/test/edit_test.go +++ b/test/edit_test.go @@ -48,7 +48,7 @@ func TestEdit_Throttling(t *testing.T) { id := whisper[15 : len(whisper)-2] edit := server.Handle(fmt.Sprintf("/users/edit/%s?Hello%%20followers", id), server.Bob) - assert.Equal("40 Please try again later\r\n", edit) + assert.Regexp(`^40 Please wait for \S+\r\n$`, edit) users = server.Handle("/users", server.Alice) assert.Contains(users, "No posts.") @@ -98,7 +98,7 @@ func TestEdit_HappyFlow(t *testing.T) { assert.Contains(users, "Hello followers") edit = server.Handle(fmt.Sprintf("/users/edit/%s?Hello,%%20followers", id), server.Bob) - assert.Equal("40 Please try again later\r\n", edit) + assert.Regexp(`^40 Please wait for \S+\r\n$`, edit) users = server.Handle("/users", server.Alice) assert.NotContains(users, "No posts.") diff --git a/test/poll_test.go b/test/poll_test.go index 8b19c6ae..1ed3a538 100644 --- a/test/poll_test.go +++ b/test/poll_test.go @@ -516,7 +516,7 @@ func TestPoll_DeleteReply(t *testing.T) { assert.Equal(1, valid) edit := server.Handle(fmt.Sprintf("/users/edit/%s?chocolate", reply[15:len(reply)-2]), server.Alice) - assert.Equal("40 Please try again later\r\n", edit) + assert.Regexp(`^40 Please wait for \S+\r\n$`, edit) } func TestPoll_Update(t *testing.T) { diff --git a/test/say_test.go b/test/say_test.go index 536159ba..6b1f3b2a 100644 --- a/test/say_test.go +++ b/test/say_test.go @@ -57,7 +57,7 @@ func TestSay_Throttling(t *testing.T) { assert.Contains(outbox, "Hello world") say = server.Handle("/users/say?Hello%20once%20more,%20world", server.Alice) - assert.Equal("40 Please wait before posting again\r\n", say) + assert.Regexp(`^40 Please wait for \S+\r\n$`, say) outbox = server.Handle("/users/outbox/"+strings.TrimPrefix(server.Alice.ID, "https://"), server.Bob) assert.Contains(outbox, "Hello world") diff --git a/test/upload_edit_test.go b/test/upload_edit_test.go index b6bdc4af..505abd72 100644 --- a/test/upload_edit_test.go +++ b/test/upload_edit_test.go @@ -59,7 +59,7 @@ func TestUploadEdit_HappyFlow(t *testing.T) { assert.Contains(users, "Hello followers") edit = server.Upload(fmt.Sprintf("/users/upload/edit/%s;mime=text/plain;size=16", id), server.Bob, []byte("Hello, followers")) - assert.Equal("40 Please try again later\r\n", edit) + assert.Regexp(`^40 Please wait for \S+\r\n$`, edit) assert.NoError((inbox.FeedUpdater{Domain: domain, Config: server.cfg, DB: server.db}).Run(context.Background())) diff --git a/test/whisper_test.go b/test/whisper_test.go index 5535dfe4..045b9f2b 100644 --- a/test/whisper_test.go +++ b/test/whisper_test.go @@ -89,7 +89,7 @@ func TestWhisper_Throttling(t *testing.T) { assert.Contains(outbox, "Hello world") whisper = server.Handle("/users/whisper?Hello%20once%20more,%20world", server.Alice) - assert.Equal("40 Please wait before posting again\r\n", whisper) + assert.Regexp(`^40 Please wait for \S+\r\n$`, whisper) outbox = server.Handle("/users/outbox/"+strings.TrimPrefix(server.Alice.ID, "https://"), server.Bob) assert.Contains(outbox, "Hello world")