AutoWebCreds.psm1

$ThisModule = $(Get-Item $PSCommandPath).BaseName

<#
if (!$IsWindows) {
    Write-Error "This $ThisModule must be run on PowerShell 6 or higher on a Windows operating system! Halting!"
    return
}
#>


[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"

# Get public and private function definition files.
[array]$Public  = Get-ChildItem -Path "$PSScriptRoot\Public\*.ps1" -ErrorAction SilentlyContinue
[array]$Private = Get-ChildItem -Path "$PSScriptRoot\Private\*.ps1" -ErrorAction SilentlyContinue


# Dot source the Private functions
foreach ($import in $Private) {
    try {
        . $import.FullName
    }
    catch {
        Write-Error -Message "Failed to import function $($import.FullName): $_"
    }
}

[System.Collections.Arraylist]$ModulesToInstallAndImport = @()
if (Test-Path "$PSScriptRoot\module.requirements.psd1") {
    $ModuleManifestDataPrep = Import-PowerShellDataFile "$PSScriptRoot\module.requirements.psd1"
    $ModuleManifestDataPrep.Keys | Where-Object {$_ -ne "PSDependOptions"} | foreach {$null = $ModulesToinstallAndImport.Add($_)}
    $ModuleManifestData = $($ModuleManifestDataPrep.GetEnumerator()) | Where-Object {$_.Name -ne "PSDependOptions"}
}

if ($ModulesToInstallAndImport.Count -gt 0) {
    # Set $env:PSModulePath correctly
    # Determine installed PowerShell Core Versions
    $PSCoreDirItems = @(Get-ChildItem -Path "$env:ProgramFiles\Powershell" -Directory | Where-Object {$_.Name -match "[0-9]"})
    $LatestPSCoreDirPath = $($PSCoreDirItems | Sort-Object -Property CreationTime)[-1].FullName
    $PSCoreUserDocsModulePath = "$HOME\Documents\PowerShell\Modules"
    $WinPSUserDocsModulePath = "$HOME\Documents\WindowsPowerShell\Modules"
    $LatestPSCoreSystemPath = "$LatestPSCoreDirPath\Modules"
    $LatestWinPSSystemPath = "$env:ProgramFiles\WindowsPowerShell\Modules"

    $AllPSModulePaths = @(
        $PSCoreUserDocsModulePath
        $WinPSUserDocsModulePath
        $($LatestPSCoreDirPath | Split-Path -Parent)
        $LatestPSCoreSystemPath
        $LatestWinPSSystemPath
        "$env:SystemRoot\system32\WindowsPowerShell\v1.0\Modules"
    )

    <#
    foreach ($ModPath in $AllPSModulePaths) {
        if (![bool]$($($env:PSModulePath -split ";") -match [regex]::Escape($ModPath))) {
            $env:PSModulePath = "$ModPath;$env:PSModulePath"
        }
    }
    #>


    # Attempt to import the Module Dependencies
    foreach ($ModuleData in $ModuleManifestData) {
        $ModuleName = $ModuleData.Name

        # Make sure it's installed
        $GetModResult = [System.Collections.Generic.List[object]]::new()
        @(Get-Module -ListAvailable -Name $ModuleName) | foreach {$GetModResult.Add($_)}
        $AllPSModulePaths | foreach {
            if (Test-Path $_) {
                $ModuleDir = Get-ChildItem -Path $_ -Directory | Where-Object {$_.Name -eq $ModuleName}
                if ($ModuleDir) {$GetModResult.Add($ModuleDir)}
            }
        }

        if ($GetModResult.Count -eq 0) {
            try {
                if ($ModuleData.Value.PSVersion -eq "WinPS" -and $PSVersionTable.PSEdition -eq "Core") {
                    powershell.exe -NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Install-Module $ModuleName -Scope CurrentUser -AllowClobber -Force"
                }
                if ($($ModuleData.Value.PSVersion -eq "PSCore" -and $PSVersionTable.PSEdition -eq "Core") -or $PSVersionTable.PSEdition -eq "Desktop") {
                    $null = Install-Module -Name $ModuleName -Scope CurrentUser -AllowClobber -Force -ErrorAction Stop -WarningAction SilentlyContinue
                }
                if ($ModuleData.Value.PSVersion -eq "WinPSAndPSCore" -and $PSVersionTable.PSEdition -eq "Core") {
                    powershell.exe -NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Install-Module $ModuleName -Scope CurrentUser -AllowClobber -Force"
                    $null = Install-Module -Name $ModuleName -Scope CurrentUser -AllowClobber -Force -ErrorAction Stop -WarningAction SilentlyContinue
                }
            }
            catch {
                Write-Error "Problem installing Module dependency $ModuleName ! Halting!"
                return
            }

            # Check again to make sure it's installed
            $GetModResult = [System.Collections.Generic.List[object]]::new()
            @(Get-Module -ListAvailable -Name $ModuleName) | foreach {$GetModResult.Add($_)}
            $AllPSModulePaths | foreach {
                if (Test-Path $_) {
                    $ModuleDir = Get-ChildItem -Path $_ -Directory | Where-Object {$_.Name -eq $ModuleName}
                    if ($ModuleDir) {$GetModResult.Add($ModuleDir)}
                }
            }

            if ($GetModResult.Count -eq 0) {
                Write-Error "Problem installing Module dependency $ModuleName ! Halting!"
                return
            }
        }
        
        # Import the Module
        if ($ModuleData.Value.PSVersion -eq "WinPS" -or $ModuleData.Value.PSVersion -eq "WinPSAndPSCore") {
            try {
                if ($PSVersionTable.PSEdition -eq 'Core') {
                    Import-Module $ModuleName -UseWindowsPowerShell -ErrorAction Stop
                } else {
                    Import-Module $ModuleName -ErrorAction Stop
                }
            } catch {
                Write-Error "Problem importing Module dependency $ModuleName ! Halting!"
                return
            }
        }
        else {
            try {
                Import-Module -Name $ModuleName -ErrorAction Stop
            }
            catch {
                Write-Error "Problem importing Module dependency $ModuleName ! Halting!"
                return
            }
        }

        # Alternate Module Import Logic (that assumes $ThisModule is compatible with WinPS and PSCore)
        <#
        try {
            Import-Module -Name $ModuleName -ErrorAction Stop
        }
        catch {
            # If we're in PSCore, then we need to potentially try the -UseWindowsPowerShell switch
            if ($PSVersionTable.PSEdition -eq "Core") {
                try {
                    Import-Module -Name $ModuleName -UseWindowsPowerShell -ErrorAction Stop
                }
                catch {
                    Write-Error "Problem importing Module dependency $ModuleName ! Halting!"
                    return
                }
            }
            else {
                Write-Error "Problem importing Module dependency $ModuleName ! Halting!"
                return
            }
        }
        #>

    }
}

# Public Functions



<#
    .SYNOPSIS
        This function uses chromedriver.exe via Selenium to log you into web service specified by the -ServiceName parameter.
 
    .DESCRIPTION
        See .SYNOPSIS
 
    .NOTES
 
    .PARAMETER ServiceName
        This parameter is MANDATORY.
 
        This parameter takes a string that represents the name of the service that you would like to log into via
        Google Chrome (chromedriver.exe). Currently, supported services are:
 
        AmazonMusic, Audible, GooglePlay, InternetArchive, NPR, Pandora, ReelGood, Spotify, Tidal, TuneIn, YouTube,
        and YouTubeMusic
 
    .PARAMETER ChromeProfileNumber
        This parameter is OPTIONAL.
 
        This parameter is takes an int that represents the Chrome Profile that you would like to use when
        launching Google Chrome via chromedriver.exe. Use the following PowerShell one-liner to list all available
        Chrome Profiles under the current Windows user:
         
        (Get-ChildItem -Path "$HOME\AppData\Local\Google\Chrome\User Data" -Directory -Filter "Profile *").Name
 
    .EXAMPLE
        # Open an PowerShell session, import the module, and -
         
        PS C:\Users\zeroadmin> New-WebLogin -ServiceName AmazonMusic -ChromeProfileNumber 1
#>

function New-WebLogin {
    [CmdletBinding()]
    param(
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet("AmazonMusic","Audible","GooglePlay","InternetArchive","NPR","Pandora","ReelGood","Spotify","Tidal","TuneIn","YouTube","YouTubeMusic")]
        [string]$ServiceName,

        [parameter(Mandatory=$false)]
        [int]$ChromeProfileNumber
    )

    $PSCmdString = $ServiceName + 'SeleniumLoginCheck'

    if ($ChromeProfileNumber) {
        $PSCmdString = $PSCmdString + ' ' + '-ChromeProfileNumber' + ' ' + $ChromeProfileNumber
    }

    Invoke-Expression -Command $PSCmdString

}


<#
    .SYNOPSIS
        This function updates existing credentials in the Windows Credential Manager - or if the credential Target
        doesn't already exist, this function creates a new Windows Credential Manager entry.
 
    .DESCRIPTION
        See .SYNOPSIS
 
    .NOTES
 
    .PARAMETER ServiceName
        This parameter is MANDATORY.
 
        This parameter takes a string that represents the name of the service that you would like to log into via
        Google Chrome (chromedriver.exe). Currently, supported services are:
 
        AmazonMusic, Audible, GooglePlay, InternetArchive, NPR, Pandora, ReelGood, Spotify, Tidal, TuneIn, YouTube,
        and YouTubeMusic
 
    .PARAMETER SiteUrl
        This parameter is OPTIONAL.
 
        This parameter is takes a string that represents the URL of the website where these credentials are used.
 
    .EXAMPLE
        # Open an PowerShell session, import the module, and -
         
        PS C:\Users\zeroadmin> Update-StoredCredential -ServiceName Spotify -SiteUrl "https://open.spotify.com"
#>

function Update-StoredCredential {
    [CmdletBinding()]
    param(
        [parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [ValidateSet("AmazonMusic","Audible","GooglePlay","InternetArchive","NPR","Pandora","ReelGood","Spotify","Tidal","TuneIn","YouTube","YouTubeMusic")]
        [string]$ServiceName,

        [parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [string]$SiteUrl
    )

    $ExistingStoredCreds = Get-StoredCredential -Target $ServiceName -ErrorAction SilentlyContinue
    if ($ExistingStoredCreds) {
        try {
            Remove-StoredCredential -Target $ServiceName -ErrorAction Stop
        } catch {
            Write-Error $_
            return
        }
    }
    
    if ([System.Environment]::OSVersion.Version.Build -lt 10240) {
        try {
            # Have the user provide Credentials
            [pscredential]$PSCreds = GetAnyBoxPSCreds -ServiceName $ServiceName
        } catch {
            Write-Error $_
            return
        }
    } else {
        try {
            if ($SiteUrl) {
                [pscredential]$PSCreds = UWPCredPrompt -ServiceName $ServiceName -SiteUrl $SiteUrl
            } else {
                [pscredential]$PSCreds = UWPCredPrompt -ServiceName $ServiceName
            }
        } catch {
            Write-Error $_
            return
        }
    }

    # Output
    $PSCreds
}


[System.Collections.ArrayList]$script:FunctionsForSBUse = @(
    ${Function:AddPath}.Ast.Extent.Text
    ${Function:AmazonAccountLogin}.Ast.Extent.Text
    ${Function:AmazonMusicSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:AmazonMusicUserNamePwdLogin}.Ast.Extent.Text
    ${Function:AppleAccountLogin}.Ast.Extent.Text
    ${Function:AudibleSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:CheckUrlStatus}.Ast.Extent.Text
    ${Function:ChromeDriverAndEventGhostCheck}.Ast.Extent.Text
    ${Function:FacebookAccountLogin}.Ast.Extent.Text
    ${Function:GetAnyBoxPSCreds}.Ast.Extent.Text
    ${Function:GetElevation}.Ast.Extent.Text
    ${Function:GoogleAccountLogin}.Ast.Extent.Text
    ${Function:GooglePlayMusicSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:InstallEventGhost}.Ast.Extent.Text
    ${Function:InternetArchiveSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:InternetArchiveUserNamePwdLogin}.Ast.Extent.Text
    ${Function:NPRSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:NPRUserNamePwdLogin}.Ast.Extent.Text
    ${Function:PandoraSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:PandoraUserNamePwdLogin}.Ast.Extent.Text
    ${Function:ReelGoodSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:ReelGoodUserNamePwdLogin}.Ast.Extent.Text
    ${Function:SeleniumDriverSetup}.Ast.Extent.Text
    ${Function:SetupEventGhost}.Ast.Extent.Text
    ${Function:SpotifySeleniumLoginCheck}.Ast.Extent.Text
    ${Function:SpotifyUserNamePwdLogin}.Ast.Extent.Text
    ${Function:TidalSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:TidalUserNamePwdLogin}.Ast.Extent.Text
    ${Function:TuneInSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:TuneInUserNamePwdLogin}.Ast.Extent.Text
    ${Function:TwitterAccountLogin}.Ast.Extent.Text
    ${Function:UpdateSystemPathNow}.Ast.Extent.Text
    ${Function:UWPCredPrompt}.Ast.Extent.Text
    ${Function:YouTubeSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:YouTubeMusicSeleniumLoginCheck}.Ast.Extent.Text
    ${Function:New-WebLogin}.Ast.Extent.Text
    ${Function:Updated-StoredCredential}.Ast.Extent.Text
)