Skip to content

Commit

Permalink
Merge pull request #298 from atc0005/i288-codeblock-tweaks
Browse files Browse the repository at this point in the history
Update documentation for CodeBlock element
  • Loading branch information
atc0005 authored Aug 23, 2024
2 parents c0d6d3e + 05de9ca commit 6ac6dc0
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 2 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ A package to send messages to a Microsoft Teams channel.
- [Basic](#basic)
- [Specify proxy server](#specify-proxy-server)
- [User Mention](#user-mention)
- [CodeBlock](#codeblock)
- [Tables](#tables)
- [Set custom user agent](#set-custom-user-agent)
- [Add an Action](#add-an-action)
Expand Down Expand Up @@ -396,6 +397,14 @@ deprecated][o365-connector-retirement-announcement] `MessageCard` card format.
- File: [user-mention-verbose](./examples/adaptivecard/user-mention-verbose/main.go)
- this example does not necessarily reflect an optimal implementation

#### CodeBlock

This example illustrates the use of a [`CodeBlock`][adaptivecard-codeblock].
This feature is not available in the legacy [🚫
deprecated][o365-connector-retirement-announcement] `MessageCard` card format.

- File: [codeblock](./examples/adaptivecard/codeblock/main.go)

#### Tables

These examples illustrates the use of a [`Table`][adaptivecard-table]. This
Expand Down Expand Up @@ -511,4 +520,6 @@ using either this library or the original project.
[adaptivecard-user-mentions]: <https://docs.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-format#mention-support-within-adaptive-cards>
[adaptivecard-table]: <https://adaptivecards.io/explorer/Table.html>

[adaptivecard-codeblock]: <https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-format?tabs=adaptive-md%2Cdesktop%2Cconnector-html#codeblock-in-adaptive-cards>

<!-- []: PLACEHOLDER "DESCRIPTION_HERE" -->
34 changes: 32 additions & 2 deletions adaptivecard/adaptivecard.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ const (
TypeElementTextRun string = "TextRun" // Introduced in version 1.2
)

// Known exension types for an Adaptive Card element.
// Known extension types for an Adaptive Card element.
//
// - https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-format?tabs=adaptive-md%2Cdesktop%2Cconnector-html#codeblock-in-adaptive-cards
const (
Expand Down Expand Up @@ -612,7 +612,7 @@ type Element struct {
// CodeSnippet provides the content for a CodeBlock element, specific to MSTeams.
CodeSnippet string `json:"codeSnippet,omitempty"`

// Language specifies the langauge of a CodeBlock element, specific to MSTeams.
// Language specifies the language of a CodeBlock element, specific to MSTeams.
Language string `json:"language,omitempty"`

// StartLineNumber specifies the initial line number of CodeBlock element, specific to MSTeams.
Expand Down Expand Up @@ -3167,6 +3167,36 @@ func (c *Card) AddContainer(prepend bool, container Container) error {

// NewCodeBlock creates a new CodeBlock element with snippet, language, and
// optional firstLine. This is an MSTeams extension element.
//
// Supported languages include:
//
// - Bash
// - C
// - C#
// - C++
// - CSS
// - DOS
// - Go
// - GraphQL
// - HTML
// - Java
// - JavaScript
// - JSON
// - Perl
// - PHP
// - PlainText
// - PowerShell
// - Python
// - SQL
// - TypeScript
// - Verilog
// - VHDL
// - Visual Basic
// - XML
//
// See
// https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-format
// for additional languages that may be supported.
func NewCodeBlock(snippet string, language string, firstLine int) Element {
codeBlock := Element{
Type: TypeElementMSTeamsCodeBlock,
Expand Down
128 changes: 128 additions & 0 deletions examples/adaptivecard/codeblock/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright 2022 Adam Chalkley
//
// https://github.com/atc0005/go-teams-notify
//
// Licensed under the MIT License. See LICENSE file in the project root for
// full license information.

/*
This is an example of a client application which uses this library to generate
a Microsoft Teams message containing a codeblock in Adaptive Card format.
Of note:
- default timeout
- package-level logging is disabled by default
- validation of known webhook URL formats is *enabled*
- message submitted to Microsoft Teams consisting of title, formatted message
body and embedded codeblock
See these links for Adaptive Card text formatting options:
- https://docs.microsoft.com/en-us/adaptive-cards/authoring-cards/text-features
- https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-format?tabs=adaptive-md%2Cdesktop%2Cconnector-html#codeblock-in-adaptive-cards
*/

package main

import (
"log"
"os"
"strings"

goteamsnotify "github.com/atc0005/go-teams-notify/v2"
"github.com/atc0005/go-teams-notify/v2/adaptivecard"
)

func main() {

// Initialize a new Microsoft Teams client.
mstClient := goteamsnotify.NewTeamsClient()

// Set webhook url.
//
// NOTE: This is for illustration purposes only. Best practice is to NOT
// hardcode credentials of any kind.
webhookUrl := "https://example.logic.azure.com:443/workflows/GUID_HERE/triggers/manual/paths/invoke?api-version=YYYY-MM-DD&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=SIGNATURE_HERE"

// Allow specifying webhook URL via environment variable, fall-back to
// hard-coded value in this example file.
expectedEnvVar := "WEBHOOK_URL"
envWebhookURL := os.Getenv(expectedEnvVar)
switch {
case envWebhookURL != "":
log.Printf(
"Using webhook URL %q from environment variable %q\n\n",
envWebhookURL,
expectedEnvVar,
)
webhookUrl = envWebhookURL
default:
log.Println(expectedEnvVar, "environment variable not set.")
log.Printf("Using hardcoded value %q as fallback\n\n", webhookUrl)
}

// The title for message (first TextBlock element).
msgTitle := "Hello world"

// Formatted message body.
msgText := "Here are some examples of formatted stuff like " +
"\n * this list itself \n * **bold** \n * *italic* \n * ***bolditalic***"

// Create card using provided formatted title and text. We'll modify the
// card and when finished use it to generate a message for delivery.
card, err := adaptivecard.NewTextBlockCard(msgText, msgTitle, true)
if err != nil {
log.Printf(
"failed to create card: %v",
err,
)
os.Exit(1)
}

// See also https://yourbasic.org/golang/multiline-string/ for other
// approaches to embedding formatted strings.
codeSnippet := `
package main
import "log/slog"
func main() {
slog.Info("hello, world")
}
`

// If you want to strip leading/trailing whitespace.
codeSnippet = strings.TrimSpace(codeSnippet)

// Create CodeBlock using our snippet.
codeBlock := adaptivecard.NewCodeBlock(codeSnippet, "Go", 1)

// Add CodeBlock to our Card.
if err := card.AddElement(false, codeBlock); err != nil {
log.Printf(
"failed to add codeblock to card: %v",
err,
)
os.Exit(1)
}

// Create Message from Card
msg, err := adaptivecard.NewMessageFromCard(card)
if err != nil {
log.Printf("failed to create message from card: %v", err)
os.Exit(1)
}

// Send the message with default timeout/retry settings.
if err := mstClient.Send(webhookUrl, msg); err != nil {
log.Printf(
"failed to send message: %v",
err,
)
os.Exit(1)
}
}

0 comments on commit 6ac6dc0

Please sign in to comment.