awsNetSec.psm1

function Start-NetSecTray {
    [Alias('Start-Tray', 'ciscocansuckadick', 'suckadickcisco', 'ciscosucksdick', 'ciscosucksdicks', 'ciscosucksadick', 'ciscocansuckmydick', 'suckdickscisco', 'ciscodick', 'dickcisco', 'ciscosucks', 'ciscocansuckit', 'ciscosuckit', 'ciscosuck', 'ciscosucks')]
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)][string]$Course
    )
    Begin {
        
        $PrevPID = Get-Content $Env:TEMP\NetSecTrayPID.tmp -ErrorAction SilentlyContinue

        if ($PrevPID) {
            if (Get-Process -Id $PrevPID -ErrorAction SilentlyContinue) {
                Get-Process -Id $PrevPID | Stop-Process -Force
            } else {
                Remove-Item $Env:TEMP\NetSecTrayPID.tmp -Force
            }
        }

        if ($Course) {
            $Keyword = ($Course -replace ('-? ?(chapter [0-9]{0,2}|final|exam|answers)+ *', '')).TrimEnd()
            $Qualifier = ($Course -replace ("$Keyword ?-? ?", '')).TrimEnd()
            if ([string]::IsNullOrWhiteSpace($Qualifier)) {
                $Qualifier = 'final exam answers'
            }
            $SearchURI = "https://itexamanswers.net/?s=%22$Keyword%22+%22$Qualifier%22".Replace(' ', '+')
            $Links = (Invoke-WebRequest -Uri $SearchURI)
            $LinkMatches = $Links.links | Where-Object { $_.Title -match $Keyword -and $_.Title -match $Qualifier }
            $BestMatch = $LinkMatches | Sort-Object @{Expression = { (($_.Title -replace ($Keyword, '')) -replace ("$qualifier", '')).Length } } | Select-Object -First 1
            $URL = $BestMatch.href
        } else {
            Return 'No course specified'
        }

        $ScriptBlock = {  

            $TempFiles = [CodeDom.Compiler.TempFileCollection]::New($Env:TEMP, $false)
            $TempFile = New-Item -ItemType 'File' -Path $Env:TEMP -Name NetSecTrayPID.tmp -Value $PID -Force
            $TempFiles.AddFile($TempFile.FullName, $false)

            Try {
                Import-Module -Name PSParseHTML -ErrorAction Stop
            } Catch {
                Try {
                    Install-Module -Name PSParseHTML -Force -AllowClobber -Scope CurrentUser -ErrorAction Stop
                    Import-Module -Name PSParseHTML -ErrorAction Stop
                } Catch {
                    Write-Output 'Failed to install PSParseHTML module'
                    Exit
                }
            }

            $Array = @()
            $HTMLSplit = (Invoke-WebRequest -Uri '<INPUTURL>').Content -split '<nav class='
            foreach ($HTML in $HTMLSplit) {
                $ParsedHTML = (((ConvertFrom-HTMLTag -Content $HTML -Tag 'strong') -join "`n") -split ("`n[0-9]{1,3}\. +")) | Select-Object -Skip 1
                $i = 0
                $ParsedHTML | ForEach-Object {
                    $ParsedHTML[$i] = ($ParsedHTML[$i] -split "`n" | Where-Object { $_ -notmatch '^Explanation:' -and $_ -notmatch '^Download PDF File' }) -join "`n"
                    $i++
                }
                $Array += $ParsedHTML
            }

            $QA_Array = @()

            $Array | ForEach-Object {
                $Entry = $_ -split "`n"
                $QA_Array += [PSCustomObject]@{
                    Question = $Entry | Select-Object -First 1
                    Answer   = $Entry | Select-Object -Skip 1
                }
            }

            Remove-Item $env:TEMP\netsectray.ps1 -Force

            function Get-Answer {
                param (
                )
                $Qtext = (Get-Clipboard | Out-String).trim()                    
                $Answer = @()
                try {
                    $Answer += ($Script:QA_Array | Where-Object { $_.Question -match [RegEx]::Escape("$Qtext") }).Answer
                    while ($Answer.count -lt 3) {
                        $Answer += ''
                    }
                } catch {
                    $Answer = 'No_answer'
                }

                if (($Answer[0] + $Answer[1] + $Answer[2]).length -gt 123) {
                    $CharAllotment = 41
                    $NewAnswer = @()
                    $SpareChars = 0
                    foreach ($SubAnsw in $Answer) {
                        if ($SubAnsw.length -lt $CharAllotment) {
                            $SpareChars += ($CharAllotment - ($SubAnsw.length))
                            $NewAnswer += $SubAnsw
                        }
                    }
                    foreach ($SubAnsw in ($Answer | Where-Object { $_.length -gt $CharAllotment })) {
                        $MaxChars = $CharAllotment + ($SpareChars / ($Answer | Where-Object { $_.length -gt $CharAllotment }).count)
                        $SubAnswShort = $SubAnsw.Substring(0, $MaxChars)
                        $NewAnswer += $SubAnswShort
                    }
                    $Answer = $NewAnswer
                }

                Return $Answer
            }

            [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | Out-Null
            [System.Reflection.Assembly]::LoadWithPartialName('PresentationFramework') | Out-Null

            $Form = [System.Windows.Forms.Form] @{
                ShowInTaskbar   = $false
                WindowState     = 'Minimized'
                FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedToolWindow
                Opacity         = 0
            }
            [Void]$Form.Hide()

            $Icon = [System.Drawing.Icon]::ExtractAssociatedIcon("$Env:WinDir\explorer.exe")

            [System.GC]::Collect()

            $Output = Get-Answer

            $Menu_Exit = New-Object System.Windows.Forms.ToolStripMenuItem
            $Menu_Exit.Text = 'Exit'
            $Menu_Exit.Add_Click({ $TempFiles.Dispose() ; $Main_Tool_Icon.Dispose(); $form.dispose(); Exit -ErrorAction SilentlyContinue ; ```  })

            $Main_Tool_Icon = New-Object System.Windows.Forms.NotifyIcon
            $Main_Tool_Icon.ContextMenuStrip = New-Object System.Windows.Forms.ContextMenuStrip
            $Main_Tool_Icon.ContextMenuStrip.items.Add($Menu_Exit) | Out-Null
            $Main_Tool_Icon.Text = 'click for stuff'
            $Main_Tool_Icon.Icon = $icon
            $Main_Tool_Icon.Add_Click({
                    $Output = Get-Answer
                    if ($Output -ne 'No_answer') {
                        $Main_Tool_Icon.Text = "$($Output[0])`n$($Output[1])`n$($Output[2])"
                    } })
            $Main_Tool_Icon.Visible = $true

            $RefreshTimer = New-Object System.Windows.Forms.Timer
            $RefreshTimer.Interval = 2000
            $RefreshTimer.Add_Tick({
                    $Output = Get-Answer
                    if ($Output -ne 'No_answer') {
                        $Main_Tool_Icon.Text = "$($Output[0])`n$($Output[1])`n$($Output[2])"
                    }
                })
            $RefreshTimer.Enabled = $true

            [void][System.Windows.Forms.Application]::Run($Form)
        }

        ($ScriptBlock | Out-String).Replace('<INPUTURL>', $URL)  | Out-File $env:TEMP\netsectray.ps1 -Width 2000 -Force
    }
    Process {
        try {
            Start-Process pwsh.exe -WindowStyle hidden -ArgumentList "-ExecutionPolicy Bypass -File ""$env:TEMP\NetSecTray.ps1"""
        } catch {
            Start-Process powershell.exe -WindowStyle hidden -ArgumentList "-ExecutionPolicy Bypass -File ""$env:TEMP\NetSecTray.ps1"""
        }
    }
    End {
        Return $BestMatch.Title
    }
}