Tag Archives: Teams

Microsoft Teams MessageCards

โ€˜Sup PSHomies,

I was excited to give the MS Teams module a go! I was secretly hoping for a cmdlet to send messages to channels. Unfortunately no such luck… yet! If push comes to shove you can always take the Graph route! ๐Ÿ˜‰

I posted the blog on social media and that generated some interesting ideas. Emotions and opinions varied quite a bit.ย Prateek raised an interesting question on whether slack would become obsolete in the near future. MS Teams is gaining momentum and it integrates nicely in Microsoft’s eco system, so why wouldn’t you use it? It doesn’t have to be black or white, use whatever adds value to your business I’d say!

This is where social media can be a treasure trove at times, got an interesting tip from Brett Millerย on posting messages to channels using webhooks! Ah! the missing cmdlet I was hoping for! “So basically it’s just an Invoke-RestMethod?” Cool! I gave it a spin:

New-TeamMessage

Nice! Hmmm… Webhooks eh? Sounds familiar… Where did I read about that? Ah yes! Stefan Stranger did a blog about that. To be honest, I did read his blog, but at that time I didn’t have access to Teams… ๐Ÿ˜‰ Just follow his instructions and you’re golden!

Here’s when the fun really started! Come to find out that there’s a lot more you can post using the message card reference! There’s even a card playground where you can try out your message cards. It’s all JSON, no problem, we’ve got cmdlets for that.

There’s a whole design guide on Messagecards. Best of all it supports MarkDown format! I tried a sending a table but that didn’t work as planned.

Just imagine the automation possibilities here… I understand now why ChatOps is really taking off…

My first attempt at DSL

Looking at the MessageCard format I thought: “This would be interesting as a DSL (Domain Specific Language) implementation… Hmmm…” I’ve been meaning to look into DSL after reading Kevin Marquette’s blog series on the subject. Seems now is a good time as any to start! This is what I came up with so far… It’s a work in progress ( sharing is caring) , but it works!

#region MessageCard function helpers
function MessageCard {
param([scriptblock]$ScriptBlock)
$newScript = "@{$($ScriptBlock.ToString())}"
$newScriptBlock = [scriptblock]::Create($newScript)
& $newScriptBlock
}
function section {
param([scriptblock]$ScriptBlock)
$newScript = "[Ordered]@{$($ScriptBlock.ToString())}"
$newScriptBlock = [scriptblock]::Create($newScript)
& $newScriptBlock
}
function fact {
param([scriptblock]$ScriptBlock)
$Invoked = $ScriptBlock.Invoke()
$Invoked.Keys |
ForEach-Object {
@{
Name = $_
Value = $Invoked.$_
}
}
}
#endregion
#region Main
$NewMessage = MessageCard {
summary = 'This is the summary property'
title = "This is the card's title property"
text = 'This is the cards text property.'
sections = @(
section {
activityTitle = 'Activity Title'
activitySubtitle = 'Activity **Sub**Title'
images = @(
@{
image = "http://connectorsdemo.azurewebsites.net/images/WIN12_Scene_01.jpg"
title = "This is the image alternate text Pic 01"
}
@{
image = "http://connectorsdemo.azurewebsites.net/images/WIN12_Anthony_02.jpg"
title = "This is the image alternate text Pic 02"
}
)
PotentialAction = @(
@{
'@type' = 'Actioncard'
Name = 'Comment'
Inputs = @(
@{
'@type' = 'TextInput'
Id = 'Comment'
isMultiLine = $true
Title = 'Input title property'
}
)
Actions = @(
@{
'@type' = 'HttpPOST'
Name = 'Save'
Target = 'http://...'
}
)
}
@{
'@type' = 'Actioncard'
Name = 'Due Date'
Inputs = @(
@{
'@type' = 'DateInput'
Id = 'dueDate'
Title = 'Input due date'
}
)
Actions = @(
@{
'@type' = 'HttpPOST'
Name = 'Save'
Target = 'http://...'
}
)
}
)
}
section {
title = 'Details:'
facts = fact {
@{
GivenName = 'Irwin'
SurName = 'Strachan'
}
}
}
section {
activityTitle = 'Default MD Support'
activitySubtitle = 'Activity **Subtitle**'
facts = fact {
@{
Email = 'Irwin@DosSantos.ca'
WebSite = '[pshirwins](https://pshirwin.wordpress.com)'
}
}
}
)
}
$restparams = @{
Uri = "Your WebHook Uri"
Method = 'POST'
Body = $($NewMessage | ConvertTo-Json -Depth 6)
ContentType = 'application/JSON'
}
Invoke-RestMethod @restparams
#endregion

And here’s the result:

New-MessageCard

I used the full card format as reference.ย  I realize that others in the community could easily knock this out the park. Maybe we can make this a community project? I would love to see what the possibilities are here…

Turns out not having a Send-TeamMessage wasn’t as painful as I thought it would be. Many ways to Rome…

Shout out to Brett & Stefan! Gotta love the PowerShell community!!!

Hope itโ€™s worth something to you,

Ttyl,

Urv

Microsoft Teams cmdlets are here!

‘Sup PSHomies,

Microsoft Teams has released the long anticipated Teams module! And with that a great blog to get you started.

Microsoft Teams is Microsoft’s version of Slack (Ok, I oversimplified that… I know). I’ve been following MSTeams development with Graph Explorerย for some time now (Something you should definitely look into).

So I followed the blog’s instructions and everything works as expected!

The cmdlets support the pipeline.ย  (Get-Command -Name <cmdlet>).Parameterset will get you an overview of what’s supported and/or mandatory. Generallyspeaking, GroupId is mandatory and accepted from the pipeline.

TeamChannel supports value from pipeline

Here’s some code to help test drive the cmdlets.

#region Connect
Connect-MicrosoftTeams
#endregion
#region MSTeams cmdlets
#Get all cmdlets
Get-Command -Module *Teams*
#Only interested in Get-*?
Get-Command -Module *Teams* -Name Get*
#Find out what mandatory and/or accepts ValueFrom* for Get-TeamUser
(Get-Command -Name Get-TeamUser).ParameterSets
#endregion
#region Test drive cmdlets
#Get Team Displays all Teams (Ofcourse it does)
Get-Team
#Get Team Channels. GroupId ValueFromPipelineByPropertyName = True
Get-Team | Get-TeamChannel
#Group TeamChannels by Teams
Get-Team |
ForEach-Object{
$result = Get-TeamChannel -GroupId $_.GroupId
[PSCustomObject]@{
Team = $_.DisplayName
TeamChannel = $result
}
} -OutVariable TeamChannels
#Get Team Users. GroupId ValueFromPipelineByPropertyName = True
Get-Team | Get-TeamUser
#Get TeamUsers
Get-Team |
ForEach-Object{
$result = Get-TeamUser -GroupId $_.GroupId
[PSCustomObject]@{
Team = $_.DisplayName
Users = $result
}
} -OutVariable TeamUsers
#Get TeamMemberSettings
Get-Team |
ForEach-Object{
$result = Get-TeamMemberSettings -GroupId $_.GroupId
[PSCustomObject]@{
Team = $_.DisplayName
TeamMemberSettings = $result
}
} -OutVariable TeamMemberSettings
#endregion

So one thing I was hoping for, was to have a cmdlet to post to TeamChannels. For now posting can be done using Graph beta support for teams. Looking forward to having cmdlets for posting as well (fingers crossed!). Before the cmdlets you needed to do some pre-configuration in order to post using Graph, so the cmdlets definitely makes that step easier!

Well that’s it in a nutshell, happy Testing

Hope it’s worth something to you,

Ttyl,

Urv