55 lines
2.7 KiB
C#
55 lines
2.7 KiB
C#
namespace BlueLaminate.EFCore.Entities;
|
|
|
|
/// <summary>
|
|
/// One offer observed on skin.land via its internal
|
|
/// <c>GET /api/v2/obtained-skins?skin_id={id}&page={n}</c> endpoint (scraped through
|
|
/// the Python worker, since skin.land has no public API and sits behind Cloudflare).
|
|
/// <para>
|
|
/// Kept in its own table like <see cref="CsMoneyListing"/>, but deliberately thinner:
|
|
/// skin.land exposes a full-precision float and price but <b>no paint seed / def index</b>,
|
|
/// so an offer can't be fingerprinted to a market-agnostic <see cref="SkinInstance"/> and
|
|
/// there is no cross-market roll-up or dupe detection here (revisit if pattern is ever
|
|
/// exposed). StatTrak and Souvenir live on <em>separate</em> skin.land pages (their own
|
|
/// <c>stattrak-</c>/<c>souvenir-</c> slugs); v1 sweeps the base page per skin+wear, so
|
|
/// <see cref="IsStatTrak"/>/<see cref="IsSouvenir"/> are normally false.
|
|
/// </para>
|
|
/// Soft-tracked across sweeps exactly like <see cref="CsMoneyListing"/>:
|
|
/// <see cref="FirstSeenAt"/>/<see cref="LastSeenAt"/> bound the observation window and
|
|
/// <see cref="Status"/> flips to <see cref="ListingStatus.Removed"/> when a once-seen
|
|
/// offer stops appearing (sold/delisted).
|
|
/// </summary>
|
|
public class SkinLandListing
|
|
{
|
|
public int Id { get; set; }
|
|
|
|
/// <summary>skin.land's offer id (obtained-skin <c>id</c>). Natural key for dedup.</summary>
|
|
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; }
|
|
}
|