man thinking

Download the Build 2016 Content We Care About using PowerShell

As I am writing this we are about half way through the //build/ 2016 conference. Some sessions from earlier in the week have already appeared as recordings and there are also many pre-recorded sessions that were made available immediately following the relevant keynote presentations.

Of course it can be a bit tedious going through the Channel 9 listings and following links to download the recordings. It's even worse if most of the time you find that the session content hasn't been uploaded yet.

So here is a PowerShell script that allows you to specify a list of filters and categories (i.e. the tags) in order to select the content that is most important to you and download the recordings. I already set the filters up for you with the important stuff, but you can adjust to your requirements. If you are a Yammer enthusiast then feel free to add it to the list of filter strings (sorry, I didn't add a negative filter, in case you were wondering).

The filename is canonicalized so that it won't download the same session twice (I hope). So you can keep running the script at intervals and it will pick up any new recordings as they become available. It will also pick up the first mp4 in the RSS feed, which is usually the lowest quality one which is usually good enough. You can always go back and get the higher resolution version if needed, or modify the script to look for the "*high.mp4" in the filename if you are lucky enough to have a vast amount of bandwidth (and disk storage).

​# Channel 9 download script
$feedUrl = 'http://s.ch9.ms/Events/Build/2016/RSS'
$filters = @("*Microsoft Graph*", "*Azure AD*", "*SharePoint*", "*Office 365*")
$categories = @("office", "office-365")
  
[Environment]::CurrentDirectory=(Get-Location -PSProvider FileSystem).ProviderPath
function Get-Media([Object]$url, [Object]$title)
{       
    $u = New-Object System.Uri($url)
    $extension = [System.IO.Path]::GetExtension($u.Segments[-1])
    $fileName = $title + $extension
    # clean up filename  
    $fileName = $fileName -replace "’", ''
    $fileName = $fileName -replace "™", ''
    $fileName = $fileName -replace '–', '-'
    $fileName = $fileName -replace '“', ''
    $fileName = $fileName -replace "â€", '-'
    $fileName = $fileName -replace "\?", ''
    $fileName = $fileName -replace ":", ''
    $fileName = $fileName -replace '/', ''
    $fileName = $fileName -replace ",", ''
    $fileName = $fileName -replace '"', ''
   
              
    if (Test-Path($fileName)) {
        Write-Host $fileName ' (already downloaded)' -ForegroundColor Green
    }
    else {
        Write-Host $fileName '<--' $url
        Invoke-WebRequest $url -OutFile $fileName
    }
}
    
$feed=[xml](New-Object System.Net.WebClient).DownloadString($feedUrl)

Write-Host
Write-Host "Searching by filters: " $filters
Write-Host
foreach($f in $feed.rss.channel.item) {
    foreach($m in $f.group) {
        $stillsearching = $true
        for ($i=0; $i -lt $filters.length -and $stillsearching; $i++) {
            $filter = $filters[$i]
            if($f.title -like $filter) {
                foreach($u in $m.content | Where-Object {
                    $_.type -eq 'video/mp4' -and $_.fileSize -gt 1000 } ) {
                    Get-Media -url $u.url -title $f.title
                    $stillsearching = $false
                    break
                }
            }
        }
    }
}

Write-Host
Write-Host "Searching by categories: " $categories
Write-Host
foreach($f in $feed.rss.channel.item) {
    foreach($m in $f.group) {
        $stillsearching = $true
        for ($i=0; $i -lt $categories.length -and $stillsearching; $i++) {
            $category = $categories[$i]
            if($f.category -contains $category) {
                foreach($u in $m.content | Where-Object { 
                    $_.type -eq 'video/mp4' -and $_.fileSize -gt 1000 } ) {
                    Get-Media -url $u.url -title $f.title
                    $stillsearching = $false
                    break
                }
            }
        }
    }
}