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
17 changes: 11 additions & 6 deletions examples/reactions/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,24 @@ async def handle_message(ctx: ActivityContext[MessageActivity]):
return

# ============================================
# Remove Reaction
# Remove Reaction (adds first so there's something to remove)
# ============================================
if text.startswith("unreact "):
reaction_type = text[8:].strip()

await ctx.api.reactions.add(
conversation_id=conversation_id,
activity_id=activity_id,
reaction_type=reaction_type,
)
await ctx.reply(f"✅ Added {reaction_type} reaction, removing in 2s...")
await asyncio.sleep(2)
await ctx.api.reactions.delete(
conversation_id=conversation_id,
activity_id=activity_id,
reaction_type=reaction_type,
)

await ctx.reply(f"✅ Removed {reaction_type} reaction from your message!")
print(f"[REACTION] Removed '{reaction_type}' from activity {activity_id}")
print(f"[REACTION] Cycled '{reaction_type}' on activity {activity_id}")
return

# ============================================
Expand All @@ -69,9 +74,9 @@ async def handle_message(ctx: ActivityContext[MessageActivity]):
"**Message Reactions Bot**\n\n"
"**Commands:**\n"
"- `react <type>` - Add a reaction to your message\n"
"- `unreact <type>` - Remove a reaction from your message\n\n"
"- `unreact <type>` - Add then remove a reaction (2s cycle) to demo deletion\n\n"
"- `react like` - Adds a 👍 to your message\n"
"- `unreact like` - Removes the 👍 from your message"
"- `unreact like` - Adds a 👍 then removes it after 2 seconds"
)
return

Expand Down
84 changes: 36 additions & 48 deletions examples/tab/Web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/tab/Web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"build": "npx vite build"
},
"dependencies": {
"@microsoft/teams.client": "^2.0.0",
"@microsoft/teams.client": "^2.0.9",
"@microsoft/teams.common": "^2.0.0",
"@microsoft/teams.graph": "^2.0.0",
"@microsoft/teams.graph-endpoints": "^2.0.0",
Expand Down
169 changes: 75 additions & 94 deletions examples/targeted-messages/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"""

import asyncio
from datetime import datetime, timezone

from microsoft_teams.api import Account, MessageActivity, MessageActivityInput
from microsoft_teams.api.activities.typing import TypingActivityInput
from microsoft_teams.api import MessageActivity, MessageActivityInput
from microsoft_teams.apps import ActivityContext, App

"""
Expand All @@ -23,112 +23,93 @@
@app.on_message
async def handle_message(ctx: ActivityContext[MessageActivity]):
"""Handle message activities."""
await ctx.reply(TypingActivityInput())
activity = ctx.activity
text = (activity.text or "").lower()

text = (ctx.activity.text or "").lower()
print(f"[MESSAGE] Received: {text}")

# ============================================
# Test targeted SEND (create)
# ============================================
if "test send" in text:
members = await ctx.api.conversations.members(ctx.activity.conversation.id).get_all()
if "test update" in text:
# UPDATE: Send a targeted message, then update it after 3 seconds
conversation_id = activity.conversation.id

for member in members:
print(f"Member: {member.name} - {member.id}")
targeted_message = MessageActivityInput(
text="📝 This message will be **updated** in 3 seconds..."
).with_recipient(activity.from_, is_targeted=True)

targeted_message = MessageActivityInput(
text="🔒 [SEND] This is a targeted message - only YOU can see this!"
).with_recipient(Account(id=member.id, name=member.name), is_targeted=True)
result = await ctx.send(targeted_message)

result = await ctx.send(targeted_message)
print("[SEND] Sent targeted message")
return

# ============================================
# Test targeted REPLY
# ============================================
if "test reply" in text:
targeted_reply = MessageActivityInput(text="🔒 [REPLY] Targeted reply - only YOU can see this!").with_recipient(
ctx.activity.from_, is_targeted=True
)
if result.id:
message_id = result.id

result = await ctx.reply(targeted_reply)
print(f"Targeted REPLY result: {result}")
return
async def update_after_delay():
await asyncio.sleep(3)
try:
timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S")
updated_message = MessageActivityInput(
text=f"✏️ **Updated!** This message was modified at {timestamp}"
)
updated_message.id = message_id

# ============================================
# Test targeted UPDATE
# ============================================
if "test update" in text:
# First send a targeted message
targeted_message = MessageActivityInput(text="🔒 [UPDATE] Original targeted message...").with_recipient(
ctx.activity.from_, is_targeted=True
)
await ctx.api.conversations.activities(conversation_id).update_targeted(message_id, updated_message)
print("[UPDATE] Updated targeted message")
except Exception as err:
print(f"[UPDATE] Error: {err}")

asyncio.create_task(update_after_delay())

print("[UPDATE] Scheduled update in 3 seconds")

elif "test delete" in text:
# DELETE: Send a targeted message, then delete it after 3 seconds
conversation_id = activity.conversation.id

result = await ctx.send(targeted_message)
print(f"Initial targeted message ID: {result.id}")

# Wait then update
async def update_after_delay():
await asyncio.sleep(3)
try:
# For targeted updates, do not include recipient in the payload.
updated_message = MessageActivityInput(
text="🔒 [UPDATE] ✅ UPDATED targeted message! (only you see this)"
)
updated_message.id = result.id

await ctx.api.conversations.activities(ctx.activity.conversation.id).update_targeted(
result.id, updated_message
)
print("Targeted UPDATE completed")
except Exception as err:
print(f"Targeted UPDATE error: {err}")

asyncio.create_task(update_after_delay())
return

# ============================================
# Test targeted DELETE
# ============================================
if "test delete" in text:
# First send a targeted message
targeted_message = MessageActivityInput(
text="🔒 [DELETE] This targeted message will be DELETED in 5 seconds..."
).with_recipient(ctx.activity.from_, is_targeted=True)
text="🗑️ This message will be **deleted** in 3 seconds..."
).with_recipient(activity.from_, is_targeted=True)

result = await ctx.send(targeted_message)
print(f"Targeted message to delete, ID: {result.id}")

# Wait then delete using the targeted API
async def delete_after_delay():
await asyncio.sleep(5)
try:
await ctx.api.conversations.activities(ctx.activity.conversation.id).delete_targeted(result.id)
print("Targeted DELETE completed")
except Exception as err:
print(f"Targeted DELETE error: {err}")

asyncio.create_task(delete_after_delay())
return

# ============================================
# Help / Default
# ============================================
if "help" in text:
await ctx.reply(
"**Targeted Messages Test Bot**\n\n"

if result.id:
message_id = result.id

async def delete_after_delay():
await asyncio.sleep(3)
try:
await ctx.api.conversations.activities(conversation_id).delete_targeted(message_id)
print("[DELETE] Deleted targeted message")
except Exception as err:
print(f"[DELETE] Error: {err}")

asyncio.create_task(delete_after_delay())

print("[DELETE] Scheduled delete in 3 seconds")

elif "test public" in text:
# PUBLIC: Send a public message visible to everyone in the chat.
await ctx.send(MessageActivityInput(text="📋 Here is the public result — everyone can see this!"))
print("[PUBLIC] Sent public message")

elif "test send" in text:
# SEND: Send a targeted message visible only to the sender.
targeted_message = MessageActivityInput(
text="👋 This is a **targeted message** — only YOU can see this!"
).with_recipient(activity.from_, is_targeted=True)
await ctx.send(targeted_message)
print("[SEND] Sent targeted message")

elif "help" in text:
await ctx.send(
"**🎯 Targeted Messages Demo**\n\n"
"**Commands:**\n"
"- `test send` - Send a targeted message\n"
"- `test reply` - Reply with a targeted message\n"
"- `test update` - Send then update a targeted message\n"
"- `test delete` - Send then delete a targeted message\n\n"
"💡 *Test in a group chat to verify others don't see targeted messages!*"
"- `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"
"_Targeted messages are only visible to you, even in group chats!_"
)
return

# Default
await ctx.reply('Say "help" for available commands.')
else:
await ctx.send(f"You said: '{activity.text}'\n\nType `help` to see available commands.")


if __name__ == "__main__":
Expand Down
Loading
Loading