Public/Send-SlackMessage.ps1

function Send-SlackMessage {
    <#
    .SYNOPSIS
        Send a Slack message
 
    .DESCRIPTION
        Send a Slack message
 
        You can use the parameters here to build the message, or
        provide a SlackMessage created with New-SlackMessage
 
    .PARAMETER Token
        Token to use for the Slack API
 
        Default value is the value set by Set-PSSlackConfig
 
        This takes precedence over Uri
 
    .PARAMETER Uri
        Uri to use for an incoming webhook
 
        Default value is the value set by Set-PSSlackConfig
 
        If Token is set, this is ignored
 
    .PARAMETER Proxy
        Proxy server to use
 
        Default value is the value set by Set-PSSlackConfig
 
    .PARAMETER SlackMessage
        A SlackMessage created by New-SlackMessage
 
    .PARAMETER Channel
        Channel, private group, or IM channel to send message to. Can be an encoded ID, or a name.
 
    .PARAMETER Text
        Text of the message to send
 
        See formatting spec for more information. https://api.slack.com/docs/formatting
 
    .PARAMETER Username
        Set your bot's user name.
 
        If using a Token, must be used in conjunction with as_user set to false, otherwise ignored
 
        See authorship details: https://api.slack.com/methods/chat.postMessage#authorship
 
    .PARAMETER Thread
        The id of the parent message you want to thread. This is usually seen as ts or thread_ts in a response.
 
        Can find a ts by querying https://api.slack.com/methods/conversations.history
 
    .PARAMETER IconUrl
        URL to an image to use as the icon for this message.
 
        If using a Token, must be used in conjunction with as_user set to false, otherwise ignored.
 
        See authorship details: https://api.slack.com/methods/chat.postMessage#authorship
 
    .PARAMETER IconEmoji
        Emoji to use as the icon for this message.
        Overrides icon_url.
 
        Must be used in conjunction with as_user set to false, otherwise ignored
 
    .PARAMETER AsUser
        Use true to post the message as the authed user, instead of as a bot. Defaults to false.
 
        See authorship details: https://api.slack.com/methods/chat.postMessage#authorship
 
    .PARAMETER LinkNames
        Find and link channel names and usernames.
 
    .PARAMETER Parse
        Change how messages are treated. Defaults to none
 
        If set to full, channels like #general and usernames like @bob will be linkified.
 
        More details here: https://api.slack.com/docs/formatting#linking_to_channels_and_users
 
    .PARAMETER UnfurlLinks
        Use true to enable unfurling of primarily text-based content.
 
    .PARAMETER UnfurlMedia
        Use false to disable unfurling of media content.
 
    .PARAMETER Attachments
        Optional rich structured message attachments.
 
        Provide one or more hash tables created using New-SlackMessageAttachment
 
        See attachments spec https://api.slack.com/docs/attachments
 
    .PARAMETER ForceVerbose
        If specified, don't explicitly remove verbose output from Invoke-RestMethod
 
        *** WARNING ***
        This will expose your token in verbose output
 
    .EXAMPLE
        # This example shows a crudely crafted message without any attachments,
        # using parameters from Send-SlackMessage to construct the message.
 
        #Previously set up Uri from https://<YOUR TEAM>.slack.com/apps/A0F7XDUAZ
        $Uri = "Some incoming webhook uri from Slack"
 
        Send-SlackMessage -Uri $Uri `
                          -Channel '@wframe' `
                          -Parse full `
                          -Text 'Hello @wframe, join me in #devnull!'
 
        # Send a message to @wframe (not a channel), parsing the text to linkify usernames and channels
 
    .EXAMPLE
        # This is a simple example illustrating some common options
        # when constructing a message attachment
        # giving you a richer message
        $Token = 'A token. maybe from https://api.slack.com/docs/oauth-test-tokens'
 
        New-SlackMessageAttachment -Color $_PSSlackColorMap.red `
                                   -Title 'The System Is Down' `
                                   -TitleLink https://www.youtube.com/watch?v=TmpRs7xN06Q `
                                   -Text 'Please Do The Needful' `
                                   -Pretext 'Everything is broken' `
                                   -AuthorName 'SCOM Bot' `
                                   -AuthorIcon 'http://ramblingcookiemonster.github.io/images/tools/wrench.png' `
                                   -Fallback 'Your client is bad' |
            New-SlackMessage -Channel '@wframe' `
                             -IconEmoji :bomb: |
            Send-SlackMessage -Token $Token
 
        # Create a message attachment with details about an alert
        # Attach this to a slack message sending to the devnull channel
        # Send the newly created message using a token
 
    .EXAMPLE
        # This example demonstrates that you can chain new attachments
        # together to form a multi-attachment message
 
        $Token = 'A token. maybe from https://api.slack.com/docs/oauth-test-tokens'
 
        New-SlackMessageAttachment -Color $_PSSlackColorMap.red `
                                   -Title 'The System Is Down' `
                                   -TitleLink https://www.youtube.com/watch?v=TmpRs7xN06Q `
                                   -Text 'Everybody panic!' `
                                   -Pretext 'Everything is broken' `
                                   -Fallback 'Your client is bad' |
            New-SlackMessageAttachment -Color $_PSSlackColorMap.orange `
                                       -Title 'The Other System Is Down' `
                                       -TitleLink https://www.youtube.com/watch?v=TmpRs7xN06Q `
                                       -Text 'Please Do The Needful' `
                                       -Fallback 'Your client is bad' |
            New-SlackMessage -Channel '@wframe' `
                             -IconEmoji :bomb: `
                             -AsUser `
                             -Username 'SCOM Bot' |
            Send-SlackMessage -Token $Token
 
        # Create an attachment, create another attachment,
        # add these to a message,
        # and send with a token
 
    .EXAMPLE
 
        # This example illustrates a pattern where you might
        # want to send output from a script; you might
        # include errors, successful items, or other output
 
        # Pretend we're in a script, and caught an exception of some sort
        $Fail = [pscustomobject]@{
            samaccountname = 'bob'
            operation = 'Remove privileges'
            status = "An error message"
            timestamp = (Get-Date).ToString()
        }
 
        # Create an array from the properties in our fail object
        $Fields = @()
        foreach($Prop in $Fail.psobject.Properties.Name)
        {
            $Fields += @{
                title = $Prop
                value = $Fail.$Prop
                short = $true
            }
        }
 
        $Token = 'A token. maybe from https://api.slack.com/docs/oauth-test-tokens'
 
        # Construct and send the message!
        New-SlackMessageAttachment -Color $_PSSlackColorMap.orange `
                                   -Title 'Failed to process account' `
                                   -Fields $Fields `
                                   -Fallback 'Your client is bad' |
            New-SlackMessage -Channel 'devnull' |
            Send-SlackMessage -Uri $uri
 
        # We build up a pretend error object, and send each property to a 'Fields' array
        # Creates an attachment with the fields from our error
        # Creates a message fromthat attachment and sents it with a uri
 
    .NOTES
 
    ON AUTHORIZATION:
 
        We don't get fancy with ParameterSets. Here's a breakdown of how we pick Uri or Token:
 
            Parameters are used before Set-PSSlackConfig settings
            Tokens are used before Uri
 
            Examples:
                Uri parameter specified, token exists in Set-PSSlackConfig: Uri is used
                Uri and token exist in Set-PSSlackConfig: token is used
                Token and Uri parameters are specified: Token is used
 
    ON OUTPUT:
 
        The Slack API and Incoming Webhook alter the output Send-SlackMessage will provide.
 
        If you use a Uri for an Incoming Webhook, Slack will return a string:
           "ok" if the call succeeded
           An error string if something went wrong
 
        If you use a token, we get a bit more detail back:
            ok : True
            channel : D0ST7FE6Q
            ts : 1463254594.000027
            message : @{text=; username=Slack API Tester; icons=; attachments=System.Object[]; type=message;...
            link : ArchiveUri.From.Set-PSSlackConfig/D0ST7FE6Q/p1463254594000027
 
        If you use a token and things don't go so well, the OK field will not be true:
            ok error
            -- -----
            False channel_not_found
 
    .FUNCTIONALITY
        Slack
    #>


    [cmdletbinding(DefaultParameterSetName = 'SlackMessage')]
    param (

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$Token = $Script:PSSlack.Token,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$Uri = $Script:PSSlack.Uri,

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$Proxy = $Script:PSSlack.Proxy,

        [PSTypeName('PSSlack.Message')]
        [parameter(ParameterSetName = 'SlackMessage',
                   ValueFromPipeline = $True)]
        $SlackMessage,

        $Channel,

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True,
                   Position = 1)]
        $Text,

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True)]
        $Username,

        [parameter(ParameterSetName = 'Param',
        ValueFromPipelineByPropertyName = $True)]
        $Thread,

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True)]
        $IconUrl,

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True)]
        $IconEmoji,

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True)]
        [switch]$AsUser,

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True)]
        [switch]$LinkNames,

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True)]
        [validateset('full','none')]
        [string]$Parse = 'none',

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True)]
        [validateset($True, $False)]
        [bool]$UnfurlLinks,

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True)]
        [validateset($True, $False)]
        [bool]$UnfurlMedia,

        [parameter(ParameterSetName = 'Param',
                   ValueFromPipelineByPropertyName = $True)]
        [PSTypeName('PSSlack.MessageAttachment')]
        [System.Collections.Hashtable[]]$Attachments,

        [switch]$ForceVerbose = $Script:PSSlack.ForceVerbose
    )
    begin
    {
        Write-Debug "Send-SlackMessage Bound parameters: $($PSBoundParameters | Remove-SensitiveData | Out-String)`nParameterSetName $($PSCmdlet.ParameterSetName)"
        $Messages = @()
        $ProxyParam = @{}
        if($Proxy)
        {
            $ProxyParam.Proxy = $Proxy
        }
    }
    process
    {
        if($PSCmdlet.ParameterSetName -eq 'Param')
        {
            $body = @{ }

            switch ($psboundparameters.keys)
            {
                'channel'     {$body.channel = $channel }
                'text'        {$body.text     = $text}
                'thread'      {$body.thread_ts = $Thread}
                'username'    {$body.username = $username}
                'asuser'      {$body.as_user = $AsUser}
                'iconurl'     {$body.icon_url = $iconurl}
                'iconemoji'   {$body.icon_emoji   = $iconemoji}
                'linknames'   {$body.link_names = 1}
                'parse'       {$body.parse = $Parse}
                'UnfurlLinks' {$body.unfurl_links = $UnfurlLinks}
                'UnfurlMedia' {$body.unfurl_media = $UnfurlMedia}
                'attachments' {$body.attachments = $Attachments}
            }
            $Messages += $Body
        }
        else
        {
            foreach($Message in $SlackMessage)
            {
                $Messages += $SlackMessage
            }
        }
    }
    end
    {
        foreach($Message in $Messages)
        {
            if($Token -or ($Script:PSSlack.Token -and -not $Uri))
            {
                if($Message.attachments)
                {
                    $Message.attachments = ConvertTo-Json -InputObject @($Message.attachments) -Depth 6 -Compress
                }

                Write-Verbose "Send-SlackApi -Body $($Message | Format-List | Out-String)"
                $response = Send-SlackApi @ProxyParam -Method chat.postMessage -Body $Message -Token $Token -ForceVerbose:$ForceVerbose

                if ($response.ok)
                {
                    $link = "$($Script:PSSlack.ArchiveUri)/$($response.channel)/p$($response.ts -replace '\.')"
                    $response | Add-Member -MemberType NoteProperty -Name link -Value $link
                }

                $response
            }
            elseif($Uri -or $Script:PSSlack.Uri)
            {
                if(-not $ForceVerbose) {
                    $ProxyParam.Add('Verbose', $False)
                }
                if($ForceVerbose) {
                    $ProxyParam.Add('Verbose', $true)
                }
                $json = ConvertTo-Json -Depth 6 -Compress -InputObject $Message
                Invoke-RestMethod @ProxyParam -Method Post -Body $json -Uri $Uri -ContentType "application/json; charset=utf-8"
            }
            else
            {
                Throw 'No Uri or Token specified. Specify a Uri or Token in the parameters or via Set-PSSlackConfig'
            }
        }
    }
}