GBWunderlist.psm1
Set-StrictMode -Version 5 $LIST_URL = "a.wunderlist.com/api/v1/lists" $TASK_URL = "a.wunderlist.com/api/v1/tasks" $SUBTASK_URL = "a.wunderlist.com/api/v1/subtasks" $NOTE_URL = "a.wunderlist.com/api/v1/notes" $FILE_URL = "a.wunderlist.com/api/v1/files" $script:permissionHeaders = $null function Set-WunderlistPermissionHeaders { param( [Parameter(Mandatory = $true, ValueFromPipeline = $false, ParameterSetName = "Table")] [hashtable] $PermissionHeaders, [Parameter(Mandatory = $true, ValueFromPipeline = $false, ParameterSetName = "Field")] [string] $ClientId, [Parameter(Mandatory = $true, ValueFromPipeline = $false, ParameterSetName = "Field")] [string] $AccessToken ) switch ($PsCmdlet.ParameterSetName) { "Table" { EnsureKey -Object $PermissionHeaders -Key "ClientId" EnsureKey -Object $PermissionHeaders -Key "AccessToken" $script:permissionHeaders = @{ "X-Client-Id" = $PermissionHeaders["ClientId"] "X-Access-Token" = $PermissionHeaders["AccessToken"] } } "Field" { $script:permissionHeaders = @{ "X-Client-Id" = $ClientId "X-Access-Token" = $AccessToken } }} Write-Output "Permission headers successfully set" } function Get-WunderlistList { param( [Parameter(Mandatory = $false, ValueFromPipeline = $false)] [string] $Id ) EnsurePermissionHeadersNotNull $listUrl = $LIST_URL if ($Id) { $listUrl = "$listUrl/$Id" } $lists = TryInvokeWebRequest -Uri $listUrl -Headers $script:PermissionHeaders # Add additional properties to the return value for easy piping to get tasks $lists | ForEach-Object { Add-Member -InputObject $_ -NotePropertyName "ListId" -NotePropertyValue $_.id -PassThru } } function Get-WunderlistTask { param( [Parameter(Mandatory = $true, ValueFromPipeline = $false, ParameterSetName = "Task")] [String] $Id, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "List")] [String] $ListId, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = "List")] [switch] $IncludeCompleted ) begin { EnsurePermissionHeadersNotNull $taskUrl = $TASK_URL } process { switch ($PsCmdlet.ParameterSetName) { "Task" { $taskUrl = "$taskUrl/$Id" # Weird. Have to take a copy, else it acts as immutable for Add-Member $temp = TryInvokeWebRequest -Uri $taskUrl -Headers $script:PermissionHeaders # Add additional properties to the return value for easy piping to get subtasks $temp | ForEach-Object { Add-Member -InputObject $_ -NotePropertyName "TaskId" -NotePropertyValue $_.id -PassThru } } "List" { # Weird. Have to take a copy, else it acts as immutable for Add-Member $temp = TryInvokeWebRequest -Uri $taskUrl -Headers $script:PermissionHeaders -Body @{ "list_id" = $ListId } # Add additional properties to the return value for easy piping to get subtasks $temp | ForEach-Object { Add-Member -InputObject $_ -NotePropertyName "TaskId" -NotePropertyValue $_.id -PassThru } # Wunderlist API returns only completed tasks when "complete"=true is set, but this behavior does not seem useful. # IncludeCompleted switch will return everything including completed tasks if ($IncludeCompleted) { # Weird. Have to take a copy, else it acts as immutable for Add-Member $temp = TryInvokeWebRequest -Uri $taskUrl -Headers $script:PermissionHeaders -Body @{ "list_id" = $ListId; "completed" = $true } # Add additional properties to the return value for easy piping to get subtasks $temp | ForEach-Object { Add-Member -InputObject $_ -NotePropertyName "TaskId" -NotePropertyValue $_.id -PassThru } } } } } } function Get-WunderlistSubTask { param( [Parameter(Mandatory = $true, ValueFromPipeline = $false, ParameterSetName = "SubTask")] [String] $Id, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Task")] [String] $TaskId, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "List")] [String] $ListId, [Parameter(Mandatory = $false, ValueFromPipeline = $false, ParameterSetName = "List")] [Parameter(ParameterSetName = "Task")] [switch] $IncludeCompleted ) begin { EnsurePermissionHeadersNotNull $subTaskUrl = $SUBTASK_URL } process { switch ($PsCmdlet.ParameterSetName) { "SubTask" { $subTaskUrl = "$subTaskUrl/$Id" TryInvokeWebRequest -Uri $subTaskUrl -Headers $script:PermissionHeaders } "Task" { # Another bad\contradicting API design. Querying by task_id will return all subtasks including the completed ones!! $subTasks = TryInvokeWebRequest -Uri $subTaskUrl -Headers $script:PermissionHeaders -Body @{ "task_id" = $TaskId } if ($IncludeCompleted) { $subTasks } else { $subTasks | Where-Object { $_.completed -eq $false } } } "List" { # Another bad\contradicting API design. Querying by list_id will return all subtasks including the completed ones!! $subTasks = TryInvokeWebRequest -Uri $subTaskUrl -Headers $script:PermissionHeaders -Body @{ "list_id" = $ListId } if ($IncludeCompleted) { $subTasks } else { $subTasks | Where-Object { $_.completed -eq $false } } } } } } function Get-WunderlistNote { param( [Parameter(Mandatory = $true, ValueFromPipeline = $false, ParameterSetName = "Note")] [String] $Id, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Task")] [String] $TaskId, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "List")] [String] $ListId ) begin { EnsurePermissionHeadersNotNull $noteUrl = $NOTE_URL } process { switch ($PsCmdlet.ParameterSetName) { "Note" { $noteUrl = "$noteUrl/$Id" TryInvokeWebRequest -Uri $noteUrl -Headers $script:PermissionHeaders } "Task" { TryInvokeWebRequest -Uri $noteUrl -Headers $script:PermissionHeaders -Body @{ "task_id" = $TaskId } } "List" { TryInvokeWebRequest -Uri $noteUrl -Headers $script:PermissionHeaders -Body @{ "list_id" = $ListId } } } } } function Get-WunderlistFile { param( [Parameter(Mandatory = $true, ValueFromPipeline = $false, ParameterSetName = "File")] [String] $Id, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "Task")] [String] $TaskId, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "List")] [String] $ListId ) begin { EnsurePermissionHeadersNotNull $fileUrl = $FILE_URL } process { switch ($PsCmdlet.ParameterSetName) { "File" { $fileUrl = "$fileUrl/$Id" TryInvokeWebRequest -Uri $fileUrl -Headers $script:PermissionHeaders } "Task" { TryInvokeWebRequest -Uri $fileUrl -Headers $script:PermissionHeaders -Body @{ "task_id" = $TaskId } } "List" { TryInvokeWebRequest -Uri $fileUrl -Headers $script:PermissionHeaders -Body @{ "list_id" = $ListId } } } } } function EnsureKey { param( [hashtable] $Object, [string] $Key ) $res = $Object.ContainsKey($Key) ` -and -not ([string]::IsNullOrWhiteSpace($Object[$Key])) ` -and $Object[$Key].Length -gt 0 if (-not $res) { throw "'" + $Key + "' is either missing or empty" } } function EnsurePermissionHeadersNotNull { if (-not $script:PermissionHeaders) { throw "Permission header('X-Client-Id' or 'X-Access-Token') is null." + ` "Please call 'Set-PermissionHeaders' to set the appropriate permission headers(ClientId & AccessToken)." + ` "If you are not sure what this is about, please visit 'https://developer.wunderlist.com/' to register the app and obtain clientid and access token." } } function TryInvokeWebRequest { param( [string] $Uri, [hashtable] $Headers, [hashtable] $Body ) try { $result = Invoke-WebRequest -Uri $Uri -Headers $Headers -Body $Body $result.Content | ConvertFrom-Json } catch [System.Net.WebException] { # Invoke-WebRequest throws regular WebExceptions with confusing text; hence casting to a much # useful text with this throw throw $_.Exception.Message + " " + $_.ErrorDetails } } |