Overview
Rambling
I grew up using IRC. Before Napster and Steam, there were other ways to find music and games. As time went by, I shifted over to more legitimate use, with freenode and other networks offering solid technical resources, including channels for PowerShell, VMware, Citrix, and more.
At some point, the Slack craze started, and Joel Bennett created the PowerShell Slack team (invite link). It took some convincing, but sometimes I just want a pretty, simple to use solution that works across platforms. Slack fit the bill, so I hopped on!
Eventually, I ended up on a team that uses Slack for communication. Perfect excuse to write a Slack module!
Why Chat?
So! Let’s step back a moment and consider why you might want a synchronous group chat system… Let’s use two example cases. Which would you prefer:
Case 1:
- A critical issue occurs. You’re heading to a physical war room. Not a loud person? Good luck getting your voice in there. Love repeating the status? Perfect, you’ll do this each time someone new steps in the room. Want a comfy keyboard and monitor? Ha, enjoy your laptop. Good luck writing your postmortem from this havoc
- Something big happens, but doesn’t warrant a war room. Get ready for 10 different e-mail threads with different recipients and miscommunication galore, and a ticket or two with duplicate but not complete information. Good luck piecing things together!
- You want to work remotely. You’re stuck with e-mail, phone calls, and 1:1 oriented IM with something like Lync. This isn’t condusive to communication
- You check a variety of sources. You have a logging solution, a monitoring solution or three, ad hoc e-mail notifications from scripts that go straight to junk mail, and more!
Case 2:
- A critical issues occurs. You head to a generic emergency chat room, or maybe create a new one specifically for this issue. You don’t need to interrupt people to raise an important point. Anyone who joins in can scroll up and read the full transcript. You can work from the comfort of wherever you want to work. When all is said and done, you have a good starting point for a postmortem
- Something big happens, but doesn’t warrant a war room. You hop on chat, maybe join a generic war room, and hash things out. You can mention or invite folks to join, and everyone can see the transcript, rather than try to parse 10 e-mail threads. You can add the chat transcript to your ticketing system, if that’s your thing
- You want to work remotely. If everyone is using chat, you can keep up to date with what everyone is up to, start up discussions, and generally have an easier time communicating with your team, regardless of where you are
- You check a variety of sources. But many or most of them funnel into a channel or two that you can view to get a quick read on things. You can search these things after the fact
- Your chat system is likely hosted. This means when shit hits the fan, you have a medium that isn’t depending on your infrastructure to run (on-prem IRC? No thanks)
Oh. And if you go beyond sending messages to your chat system, you can do some crazy fun things with a bot. Check out this awesome bit from Matt Hodgkins on setting up Hubot with PowerShell
So! Hyperbole (or is it?) aside, consider a group chat system; they can be incredibly helpful. There are a variety of options out there. Slack and HipChat are two of the better solutions out there.
Slack
Slack is a solid gif library chat solution. It has a slick client for most platforms, and a huge library of integrations. That being said, you might run into cases where you just want to send a message to Slack. Why?
- Maybe the system you want to hook into Slack doesn’t have an integration
- Maybe the existing integration is unhelpful, and blends into a sea of other messages that looks the same
- Maybe the existing integration doesn’t offer enough customization
- Some mix. SCOM is a great example. No Slack integration, and even if there were, you could add context to SCOM alerts and send them along to Slack, perhaps in addition to pretty HTML e-mails
Wait. But why would I send my stuff to Slack? It turns out that this is quite helpful.
Who wouldn’t want to have informational logs, various levels of alerts, conversation, and other data, all in one spot, search-able from any client, without worrying about it hitting you junk mail, being archived, or being spread across your various logging, monitoring, mail, file systems, event logs, and other sources that usually house this data? Sure, use those other solutions, but do consider how helpful it is to send this stuff to a chat system.
Isn’t this a PowerShell post, where’s the PowerShell?
PSSlack
Like any project, I like to look around to see what’s available in the community. There might be an existing module, or at least some functions that you could contribute to or borrow from.
I found an awesome function or two from jgigler, and a handy module from Steven Murawski, but I was looking for a bit more functionality.
I borrowed some work and ideas from jgigler and Steven, and put together a quick and dirty PSSlack module! Let’s do a quick walk through.
PSSlack Prerequisites
First things first, we need a way to authorize with Slack.
You can read more, but we’re just going to grab a test token for this exercise.
- Make sure you’ve signed into your Slack team in the browser (not just the app)
- Browse to this page, create a token, and copy it! Don’t give this out. Treat it like your username+password
If you’re just sending messages, you could also set up an incoming webhook and use the Uri (which you should also treat like a username+password).
PSSlack Installation
The next part is easy! We’ll use the PowerShell Gallery to grab the module (works with Windows 10, WMF 5, or a separate MSI installer at the link). You could also pull it down from GitHub.
Install-Module PSSlack -Force
That’s it! Now you can start exploring the commands and help:
# Import the module.
Import-Module PSSlack #Alternatively, Import-Module \\Path\To\PSSlack
# Get commands in the module
Get-Command -Module PSSlack
# Get help
Get-Help Send-SlackMessage -Full
Get-Help about_PSSlack
Using PSSlack
We’re done with the boring bits, lets look at the actual module! First things first, you can send a simple message with no bells or whistles:
$token = 'xoxp-some-token'
Send-SlackMessage -Token $token `
-Channel '@wframe' `
-Parse full `
-Text 'Hello @wframe, join me in #devnull!'
Let’s look at some more features.
Rich Attachments
New-SlackMessageAttachment -Color $([System.Drawing.Color]::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 'devnull' `
-IconEmoji :bomb: |
Send-SlackMessage -Token $Token
In this example, we create a Slack attachment, a way to provide a richer message. We pipe this along to New-SlackMessage, which constructs a Slack message. Finally, we send the newly create message with our existing token.
Multiple Attachments and Fields
Let’s throw in a kitchen sink. We can pipe multiple attachments together, and include a table of fields from any PowerShell object. We made up a fake example here:
#You could pipe anything into New-SlackField. We'll pretend to pull monitoring alert data:
$Fields = [pscustomobject]@{
ImpactedService = 'All The Things'
Severity = 11
ImpactedDepartment = 'All'
URL = 'https://www.youtube.com/watch?v=TmpRs7xN06Q'
} | New-SlackField -Short
# Notice that we can chain multiple attachments:
New-SlackMessageAttachment -Color $([System.Drawing.Color]::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-SlackMessageAttachment -Color $([System.Drawing.Color]::Orange) `
-Fields $Fields `
-Fallback 'Your client is bad' |
New-SlackMessage -Channel 'devnull' `
-IconEmoji :bomb: `
-AsUser `
-Username 'SCOM Bot' |
Send-SlackMessage -Token $Token
That’s about it for messages! Get creative. A while back we replaced our default, contextless SCOM notifications with a nice HTML e-mail notification. It would be simple to hook the same alerts into Slack, for example.
What else can we do?
Searching Slack
Slack has a great built in search, but maybe you want to hook something up that only sends messages if a UID or search term doesn’t appear in Slack already.
We’ll look for PowerShell discussion:
Find-SlackMessage -Token $Token `
-Query 'PowerShell' `
-SortBy timestamp
There’s a lot more context if we use Select-Object:
Find-SlackMessage -Token $Token `
-Query 'PowerShell' `
-SortBy timestamp |
Select-Object -Property *
We can also do something similar with channel history.
Getting History
There was recently a call for PowerShell / DevOps related topics. We’ll use this as a demo for what you might do with history:
Get-SlackChannel -Token $token -Name *topic-requests |
Get-SlackHistory -Token $token -Count 1000 |
Where-Object {$_.Reactions.Count -gt 0} |
Select @{ l='Thumbs'; e={$_.Reactions[0].count}}, Text |
Sort Thumbs -Descending
We find the channel in question, look for history, only return messages with reactions, add a thumbs property that contains the count of reactions, and sort:
Posting Files
This is a work in progress, but here’s an example of uploading a snippet:
$Snippet = @'
Send-SlackFile -Token $Token `
-Channel general `
-Content $Snippet `
-FileType powershell `
-filename example.ps1
'@
Send-SlackFile -Token $Token `
-Channel general `
-Content $Snippet `
-FileType powershell `
-filename example.ps1
Notice that this sends as me - you would need to register an application and grab a real token if you want this to appear from a bot.
Thanks to Brooks’ pull request, we now support sending files, because your Slack team could use a few more gifs!
That’s about it!
Next Steps
There’s more to come. Slack has a nice, well documented API, that offers you a GUI for simple testing of each method. We’re slowly working our way through these methods to see what would be valuable, so be sure to stop back, this module will be changing rapidly.
Suggestions, pull requests, and other contributions would be more than welcome. If you have any ideas, check to see if there’s already a request in the issues, and open an issue!
Cheers!