Skip to content

Plugin development

Pierre edited this page Oct 29, 2026 · 1 revision

Zukan discovers installed plugins through Python package entry points. Installing Python files alone is insufficient: the package metadata must register the object, and the server image/environment must include it.

Entry-point group Contract Purpose
zukan.games app.games.base.GameProvider Game catalog, variants, OCR and provider prices
zukan.prices app.prices.base.PriceSource Market identity, links and optional market fetch
zukan.sources app.sources.base Generic supplemental catalog sources

Add a game

A game object needs id, name, colors, finishes, languages, price_sources, and methods fetch_catalog, fetch_prices, image_file_stems and parse_ocr. Consult the actual Protocol in backend/app/games/base.py and a neighboring provider for executable patterns.

fetch_catalog(http) is an async iterator of CatalogBatch objects. Define sets before their printings. Normalize upstream data into SetData, CardData and PrintingData; the core catalog service stores it. Stable external IDs are essential to avoid losing associations with owned printings.

fetch_prices(http, owned) yields batches of PriceQuote. Providers with bulk feeds can return broader data; per-card APIs can use PriceTarget. Set source explicitly for nondefault markets and declare supported source IDs.

parse_ocr(lines) returns OcrHints such as name, set code, collector number, language and whether the text resembles that game's cards. It must tolerate partial/noisy OCR without treating every text line as a perfect match.

Register the provider:

[project.entry-points."zukan.games"]
mygame = "my_package.provider:provider"

The loaded object must satisfy the runtime-checkable Protocol. Duplicate IDs are rejected.

Optional game capabilities

  • filters, rarities, short_names, set aliases and regional group metadata provide client-visible choices.
  • catalog_version makes older stored catalogs due for refresh after normalization changes.
  • fetch_cards supports targeted stale-card refresh.
  • cache_all_images requests broader caching for small catalogs.
  • image_fallback selects a fallback language or disables fallback.
  • secondary_sources and source_keys connect cross-check/gap-filling integrations.
  • legal_notice supplies publisher-required notice text to clients.
  • rarity_in_printing signals variants distinguished by rarity, as in Yu-Gi-Oh!.

Client interfaces are mostly driven by metadata, but do not assume an arbitrary new data shape needs no client tests. Check filters, long names, symbols, language fallback and printing selection in both clients.

Partial data and moved printings

CardData.partial and PrintingData.partial let supplemental records fill missing fields while preserving existing primary information and merging supported lists. CatalogBatch.moved uses PrintingMove to move inventory references when external printing IDs change. Test collisions and existing collection variants explicitly.

CatalogIndex/StoredPrinting give secondary sources a normalized view of existing data. SecondaryBatch can carry partial cards, disagreements and checked-set boundaries. Core comparisons keep primary values unless arbitration says otherwise.

Add a market

A market object exposes id, name, ISO currency and link(game_id, market_id, lang). For data obtained through game providers, tag quotes and list that source in the provider. For a market with its own API, expose supported games and fetch(http, game_id, targets) yielding quotes.

Store market IDs under printing.attributes["market_ids"][source_id]. Register the source under zukan.prices. The core game_sources, shown_sources and preferred-source logic drive UI capability and fallback behavior.

MarketTarget.quoted identifies markets that already supplied today's quote; a gap-filling source can avoid overwriting them. CardNexus demonstrates a market source that also supplies missing quotes for other markets.

Credentials, budgets and caching

Read API keys through api_token, using TCG_APITOKEN_GAMES_... or TCG_APITOKEN_PRICES_...; document the exact key in .env.example. Use the core HTTP, budget and cache facilities rather than issuing unbounded requests. Preserve upstream rate limits and distinguish a source refusal from a nonexistent card.

Validation

Use small fixtures and mocked HTTP responses. Test localized names, unique printing IDs, same-number rarities, zero-padding, partial source output, missing images, prices by finish/source, upstream failures, and inventory survival across catalog changes. Update schema/client types when public contracts change.

Implementation references

Clone this wiki locally