Files
Operation-Blue-Laminate-v2/BlueLaminate/BlueLaminate.EFCore/Data/SkinTrackerDbContext.cs
bob dc7c3f99ae Add cs.money worker stack with per-worker IPRoyal residential proxy
Brings up the pull-model scraper: the .NET C2 hands skin+wear jobs to Python nodriver workers that scrape cs.money and post results back, plus the supporting Core/EFCore data model, migrations, and docker-compose orchestration.

IPRoyal proxying lets workers scale horizontally with a distinct residential exit IP each: every worker process mints its own sticky session at startup, and an in-process forwarding proxy injects the gateway auth so Chromium talks only to an auth-free localhost endpoint (zero CDP). On a Cloudflare challenge a worker rotates to a fresh session/IP and re-warms. Verified end-to-end against live IPRoyal: distinct US residential exits per worker and IP rotation on demand.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 15:03:53 -05:00

61 lines
2.8 KiB
C#

using BlueLaminate.EFCore.Configurations;
using BlueLaminate.EFCore.Entities;
using Microsoft.EntityFrameworkCore;
namespace BlueLaminate.EFCore.Data;
public class SkinTrackerDbContext : DbContext
{
static SkinTrackerDbContext()
{
// Store and read all timestamps as UTC (timestamptz). Required so that
// DateTimeOffset properties round-trip correctly with Npgsql.
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", false);
}
public SkinTrackerDbContext(DbContextOptions<SkinTrackerDbContext> options)
: base(options)
{
}
public DbSet<Weapon> Weapons => Set<Weapon>();
public DbSet<ScrapeRun> ScrapeRuns => Set<ScrapeRun>();
public DbSet<Collection> Collections => Set<Collection>();
public DbSet<Skin> Skins => Set<Skin>();
public DbSet<SkinCondition> SkinConditions => Set<SkinCondition>();
public DbSet<SteamUser> SteamUsers => Set<SteamUser>();
public DbSet<SkinInstance> SkinInstances => Set<SkinInstance>();
public DbSet<InventoryItem> InventoryItems => Set<InventoryItem>();
public DbSet<Trade> Trades => Set<Trade>();
public DbSet<TradeItem> TradeItems => Set<TradeItem>();
public DbSet<PriceHistory> PriceHistories => Set<PriceHistory>();
public DbSet<Listing> Listings => Set<Listing>();
public DbSet<CsMoneyListing> CsMoneyListings => Set<CsMoneyListing>();
/// <summary>Read-only cross-market view UNIONing the per-market listing tables.</summary>
public DbSet<MarketListing> MarketListings => Set<MarketListing>();
/// <summary>The PostgreSQL schema that owns all of this context's tables.</summary>
public const string Schema = "skintracker";
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema(Schema);
modelBuilder.ApplyConfiguration(new WeaponConfiguration());
modelBuilder.ApplyConfiguration(new ScrapeRunConfiguration());
modelBuilder.ApplyConfiguration(new CollectionConfiguration());
modelBuilder.ApplyConfiguration(new SkinConfiguration());
modelBuilder.ApplyConfiguration(new SkinConditionConfiguration());
modelBuilder.ApplyConfiguration(new SteamUserConfiguration());
modelBuilder.ApplyConfiguration(new SkinInstanceConfiguration());
modelBuilder.ApplyConfiguration(new InventoryItemConfiguration());
modelBuilder.ApplyConfiguration(new TradeConfiguration());
modelBuilder.ApplyConfiguration(new TradeItemConfiguration());
modelBuilder.ApplyConfiguration(new PriceHistoryConfiguration());
modelBuilder.ApplyConfiguration(new ListingConfiguration());
modelBuilder.ApplyConfiguration(new CsMoneyListingConfiguration());
modelBuilder.ApplyConfiguration(new MarketListingConfiguration());
}
}