namespace BlueLaminate.EFCore.Entities; /// /// One offer observed on skin.land via its internal /// GET /api/v2/obtained-skins?skin_id={id}&page={n} endpoint (scraped through /// the Python worker, since skin.land has no public API and sits behind Cloudflare). /// /// Kept in its own table like , but deliberately thinner: /// skin.land exposes a full-precision float and price but no paint seed / def index, /// so an offer can't be fingerprinted to a market-agnostic and /// there is no cross-market roll-up or dupe detection here (revisit if pattern is ever /// exposed). StatTrak and Souvenir live on separate skin.land pages (their own /// stattrak-/souvenir- slugs); v1 sweeps the base page per skin+wear, so /// / are normally false. /// /// Soft-tracked across sweeps exactly like : /// / bound the observation window and /// flips to when a once-seen /// offer stops appearing (sold/delisted). /// public class SkinLandListing { public int Id { get; set; } /// skin.land's offer id (obtained-skin id). Natural key for dedup. public long ListingId { get; set; } // Catalogue links. Like cs.money (and unlike the CSFloat global sweep) these are NOT // best-effort: each scrape job targets one skin+wear, so we set them directly. public int SkinId { get; set; } public Skin Skin { get; set; } = null!; public int? ConditionId { get; set; } public SkinCondition? Condition { get; set; } // Item identity, from the offer's skin block. public string MarketHashName { get; set; } = null!; public decimal? FloatValue { get; set; } // item_float (string, full precision) public bool IsStatTrak { get; set; } public bool IsSouvenir { get; set; } public string? NameTag { get; set; } // offer.name_tag (rare; affects value) public int StickerCount { get; set; } // Pricing. skin.land returns a single price (the amount to buy/withdraw the item). public decimal Price { get; set; } // final_withdrawal_price public string Currency { get; set; } = "USD"; // prices are read in USD public string? InspectLink { get; set; } // item_link (steam:// inspect) // Soft-tracking across sweeps. public DateTimeOffset FirstSeenAt { get; set; } public DateTimeOffset LastSeenAt { get; set; } public ListingStatus Status { get; set; } public DateTimeOffset? RemovedAt { get; set; } }