Fix CheapShark returning zero deals by using dual-fetch strategy and relaxing filters

The bot stopped posting because sortBy=recent only returned low-discount deals,
and desc=1 was inverting the sort order for savings/DealRating queries. Now fetches
both recent and top-rated deals, merges with dedup. Lowered default thresholds to
20% min discount, 7.0 min rating, and $45 max price.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-03-22 02:09:27 -07:00
parent dcce744b5a
commit 29abc836d5
3 changed files with 46 additions and 10 deletions

View File

@@ -36,8 +36,8 @@ EXTRA_CURRENCIES=CAD,EUR,GBP
#ITAD_DEALS_LIMIT=200
# Shared filter defaults (used when source-specific values are not set)
MIN_DISCOUNT_PERCENT=50
MAX_PRICE=20
MIN_DISCOUNT_PERCENT=20
MAX_PRICE=45
# Matrix threads — post deals into per-category threads instead of the room
# Categories: Game Deals, DLC Deals, Epic Free Games, Non-Game Deals

View File

@@ -63,9 +63,9 @@ func Load() (*Config, error) {
}
}
c.MinDealRating = envFloat("MIN_DEAL_RATING", 8.0)
c.MinDiscountPercent = envInt("MIN_DISCOUNT_PERCENT", 50)
c.MaxPriceUSD = envFloat("MAX_PRICE_USD", 20)
c.MinDealRating = envFloat("MIN_DEAL_RATING", 7.0)
c.MinDiscountPercent = envInt("MIN_DISCOUNT_PERCENT", 20)
c.MaxPriceUSD = envFloat("MAX_PRICE_USD", 45)
c.DatabasePath = envStr("DATABASE_PATH", "deals.db")
intro := strings.ToLower(os.Getenv("SEND_INTRO_MESSAGE"))

View File

@@ -47,13 +47,49 @@ type cheapSharkRaw struct {
SteamAppID string `json:"steamAppID"`
}
// FetchCheapSharkDeals fetches deals from CheapShark API.
// FetchCheapSharkDeals fetches deals from CheapShark API using multiple
// sort strategies to ensure both new and high-value deals are captured.
func FetchCheapSharkDeals(maxPrice float64, pageSize int) ([]CheapSharkDeal, error) {
reqURL := fmt.Sprintf(
"https://www.cheapshark.com/api/1.0/deals?storeID=1,7,11,23&upperPrice=%d&sortBy=recent&desc=1&pageSize=%d",
// Fetch recent deals and top-rated deals, then merge.
// CheapShark's desc=0 (default) returns highest values first for savings/DealRating.
queries := []string{
fmt.Sprintf(
"https://www.cheapshark.com/api/1.0/deals?storeID=1,7,11,23&upperPrice=%d&sortBy=recent&pageSize=%d",
int(maxPrice), pageSize,
)
),
fmt.Sprintf(
"https://www.cheapshark.com/api/1.0/deals?storeID=1,7,11,23&upperPrice=%d&sortBy=DealRating&pageSize=%d",
int(maxPrice), pageSize,
),
}
seen := make(map[string]bool)
var allDeals []CheapSharkDeal
for _, reqURL := range queries {
fetched, err := fetchCheapSharkPage(reqURL)
if err != nil {
slog.Warn("cheapshark: fetch failed for query", "url", reqURL, "error", err)
continue
}
for _, d := range fetched {
if seen[d.DedupID] {
continue
}
seen[d.DedupID] = true
allDeals = append(allDeals, d)
}
}
if len(allDeals) == 0 {
return nil, fmt.Errorf("cheapshark: all queries failed or returned no results")
}
return allDeals, nil
}
// fetchCheapSharkPage fetches and parses a single CheapShark API page.
func fetchCheapSharkPage(reqURL string) ([]CheapSharkDeal, error) {
resp, err := http.Get(reqURL)
if err != nil {
return nil, fmt.Errorf("cheapshark request failed: %w", err)