From 0fdc45a668d95d603a9013f90392f6bc966c72f9 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Tue, 14 Jul 2026 20:22:04 -0500 Subject: deps: migrate to github.com/zerolabsco/devianter v0.3.1 Repoint the import path from git.macaw.me/skunky/devianter, replacing a placeholder v0.0.0 require that had no go.sum entry and did not resolve. v0.3.1 reorders the last two return values of PerformSearch, Group.Get and Group.Gallery from (..., error, Error) to (..., Error, error); adapt the call sites. The two types differ, so the compiler enforces this. --- app/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/api.go') diff --git a/app/api.go b/app/api.go index d2a5655..cd574b8 100755 --- a/app/api.go +++ b/app/api.go @@ -5,7 +5,7 @@ import ( "math/rand" "strings" - "git.macaw.me/skunky/devianter" + "github.com/zerolabsco/devianter" ) type API struct { @@ -63,7 +63,7 @@ func (a API) Random() { a.Error("Sorry, butt NSFW on this are disabled, and the instance failed to find a random art without NSFW", 500) } - s, err, daErr := devianter.PerformSearch(string(rand.Intn(999)), rand.Intn(30), 'a') + s, daErr, err := devianter.PerformSearch(string(rand.Intn(999)), rand.Intn(30), 'a') try(err) if daErr.RAW != nil { continue -- cgit v1.2.3 From 8a00f7c55cdbcddcd878c01a79f2db7dc3f080ef Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Tue, 14 Jul 2026 20:22:14 -0500 Subject: fix(api): harden random-art retry loop Three bugs in Random(): - The retry loop was unbounded. Only the NSFW path incremented attempt, so a run of DeviantArt errors span forever, hammering the API and risking an egress-IP ban. - string(rand.Intn(999)) converts a rune, not a number: string(65) is "A", not "65". Searches were querying garbage. Use strconv.Itoa. - rand.Intn panics on 0, so an empty result set crashed the handler. Skip empty results. The exhausted-retries error now fires when the loop ends rather than falling through to index an empty slice. --- app/api.go | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'app/api.go') diff --git a/app/api.go b/app/api.go index cd574b8..0398d3c 100755 --- a/app/api.go +++ b/app/api.go @@ -3,6 +3,7 @@ package app import ( "encoding/json" "math/rand" + "strconv" "strings" "github.com/zerolabsco/devianter" @@ -58,25 +59,32 @@ func (a API) sendMedia(d *devianter.Deviation) { // TODO: сделать фильтры func (a API) Random() { - for attempt := 1; ; { - if attempt > 3 { - a.Error("Sorry, butt NSFW on this are disabled, and the instance failed to find a random art without NSFW", 500) - } + // Bounded retries: the loop used to be unbounded, and the DeviantArt-error + // path never incremented attempt, so a single request could spin forever + // hammering the API (and get this instance's egress IP banned). + const maxAttempts = 3 - s, daErr, err := devianter.PerformSearch(string(rand.Intn(999)), rand.Intn(30), 'a') + for attempt := 0; attempt < maxAttempts; attempt++ { + // strconv.Itoa, not string(): string(65) is "A", not "65". + s, daErr, err := devianter.PerformSearch(strconv.Itoa(rand.Intn(999)), rand.Intn(30), 'a') try(err) if daErr.RAW != nil { continue } - deviation := &s.Results[rand.Intn(len(s.Results))] + // rand.Intn panics on 0, so an empty result set must be skipped. + if len(s.Results) == 0 { + continue + } + deviation := &s.Results[rand.Intn(len(s.Results))] if deviation.NSFW && !CFG.Nsfw { - attempt++ continue } a.sendMedia(deviation) return } + + a.Error("Sorry, butt NSFW on this are disabled, and the instance failed to find a random art without NSFW", 500) } -- cgit v1.2.3