Show T5 products in the client's shop; keep float IDs and unknown paths off IMVU
CI / build (push) Successful in 34s

The shop's T5 filter (maturity_rating "t5") is answered from the hub's products, fetched so they can be
shown and tried on; buying T5 products adds them to the hub library, and product.php details for
community products are answered here.

The client sends some product IDs as floats ("2000000008.0"): product.php passed the worn community
product to IMVU that way. Every ID is now read either way, and products.Guard refuses any request to
IMVU that still names a local ID given out. T5DE_PROXY_DUMP logs request and response bodies.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
dhkatzandClaude Opus 5.5 committed 2026-10-30 01:15:16 -07:00
1 parent 6506c641f0
commit 2280ad6314
14 files changed
+785 -18

No files matched your search

+11 -3
View File
@@ -153,6 +153,10 @@ func run(logger *log.Logger, listen, ready string, parentPID int, trace bool, pa
fetcher.OnLibrary = prods.RefreshInventory
prods.Want = fetcher.Want
prods.HubDir, prods.Owned = hubProducts, fetcher.Owned
prods.Shop, prods.Fetch = client.Products, fetcher.Ensure
prods.AddToLibrary = func(ctx context.Context, id string) error {
return client.Call(ctx, "PUT", "/api/v1/library/"+id, map[string]any{}, nil)
}
prods.OnHide = func(id string) {
if fetch.IsHubID(id) {
go func() {
@@ -164,11 +168,15 @@ func run(logger *log.Logger, listen, ready string, parentPID int, trace bool, pa
}
}
manager.Start()
chain := proxy.Interceptors{manager}
if prods != nil {
handler.Interceptor = proxy.Interceptors{manager, prods}
} else {
handler.Interceptor = manager
chain = append(chain, prods)
}
chain = append(chain, proxy.Dump{Match: os.Getenv("T5DE_PROXY_DUMP"), Log: logger})
if prods != nil {
chain = append(chain, products.Guard{Products: prods}) // last: nothing naming a community product reaches IMVU
}
handler.Interceptor = chain
server := &http.Server{
Handler: handler,
ReadHeaderTimeout: 30 * time.Second,