PowerShell: Using REST API from MagicCardMarket

Problem

When i’m not doing anything productive I sometimes play Magic: The Gathering.
As a result I have many cards, and most of them I don’t even play. I try selling those cards on magiccardmarket.eu.
While this is a great site for selling, their user interface and especially their inventory listing is not really great.
BUT they have a REST API, and I decided I wanted to get my inventory using PowerShell.

Solution

I created a PowerShell module that gets my entire stock from MCM with all the attributes I consider usefull. Then it puts all the cars on a nice html file grouped by prices.
To make it all a bit more easy to read I also download the images from MCM and use those instead of text.
I used the documentation for the MCM API on their website.

Result

[CmdletBinding()]
Param(
    [Parameter(
        Mandatory = $false,
        Position = 1
    )]
    [Alias("User","Name")]
    [string] $UserName = (Read-Host "UserName: "),
    [Parameter(
        Mandatory = $false,
        Position = 2
    )]
    [Alias("API","Key")]
    [string] $APIKey = (Read-Host "API Key: "),
    [Parameter(
        Mandatory = $false,
        Position = 3
    )]
    [Alias("Directory")]
    [string] $StorageDir = $PWD
)
Begin {
    # Static variables
    $url = "https://www.mkmapi.eu/ws/$UserName/$APIKey"
    $webClient = New-Object System.Net.WebClient
    $imgURL = "http://www.magiccardmarket.eu"
}
Process {
    #region Fill Stock List
    $stockList = @()

    $stockQuery = (Invoke-RestMethod ($url + "/stock")).response.article
    $stockResult = $stockQuery
    while(($stockQuery).Count -ge 100){
        $stockQuery = (Invoke-RestMethod($url + "/stock/" + ($stockResult).Count)).response.article
        $stockResult += $stockQuery
    }

    $progressTotal = ($stockResult).Count
    $progressCurrent = 0
    foreach($article in ($stockResult)){
        #progress
        ++$progressCurrent
        write-progress -activity "Loading Stock" -status ("Progress (" + [int]($progressCurrent/$progressTotal*100) + "%):") -percentcomplete ($progressCurrent/$progressTotal*100)

        # Get article information
        $decPrice = [decimal]$article.price
        $intCount = [int]$article.count
        if($article.isPlayset -eq "true"){
            $isPlayset = $true
        } else {
            $isPlayset = $false
        }
        if($article.isFoil -eq "true"){
            $isFoil = $true
        } else {
            $isFoil = $false
        }
        $strArticleID = $article.idArticle
    
        # Get product information
        $productURL = $url + "/product/" + $article.idProduct
        $productResult = Invoke-RestMethod ($productURL)
        foreach ($product in ($productResult.response.product)){
            $strExpansion = $product.expansion
            $strRarity = $product.rarity
        
            # Get English name
            foreach ($name in ($product.name)){
                if($name.idLanguage -eq "1"){
                    $strName = $name.productName
                }
            }
        
            # Download Image + create img folder if needed
            if(-not (Test-Path "$StorageDir\img")){
                New-Item -ItemType directory -Path "$StorageDir\img" | Out-Null
            }
            $strImage = "$StorageDir\img\$strName.jpg"
            $productImage = ($imgURL + ($product.image).Substring(1))
            $webClient.DownloadFile($productImage,$strImage)
        }

        # Create custom object
        $object = New-Object –TypeName PSObject
        $object | Add-Member –MemberType NoteProperty –Name ID –Value $strArticleID
        $object | Add-Member –MemberType NoteProperty –Name Name –Value $strName
        $object | Add-Member –MemberType NoteProperty –Name Expansion –Value $strExpansion
        $object | Add-Member –MemberType NoteProperty –Name Rarity –Value $strRarity
        $object | Add-Member –MemberType NoteProperty –Name Image –Value $strImage
        $object | Add-Member –MemberType NoteProperty –Name IsFoil –Value $isFoil
        $object | Add-Member –MemberType NoteProperty –Name IsPlayset –Value $isPlayset
        # Set Price to price per unit for playsets
        if($isPlayset){
            $playsetPrice = ($decPrice/4)
            $object | Add-Member –MemberType NoteProperty –Name Price –Value $playsetPrice
        } else {
            $object | Add-Member –MemberType NoteProperty –Name Price –Value $decPrice
        }
        # Add each card as many times as they are in the inventory (just like a real folder)
        for($i=0; $i -lt $intCount; ++$i){
            $stockList += $object
        }
    
    }
    #endregion

    #region Format Stock List to HTML

    # List howmany collumns you want in your list
    $intColCount = 3

    $strHTML = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
    $strHTML += '<html xmlns="http://www.w3.org/1999/xhtml">'
    $strHTML += '<head>'
    $strHTML += '<title>HTML TABLE</title>'
    $strHTML += '</head>'
    $strHTML += '<body>'
    $strHTML += "<h1>Stock of $UserName on $(Get-Date -Format "yy/MM/dd HH:mm:ss")</h1>"
    $strHTML += '<table>'
    # Make a table for each price group
    foreach ($price in ($stockList | Sort-Object Price -Unique -Descending | Select-Object Price).price){
        $strHTML += '<th colspan="' + $intColCount + '">' + $price + '<th>'
        $strHTML += '<tr>'
        $intCurrentCol = 0
        # List each item in the price group order by isPlayset > isFoil > Name
        foreach ($item in $stockList | Where-Object {$_.Price -eq $price} | Sort-Object @{expression="IsPlayset";Descending=$true},@{expression="IsFoil";Descending=$true},@{expression="Name";Ascending=$true}){
            ++$intCurrentCol
            $strHTML += '<td><img src="' + $item.Image + '" alt="' + $item.Name + '"/>'
            # Add a * after the image if its a playset
            if ($item.IsPlayset){
                $strHTML += '*'
            }
            # Add an F after the image if its a foil
            if ($item.IsFoil){
                $strHTML += 'F'
            }
            $strHTML += '</td>'
            if($intCurrentCol -ge $intColCount){
                $strHTML += '</tr><tr>'
                $intCurrentCol = 0
            }
        }
        $strHTML += '</tr>'
    }
    $strHTML += '</table>'
    $strHTML += '</body>'
    $strHTML += '</html>'

    # Write to a .html document with username and timestamp in its name
    $strHTMLName = "$StorageDir\MCM-Stock-$UserName.html"
    $strHTML | Out-File $strHTMLName

    # Open the .html document
    Invoke-Expression $strHTMLName

    #endregion
}
End {}

I developed this cmdlet with PowerShell 4.0 it might work on 3.0 but I’m not sure.

The Parameters are not mandatory but the script will prompt them if you did not give a value for them.

Your UserName and API key can be found on your profile page on MCM
I also added in a neat little progress bar so you can track the progress because it can sometimes take a few minutes to get all the data and images loaded.

The script will save the html-file and its images in the directory specified. If no directory is specified it will place them in the current working directory.

You can download the cmdlet and a nice .bat file that runs it all for you from my OneDrive

Advertisements

Tags: , , , , , , , , , , , , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: