mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
Forex/camp review hardening: bound CoinGecko body, escape URL params, fail-open camp on DB error
- forex_crypto.go: cap the CoinGecko response with io.LimitReader(64KiB); build the simple/price query via url.Values instead of bare Sprintf. - dnd_expedition_camp.go: a combat-session lookup error now fails open (allow camp) + logs a warning, instead of blocking standard camp with a misleading empty 'not cleared' rejection.
This commit is contained in:
@@ -2,6 +2,7 @@ package plugin
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"math/rand/v2"
|
"math/rand/v2"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -369,7 +370,13 @@ func campLocationCheck(exp *Expedition) (cleared bool, problem string) {
|
|||||||
encID := encounterIDForRoom(run.CurrentRoom)
|
encID := encounterIDForRoom(run.CurrentRoom)
|
||||||
sess, err := getCombatSessionForEncounter(run.RunID, encID)
|
sess, err := getCombatSessionForEncounter(run.RunID, encID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, ""
|
// Can't read the encounter's combat state. Fail open like the
|
||||||
|
// run-lookup path above rather than blocking standard camp with an
|
||||||
|
// empty (misleading "not cleared") rejection — a DB hiccup shouldn't
|
||||||
|
// strand a player who only wants to rest.
|
||||||
|
slog.Warn("camp: combat session lookup failed; allowing camp",
|
||||||
|
"run", run.RunID, "encounter", encID, "err", err)
|
||||||
|
return true, ""
|
||||||
}
|
}
|
||||||
if sess != nil && sess.Status == CombatStatusActive {
|
if sess != nil && sess.Status == CombatStatusActive {
|
||||||
return false, "You can't camp mid-fight — finish the encounter first."
|
return false, "You can't camp mid-fight — finish the encounter first."
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -82,8 +84,11 @@ func (p *ForexPlugin) cgSpotUSD(sym string) (float64, error) {
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
url := fmt.Sprintf("%s/simple/price?ids=%s&vs_currencies=usd", coinGeckoBaseURL, info.CoinGeckoID)
|
q := url.Values{}
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
q.Set("ids", info.CoinGeckoID)
|
||||||
|
q.Set("vs_currencies", "usd")
|
||||||
|
reqURL := coinGeckoBaseURL + "/simple/price?" + q.Encode()
|
||||||
|
req, err := http.NewRequestWithContext(ctx, "GET", reqURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -99,7 +104,7 @@ func (p *ForexPlugin) cgSpotUSD(sym string) (float64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var data map[string]map[string]float64
|
var data map[string]map[string]float64
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
if err := json.NewDecoder(io.LimitReader(resp.Body, 64<<10)).Decode(&data); err != nil {
|
||||||
return 0, fmt.Errorf("coingecko decode error: %w", err)
|
return 0, fmt.Errorf("coingecko decode error: %w", err)
|
||||||
}
|
}
|
||||||
entry, ok := data[info.CoinGeckoID]
|
entry, ok := data[info.CoinGeckoID]
|
||||||
|
|||||||
Reference in New Issue
Block a user