GetWebAlertsFunctions.ps1

# GetWebAlertsFunctions.ps1

function Log-Message {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Msg,
        [ValidateSet('INFO','WARNING','ERROR')]
        [string]$Lvl = 'INFO'
    )
    Write-Host ("{0:yyyy-MM-dd HH:mm:ss} [{1}] {2}" -f (Get-Date), $Lvl, $Msg)
}

function Test-PnPConnection {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)] $Connection,
        [Parameter(Mandatory)][string]$Url,
        [Parameter(Mandatory)][string]$AppId,
        [Parameter(Mandatory)][string]$Tenant,
        [Parameter(Mandatory)][string]$CertificatePath,
        [SecureString]$CertificatePassword
    )
    try {
        Get-PnPWeb -Connection $Connection -ErrorAction Stop | Out-Null
        Log-Message "Connection validated for $Url" -Lvl 'INFO'
        return $Connection
    } catch {
        Log-Message "Connection invalid for $Url, reconnecting..." -Lvl 'WARNING'
        $retryCount = 0; $maxRetries = 3; $baseDelay = 5
        while ($retryCount -lt $maxRetries) {
            try {
                $params = @{
                    Url              = $Url
                    ClientId         = $AppId
                    Tenant           = $Tenant
                    CertificatePath  = $CertificatePath
                    ReturnConnection = $true
                    ErrorAction      = 'Stop'
                }
                if ($CertificatePassword) { $params.CertificatePassword = $CertificatePassword }
                $newConn = Connect-PnPOnline @params
                Log-Message "Reconnected to $Url" -Lvl 'INFO'
                return $newConn
            } catch {
                $retryCount++
                $delay = $baseDelay * [math]::Pow(2, $retryCount)
                Log-Message "Retry $retryCount/$maxRetries for $Url after ${delay}s – $_" -Lvl 'WARNING'
                Start-Sleep -Seconds $delay
            }
        }
        Log-Message "Failed to reconnect to $Url after $maxRetries attempts" -Lvl 'ERROR'
        return $null
    }
}

function Get-WebAlerts {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)][string]$Url,
        [Parameter(Mandatory)][string]$AppId,
        [Parameter(Mandatory)][string]$Tenant,
        [Parameter(Mandatory)][string]$CertificatePath,
        [SecureString]$CertificatePassword,
        [Parameter(Mandatory)][ValidateSet('AllLibraries','SpecificLibrary')][string]$ListMode,
        [string]$ListTitle
    )
    $localAlerts = @()

    # Connect using app-only
    $connParams = @{
        Url              = $Url
        ClientId         = $AppId
        Tenant           = $Tenant
        CertificatePath  = $CertificatePath
        ReturnConnection = $true
        ErrorAction      = 'Stop'
    }
    if ($CertificatePassword) { $connParams.CertificatePassword = $CertificatePassword }
    $conn = Connect-PnPOnline @connParams

    # Validate or reconnect
    $conn = Test-PnPConnection -Connection $conn -Url $Url -AppId $AppId -Tenant $Tenant -CertificatePath $CertificatePath -CertificatePassword $CertificatePassword
    if (-not $conn) { return $localAlerts }

    # Get lists (only user doc libs)
    $lists = if ($ListMode -eq 'SpecificLibrary' -and $ListTitle) {
        @(Get-PnPList -Identity $ListTitle -Connection $conn -ErrorAction Stop)
    } else {
        Get-PnPList -Connection $conn -ErrorAction Stop |
          Where-Object {
              $_.BaseTemplate        -eq 101           -and
              -not $_.Hidden                        -and
              -not $_.IsCatalog                     -and
              -not $_.IsSiteAssetsLibrary           -and
              $_.Title -notin @(
                'Site Pages','Style Library','Form Templates',
                'Asset Library','Picture Library','Data Connection Library','Wiki Page Library'
              )
          }
    }

    foreach ($list in $lists) {
        $alerts = Get-PnPAlert -List $list.Title -AllUsers -Connection $conn -ErrorAction SilentlyContinue
        foreach ($alert in $alerts) {
            $user = Get-PnPProperty -ClientObject $alert -Property User -Connection $conn
            $localAlerts += [pscustomobject]@{
                SiteUrl    = $Url
                AlertTitle = $alert.Title
                User       = $user.LoginName
                Frequency  = $alert.AlertFrequency
                EventType  = $alert.EventType
                ListTitle  = $list.Title
                ListUrl    = $list.DefaultViewUrl
            }
        }
    }

    return $localAlerts
}