top of page
Search
  • benhaguenz

Downloading PGN files from LiveChess Cloud

Quite a few places are using LiveChess Cloud from DGT to broadcast chess games over the internet, e.g. http://view.livechesscloud.com/ba9ad40e-88e7-491b-b48f-4efd5a761ed2 or https://view.livechesscloud.com/c2613337-5068-4fe3-903e-e63307a7beaa. This works pretty well for viewing games, but it does have one limitation which is that there's no way to download the games. This happened to irritate me one New Zealand championship so I decided to come up with a way to download them. Monitoring it via the network section of the developer tools revealed that it was just calling a series of JSON files, first to get the server, then the tournament, then the player names for the round, and finally the moves for each game. Based on that it was fairly easy to come up with a PowerShell script to do the same thing. Using it just needs the URL and an output file name, so .\DGTtoPGN.ps1 -url <url> -outputFile <output>. E.g. .\DGTtoPGN.ps1 -url "http://view.livechesscloud.com/099d4668-eb48-447d-ab0a-8ea795e660b0" -outputFile "c:\temp\test3.pgn". So far it's worked for me reliably, but no guarantees.



DGTtoPGN
.zip
Download ZIP • 1KB

param ($url, $outputFile)

# Names aren't always input in the correct field so this function attempts to correct for the more common mistakes.
function GenerateName {
 param ($firstName, $middleName, $lastName)
 $name = ""
 if ($null -eq $firstName) {
 $name = "$lastname, $middlename"
 } else {
 if ($null -eq $middleName) {
 $name = "$lastname, $firstname"
 } else {
 if ($null -eq $lastName) {
 $name = "$middlename, $firstname"
 } else {
 $name = "$lastname, $firstname $middlename"
 }
 } 
 }

 return $name
}

# A regexp to get everything from the last forward slash to the end of the string.
$reg = '.*/(.*?)$'
$guid = ""
if ($url -match $reg) {
 $guid = $matches[1]
}
else {
 return 1
}

$baselookup = "https://lookup.livechesscloud.com/meta/$guid"

# First request to get the server name
$server = Invoke-WebRequest -Uri "$baselookup"

$hostname = ($server.Content |ConvertFrom-Json).host

# Second request to get the tournament details
$tournamentJson = Invoke-WebRequest -Uri "https://$hostname/get/$guid/tournament.json"

$tournament = $tournamentJson.Content |ConvertFrom-Json

$eventName = "[Event `"$($tournament.name)`"]"
$site = "[Site `"$($tournament.location)`"]"
$country = ""
if ($tournament.country) {
 $country = "[Country `"$($tournament.country)`"]"
}
$timeControl = ""
if ($tournament.timecontrol) {
 $timeControl = "[TimeControl `"$($tournament.timecontrol)`"]"
}

$numberOfRounds = $tournament.rounds.Count

for ($i=1;$i -le $numberOfRounds;$i++) {
 # Third request to get the player details
 $headerjson = Invoke-WebRequest -Uri "https://$hostname/get/$guid/round-$i/index.json"
 $header = $headerjson.content |ConvertFrom-Json
 
 $round = "[Round `"$i`"]"
 $date = "[Date `"$($header.date)`"]"
 
 $numberOfGames = $tournament.rounds[$i-1].count

 for ($j=1;$j -le $numberOfGames; $j++) {
 $whiteFirstname = $header.pairings.white[$j-1].fname
 $whiteMiddlename = $header.pairings.white[$j-1].mname
 $whiteLastname = $header.pairings.white[$j-1].lname
 
 $blackFirstname = $header.pairings.black[$j-1].fname
 $blackMiddlename = $header.pairings.black[$j-1].mname
 $blackLastname = $header.pairings.black[$j-1].lname
 
 $whiteName = GenerateName $whiteFirstname $whiteMiddlename $whiteLastname
 $blackName = GenerateName $blackFirstname $blackMiddlename $blackLastname

 $white = "[White `"$whitename`"]"
 $black = "[Black `"$blackname`"]"
 $result = "[Result `"$($header.pairings.result[$j-1])`"]"

 # Fourth request gets the actual moves
 $gamejson = Invoke-WebRequest -Uri "https://$hostname/get/$guid/round-$i/game-$($j).json?poll"
 $game = $gamejson.content |ConvertFrom-Json
 
 Add-Content -Path $outputFile $eventName
 Add-Content -Path $outputFile $site
 if ($country) { Add-Content -Path $outputFile $country }
 if ($timeControl) { Add-Content -Path $outputFile $timeControl }
 Add-Content -Path $outputFile $round
 Add-Content -Path $outputFile $date
 Add-Content -Path $outputFile $white
 Add-Content -Path $outputFile $black
 Add-Content -Path $outputFile $result

 <#  The moves are stored as simply white move, black move, white move etc until the end of the game
            There is a time recorded for each move, but I wasn't interested in that so it's stripped out
        #>
 $whiteMove = $true
 $moveNumber = 1
 $pgn = ""
 foreach ($move in $game.moves) {
 $m = $move.split(' ')[0]
 if ($whiteMove) {
 $pgn += "$moveNumber. $m "
 $moveNumber++
 $whiteMove = $false
 } else {
 $pgn += " $m "
 $whiteMove = $true
 } 
 }
 $pgn += $header.pairings.result[$j-1]
 Add-Content -Path $outputFile $pgn
 Add-Content -Path $outputFile "`r`n"
 }
}


2 views0 comments

Recent Posts

See All

A daily random XKCD in Teams

This builds on the previous post to get a random post rather than just the latest. That post can be found here: https://benhaguenz.wixsite.com/my-site/post/automatically-posting-xkcd-in-teams The firs

bottom of page