sixkcd.psm1
class xkcd { [int] $id [datetime] $Date [string] $Title [uri] $Image [string] $Alt } function Get-xkcdobj { [CmdletBinding()] param( [int]$id ) $url = 'https://xkcd.com/{0}/info.0.json' $x = Invoke-RestMethod ($url -f $id) [xkcd]@{ id = $x.num Date = Get-Date -Year $x.year -Month $x.month -Day $x.day Title = $x.safe_title Image = $x.img Alt = $x.alt } } function Import-xkcd { [CmdletBinding()] param() $dict = [System.Collections.Generic.Dictionary[int, xkcd]]::new() $json = Get-Content -Raw "$PSScriptRoot\sixkcd.json" | ConvertFrom-Json foreach ($x in $json) { if (!$dict.ContainsKey($x.id)) { $dict.add($x.id, [xkcd]@{ id = $x.id Date = $x.Date Title = $x.Title Image = $x.Image Alt = $x.Alt }) } } return $dict } function Update-xkcd { [CmdletBinding()] param() [int]$Newest = (Invoke-RestMethod 'https://xkcd.com/info.0.json').num [int]$Lastcached = @($script:cache.Get_Keys())[-1] if ($Newest -gt $Lastcached) { $Lastcached..$Newest | ForEach-Object { if (!$script:cache.ContainsKey($_)) { $t = Get-xkcdobj $_ $script:cache.add($t.id, $t) } } $script:cache.GetEnumerator() | ForEach-Object { $_.Value } | ConvertTo-Json | Set-Content "$PSScriptRoot\sixkcd.json" } } function prettyxkcd { param( [string]$sixel, [xkcd] $xkcd ) $colors = Get-PSReadLineOption $line = '━' * $host.ui.RawUI.WindowSize.Width $sb = [System.Text.StringBuilder]::new() $null = & { $sb.AppendLine($line). Append($PSStyle.Bold). Append('# xkcd '). Append($colors.NumberColor). AppendLine($PSStyle.FormatHyperlink($xkcd.id, ('https://xkcd.com/' + $xkcd.id))). Append($PSStyle.Reset). Append('Title: '). Append($colors.StringColor). Append($xkcd.Title). Append($PSStyle.Reset). Append(' Date: '). Append($colors.TypeColor). Append($xkcd.Date.ToShortDateString()). Append($PSStyle.Reset). Append($PSStyle.Bold). Append(' Image: '). Append($PSStyle.Foreground.Blue). AppendLine($PSStyle.FormatHyperlink(([system.io.path]::GetFileNameWithoutExtension($xkcd.image)), $xkcd.Image)). Append($PSStyle.Reset). AppendLine($line). AppendLine(). AppendLine($sixel). Append($colors.OperatorColor). Append($PSStyle.Italic). Append($xkcd.Alt). Append($PSStyle.Reset). AppendLine() } $sb.ToString() } function Get-xkcd { <# .DESCRIPTION displays XKCD comics in the console using Sixel images. .PARAMETER Number The number of the XKCD comic to display. .PARAMETER Width The width of the Sixel image. .PARAMETER OnlySixel Only display the Sixel image. .PARAMETER Latest Display the latest XKCD comic. .PARAMETER xkcd The XKCD object to display. #> [cmdletbinding()] param( [Parameter(Position = 0)] [int] $Number, [Parameter(Position = 1)] [int] $Width, [switch] $OnlySixel, [Alias('Newest')] [switch] $Latest, [Parameter(ValueFromPipeline)] [xkcd] $xkcd ) begin { $params = @{} if ($Width) { $params.Width = $Width } } process { if ($Number) { $xkcd = $script:cache[$Number] } elseif ($Latest) { # +1 is just for 404 missing. $xkcd = $script:cache[$script:cache.count + 1] } elseif (-Not $xkcd) { # comic 404 might error here some day, but thats just gonna be a bit fun i think. $random = Get-Random -Minimum 1 -Maximum $script:cache.Count $xkcd = $script:cache[$random] } if ($xkcd) { if ($OnlySixel) { return ConvertTo-Sixel -Uri $xkcd.Image @params } prettyxkcd -xkcd $xkcd -Sixel (ConvertTo-Sixel -Uri $xkcd.Image @params) } } } function Search-xkcd { <# .DESCRIPTION Search for XKCD comics by title or alt text. .PARAMETER Title The title of the XKCD comic to search for. .PARAMETER Alt The alt text of the XKCD comic to search for. .PARAMETER MaxResults The maximum number of results to return. .PARAMETER Width The width of the Sixel image. .PARAMETER List List the results instead of displaying them. .PARAMETER OnlySixel Only display the Sixel image. #> [cmdletbinding()] param( [string] $Title, [string] $Alt, [int] $MaxResults = 3, [int] $Width, [Switch] $List, [switch] $OnlySixel ) $params = @{} if ($Width) { $params.Width = $Width } if ($OnlySixel) { $params.OnlySixel = $true } foreach ($x in $script:cache.GetEnumerator()) { if ($MaxResults -eq 0) { break } if ($Title) { if ($x.Value.Title -match $Title) { if ($List) { $x.Value } else { $x.Value | Get-xkcd @params } $MaxResults-- continue } } if ($Alt) { if ($x.Value.Alt -match $Alt) { if ($List) { $x.Value } else { $x.Value | Get-xkcd @params } $MaxResults-- continue } } } } $script:cache = Import-xkcd Update-xkcd |