Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ examples/**/infra/
examples/**/teamsapp*
examples/**/aad.manifest.json

# Targeted-messages sample ships a manifest to demonstrate the slash-commands
# opt-in fields (supportsTargetedMessages, commandLists[].triggers).
!examples/targeted-messages/appPackage/
!examples/targeted-messages/appPackage/manifest.json

# Node (from tab)
node_modules
dist/
Expand Down
14 changes: 12 additions & 2 deletions examples/targeted-messages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,25 @@ Targeted messages are messages that only a specific recipient can see - other pa
| Command | Behavior |
|---------|----------|
| `test send` | Sends a targeted message (only you see it) |
| `test reply` | Replies with a targeted message |
| `test update` | Sends a targeted message, then updates it after 3 seconds |
| `test delete` | Sends a targeted message, then deletes it after 5 seconds |
| `test delete` | Sends a targeted message, then deletes it after 3 seconds |
| `test public` | Sends a public reply (visible to everyone) |
| `test inbound` | Reads `activity.recipient.is_targeted` and reports whether the inbound message was targeted at the bot |
| `help` | Shows available commands |

## How It Works

When sending targeted messages, use `with_recipient(Account(...), is_targeted=True)` to mark the recipient as targeted.

## Manifest configuration

The `appPackage/manifest.json` uses `manifestVersion: "devPreview"` because the slash-command opt-in fields are only defined in the devPreview schema:

- `bots[].supportsTargetedMessages: true` — opts the bot into receiving slash-command-style targeted messages.
- `bots[].commandLists[].triggers: ["slash"]` — declares the listed commands as slash commands. They appear in the Teams `/` picker for group chats and channels.

Slash commands arrive at the bot as regular `MessageActivity` events with `activity.recipient.is_targeted == True`, which the `test inbound` handler in this sample demonstrates.
Comment thread
corinagum marked this conversation as resolved.

## Testing in a Group Chat

To properly test targeted messages:
Expand Down
55 changes: 55 additions & 0 deletions examples/targeted-messages/appPackage/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.schema.json",
"version": "1.0.0",
"manifestVersion": "devPreview",
"id": "${{TEAMS_APP_ID}}",
"name": {
"short": "targeted-messages",
"full": "Targeted Messages Example"
},
"developer": {
"name": "Microsoft",
"mpnId": "",
"websiteUrl": "https://microsoft.com",
"privacyUrl": "https://privacy.microsoft.com/privacystatement",
"termsOfUseUrl": "https://www.microsoft.com/legal/terms-of-use"
},
"description": {
"short": "Bot demonstrating targeted (ephemeral) messages",
"full": "A sample bot that demonstrates how to send targeted messages that are only visible to specific recipients in Microsoft Teams."
},
"icons": {
"outline": "outline.png",
"color": "color.png"
},
Comment thread
corinagum marked this conversation as resolved.
"accentColor": "#FFFFFF",
"bots": [
{
"botId": "${{BOT_ID}}",
"scopes": ["personal", "team", "groupChat"],
"isNotificationOnly": false,
"supportsCalling": false,
"supportsVideo": false,
"supportsFiles": false,
"supportsTargetedMessages": true,
"commandLists": [
{
"scopes": ["team", "groupChat"],
"triggers": ["slash"],
"commands": [
{ "title": "test send", "description": "Send a targeted message visible only to you" },
{ "title": "test update", "description": "Send a targeted message then update it after 3 seconds" },
{ "title": "test delete", "description": "Send a targeted message then delete it after 3 seconds" },
{ "title": "test public", "description": "Send a public message visible to everyone" },
{ "title": "test inbound", "description": "Show whether the inbound message was targeted at the bot" }
]
}
]
}
],
"validDomains": ["${{BOT_DOMAIN}}", "*.botframework.com"],
"webApplicationInfo": {
"id": "${{BOT_ID}}",
"resource": "api://botid-${{BOT_ID}}"
}
}
15 changes: 14 additions & 1 deletion examples/targeted-messages/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,27 @@ async def delete_after_delay():
await ctx.send(targeted_message)
print("[SEND] Sent targeted message")

elif "test inbound" in text:
# INBOUND: Detect whether the inbound message was itself targeted at the bot
# (i.e. delivered as a slash command). Slash commands arrive as message
# activities with `activity.recipient.is_targeted == True`.
was_targeted = activity.recipient.is_targeted is True
await ctx.send(
"✅ Your message was delivered to me as a targeted message."
if was_targeted
else "ℹ️ Your message was delivered to me as a regular (broadcast) message."
)
print(f"[INBOUND] is_targeted={was_targeted}")

elif "help" in text:
await ctx.send(
"**🎯 Targeted Messages Demo**\n\n"
"**Commands:**\n"
"- `test send` - Send a targeted message (only visible to you)\n"
"- `test update` - Send a targeted message, then update it after 3 seconds\n"
"- `test delete` - Send a targeted message, then delete it after 3 seconds\n"
"- `test public` - Send a public reply (visible to all)\n\n"
"- `test public` - Send a public reply (visible to all)\n"
"- `test inbound` - Show whether the inbound message was targeted at the bot\n\n"
"_Targeted messages are only visible to you, even in group chats!_"
)

Expand Down
Loading