Mit Adaptive Cards kann eine Nachricht in Teams mit weiteren Informationen und möglichen Aktionen publiziert werden. Ich nutze eine Adaptive Card um über Power Automate eine Nachricht in einem Teams Kanal zu publizieren, wenn ein neuer Beitrag auf einer SharePoint Seite veröffentlicht wird.
Ich finde die Art über Power Automate aus persönlicher Sicht umständlich und der Power Automate Designer nervt mich immer wieder neu. Ich probierte es darum über PowerShell. Persönlich finde ich die Art mit PowerShell einfacher und für die Wiederverwendung schneller in der Umsetzung.
Was solltest du für Adaptive Cards beachten?
- Beachte das Schema für Adaptive Cards. Es gibt mittlerweile Version 1.6. Abhängig zu den genutzten Funktionen benötigst du eine Mindestversion. Oft ist die Standardversion noch 1.0. Funktioniert, aber bestimmte Möglichkeiten sind nicht unterstützt. In meinem Beispiel nutze ich Version 1.0.
- Es gibt einen Adaptive Card Designer. Der Designer kann unterstützen um einen Block oder bestimmte Funktionen abzubilden (wenn es jemand nicht selbst schreiben möchte).
- Für die Möglichkeit über PowerShell müssen in Teams Incoming Webhooks konfiguriert sein. Über die Webhooks kann eine Adaptive Card publiziert werden.
Content
Adaptive Card mit PowerShell veröffentlichen
Wie oben vermerkt ist in dem gewünschten Teams Kanal ein Incoming Webhook erforderlich.
- Im ersten Schritt musst du den Incoming Webhook Connector in einem Kanal manuell hinzufügen. Teams unterstützt es bisher nicht einen Connector über PowerShell einzufügen. Beachte die Anleitung und kopiere die URL des Webhooks. Halte die URL geheim.
- Erstelle das Schema für eine Adaptive Card im JSON-Format und ergänze die Textfelder nach Bedarf. In der Dokumentation findest du ein Beispiel.
Das Bild sollte ein öffentlich verfügbares Bild sein, oder intern ein Bild auf das Mitglieder lesend berechtigt sind. In meiner Demo wird das Bild über Unsplash durch Greg Rakozy bereitgestellt. Hast du kein Bild kannst du den ganzen Image Abschnitt entfernen. Die Karte zeigt dann nur den Text.
$AdaptiveCard = @"
{
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"contentUrl": null,
"content": {
"`$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{ "type": "ColumnSet",
"columns":
[
{ "type": "Column",
"width": 2,
"items": [
{ "type": "TextBlock",
"spacing": "None",
"size": "Large",
"weight": "Bolder",
"text": "Adaptive Card Demo"
},
{ "type": "TextBlock",
"size": "Small",
"text": "Hello World"
},
{ "type": "Image",
"url": "https://images.unsplash.com/photo-1444703686981-a3abbc4d4fe3",
"selectAction": {
"type": "Action.OpenUrl",
"url": "https://blog.topedia.com"
}
}
]
}
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "I want to read this page",
"url": "https://blog.topedia.com"
}
]
}
}
]
}
"@
- Als letzten Schritt wird die Adaptive Card an den Webhook gesendet und im Teams Kanal publiziert. Ergänze die URL mit deiner Webhook-URL aus Schritt 1.
$WebhookUrl = "<WebhookURL>"
Invoke-RestMethod -Method POST -Uri $WebhookUrl -Body $AdaptiveCard -ContentType 'application/json'
Im Kanal wird eine neue Nachricht mit der Adaptive Card veröffentlicht.
Über die Textelemente in der Adaptive Card ist es mit PowerShell nun einfach dynamische Werte aus einer SharePoint News zu veröffentlichen.
Adaptive Card mit PowerShell und base64-String veröffentlichen
Bekanntlich hat das neue Teams im Moment bei manchen Bildern einen Bug und zeigt die Bilder teils nicht korrekt an.
Externe Bilder, wie in meinem Beispiel von Unsplash, sind davon nicht betroffen. Ich sah das Problem bei Bildern einer SharePoint Ablage. Laut letztem Update ist ein Fix im Rollout.
Für die Übergangsphase wird in dem Post ein Workaround über base64-String erwähnt. Damit wird das Bild nicht über eine URL an Teams übermittelt, sondern der fixe Wert von dem Bild. Teams zeigt dadurch das statische Bild statt es über eine URL abzufragen. Die fehlerhafte Abfrage der URL ist der aktuelle Bug für die inkorrekte Darstellung im neuen Teams.
Der base64-String wird über den Inhalt von dem Bild gebildet und muss in das JSON der Adaptive Card eingefügt werden. Dabei gibt es die Einschränkung das JSON darf in Summe nicht grösser als 28 KB sein, andernfalls verweigert Teams die Annahme mit einem Too large. Das Bild sollte somit nicht grösser als 20 KB sein.
In meinem Beispiel von Unsplash muss ich das Bild in einen base64-String konvertieren und dabei beachten das Bild darf nicht grösser als 20 KB sein. Im Vergleich zur Methode über die URL ist es aufwändiger.
- Ich lade mir das Bild über die Unsplash API herunter. Dafür nutze ich bei Unsplash die Möglichkeiten für Developer.
$Url = "https://api.unsplash.com/photos/oMpAz-DN-9I?client_id=<DeveloperApplicationAccessKey>"
$ImageResult = Invoke-RestMethod -Method Get -Uri $Url
$ImageFilePath = ("C:\Temp\" + $ImageResult.id + ".jpg")
Invoke-WebRequest -Uri $ImageResult.links.download -OutFile $ImageFilePath
Das Bild wurde heruntergeladen und hat eine Grösse von rund 3 MB. Um ein vielfaches zu gross für die Adaptive Card.
- Ich verkleinere die Bildgrösse auf 500×333. Der Beitrag von Patrick Domingues unterstützt dabei.
$ResizedImagePath_Resized = ("C:\Temp\" + $ImageResult.id + "-Resized.jpg")
$Image = [System.Drawing.Image]::FromFile($ImageFilePath)
$ResizedImage = New-Object System.Drawing.Bitmap(500, 333)
$ImageGraphic = [System.Drawing.Graphics]::FromImage($ResizedImage)
$ImageGraphic.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBilinear
$ImageGraphic.DrawImage($Image, 0, 0, 500, 333)
$ImageGraphic.Dispose()
$Image.Dispose()
$ResizedImage.Save($ResizedImagePath_Resized)
Das Bild ist nun 335 KB gross. Weiterhin zu gross für die Adaptive Card.
- Ich verringere die Qualität von dem Bild um 30%. Dabei unterstützt ein Beitrag von Patrick Domingues erneut.
$ResizedImagePath_LowQuality = ("C:\Temp\" + $ImageResult.id + "-LowQuality.jpg")
$CompressionQuality = 70
$jpegCodec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object { $_.MimeType -eq "image/jpeg" }
$Image = [System.Drawing.Image]::FromFile($ResizedImagePath_Resized)
$encoderParams = New-Object System.Drawing.Imaging.EncoderParameters
$Encoder = [System.Drawing.Imaging.Encoder]::Quality
$EncoderParam = New-Object System.Drawing.Imaging.EncoderParameter($Encoder, $CompressionQuality)
$EncoderParams.Param[0] = $EncoderParam
$Image.Save($ResizedImagePath_LowQuality, $jpegCodec, $EncoderParams)
Das Bild hat jetzt eine Grösse von 18 KB und sieht noch passend aus.
- In der Grösse kann das Bild in einen base64-String konvertiert werden.
$ImageBytes = [System.IO.File]::ReadAllBytes($ResizedImagePath_LowQuality)
$ImageBase64 = [System.Convert]::ToBase64String($ImageBytes)
$base64URL = "data:image/png;base64,$ImageBase64"
Die base64 URL ist eine lange Zeichenfolge.
- Die base64 URL füge ich in die Adaptive Card als Image URL ein. Ergänze die URL mit deiner Webhook-URL.
$WebhookUrl = "<WebhookURL>"
$AdaptiveCard = @"
{
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"contentUrl": null,
"content": {
"`$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{ "type": "ColumnSet",
"columns":
[
{ "type": "Column",
"width": 2,
"items": [
{ "type": "TextBlock",
"spacing": "None",
"size": "Large",
"weight": "Bolder",
"text": "Adaptive Card Demo (with base64 Image)"
},
{ "type": "TextBlock",
"size": "Small",
"text": "Hello World"
},
{ "type": "Image",
"url": "$base64URL",
"selectAction": {
"type": "Action.OpenUrl",
"url": "https://blog.topedia.com"
}
}
]
}
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "I want to read this page",
"url": "https://blog.topedia.com"
}
]
}
}
]
}
"@
Invoke-RestMethod -Method POST -Uri $WebhookUrl -Body $AdaptiveCard -ContentType 'application/json'
Im Kanal wird eine neue Nachricht mit der Adaptive Card veröffentlicht. Die Karte inkludiert nun das base64 Bild. 👍