← Back to Marketplace Gameplay
SkinScope banner
SkinScope icon

SkinScope

Discord plugin · Gameplay
by Paul
v0.0.13 ↓2 installs

Explore CS2 skin prices from the Steam Market in one Discord embed.

SkinScope screenshot 1
SkinScope screenshot 2
SkinScope screenshot 3
SkinScope screenshot 4
SkinScope screenshot 5

Commands this plugin adds

/skin /skin-config

About this plugin

SkinScope

CS2 skin price lookup for the YourBot.gg Discord bot platform (formerly branded MMO Maid; the platform rename shipped with SDK 0.6.0).

/skin query: ak redline

Returns a rich Discord embed with the skin's image, rarity tier, valid wears, and Steam Market + Skinport + CSFloat prices side by side (USD, from build-time bundled dumps) — each non-Steam field shows its lowest ask, a vs Steam delta, and the listing count. The embed title is a clickable hyperlink to the Steam Market listings page — the buy path. Interactive wear and quality buttons let users explore variants, editing the card in place.

Features

  • Three price sources, side by side — Steam Market (crawled directly from the Community Market's search/render endpoint), Skinport (public /v1/items API) and CSFloat (public /v1/listings/price-list), all sourced at build time. Each non-Steam field carries a −X.X% vs Steam delta and listing count, so the card is a real cross-market comparison — and the two independent markets are usually the cheaper places to buy. Refresh with tools/build_steam.py + tools/build_skinport.py + tools/build_csfloat.py — see "Refreshing prices" below.
  • Cheapest-market headline — the line under the card title names the lowest-priced market for that exact variant and how far under Steam it sits (**Cheapest: CSFloat $6.00** · −40.0% vs Steam). Shown only when at least two markets priced it; a single price is not a comparison.
  • Honest deltas — a vs Steam figure computed against a dump refreshed weeks apart is prefixed ~, because it measures elapsed time as much as market spread. Each field also states its own age ("priced 3d ago").
  • Clickable embed title — links straight to the Steam Market listings page for the exact (skin, wear, quality) variant. One-click buy path.
  • In-place card editing — wear/quality/jump buttons update the existing card (Discord UPDATE_MESSAGE, SDK 0.7.0+) instead of posting a new message.
  • Your search stays on the card — the bottom row hops between the other matches from your query (and back to the one you came from). The whole result set rides in each button's custom_id, so it survives every click instead of disappearing after the first one.
  • One-click onboarding — a bare /skin shows a numbered quick-start with a "Try an example" button that renders a live result in one click.
  • Smart filters: category (rifle/SMG/pistol/sniper/knife/glove/agent), rarity tier (Consumer → Covert → Knife/Glove), wear (FN/MW/FT/WW/BS), StatTrak/Souvenir/Normal
  • Browse mode: /skin category: knife (no query) shows top items in that category, each reachable from the jump row
  • Admin dashboard (YourBot panel → plugin → Overview): lookup volume, bundled-data health (every source, with each dump's provenance and age), error-code table — no Discord commands needed
  • 2155-item catalog (2092 skins + 63 agents) bundled in the plugin, no external DB needed
  • Zero runtime HTTP — all three price dumps and the catalog ship in the zip; no allowlist setup needed
  • Sandbox-safe — fits in the platform's 64MB RAM envelope; no egress required

Why bundled-only

The v0.1.x design fetched prices live from Steam Market and DMarket. The v0.2.1 design added live SkinBaron alongside the bundled Steam dump. Both live-fetch directions failed in production for the same reason: MMO Maid's sandbox proxy egress IPs are TCP-reset by every Cloudflare-fronted skin marketplace during TLS handshake (Steam, DMarket, and SkinBaron all honour the same shared blocklist). The connection dies below the HTTP layer, so no in-plugin mitigation works.

v0.2.0 sidestepped Steam's block by baking ByMykel's CS2 price tracker data into the zip. v0.7.0 applies the same lesson to restore the comparative pricing the plugin was built around: Skinport is also Cloudflare-fronted (a live fetch would hit the same wall), but its /v1/items API is reachable from the build host, so a second bundled dump gives a genuine Steam-vs-Skinport comparison with zero runtime HTTP. See ARCHITECTURE.md and SDK-ASSUMPTIONS.md for the rationale and CHANGELOG.md v0.7.0 for how Skinport was chosen (CSGOTrader's old aggregate feed is dead; the choice was made by live-probing, not memory).

Quickstart

# Build the catalog from byMykel/CSGO-API (run when refreshing for new Valve content)
py tools/build_catalog.py

# Build the bundled price dumps (Steam crawled direct, Skinport from /v1/items)
py tools/build_steam.py      # long-running: a full crawl is ~2,200 pages, resumable
py -m pip install brotli   # one-time: Skinport's API only serves Brotli (build host only)
py tools/build_skinport.py
py tools/build_csfloat.py    # single unauthenticated GET, seconds

# Run the full test suite
py -m pytest tests/ -q

# Run all 9 audit gates
py tools/run_audit.py

# Produce the shippable plugin zip
py tools/build_bundle.py
# -> dist/skinscope.zip

# Run the platform's own upload validator against the artifact
py tools/validate_artifact.py

Refreshing prices

Both bundled dumps are point-in-time. Re-run the builds when prices feel stale:

py tools/build_steam.py      # Steam: direct Community Market crawl → data/prices.json.gz
py tools/build_skinport.py   # Skinport: fetches /v1/items (needs brotli) → data/skinport.json.gz
py tools/build_csfloat.py    # CSFloat: one GET of /v1/listings/price-list → data/csfloat.json.gz
py tools/build_bundle.py     # repackages dist/skinscope.zip
# upload dist/skinscope.zip on the YourBot dev portal (auto-deploy on push if wired up)

The Steam crawl walks ~2,200 pages under the politeness budget recorded in docs/SOURCES-LEGAL.md (≤100 req/5min, 3s inter-page), so a full rebuild takes hours. It checkpoints into .build-cache/ and resumes, so an interrupted run continues instead of restarting; --max-pages N runs a bounded smoke crawl that confirms the live response shape without writing the dump. Skinport and CSFloat are each a single API call. Every builder gates on catalog coverage and exits non-zero on a partial result. The three dumps are independent — refresh one without the others if you like, and a dump that fails to load at runtime degrades only its own field on the card.

Whatever is currently bundled stamps its own provenance into the dump, and /skin-config plus the dashboard's Data health widget report it at runtime — read it there rather than inferring it from this README.

Deploy

No HTTP Domains allowlist setup is required — v0.2.2 has zero runtime HTTP. Drop the bundle into the YourBot plugin manager (or push to GitHub if auto-deploy is wired up) and confirm the two Safe-tier capabilities (interaction:respond, storage:kv) when prompted. Run py tools/validate_artifact.py first — it's the same validator the upload pipeline runs.

Repository layout

manifest.json         YourBot plugin manifest
dashboard_manifest.json  admin dashboard (generated by tools/build_dashboard.py)
__main__.py           platform entry point — imports plugin.py, calls plugin.run()
plugin.py             slash handlers + component dispatcher (importable for tests)
requirements.txt      empty (no pip deps — stdlib only)
lib/
  catalog.py          load + search bundled compact catalog (inverted token index)
  pricing.py          Steam + Skinport lookup via bundled price dumps; SOURCE_META feature matrix
  links.py            Steam Market deep-link URL builders (clickable embed title)
  embed.py            Discord embed + button-row builders (two side-by-side source fields)
  state.py            wear/quality enums, custom_id encode/decode (versioned)
  scoring.py          pure-Python fuzzy search scorer
  config.py           per-server currency table (USD-only surface in v0.2)
  reasons.py          negative-cache reason-code constants + user-facing hints
  logctx.py           per-request correlation id (ContextVar)
  metricq.py          request-scoped deferred-metrics queue (3s-deadline guard)
data/
  catalog.json.gz             ~190 KB compact CS2 catalog (regenerated by tools/build_catalog.py)
  prices.json.gz              ~97 KB Steam Market prices (regenerated by tools/build_steam.py)
  skinport.json.gz            ~142 KB Skinport prices (regenerated by tools/build_skinport.py)
  csfloat.json.gz             ~122 KB CSFloat prices (regenerated by tools/build_csfloat.py)
tools/                        offline build + audit + bundle scripts (not shipped in zip)
tests/                        pytest suite (not shipped in zip)

Documentation

File Purpose
CLAUDE.md Handoff doc — what a contributor needs to know first
ARCHITECTURE.md The "why" doc — design decisions and rationale
reference.md SDK contract transcription (v0.5.x — superseded by the installed yourbot_sdk source on any conflict)
AUDIT-REPORT.md Hardening audits, all findings + status
RUNBOOK.md Operational scenarios + recovery procedures
CHANGELOG.md Versioned change log
SDK-ASSUMPTIONS.md Confirmed SDK-behavior assumptions discovered in production

Plugin spec at a glance

  • SDK: yourbot-sdk 0.10.0 installed (latest on PyPI; renamed from mmo_maid_sdk in 0.6.0; the installed source is authoritative over any doc)
  • Capabilities: interaction:respond, storage:kv (Safe tier, no install warning)
  • Python: 3.11+
  • External APIs at runtime: none. All three price dumps and the catalog ship in the zip.
  • Catalog source: byMykel/CSGO-API
  • Steam prices source: Steam Community Market search/render, crawled directly by tools/build_steam.py (posture: docs/SOURCES-LEGAL.md)
  • Skinport prices source: Skinport /v1/items API (build-time only; needs brotli)
  • CSFloat prices source: CSFloat /api/v1/listings/price-list (build-time only; unauthenticated — note that /api/v1/listings, which the vendor docs point at, requires a login: see docs/SOURCES-LEGAL.md)
  • Audit gates: 9 / 9 passing (py tools/run_audit.py)

Status

v0.11.4 is the current shipping release: three bundled price sources (Steam Market, Skinport, CSFloat) side by side, a jump row that carries your whole result set so it survives every click, in-place card editing, and one-click onboarding. 432 tests, 9/9 audit gates, and a clean pass from the platform's own artifact validator.

v0.1.x's hardening (114 audit findings across three rounds — concurrency races, adversarial Unicode, partial upstream outages, cache-stampede thundering herds, SDK contract drift) is preserved where applicable; the pieces that became dead code after the bundled-only pivot were removed cleanly. See CHANGELOG.md for the full per-release history.

Steam prices are first-party as of v0.11.3: the bundled dump is stamped steam-market-direct — a full crawl of the Community Market's search/render endpoint by tools/build_steam.py (14,511 priced catalog entries, walked 2026-09-11/12). The ByMykel aggregator is gone from the Steam price path. All three dumps now date from the same day, so vs Steam deltas render without the ~ approximate marker. /skin-config reports each dump's real provenance and age.

License

TBD.

Related plugins

Have a question?

Ask the developer of SkinScope directly. Sign in with Discord to send your question. You'll be notified when they reply.

Sign in to ask the developer →

Ready to install SkinScope?

Sign in with Discord, set up your server and add it in minutes.

Install on your server →
Screenshot preview