Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I use Apprise to send Adaptive Cards through Teams Workflows? #1221

Open
miguelbalmeida opened this issue Oct 8, 2024 · 2 comments
Labels

Comments

@miguelbalmeida
Copy link

miguelbalmeida commented Oct 8, 2024

I'm struggling to follow Apprise and Microsoft Teams documentation to do something simple: send a Markdown table as a message to a Teams channel from a Python script.

I've managed to do this before using the Incoming Webhook app in Teams plus Apprise's MS Teams functionality. Sadly, that way of doing things is now deprecated (see the top of the Microsoft link) and new webhooks do not work. Therefore, I am forced to use the new Workflows functionality within Teams.

I have managed to successfully send a message to Teams from within Python using Apprise. However, Markdown table syntax is no longer supported because Microsoft now uses Adaptive Cards. That led me to the new Apprise connector for Microsoft Workflows and Microsoft's documentation on including tables on Adaptive Cards.

What I cannot understand is how I send an Adaptive Card through Apprise from Python. My previous code using the (now deprecated) Incoming Webhook worked like this:

import apprise

teams_webhook = 'https://myorg.webhook.office.com/...'

apprise_object = apprise.Apprise()
apprise_object.add(teams_webhook)

notification_body = """| Heading 1 | Heading 2 | Heading 3 |
|-----------|-----------|-----------|
| Cell A1 | Cell A2 | Cell A3 |
| Cell B1 | Cell B2 | Cell B3 |"""

apprise_object.notify(
      title='Flow Test Message',
      body=notification_body,
      notify_type=apprise.NotifyType.WARNING,
      body_format=apprise.NotifyFormat.MARKDOWN,
)

I know that I need to define a JSON object that describes the Adaptive Card I want to send, but the Apprise docs only explain how to send it via CLI, not from Python, and explain it through using templating, which I don't need. I just need to be able to create the JSON object from within Python and send that through Apprise.

What should I pass to the apprise_object.notify() function to send the Adaptive Card properly?

@caronc
Copy link
Owner

caronc commented Oct 9, 2024

The templating aspect still works, but you just need to host your template that you want to use (over-riding the default.

import apprise

# point to your template file that 
teams_webhook = 'https://myorg.webhook.office.com/...?template=/path/to/template.json'

## You're /path/to/template.json may look like:
# {
#     "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
#     "type": "AdaptiveCard",
#     "version": "1.5",
#     "body": [
#         {
#             "type": "TextBlock",
#             "text": "{{app_title}}",
#             "weight": "Bolder",
#             "separator": true
#         },
#         {
#             "type": "TextBlock",
#             "text": "{{app_body}}",
#             "wrap": true
#         }
#     ]
# }

apprise_object = apprise.Apprise()
apprise_object.add(teams_webhook)

apprise_object.notify(
      title='Flow Test Message',
      body=notification_body,
      notify_type=apprise.NotifyType.WARNING,
      body_format=apprise.NotifyFormat.MARKDOWN,
)

Or leverage the new format and card you found to build your own template using the structure Microsoft imposes. Optionally use the {{app_body}} or {{app_title}} to dynamically populate the fields you're interested in....

For example, maybe your JSON file will look like this (slighly modified from example on Microsoft site you shared):

{
  "type": "AdaptiveCard",
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "version": "1.5",
  "body": [
    {
      "type": "Table",
      "gridStyle": "accent",
      "firstRowAsHeaders": true,
      "columns": [
        {
          "width": 1
        },
        {
          "width": 1
        },
        {
          "width": 3
        }
      ],
      "rows": [
        {
          "type": "TableRow",
          "cells": [
            {
              "type": "TableCell",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "Name",
                  "wrap": true,
                  "weight": "Bolder"
                }
              ]
            },
            {
              "type": "TableCell",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "Type",
                  "wrap": true,
                  "weight": "Bolder"
                }
              ]
            },
            {
              "type": "TableCell",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "Description",
                  "wrap": true,
                  "weight": "Bolder"
                }
              ]
            }
          ],
          "style": "accent"
        },
        {
          "type": "TableRow",
          "cells": [
            {
              "type": "TableCell",
              "style": "good",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "columns",
                  "wrap": true
                }
              ]
            },
            {
              "type": "TableCell",
              "style": "warning",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "ColumnDefinition[]",
                  "wrap": true
                }
              ]
            },
            {
              "type": "TableCell",
              "style": "accent",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "Defines the table's columns (number of columns, and column sizes).",
                  "wrap": true
                }
              ]
            }
          ]
        },
        {
          "type": "TableRow",
          "cells": [
            {
              "type": "TableCell",
              "style": "good",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "rows",
                  "wrap": true
                }
              ]
            },
            {
              "type": "TableCell",
              "style": "accent",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "TableRow[]",
                  "wrap": true
                }
              ]
            },
            {
              "type": "TableCell",
              "style": "attention",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "Defines the rows of the Table, each being a collection of cells. Rows are not required, which allows empty Tables to be generated via templating without breaking the rendering of the whole card.",
                  "wrap": true
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "type": "Table",
      "gridStyle": "accent",
      "firstRowAsHeaders": true,
      "showGridLines" : false,
      "columns": [
        {
          "width": 1
        },
        {
          "width": 1
        },
        {
          "width": 3
        }
      ],
      "rows": [
        {
          "type": "TableRow",
          "cells": [
            {
              "type": "TableCell",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "Name",
                  "wrap": true,
                  "weight": "Bolder"
                }
              ]
            },
            {
              "type": "TableCell",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "Type",
                  "wrap": true,
                  "weight": "Bolder"
                }
              ]
            },
            {
              "type": "TableCell",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "{{app_title}}",
                  "wrap": true,
                  "weight": "Bolder"
                }
              ]
            }
          ],
          "style": "accent"
        },
        {
          "type": "TableRow",
          "cells": [
            {
              "type": "TableCell",
              "style": "good",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "columns",
                  "wrap": true
                }
              ]
            },
            {
              "type": "TableCell",
              "style": "warning",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "ColumnDefinition[]",
                  "wrap": true
                }
              ]
            },
            {
              "type": "TableCell",
              "style": "accent",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "Defines the table's columns (number of columns, and column sizes).",
                  "wrap": true
                }
              ]
            }
          ]
        },
        {
          "type": "TableRow",
          "cells": [
            {
              "type": "TableCell",
              "style": "good",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "rows",
                  "wrap": true
                }
              ]
            },
            {
              "type": "TableCell",
              "style": "accent",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "TableRow[]",
                  "wrap": true
                }
              ]
            },
            {
              "type": "TableCell",
              "style": "attention",
              "items": [
                {
                  "type": "TextBlock",
                  "text": "{{app_body}}",
                  "wrap": true
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

@caronc
Copy link
Owner

caronc commented Oct 27, 2024

Can i close our this ticket? I haven't heard back from you in a bit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants