mtgban

package
v0.4.57 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 23, 2024 License: MIT Imports: 14 Imported by: 3

Documentation

Overview

Package mtgban defines interfaces for scrapers and utility functions to obtain pricing information from various vendors.

Index

Constants

View Source
const (
	GameMagic   = ""
	GameLorcana = "Lorcana"
)

Variables

View Source
var (
	// The base Card fields for the canonical headers
	CardHeader = []string{
		"Key", "Name", "Edition", "Finish", "Number", "Rarity",
	}

	// The canonical header that will be present in all inventory files
	InventoryHeader = append(CardHeader, "Conditions", "Price", "Quantity", "URL")

	// The canonical header that will be present in all market files
	MarketHeader = append(InventoryHeader, "Seller", "Bundle")

	// Additional fields for Markets neecessary for Carters
	CartHeader = append(MarketHeader, "Original Id", "Instance Id")

	// The canonical header that will be present in all buylist files
	BuylistHeader = append(CardHeader, "Conditions", "Buy Price", "Trade Price", "Quantity", "Price Ratio", "URL", "Vendor")

	ArbitHeader = append(CardHeader, "Conditions", "Available", "Sell Price", "Buy Price", "Difference", "Spread", "Abs Difference", "Profitability")

	MismatchHeader = append(CardHeader, "Conditions", "Price", "Reference", "Difference", "Spread")
)
View Source
var DefaultGradeTags = []string{
	"NM", "SP", "MP", "HP",
}

The default list of conditions most scrapers output

View Source
var ErrScraperNotFound = errors.New("scraper not found")
View Source
var FullGradeTags = []string{
	"NM", "SP", "MP", "HP", "PO",
}

The full list of conditions supported

Functions

func DateEqual

func DateEqual(date1, date2 time.Time) bool

func GetExchangeRate

func GetExchangeRate(currency string) (float64, error)

func WriteArbitrageToCSV

func WriteArbitrageToCSV(arbitrage []ArbitEntry, w io.Writer) error

func WriteCombineToCSV

func WriteCombineToCSV(root *CombineRoot, w io.Writer) error

func WriteMismatchToCSV

func WriteMismatchToCSV(mismatch []ArbitEntry, w io.Writer) error

func WritePennyToCSV

func WritePennyToCSV(penny []PennystockEntry, w io.Writer) error

func WriteScraperToJSON

func WriteScraperToJSON(scraper Scraper, w io.Writer) error

func WriteSellerToCSV

func WriteSellerToCSV(seller Seller, w io.Writer) error

func WriteSellerToJSON

func WriteSellerToJSON(seller Seller, w io.Writer) error

func WriteVendorToCSV

func WriteVendorToCSV(vendor Vendor, w io.Writer) error

func WriteVendorToJSON

func WriteVendorToJSON(vendor Vendor, w io.Writer) error

Types

type ArbitEntry

type ArbitEntry struct {
	// ID of the card
	CardId string

	// The buylist used to determine Arbit
	BuylistEntry BuylistEntry

	// The actual entry that matches either of the above
	InventoryEntry InventoryEntry

	// The inventory used to determine Mismatch
	ReferenceEntry InventoryEntry

	// Difference of the prices
	Difference float64

	// Spread between the the prices
	Spread float64

	// Difference of the prices accounting for quantities available
	AbsoluteDifference float64

	// Amount of cards that can be applied
	Quantity int

	// The higher the number the better the arbit is. Using this formula
	// Profitability Index (PI) = (Difference / (Sell Price + 10)) * log(1 + Spread) * sqrt(Units)
	Profitability float64
}

func Arbit

func Arbit(opts *ArbitOpts, vendor Vendor, seller Seller) (result []ArbitEntry, err error)

func Mismatch

func Mismatch(opts *ArbitOpts, reference Seller, probe Seller) (result []ArbitEntry, err error)

func (ArbitEntry) String added in v0.4.52

func (ae ArbitEntry) String() string

ArbitEntry implements the Stringer interface

type ArbitOpts

type ArbitOpts struct {
	// Extra factor to modify Inventory prices
	Rate float64

	// Minimum Inventory price
	MinPrice float64

	// Minimum Buylist price
	MinBuyPrice float64

	// Minimum difference between prices
	MinDiff float64

	// Minimum Inventory quantities
	MinQuantity int

	// Minimum spread % between prices
	MinSpread float64

	// Maximum Spread % between prices
	MaxSpread float64

	// Maximum price ratio of Inventory
	MaxPriceRatio float64

	// Use credit for Buylist prices
	UseTrades bool

	// Whether to consider foils
	NoFoil   bool
	OnlyFoil bool

	// Whether to skip non-rl cards
	OnlyReserveList bool

	// List of conditions to ignore
	Conditions []string

	// List of rarities to ignore
	Rarities []string

	// List of editions (or set codes) to ignore
	Editions []string

	// List of editions (or set codes) to select
	OnlyEditions []string

	// List of per-edition collector numbers to select
	OnlyCollectorNumberRanges map[string][2]int

	// Only run for products with static decklists
	SealedDecklist bool

	// Only select entries which are part of a bundle
	OnlyBundles bool

	// List of seller name that wil be considered
	Sellers []string

	// Custom function to be run on the card object
	// It returns a custom factor to be applied on the compared price,
	// and whether the entry should be skipped or not
	CustomCardFilter func(co *mtgmatcher.CardObject) (float64, bool)

	// Custom function to be run on the probed inventory entry
	// It returns a custom factor to be applied on the compared price,
	// and whether the entry should be skipped or not
	CustomPriceFilter func(string, InventoryEntry) (float64, bool)

	// Constant used to offset prices (the higher the value, the less impactful
	// lower prices will be, and viceversa)
	ProfitabilityConstant float64

	// Minimum profitability value
	MinProfitability float64
}

type BanClient

type BanClient struct {
	// contains filtered or unexported fields
}

BanClient abstracts some common operations that can be performed on any Scraper type types, as well as offering a way to retrieve a single or multiple Scapers.

func NewClient

func NewClient() *BanClient

Return an empty BanClient

func (*BanClient) Load

func (bc *BanClient) Load() error

Load inventory and buylist content for each scraper registered in the client

func (*BanClient) Register

func (bc *BanClient) Register(scraper Scraper)

Add a Scraper to the client

func (*BanClient) RegisterMarket added in v0.4.21

func (bc *BanClient) RegisterMarket(scraper Market, name string)

Add a Scraper to the client, enable the Market with the given name

func (*BanClient) RegisterSeller

func (bc *BanClient) RegisterSeller(scraper Scraper)

Add a Scraper to the client, enable the seller side only (if any) If the added scraper is a market, it will be split into its subsellers

func (*BanClient) RegisterTrader added in v0.4.32

func (bc *BanClient) RegisterTrader(scraper Trader, name string)

Add a Scraper to the client, enable the Trader with the given name

func (*BanClient) RegisterVendor

func (bc *BanClient) RegisterVendor(scraper Scraper)

Add a Scraper to the client, enable the vendor side only (if any) If the added scraper is a trader, it will be split into its subvendors

func (*BanClient) ScraperByName

func (bc *BanClient) ScraperByName(shorthand string) (Scraper, error)

Return the scraper with a matching name from the ones registered in the client

func (*BanClient) Scrapers

func (bc *BanClient) Scrapers() (scrapers []Scraper)

Return a new slice containing all the scrapers registered in the client

func (*BanClient) Sellers

func (bc *BanClient) Sellers() (sellers []Seller)

Return a new slice containing all the sellers registered in the client

func (*BanClient) Vendors

func (bc *BanClient) Vendors() (vendors []Vendor)

Return a new slice containing all the vendors registered in the client

type BaseMarket added in v0.4.21

type BaseMarket struct {
	// contains filtered or unexported fields
}

Base structure for the conversion of a Market to a standard Seller This will hold the original Market scraper and retrieve the loaded subseller from its ScraperInfo

func (*BaseMarket) Info added in v0.4.21

func (m *BaseMarket) Info() ScraperInfo

func (*BaseMarket) Inventory added in v0.4.21

func (m *BaseMarket) Inventory() (InventoryRecord, error)

type BaseScraper added in v0.4.22

type BaseScraper struct {
	// contains filtered or unexported fields
}

func (*BaseScraper) Buylist added in v0.4.22

func (scraper *BaseScraper) Buylist() (BuylistRecord, error)

func (*BaseScraper) Info added in v0.4.22

func (scraper *BaseScraper) Info() (info ScraperInfo)

func (*BaseScraper) Inventory added in v0.4.22

func (scraper *BaseScraper) Inventory() (InventoryRecord, error)

type BaseSeller

type BaseSeller struct {
	// contains filtered or unexported fields
}

func (*BaseSeller) Info

func (seller *BaseSeller) Info() ScraperInfo

func (*BaseSeller) Inventory

func (seller *BaseSeller) Inventory() (InventoryRecord, error)

type BaseTrader added in v0.4.32

type BaseTrader struct {
	// contains filtered or unexported fields
}

Base structure for the conversion of a Trader to a standard Vendor This will hold the original Trader scraper and retrieve the loaded subvendor from its ScraperInfo

func (*BaseTrader) Buylist added in v0.4.32

func (m *BaseTrader) Buylist() (BuylistRecord, error)

func (*BaseTrader) Info added in v0.4.32

func (m *BaseTrader) Info() ScraperInfo

type BaseVendor

type BaseVendor struct {
	// contains filtered or unexported fields
}

func (*BaseVendor) Buylist

func (vendor *BaseVendor) Buylist() (BuylistRecord, error)

func (*BaseVendor) Info

func (vendor *BaseVendor) Info() (info ScraperInfo)

type BuylistEntry

type BuylistEntry struct {
	// Quantity of this entry
	Quantity int `json:"quantity"`

	// The grade of the current entry
	// Only supported values are listed in FullGradeTags
	// If empty it is considered "NM".
	Conditions string `json:"conditions"`

	// The price at which this entry is bought, in USD
	BuyPrice float64 `json:"buy_price"`

	// The ratio between the sale and buy prices, indicating desiderability
	// of the entry by the provider
	PriceRatio float64 `json:"price_ratio,omitempty"`

	// The link for this entry on the scraper website (if available)
	URL string `json:"url"`

	// Name of the vendor providing the entry
	VendorName string `json:"vendor_name,omitempty"`

	// Original identifier as available from the scraper
	OriginalId string `json:"original_id,omitempty"`

	// Original instance identifier as available from the scraper
	// This is usually the "SKU", or the id of the entry taking into
	// account different properties, such as conditions, language etc
	InstanceId string `json:"instance_id,omitempty"`

	// Any additional custom fields set by the scraper
	CustomFields map[string]string `json:"custom_fields,omitempty"`
}

BuylistEntry represents an entry for buying a particular Card

func (BuylistEntry) Condition

func (be BuylistEntry) Condition() string

func (BuylistEntry) Pricing

func (be BuylistEntry) Pricing() float64

func (BuylistEntry) Qty added in v0.4.57

func (be BuylistEntry) Qty() int

type BuylistRecord

type BuylistRecord map[string][]BuylistEntry

The base map for Vendor containing a uuid pointing to an array of BuylistEntry

func BuylistForVendor added in v0.4.32

func BuylistForVendor(vendor Trader, vendorName string) (BuylistRecord, error)

Return the buylsit for any given vendor present in the Trader. If possible, it will use the Buylist() call to populate data.

func LoadBuylistFromCSV

func LoadBuylistFromCSV(r io.Reader, flags ...bool) (BuylistRecord, error)

func (BuylistRecord) Add

func (bl BuylistRecord) Add(cardId string, entry *BuylistEntry) error

func (BuylistRecord) AddRelaxed

func (bl BuylistRecord) AddRelaxed(cardId string, entry *BuylistEntry) error

type Carter

type Carter interface {
	// Enable the cart interface (loading the existing cart for example).
	Activate(user, pass string) error

	// Add an InventoryEntry to the online cart.
	Add(entry InventoryEntry) error
}

Carter is the inteface used to identify Seller scrapers that can add entries to the online cart of the provider.

type CombineEntry

type CombineEntry struct {
	ScraperName string
	Price       float64
	Ratio       float64
	Quantity    int
	URL         string
}

type CombineRoot

type CombineRoot struct {
	Names   []string
	Entries map[string]map[string]CombineEntry
}

func CombineBuylists

func CombineBuylists(vendors []Vendor, useCredit bool) (*CombineRoot, error)

func CombineInventories

func CombineInventories(sellers []Seller) (*CombineRoot, error)

type GenericEntry

type GenericEntry interface {
	Pricing() float64
	Condition() string
	Qty() int
}

Interface describing common operations on entries

type InventoryEntry

type InventoryEntry struct {
	// Quantity of this entry
	Quantity int `json:"quantity"`

	// The grade of the current entry
	// Only supported values are listed in FullGradeTags
	Conditions string `json:"conditions"`

	// The price of this entry, in USD
	Price float64 `json:"price"`

	// The link for this entry on the scraper website (if available)
	URL string `json:"url"`

	// Only used for a Marketplace inventory
	SellerName string `json:"seller_name,omitempty"`

	// Part of a hub of sellers that can ship directly
	Bundle bool `json:"bundle,omitempty"`

	// Original identifier as available from the scraper
	// This is usually the "product id".
	OriginalId string `json:"original_id,omitempty"`

	// Original instance identifier as available from the scraper
	// This is usually the "SKU", or the id of the entry taking into
	// account different properties, such as conditions, language etc
	InstanceId string `json:"instance_id,omitempty"`

	// Any additional custom fields set by the scraper
	CustomFields map[string]string `json:"custom_fields,omitempty"`
}

InventoryEntry represents an entry for selling a particular Card

func (InventoryEntry) Condition

func (ie InventoryEntry) Condition() string

func (InventoryEntry) Pricing

func (ie InventoryEntry) Pricing() float64

func (InventoryEntry) Qty added in v0.4.57

func (ie InventoryEntry) Qty() int

type InventoryRecord

type InventoryRecord map[string][]InventoryEntry

The base map for Seller containing a uuid pointing to an array of InventoryEntry

func InventoryForSeller added in v0.4.22

func InventoryForSeller(seller Market, sellerName string) (InventoryRecord, error)

Return the inventory for any given seller present in the market. If possible, it will use the Inventory() call to populate data.

func LoadInventoryFromCSV

func LoadInventoryFromCSV(r io.Reader, flags ...bool) (InventoryRecord, error)

func (InventoryRecord) Add

func (inv InventoryRecord) Add(cardId string, entry *InventoryEntry) error

Add a new record to the inventory, similar existing entries are merged

func (InventoryRecord) AddRelaxed

func (inv InventoryRecord) AddRelaxed(cardId string, entry *InventoryEntry) error

Add a new record to the inventory, existing entries are always merged

func (InventoryRecord) AddStrict

func (inv InventoryRecord) AddStrict(cardId string, entry *InventoryEntry) error

Add new record to the inventory, similar existing entries are not merged

func (InventoryRecord) AddUnique added in v0.4.14

func (inv InventoryRecord) AddUnique(cardId string, entry *InventoryEntry) error

Add new record to the inventory, if same card and condition exist, error out

type LogCallbackFunc

type LogCallbackFunc func(format string, a ...interface{})

type Market

type Market interface {
	// Return all names for the sellers present in the Market
	MarketNames() []string

	// Market implements the Seller interface
	Seller

	// Market implements the MultiScraper interface
	MultiScraper
}

Market is the interface describing actions to be performed on the inventory available on a platform, usually combining different sellers

type MultiScraper added in v0.4.48

type MultiScraper interface {
	// Retrieve the ScraperInfo for an internal scraper with the given name
	InfoForScraper(name string) ScraperInfo

	// MultiScraper implements the Scraper interface
	Scraper
}

MultiScraper is the interface both Market and Trader need to implement

type PennystockEntry

type PennystockEntry struct {
	CardId string
	InventoryEntry
}

func Pennystock

func Pennystock(seller Seller, full bool, thresholds ...float64) (result []PennystockEntry, err error)

type Scraper

type Scraper interface {
	// Retrieve the ScraperInfo associated with the scraper
	Info() ScraperInfo
}

Scraper is the interface both Sellers and Vendors need to implement

func NewScraperFromData added in v0.4.22

func NewScraperFromData(inventory InventoryRecord, buylist BuylistRecord, info ScraperInfo) Scraper

type ScraperInfo

type ScraperInfo struct {
	// Full name of the store
	Name string `json:"name"`

	// Shorthand or ID of the store
	Shorthand string `json:"shorthand"`

	// Symbol for worldwide stores
	CountryFlag string `json:"country,omitempty"`

	// Timestamp of the last Inventory() execution
	InventoryTimestamp *time.Time `json:"inventory_ts,omitempty"`

	// Timestamp of the last Buylist() execution
	BuylistTimestamp *time.Time `json:"buylist_ts,omitempty"`

	// Only index-style data is available, no quantities or conditions
	MetadataOnly bool `json:"metadata,omitempty"`

	// Percentage multiplier for the store credit
	CreditMultiplier float64 `json:"credit_multiplier,omitempty"`

	// Inventory quantities are not available
	NoQuantityInventory bool `json:"no_qty_inventory,omitempty"`

	// Scraper contains sealed information instead of singles
	SealedMode bool `json:"sealed,omitempty"`

	// Whether the prices can be coalesced in a single entity
	Family string `json:"family,omitempty"`

	// Which game the scraper belongs to
	Game string `json:"game,omitempty"`
}

ScraperInfo contains

type Seller

type Seller interface {
	// Return the inventory for a Seller. If not already loaded, it will start
	// scraping the seller gathering the necessary data.
	Inventory() (InventoryRecord, error)

	// Return some information about the seller
	Info() ScraperInfo
}

Seller is the interface describing actions to be performed on a seller inventory

func NewSellerFromInventory

func NewSellerFromInventory(inventory InventoryRecord, info ScraperInfo) Seller

func ReadSellerFromJSON

func ReadSellerFromJSON(r io.Reader) (Seller, error)

type Trader added in v0.4.32

type Trader interface {
	// Return all names for the sellers present in the Trader
	TraderNames() []string

	// Trader implements the Vendor interface
	Vendor

	// Trader implements the MultiScraper interface
	MultiScraper
}

Trader is the interface describing actions to be performed on the buylist available on a platform, usually combining different vendors

type Vendor

type Vendor interface {
	// Return the buylist for a Vendor. If not already loaded, it will start
	// scraping the vendor gathering the necessary data.
	Buylist() (BuylistRecord, error)

	// Return some information about the vendor
	Info() ScraperInfo
}

Vendor is the interface describing actions to be performed on a vendor buylist

func NewVendorFromBuylist

func NewVendorFromBuylist(buylist BuylistRecord, info ScraperInfo) Vendor

func ReadVendorFromJSON

func ReadVendorFromJSON(r io.Reader) (Vendor, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL