agent-messenger 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/release.md +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/e2e.yml.disabled +69 -0
- package/README.md +16 -14
- package/biome.json +33 -1
- package/bun.lock +63 -0
- package/dist/package.json +8 -4
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +4 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/platforms/discord/cli.js +1 -1
- package/dist/src/platforms/discord/client.d.ts.map +1 -1
- package/dist/src/platforms/discord/client.js +3 -3
- package/dist/src/platforms/discord/client.js.map +1 -1
- package/dist/src/platforms/discord/commands/user.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/user.js +10 -1
- package/dist/src/platforms/discord/commands/user.js.map +1 -1
- package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/discord/credential-manager.js +18 -12
- package/dist/src/platforms/discord/credential-manager.js.map +1 -1
- package/dist/src/platforms/slack/cli.js +1 -1
- package/dist/src/platforms/slack/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/slack/credential-manager.js +20 -6
- package/dist/src/platforms/slack/credential-manager.js.map +1 -1
- package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/slack/token-extractor.js +34 -9
- package/dist/src/platforms/slack/token-extractor.js.map +1 -1
- package/dist/src/platforms/teams/cli.d.ts.map +1 -0
- package/dist/{cli.js → src/platforms/teams/cli.js} +11 -10
- package/dist/src/platforms/teams/cli.js.map +1 -0
- package/dist/src/platforms/teams/client.d.ts +32 -0
- package/dist/src/platforms/teams/client.d.ts.map +1 -0
- package/dist/src/platforms/teams/client.js +202 -0
- package/dist/src/platforms/teams/client.js.map +1 -0
- package/dist/src/platforms/teams/commands/auth.d.ts +14 -0
- package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/auth.js +176 -0
- package/dist/src/platforms/teams/commands/auth.js.map +1 -0
- package/dist/src/platforms/teams/commands/channel.d.ts +13 -0
- package/dist/src/platforms/teams/commands/channel.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/channel.js +97 -0
- package/dist/src/platforms/teams/commands/channel.js.map +1 -0
- package/dist/src/platforms/teams/commands/file.d.ts +12 -0
- package/dist/src/platforms/teams/commands/file.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/file.js +104 -0
- package/dist/src/platforms/teams/commands/file.js.map +1 -0
- package/dist/{commands → src/platforms/teams/commands}/index.d.ts +5 -2
- package/dist/src/platforms/teams/commands/index.d.ts.map +1 -0
- package/dist/{commands → src/platforms/teams/commands}/index.js +5 -2
- package/dist/src/platforms/teams/commands/index.js.map +1 -0
- package/dist/src/platforms/teams/commands/message.d.ts +17 -0
- package/dist/src/platforms/teams/commands/message.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/message.js +133 -0
- package/dist/src/platforms/teams/commands/message.js.map +1 -0
- package/dist/src/platforms/teams/commands/reaction.d.ts +9 -0
- package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/reaction.js +68 -0
- package/dist/src/platforms/teams/commands/reaction.js.map +1 -0
- package/dist/src/platforms/teams/commands/snapshot.d.ts +10 -0
- package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/snapshot.js +85 -0
- package/dist/src/platforms/teams/commands/snapshot.js.map +1 -0
- package/dist/src/platforms/teams/commands/team.d.ts +18 -0
- package/dist/src/platforms/teams/commands/team.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/team.js +130 -0
- package/dist/src/platforms/teams/commands/team.js.map +1 -0
- package/dist/src/platforms/teams/commands/user.d.ts.map +1 -0
- package/dist/src/platforms/teams/commands/user.js +88 -0
- package/dist/src/platforms/teams/commands/user.js.map +1 -0
- package/dist/src/platforms/teams/credential-manager.d.ts +18 -0
- package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -0
- package/dist/src/platforms/teams/credential-manager.js +81 -0
- package/dist/src/platforms/teams/credential-manager.js.map +1 -0
- package/dist/src/platforms/teams/index.d.ts +4 -0
- package/dist/src/platforms/teams/index.d.ts.map +1 -0
- package/dist/src/platforms/teams/index.js +6 -0
- package/dist/src/platforms/teams/index.js.map +1 -0
- package/dist/src/platforms/teams/token-extractor.d.ts +36 -0
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -0
- package/dist/src/platforms/teams/token-extractor.js +335 -0
- package/dist/src/platforms/teams/token-extractor.js.map +1 -0
- package/dist/src/platforms/teams/types.d.ts +209 -0
- package/dist/src/platforms/teams/types.d.ts.map +1 -0
- package/dist/src/platforms/teams/types.js +65 -0
- package/dist/src/platforms/teams/types.js.map +1 -0
- package/docs/teams.md +321 -0
- package/e2e/README.md +256 -0
- package/e2e/config.ts +45 -0
- package/e2e/discord.e2e.test.ts +252 -0
- package/e2e/helpers.ts +107 -0
- package/e2e/slack.e2e.test.ts +309 -0
- package/package.json +8 -4
- package/scripts/postbuild.ts +15 -0
- package/skills/agent-teams/SKILL.md +292 -0
- package/skills/agent-teams/references/authentication.md +375 -0
- package/skills/agent-teams/references/common-patterns.md +596 -0
- package/skills/agent-teams/templates/monitor-channel.sh +239 -0
- package/skills/agent-teams/templates/post-message.sh +224 -0
- package/skills/agent-teams/templates/team-summary.sh +210 -0
- package/src/cli.ts +4 -0
- package/src/platforms/discord/client.ts +3 -3
- package/src/platforms/discord/commands/auth.test.ts +48 -32
- package/src/platforms/discord/commands/channel.test.ts +54 -42
- package/src/platforms/discord/commands/file.test.ts +40 -53
- package/src/platforms/discord/commands/guild.test.ts +47 -27
- package/src/platforms/discord/commands/message.test.ts +54 -51
- package/src/platforms/discord/commands/reaction.test.ts +54 -42
- package/src/platforms/discord/commands/user.ts +12 -1
- package/src/platforms/discord/credential-manager.test.ts +137 -136
- package/src/platforms/discord/credential-manager.ts +20 -13
- package/src/platforms/discord/token-extractor.test.ts +133 -383
- package/{tests → src/platforms/slack}/cli.test.ts +3 -3
- package/{tests/slack-client.test.ts → src/platforms/slack/client.test.ts} +1 -1
- package/{tests → src/platforms/slack}/commands/auth.test.ts +25 -13
- package/{tests → src/platforms/slack}/commands/channel.test.ts +2 -2
- package/{tests → src/platforms/slack}/commands/file.test.ts +2 -2
- package/{tests → src/platforms/slack}/commands/message.test.ts +2 -2
- package/{tests → src/platforms/slack}/commands/reaction.test.ts +1 -1
- package/{tests → src/platforms/slack}/commands/snapshot.test.ts +117 -105
- package/{tests → src/platforms/slack}/commands/user.test.ts +3 -3
- package/{tests → src/platforms/slack}/commands/workspace.test.ts +44 -95
- package/{tests → src/platforms/slack}/credential-manager.test.ts +2 -2
- package/src/platforms/slack/credential-manager.ts +22 -7
- package/src/platforms/slack/token-extractor-node-test.ts +40 -0
- package/src/platforms/slack/token-extractor-node.test.ts +10 -0
- package/src/platforms/slack/token-extractor.ts +36 -10
- package/{tests → src/platforms/slack}/types.test.ts +1 -1
- package/src/platforms/teams/cli.ts +36 -0
- package/src/platforms/teams/client.test.ts +500 -0
- package/src/platforms/teams/client.ts +365 -0
- package/src/platforms/teams/commands/auth.test.ts +99 -0
- package/src/platforms/teams/commands/auth.ts +232 -0
- package/src/platforms/teams/commands/channel.test.ts +147 -0
- package/src/platforms/teams/commands/channel.ts +129 -0
- package/src/platforms/teams/commands/file.test.ts +88 -0
- package/src/platforms/teams/commands/file.ts +144 -0
- package/src/platforms/teams/commands/index.ts +12 -0
- package/src/platforms/teams/commands/message.test.ts +110 -0
- package/src/platforms/teams/commands/message.ts +188 -0
- package/src/platforms/teams/commands/reaction.test.ts +87 -0
- package/src/platforms/teams/commands/reaction.ts +104 -0
- package/src/platforms/teams/commands/snapshot.test.ts +35 -0
- package/src/platforms/teams/commands/snapshot.ts +115 -0
- package/src/platforms/teams/commands/team.test.ts +157 -0
- package/src/platforms/teams/commands/team.ts +164 -0
- package/src/platforms/teams/commands/user.test.ts +83 -0
- package/src/platforms/teams/commands/user.ts +112 -0
- package/src/platforms/teams/credential-manager.test.ts +178 -0
- package/src/platforms/teams/credential-manager.ts +92 -0
- package/src/platforms/teams/index.ts +5 -0
- package/src/platforms/teams/token-extractor.test.ts +429 -0
- package/src/platforms/teams/token-extractor.ts +462 -0
- package/src/platforms/teams/types.test.ts +226 -0
- package/src/platforms/teams/types.ts +140 -0
- package/tsconfig.json +1 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/auth.d.ts +0 -3
- package/dist/commands/auth.d.ts.map +0 -1
- package/dist/commands/auth.js +0 -140
- package/dist/commands/auth.js.map +0 -1
- package/dist/commands/channel.d.ts +0 -3
- package/dist/commands/channel.d.ts.map +0 -1
- package/dist/commands/channel.js +0 -118
- package/dist/commands/channel.js.map +0 -1
- package/dist/commands/file.d.ts +0 -3
- package/dist/commands/file.d.ts.map +0 -1
- package/dist/commands/file.js +0 -113
- package/dist/commands/file.js.map +0 -1
- package/dist/commands/index.d.ts.map +0 -1
- package/dist/commands/index.js.map +0 -1
- package/dist/commands/message.d.ts +0 -3
- package/dist/commands/message.d.ts.map +0 -1
- package/dist/commands/message.js +0 -214
- package/dist/commands/message.js.map +0 -1
- package/dist/commands/reaction.d.ts +0 -3
- package/dist/commands/reaction.d.ts.map +0 -1
- package/dist/commands/reaction.js +0 -100
- package/dist/commands/reaction.js.map +0 -1
- package/dist/commands/snapshot.d.ts +0 -3
- package/dist/commands/snapshot.d.ts.map +0 -1
- package/dist/commands/snapshot.js +0 -88
- package/dist/commands/snapshot.js.map +0 -1
- package/dist/commands/user.d.ts.map +0 -1
- package/dist/commands/user.js +0 -96
- package/dist/commands/user.js.map +0 -1
- package/dist/commands/workspace.d.ts +0 -3
- package/dist/commands/workspace.d.ts.map +0 -1
- package/dist/commands/workspace.js +0 -89
- package/dist/commands/workspace.js.map +0 -1
- package/dist/lib/credential-manager.d.ts +0 -13
- package/dist/lib/credential-manager.d.ts.map +0 -1
- package/dist/lib/credential-manager.js +0 -58
- package/dist/lib/credential-manager.js.map +0 -1
- package/dist/lib/index.d.ts +0 -3
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/index.js +0 -3
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/ref-manager.d.ts +0 -26
- package/dist/lib/ref-manager.d.ts.map +0 -1
- package/dist/lib/ref-manager.js +0 -92
- package/dist/lib/ref-manager.js.map +0 -1
- package/dist/lib/slack-client.d.ts +0 -37
- package/dist/lib/slack-client.d.ts.map +0 -1
- package/dist/lib/slack-client.js +0 -379
- package/dist/lib/slack-client.js.map +0 -1
- package/dist/lib/token-extractor.d.ts +0 -28
- package/dist/lib/token-extractor.d.ts.map +0 -1
- package/dist/lib/token-extractor.js +0 -401
- package/dist/lib/token-extractor.js.map +0 -1
- package/dist/src/platforms/discord/client.test.d.ts +0 -2
- package/dist/src/platforms/discord/client.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/client.test.js +0 -367
- package/dist/src/platforms/discord/client.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/auth.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/auth.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/auth.test.js +0 -65
- package/dist/src/platforms/discord/commands/auth.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/channel.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/channel.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/channel.test.js +0 -136
- package/dist/src/platforms/discord/commands/channel.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/file.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/file.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/file.test.js +0 -83
- package/dist/src/platforms/discord/commands/file.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/guild.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/guild.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/guild.test.js +0 -100
- package/dist/src/platforms/discord/commands/guild.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/message.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/message.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/message.test.js +0 -91
- package/dist/src/platforms/discord/commands/message.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/reaction.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/reaction.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/reaction.test.js +0 -115
- package/dist/src/platforms/discord/commands/reaction.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/snapshot.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/snapshot.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/snapshot.test.js +0 -25
- package/dist/src/platforms/discord/commands/snapshot.test.js.map +0 -1
- package/dist/src/platforms/discord/commands/user.test.d.ts +0 -2
- package/dist/src/platforms/discord/commands/user.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/commands/user.test.js +0 -103
- package/dist/src/platforms/discord/commands/user.test.js.map +0 -1
- package/dist/src/platforms/discord/credential-manager.test.d.ts +0 -2
- package/dist/src/platforms/discord/credential-manager.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/credential-manager.test.js +0 -136
- package/dist/src/platforms/discord/credential-manager.test.js.map +0 -1
- package/dist/src/platforms/discord/token-extractor.test.d.ts +0 -2
- package/dist/src/platforms/discord/token-extractor.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/token-extractor.test.js +0 -789
- package/dist/src/platforms/discord/token-extractor.test.js.map +0 -1
- package/dist/src/platforms/discord/types.test.d.ts +0 -2
- package/dist/src/platforms/discord/types.test.d.ts.map +0 -1
- package/dist/src/platforms/discord/types.test.js +0 -211
- package/dist/src/platforms/discord/types.test.js.map +0 -1
- package/dist/src/shared/utils/concurrency.test.d.ts +0 -2
- package/dist/src/shared/utils/concurrency.test.d.ts.map +0 -1
- package/dist/src/shared/utils/concurrency.test.js +0 -39
- package/dist/src/shared/utils/concurrency.test.js.map +0 -1
- package/dist/tests/cli.test.d.ts +0 -2
- package/dist/tests/cli.test.d.ts.map +0 -1
- package/dist/tests/cli.test.js +0 -83
- package/dist/tests/cli.test.js.map +0 -1
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/CURRENT +0 -1
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOCK +0 -0
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG +0 -3
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG.old +0 -1
- package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/MANIFEST-000004 +0 -0
- package/dist/tests/commands/auth.test.d.ts +0 -2
- package/dist/tests/commands/auth.test.d.ts.map +0 -1
- package/dist/tests/commands/auth.test.js +0 -304
- package/dist/tests/commands/auth.test.js.map +0 -1
- package/dist/tests/commands/channel.test.d.ts +0 -2
- package/dist/tests/commands/channel.test.d.ts.map +0 -1
- package/dist/tests/commands/channel.test.js +0 -166
- package/dist/tests/commands/channel.test.js.map +0 -1
- package/dist/tests/commands/file.test.d.ts +0 -2
- package/dist/tests/commands/file.test.d.ts.map +0 -1
- package/dist/tests/commands/file.test.js +0 -175
- package/dist/tests/commands/file.test.js.map +0 -1
- package/dist/tests/commands/message.test.d.ts +0 -2
- package/dist/tests/commands/message.test.d.ts.map +0 -1
- package/dist/tests/commands/message.test.js +0 -293
- package/dist/tests/commands/message.test.js.map +0 -1
- package/dist/tests/commands/reaction.test.d.ts +0 -2
- package/dist/tests/commands/reaction.test.d.ts.map +0 -1
- package/dist/tests/commands/reaction.test.js +0 -84
- package/dist/tests/commands/reaction.test.js.map +0 -1
- package/dist/tests/commands/snapshot.test.d.ts +0 -2
- package/dist/tests/commands/snapshot.test.d.ts.map +0 -1
- package/dist/tests/commands/snapshot.test.js +0 -280
- package/dist/tests/commands/snapshot.test.js.map +0 -1
- package/dist/tests/commands/user.test.d.ts +0 -2
- package/dist/tests/commands/user.test.d.ts.map +0 -1
- package/dist/tests/commands/user.test.js +0 -117
- package/dist/tests/commands/user.test.js.map +0 -1
- package/dist/tests/commands/workspace.test.d.ts +0 -2
- package/dist/tests/commands/workspace.test.d.ts.map +0 -1
- package/dist/tests/commands/workspace.test.js +0 -453
- package/dist/tests/commands/workspace.test.js.map +0 -1
- package/dist/tests/credential-manager.test.d.ts +0 -2
- package/dist/tests/credential-manager.test.d.ts.map +0 -1
- package/dist/tests/credential-manager.test.js +0 -199
- package/dist/tests/credential-manager.test.js.map +0 -1
- package/dist/tests/slack-client.test.d.ts +0 -2
- package/dist/tests/slack-client.test.d.ts.map +0 -1
- package/dist/tests/slack-client.test.js +0 -741
- package/dist/tests/slack-client.test.js.map +0 -1
- package/dist/tests/types.test.d.ts +0 -2
- package/dist/tests/types.test.d.ts.map +0 -1
- package/dist/tests/types.test.js +0 -215
- package/dist/tests/types.test.js.map +0 -1
- package/dist/types/index.d.ts +0 -369
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -92
- package/dist/types/index.js.map +0 -1
- package/dist/utils/error-handler.d.ts +0 -2
- package/dist/utils/error-handler.d.ts.map +0 -1
- package/dist/utils/error-handler.js +0 -5
- package/dist/utils/error-handler.js.map +0 -1
- package/dist/utils/output.d.ts +0 -2
- package/dist/utils/output.d.ts.map +0 -1
- package/dist/utils/output.js +0 -4
- package/dist/utils/output.js.map +0 -1
- /package/dist/{cli.d.ts → src/platforms/teams/cli.d.ts} +0 -0
- /package/dist/{commands → src/platforms/teams/commands}/user.d.ts +0 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# monitor-channel.sh - Monitor a Microsoft Teams channel for new messages
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./monitor-channel.sh <channel-id> [interval]
|
|
7
|
+
#
|
|
8
|
+
# Arguments:
|
|
9
|
+
# channel-id - Channel ID to monitor (use 'channel list' to find IDs)
|
|
10
|
+
# interval - Polling interval in seconds (default: 10)
|
|
11
|
+
#
|
|
12
|
+
# Example:
|
|
13
|
+
# ./monitor-channel.sh "19:abc123@thread.tacv2"
|
|
14
|
+
# ./monitor-channel.sh "19:abc123@thread.tacv2" 5
|
|
15
|
+
#
|
|
16
|
+
# NOTE: Teams tokens expire in 60-90 minutes! This script handles automatic refresh.
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
# Check arguments
|
|
21
|
+
if [ $# -lt 1 ]; then
|
|
22
|
+
echo "Usage: $0 <channel-id> [interval]"
|
|
23
|
+
echo ""
|
|
24
|
+
echo "Examples:"
|
|
25
|
+
echo " $0 '19:abc123@thread.tacv2' # Monitor channel, poll every 10s"
|
|
26
|
+
echo " $0 '19:abc123@thread.tacv2' 5 # Monitor channel, poll every 5s"
|
|
27
|
+
echo ""
|
|
28
|
+
echo "To find channel IDs, run: agent-teams channel list"
|
|
29
|
+
echo ""
|
|
30
|
+
echo "NOTE: Teams tokens expire in 60-90 minutes - this script auto-refreshes!"
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
CHANNEL_ID="$1"
|
|
35
|
+
INTERVAL="${2:-10}" # Default 10 seconds
|
|
36
|
+
|
|
37
|
+
# Colors for output
|
|
38
|
+
RED='\033[0;31m'
|
|
39
|
+
GREEN='\033[0;32m'
|
|
40
|
+
YELLOW='\033[1;33m'
|
|
41
|
+
BLUE='\033[0;34m'
|
|
42
|
+
NC='\033[0m' # No Color
|
|
43
|
+
|
|
44
|
+
# State tracking
|
|
45
|
+
LAST_ID=""
|
|
46
|
+
FIRST_RUN=true
|
|
47
|
+
LAST_TOKEN_CHECK=$(date +%s)
|
|
48
|
+
TOKEN_CHECK_INTERVAL=300 # Check token every 5 minutes
|
|
49
|
+
|
|
50
|
+
# Function to format ISO timestamp to readable format
|
|
51
|
+
format_time() {
|
|
52
|
+
local ts=$1
|
|
53
|
+
# Handle ISO 8601 format
|
|
54
|
+
if command -v gdate &> /dev/null; then
|
|
55
|
+
gdate -d "$ts" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$ts"
|
|
56
|
+
else
|
|
57
|
+
date -d "$ts" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$ts"
|
|
58
|
+
fi
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Function to truncate text
|
|
62
|
+
truncate_text() {
|
|
63
|
+
local text=$1
|
|
64
|
+
local max_length=100
|
|
65
|
+
|
|
66
|
+
if [ ${#text} -gt $max_length ]; then
|
|
67
|
+
echo "${text:0:$max_length}..."
|
|
68
|
+
else
|
|
69
|
+
echo "$text"
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# Function to refresh token if needed (TEAMS-SPECIFIC)
|
|
74
|
+
refresh_token_if_needed() {
|
|
75
|
+
local now=$(date +%s)
|
|
76
|
+
local elapsed=$((now - LAST_TOKEN_CHECK))
|
|
77
|
+
|
|
78
|
+
# Only check periodically to avoid API spam
|
|
79
|
+
if [ $elapsed -lt $TOKEN_CHECK_INTERVAL ]; then
|
|
80
|
+
return 0
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
LAST_TOKEN_CHECK=$now
|
|
84
|
+
|
|
85
|
+
echo -e "${YELLOW}Checking token validity...${NC}"
|
|
86
|
+
|
|
87
|
+
local status
|
|
88
|
+
status=$(agent-teams auth status 2>&1)
|
|
89
|
+
|
|
90
|
+
# Check if token is expired or expiring soon
|
|
91
|
+
if echo "$status" | jq -e '.error' > /dev/null 2>&1; then
|
|
92
|
+
echo -e "${YELLOW}Token expired, refreshing...${NC}"
|
|
93
|
+
agent-teams auth extract
|
|
94
|
+
return 0
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
local expires_soon
|
|
98
|
+
expires_soon=$(echo "$status" | jq -r '.token_expires_soon // false')
|
|
99
|
+
local token_age
|
|
100
|
+
token_age=$(echo "$status" | jq -r '.token_age_minutes // 0')
|
|
101
|
+
|
|
102
|
+
if [ "$expires_soon" = "true" ]; then
|
|
103
|
+
echo -e "${YELLOW}Token expiring soon (${token_age} min old), refreshing...${NC}"
|
|
104
|
+
agent-teams auth extract
|
|
105
|
+
else
|
|
106
|
+
echo -e "${GREEN}Token valid (${token_age} min old)${NC}"
|
|
107
|
+
fi
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# Function to check for new messages
|
|
111
|
+
check_messages() {
|
|
112
|
+
# Get latest message
|
|
113
|
+
MESSAGES=$(agent-teams message list "$CHANNEL_ID" --limit 1 2>&1)
|
|
114
|
+
|
|
115
|
+
# Check for token expiry error
|
|
116
|
+
if echo "$MESSAGES" | grep -Eqi "expired|401|unauthorized" 2>/dev/null; then
|
|
117
|
+
echo -e "${YELLOW}Token expired during operation, refreshing...${NC}"
|
|
118
|
+
agent-teams auth extract
|
|
119
|
+
# Retry
|
|
120
|
+
MESSAGES=$(agent-teams message list "$CHANNEL_ID" --limit 1 2>&1)
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# Check if successful
|
|
124
|
+
if echo "$MESSAGES" | jq -e '.error' > /dev/null 2>&1; then
|
|
125
|
+
ERROR_MSG=$(echo "$MESSAGES" | jq -r '.error // "Unknown error"')
|
|
126
|
+
echo -e "${RED}Error: $ERROR_MSG${NC}"
|
|
127
|
+
return 1
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# Extract latest message
|
|
131
|
+
LATEST_ID=$(echo "$MESSAGES" | jq -r '.[0].id // ""')
|
|
132
|
+
|
|
133
|
+
# No messages in channel
|
|
134
|
+
if [ -z "$LATEST_ID" ]; then
|
|
135
|
+
if [ "$FIRST_RUN" = true ]; then
|
|
136
|
+
echo -e "${YELLOW}No messages in channel yet${NC}"
|
|
137
|
+
fi
|
|
138
|
+
return 0
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
# Check if new message
|
|
142
|
+
if [ "$LATEST_ID" != "$LAST_ID" ]; then
|
|
143
|
+
# Skip notification on first run (just initialize)
|
|
144
|
+
if [ "$FIRST_RUN" = false ] && [ -n "$LAST_ID" ]; then
|
|
145
|
+
# Extract message details
|
|
146
|
+
CONTENT=$(echo "$MESSAGES" | jq -r '.[0].content // ""')
|
|
147
|
+
AUTHOR=$(echo "$MESSAGES" | jq -r '.[0].author // "Unknown"')
|
|
148
|
+
TIMESTAMP=$(echo "$MESSAGES" | jq -r '.[0].timestamp // ""')
|
|
149
|
+
|
|
150
|
+
# Format timestamp
|
|
151
|
+
TIME=$(format_time "$TIMESTAMP")
|
|
152
|
+
|
|
153
|
+
# Display new message
|
|
154
|
+
echo ""
|
|
155
|
+
echo -e "${GREEN}----------------------------------------------${NC}"
|
|
156
|
+
echo -e "${BLUE}New message in channel${NC}"
|
|
157
|
+
echo -e "${GREEN}----------------------------------------------${NC}"
|
|
158
|
+
echo -e "Time: $TIME"
|
|
159
|
+
echo -e "From: $AUTHOR"
|
|
160
|
+
echo -e "Message: $(truncate_text "$CONTENT")"
|
|
161
|
+
echo -e "${GREEN}----------------------------------------------${NC}"
|
|
162
|
+
|
|
163
|
+
# Example: Auto-respond to keywords
|
|
164
|
+
# Uncomment to enable
|
|
165
|
+
# if echo "$CONTENT" | grep -qi "bot"; then
|
|
166
|
+
# echo -e "${YELLOW}Detected keyword, responding...${NC}"
|
|
167
|
+
# agent-teams message send "$CHANNEL_ID" "You called?"
|
|
168
|
+
# fi
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
LAST_ID="$LATEST_ID"
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
FIRST_RUN=false
|
|
175
|
+
return 0
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
# Check if agent-teams is installed
|
|
179
|
+
if ! command -v agent-teams &> /dev/null; then
|
|
180
|
+
echo -e "${RED}Error: agent-teams not found${NC}"
|
|
181
|
+
echo ""
|
|
182
|
+
echo "Install it with:"
|
|
183
|
+
echo " bun install -g agent-teams"
|
|
184
|
+
exit 1
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
# Check authentication and refresh if needed
|
|
188
|
+
echo "Checking authentication..."
|
|
189
|
+
refresh_token_if_needed
|
|
190
|
+
|
|
191
|
+
AUTH_STATUS=$(agent-teams auth status 2>&1)
|
|
192
|
+
|
|
193
|
+
if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
|
|
194
|
+
echo -e "${RED}Not authenticated!${NC}"
|
|
195
|
+
echo ""
|
|
196
|
+
echo "Run this to authenticate:"
|
|
197
|
+
echo " agent-teams auth extract"
|
|
198
|
+
exit 1
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
USER_NAME=$(echo "$AUTH_STATUS" | jq -r '.user // "Unknown"')
|
|
202
|
+
TOKEN_AGE=$(echo "$AUTH_STATUS" | jq -r '.token_age_minutes // "unknown"')
|
|
203
|
+
echo -e "${GREEN}Authenticated as: $USER_NAME${NC}"
|
|
204
|
+
echo -e "Token age: ${TOKEN_AGE} minutes"
|
|
205
|
+
echo ""
|
|
206
|
+
|
|
207
|
+
# Verify channel exists
|
|
208
|
+
echo "Verifying channel..."
|
|
209
|
+
CHANNEL_INFO=$(agent-teams channel info "$CHANNEL_ID" 2>&1)
|
|
210
|
+
|
|
211
|
+
if echo "$CHANNEL_INFO" | jq -e '.error' > /dev/null 2>&1; then
|
|
212
|
+
echo -e "${RED}Channel '$CHANNEL_ID' not found${NC}"
|
|
213
|
+
echo ""
|
|
214
|
+
echo "List available channels with:"
|
|
215
|
+
echo " agent-teams channel list"
|
|
216
|
+
exit 1
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
CHANNEL_NAME=$(echo "$CHANNEL_INFO" | jq -r '.name // "Unknown"')
|
|
220
|
+
echo -e "${GREEN}Monitoring: #$CHANNEL_NAME ($CHANNEL_ID)${NC}"
|
|
221
|
+
echo ""
|
|
222
|
+
|
|
223
|
+
# Start monitoring
|
|
224
|
+
echo -e "${YELLOW}Monitoring for new messages (polling every ${INTERVAL}s)...${NC}"
|
|
225
|
+
echo -e "${YELLOW}Token will be auto-refreshed before expiry (60-90 min limit)${NC}"
|
|
226
|
+
echo -e "${YELLOW}Press Ctrl+C to stop${NC}"
|
|
227
|
+
echo ""
|
|
228
|
+
|
|
229
|
+
# Trap Ctrl+C for clean exit
|
|
230
|
+
trap 'echo -e "\n${YELLOW}Monitoring stopped${NC}"; exit 0' INT
|
|
231
|
+
|
|
232
|
+
# Main monitoring loop
|
|
233
|
+
while true; do
|
|
234
|
+
# Proactively refresh token before it expires
|
|
235
|
+
refresh_token_if_needed
|
|
236
|
+
|
|
237
|
+
check_messages
|
|
238
|
+
sleep "$INTERVAL"
|
|
239
|
+
done
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# post-message.sh - Send a message to Microsoft Teams with error handling
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./post-message.sh <channel-id> <message>
|
|
7
|
+
# ./post-message.sh --channel-name <name> <message>
|
|
8
|
+
#
|
|
9
|
+
# Example:
|
|
10
|
+
# ./post-message.sh "19:abc123@thread.tacv2" "Hello from script!"
|
|
11
|
+
# ./post-message.sh --channel-name General "Deployment completed"
|
|
12
|
+
#
|
|
13
|
+
# NOTE: Teams tokens expire in 60-90 minutes! This script handles token refresh.
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
# Colors for output
|
|
18
|
+
RED='\033[0;31m'
|
|
19
|
+
GREEN='\033[0;32m'
|
|
20
|
+
YELLOW='\033[1;33m'
|
|
21
|
+
NC='\033[0m' # No Color
|
|
22
|
+
|
|
23
|
+
# Parse arguments
|
|
24
|
+
CHANNEL_ID=""
|
|
25
|
+
CHANNEL_NAME=""
|
|
26
|
+
MESSAGE=""
|
|
27
|
+
|
|
28
|
+
if [ "$1" = "--channel-name" ]; then
|
|
29
|
+
if [ $# -lt 3 ]; then
|
|
30
|
+
echo "Usage: $0 --channel-name <name> <message>"
|
|
31
|
+
echo ""
|
|
32
|
+
echo "Example:"
|
|
33
|
+
echo " $0 --channel-name General 'Build completed'"
|
|
34
|
+
echo ""
|
|
35
|
+
echo "NOTE: Teams tokens expire in 60-90 minutes!"
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
CHANNEL_NAME="$2"
|
|
39
|
+
MESSAGE="$3"
|
|
40
|
+
elif [ $# -lt 2 ]; then
|
|
41
|
+
echo "Usage: $0 <channel-id> <message>"
|
|
42
|
+
echo " $0 --channel-name <name> <message>"
|
|
43
|
+
echo ""
|
|
44
|
+
echo "Examples:"
|
|
45
|
+
echo " $0 '19:abc123@thread.tacv2' 'Hello world!'"
|
|
46
|
+
echo " $0 --channel-name General 'Build completed'"
|
|
47
|
+
echo ""
|
|
48
|
+
echo "NOTE: Teams tokens expire in 60-90 minutes!"
|
|
49
|
+
exit 1
|
|
50
|
+
else
|
|
51
|
+
CHANNEL_ID="$1"
|
|
52
|
+
MESSAGE="$2"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Function to refresh token if needed
|
|
56
|
+
refresh_token_if_needed() {
|
|
57
|
+
local status
|
|
58
|
+
status=$(agent-teams auth status 2>&1)
|
|
59
|
+
|
|
60
|
+
# Check if token is expired or expiring soon
|
|
61
|
+
if echo "$status" | jq -e '.error' > /dev/null 2>&1; then
|
|
62
|
+
echo -e "${YELLOW}Token expired or invalid, refreshing...${NC}"
|
|
63
|
+
agent-teams auth extract
|
|
64
|
+
return 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
local expires_soon
|
|
68
|
+
expires_soon=$(echo "$status" | jq -r '.token_expires_soon // false')
|
|
69
|
+
|
|
70
|
+
if [ "$expires_soon" = "true" ]; then
|
|
71
|
+
echo -e "${YELLOW}Token expiring soon, refreshing...${NC}"
|
|
72
|
+
agent-teams auth extract
|
|
73
|
+
fi
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# Function to send message with retry logic
|
|
77
|
+
send_message() {
|
|
78
|
+
local channel_id=$1
|
|
79
|
+
local message=$2
|
|
80
|
+
local max_attempts=3
|
|
81
|
+
local attempt=1
|
|
82
|
+
local token_refresh_attempts=0
|
|
83
|
+
local max_token_refresh=2
|
|
84
|
+
|
|
85
|
+
while [ $attempt -le $max_attempts ]; do
|
|
86
|
+
echo -e "${YELLOW}Attempt $attempt/$max_attempts...${NC}"
|
|
87
|
+
|
|
88
|
+
# Send message and capture result
|
|
89
|
+
RESULT=$(agent-teams message send "$channel_id" "$message" 2>&1)
|
|
90
|
+
|
|
91
|
+
# Check if successful (has an 'id' field)
|
|
92
|
+
if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
|
|
93
|
+
echo -e "${GREEN}Message sent successfully!${NC}"
|
|
94
|
+
|
|
95
|
+
# Extract message details
|
|
96
|
+
MSG_ID=$(echo "$RESULT" | jq -r '.id')
|
|
97
|
+
|
|
98
|
+
echo ""
|
|
99
|
+
echo "Message details:"
|
|
100
|
+
echo " Channel: $channel_id"
|
|
101
|
+
echo " Message ID: $MSG_ID"
|
|
102
|
+
|
|
103
|
+
return 0
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
# Extract error information
|
|
107
|
+
if echo "$RESULT" | jq -e '.error' > /dev/null 2>&1; then
|
|
108
|
+
ERROR_MSG=$(echo "$RESULT" | jq -r '.error // "Unknown error"')
|
|
109
|
+
echo -e "${RED}Failed: $ERROR_MSG${NC}"
|
|
110
|
+
|
|
111
|
+
# Handle token expiry - refresh and retry (with a limit on refresh attempts)
|
|
112
|
+
if echo "$ERROR_MSG" | grep -Eqi "expired|401|unauthorized"; then
|
|
113
|
+
token_refresh_attempts=$((token_refresh_attempts + 1))
|
|
114
|
+
if [ $token_refresh_attempts -le $max_token_refresh ]; then
|
|
115
|
+
echo -e "${YELLOW}Token expired, refreshing (attempt $token_refresh_attempts/$max_token_refresh)...${NC}"
|
|
116
|
+
agent-teams auth extract
|
|
117
|
+
continue
|
|
118
|
+
else
|
|
119
|
+
echo -e "${RED}Token refresh failed after $max_token_refresh attempts${NC}"
|
|
120
|
+
return 1
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
# Don't retry on certain errors
|
|
125
|
+
if echo "$ERROR_MSG" | grep -q "Not authenticated"; then
|
|
126
|
+
echo ""
|
|
127
|
+
echo "Not authenticated. Run:"
|
|
128
|
+
echo " agent-teams auth extract"
|
|
129
|
+
return 1
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
if echo "$ERROR_MSG" | grep -q "Channel not found"; then
|
|
133
|
+
echo ""
|
|
134
|
+
echo "Channel '$channel_id' not found. Check channel ID."
|
|
135
|
+
echo "List channels with: agent-teams channel list"
|
|
136
|
+
return 1
|
|
137
|
+
fi
|
|
138
|
+
else
|
|
139
|
+
echo -e "${RED}Unexpected error: $RESULT${NC}"
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
# Exponential backoff before retry
|
|
143
|
+
if [ $attempt -lt $max_attempts ]; then
|
|
144
|
+
SLEEP_TIME=$((attempt * 2))
|
|
145
|
+
echo "Retrying in ${SLEEP_TIME}s..."
|
|
146
|
+
sleep $SLEEP_TIME
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
attempt=$((attempt + 1))
|
|
150
|
+
done
|
|
151
|
+
|
|
152
|
+
echo -e "${RED}Failed after $max_attempts attempts${NC}"
|
|
153
|
+
return 1
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
# Check if agent-teams is installed
|
|
157
|
+
if ! command -v agent-teams &> /dev/null; then
|
|
158
|
+
echo -e "${RED}Error: agent-teams not found${NC}"
|
|
159
|
+
echo ""
|
|
160
|
+
echo "Install it with:"
|
|
161
|
+
echo " bun install -g agent-teams"
|
|
162
|
+
exit 1
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# Check and refresh authentication
|
|
166
|
+
echo "Checking authentication..."
|
|
167
|
+
refresh_token_if_needed
|
|
168
|
+
|
|
169
|
+
AUTH_STATUS=$(agent-teams auth status 2>&1)
|
|
170
|
+
|
|
171
|
+
if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
|
|
172
|
+
echo -e "${RED}Not authenticated!${NC}"
|
|
173
|
+
echo ""
|
|
174
|
+
echo "Run this to authenticate:"
|
|
175
|
+
echo " agent-teams auth extract"
|
|
176
|
+
exit 1
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
USER_NAME=$(echo "$AUTH_STATUS" | jq -r '.user // "Unknown"')
|
|
180
|
+
TEAM_ID=$(echo "$AUTH_STATUS" | jq -r '.current_team // ""')
|
|
181
|
+
TOKEN_AGE=$(echo "$AUTH_STATUS" | jq -r '.token_age_minutes // "unknown"')
|
|
182
|
+
echo -e "${GREEN}Authenticated as: $USER_NAME${NC}"
|
|
183
|
+
echo -e "Token age: ${TOKEN_AGE} minutes"
|
|
184
|
+
|
|
185
|
+
if [ -z "$TEAM_ID" ]; then
|
|
186
|
+
echo -e "${RED}No team selected!${NC}"
|
|
187
|
+
echo ""
|
|
188
|
+
echo "Run this to select a team:"
|
|
189
|
+
echo " agent-teams team list"
|
|
190
|
+
echo " agent-teams team switch <team-id>"
|
|
191
|
+
exit 1
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
# If channel name provided, look up channel ID
|
|
195
|
+
if [ -n "$CHANNEL_NAME" ]; then
|
|
196
|
+
echo "Looking up channel #$CHANNEL_NAME..."
|
|
197
|
+
CHANNELS=$(agent-teams channel list 2>&1)
|
|
198
|
+
|
|
199
|
+
if echo "$CHANNELS" | jq -e '.error' > /dev/null 2>&1; then
|
|
200
|
+
echo -e "${RED}Failed to list channels${NC}"
|
|
201
|
+
exit 1
|
|
202
|
+
fi
|
|
203
|
+
|
|
204
|
+
CHANNEL_ID=$(echo "$CHANNELS" | jq -r --arg name "$CHANNEL_NAME" '.[] | select(.name==$name) | .id')
|
|
205
|
+
|
|
206
|
+
if [ -z "$CHANNEL_ID" ]; then
|
|
207
|
+
echo -e "${RED}Channel #$CHANNEL_NAME not found${NC}"
|
|
208
|
+
echo ""
|
|
209
|
+
echo "Available channels:"
|
|
210
|
+
echo "$CHANNELS" | jq -r '.[] | " #\(.name) (\(.id))"'
|
|
211
|
+
exit 1
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
echo -e "${GREEN}Found channel: $CHANNEL_ID${NC}"
|
|
215
|
+
fi
|
|
216
|
+
|
|
217
|
+
echo ""
|
|
218
|
+
|
|
219
|
+
# Send the message
|
|
220
|
+
echo "Sending message to channel $CHANNEL_ID..."
|
|
221
|
+
echo "Message: $MESSAGE"
|
|
222
|
+
echo ""
|
|
223
|
+
|
|
224
|
+
send_message "$CHANNEL_ID" "$MESSAGE"
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# team-summary.sh - Generate a comprehensive Microsoft Teams team summary
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# ./team-summary.sh [--json]
|
|
7
|
+
#
|
|
8
|
+
# Options:
|
|
9
|
+
# --json Output raw JSON instead of formatted text
|
|
10
|
+
#
|
|
11
|
+
# Example:
|
|
12
|
+
# ./team-summary.sh
|
|
13
|
+
# ./team-summary.sh --json > summary.json
|
|
14
|
+
#
|
|
15
|
+
# NOTE: Teams tokens expire in 60-90 minutes! This script handles token refresh.
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
OUTPUT_JSON=false
|
|
20
|
+
if [ $# -gt 0 ] && [ "$1" = "--json" ]; then
|
|
21
|
+
OUTPUT_JSON=true
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
RED='\033[0;31m'
|
|
25
|
+
GREEN='\033[0;32m'
|
|
26
|
+
YELLOW='\033[1;33m'
|
|
27
|
+
BLUE='\033[0;34m'
|
|
28
|
+
CYAN='\033[0;36m'
|
|
29
|
+
BOLD='\033[1m'
|
|
30
|
+
NC='\033[0m'
|
|
31
|
+
|
|
32
|
+
# Function to refresh token if needed
|
|
33
|
+
refresh_token_if_needed() {
|
|
34
|
+
local status
|
|
35
|
+
status=$(agent-teams auth status 2>&1)
|
|
36
|
+
|
|
37
|
+
if echo "$status" | jq -e '.error' > /dev/null 2>&1; then
|
|
38
|
+
echo -e "${YELLOW}Token expired, refreshing...${NC}" >&2
|
|
39
|
+
agent-teams auth extract >&2
|
|
40
|
+
return 0
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
local expires_soon
|
|
44
|
+
expires_soon=$(echo "$status" | jq -r '.token_expires_soon // false')
|
|
45
|
+
|
|
46
|
+
if [ "$expires_soon" = "true" ]; then
|
|
47
|
+
echo -e "${YELLOW}Token expiring soon, refreshing...${NC}" >&2
|
|
48
|
+
agent-teams auth extract >&2
|
|
49
|
+
fi
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if ! command -v agent-teams &> /dev/null; then
|
|
53
|
+
echo -e "${RED}Error: agent-teams not found${NC}" >&2
|
|
54
|
+
echo "" >&2
|
|
55
|
+
echo "Install it with:" >&2
|
|
56
|
+
echo " bun install -g agent-teams" >&2
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Check and refresh token
|
|
61
|
+
refresh_token_if_needed
|
|
62
|
+
|
|
63
|
+
AUTH_STATUS=$(agent-teams auth status 2>&1)
|
|
64
|
+
|
|
65
|
+
if echo "$AUTH_STATUS" | jq -e '.error' > /dev/null 2>&1; then
|
|
66
|
+
echo -e "${RED}Not authenticated!${NC}" >&2
|
|
67
|
+
echo "" >&2
|
|
68
|
+
echo "Run this to authenticate:" >&2
|
|
69
|
+
echo " agent-teams auth extract" >&2
|
|
70
|
+
exit 1
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
CURRENT_TEAM=$(echo "$AUTH_STATUS" | jq -r '.current_team // ""')
|
|
74
|
+
TOKEN_AGE=$(echo "$AUTH_STATUS" | jq -r '.token_age_minutes // "unknown"')
|
|
75
|
+
|
|
76
|
+
if [ -z "$CURRENT_TEAM" ]; then
|
|
77
|
+
echo -e "${RED}No team selected!${NC}" >&2
|
|
78
|
+
echo "" >&2
|
|
79
|
+
echo "Run this to select a team:" >&2
|
|
80
|
+
echo " agent-teams team list" >&2
|
|
81
|
+
echo " agent-teams team switch <team-id>" >&2
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
echo -e "${YELLOW}Fetching team snapshot...${NC}" >&2
|
|
86
|
+
echo -e "Token age: ${TOKEN_AGE} minutes" >&2
|
|
87
|
+
SNAPSHOT=$(agent-teams snapshot 2>&1)
|
|
88
|
+
|
|
89
|
+
# Handle token expiry during snapshot
|
|
90
|
+
if echo "$SNAPSHOT" | grep -Eqi "expired|401|unauthorized" 2>/dev/null; then
|
|
91
|
+
echo -e "${YELLOW}Token expired during snapshot, refreshing...${NC}" >&2
|
|
92
|
+
agent-teams auth extract >&2
|
|
93
|
+
SNAPSHOT=$(agent-teams snapshot 2>&1)
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
if echo "$SNAPSHOT" | jq -e '.error' > /dev/null 2>&1; then
|
|
97
|
+
echo -e "${RED}Failed to get snapshot${NC}" >&2
|
|
98
|
+
ERROR_MSG=$(echo "$SNAPSHOT" | jq -r '.error // "Unknown error"')
|
|
99
|
+
echo -e "${RED}Error: $ERROR_MSG${NC}" >&2
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
if [ "$OUTPUT_JSON" = true ]; then
|
|
104
|
+
echo "$SNAPSHOT"
|
|
105
|
+
exit 0
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
TEAM_NAME=$(echo "$SNAPSHOT" | jq -r '.team.name // "Unknown"')
|
|
109
|
+
TEAM_ID=$(echo "$SNAPSHOT" | jq -r '.team.id // "Unknown"')
|
|
110
|
+
|
|
111
|
+
CHANNELS=$(echo "$SNAPSHOT" | jq '.channels // []')
|
|
112
|
+
CHANNEL_COUNT=$(echo "$CHANNELS" | jq 'length')
|
|
113
|
+
STANDARD_COUNT=$(echo "$CHANNELS" | jq '[.[] | select(.type == "standard")] | length')
|
|
114
|
+
PRIVATE_COUNT=$(echo "$CHANNELS" | jq '[.[] | select(.type == "private")] | length')
|
|
115
|
+
|
|
116
|
+
MEMBERS=$(echo "$SNAPSHOT" | jq '.members // []')
|
|
117
|
+
MEMBER_COUNT=$(echo "$MEMBERS" | jq 'length')
|
|
118
|
+
|
|
119
|
+
MESSAGES=$(echo "$SNAPSHOT" | jq '.recent_messages // []')
|
|
120
|
+
MESSAGE_COUNT=$(echo "$MESSAGES" | jq 'length')
|
|
121
|
+
|
|
122
|
+
echo ""
|
|
123
|
+
echo -e "${BOLD}${BLUE}=====================================================${NC}"
|
|
124
|
+
echo -e "${BOLD}${BLUE} Microsoft Teams Summary${NC}"
|
|
125
|
+
echo -e "${BOLD}${BLUE}=====================================================${NC}"
|
|
126
|
+
echo ""
|
|
127
|
+
echo -e "${BOLD}Team:${NC} $TEAM_NAME"
|
|
128
|
+
echo -e "${BOLD}ID:${NC} $TEAM_ID"
|
|
129
|
+
echo -e "${BOLD}Token Age:${NC} ${TOKEN_AGE} minutes (expires at ~60-90 min)"
|
|
130
|
+
echo ""
|
|
131
|
+
|
|
132
|
+
echo -e "${BOLD}${CYAN}Channels (${CHANNEL_COUNT} total)${NC}"
|
|
133
|
+
echo -e " Standard: $STANDARD_COUNT"
|
|
134
|
+
echo -e " Private: $PRIVATE_COUNT"
|
|
135
|
+
echo ""
|
|
136
|
+
|
|
137
|
+
echo -e "${BOLD}${CYAN}Channels:${NC}"
|
|
138
|
+
echo "$CHANNELS" | jq -r '
|
|
139
|
+
.[0:10] |
|
|
140
|
+
.[] |
|
|
141
|
+
" #\(.name) (\(.id[0:30])...)"
|
|
142
|
+
'
|
|
143
|
+
if [ "$CHANNEL_COUNT" -gt 10 ]; then
|
|
144
|
+
echo " ... and $((CHANNEL_COUNT - 10)) more"
|
|
145
|
+
fi
|
|
146
|
+
echo ""
|
|
147
|
+
|
|
148
|
+
echo -e "${BOLD}${CYAN}Members (${MEMBER_COUNT} shown)${NC}"
|
|
149
|
+
echo ""
|
|
150
|
+
|
|
151
|
+
echo -e "${BOLD}${CYAN}Sample Members:${NC}"
|
|
152
|
+
echo "$MEMBERS" | jq -r '
|
|
153
|
+
.[0:10] |
|
|
154
|
+
.[] |
|
|
155
|
+
" \(.displayName) \(if .email then "(\(.email))" else "" end)"
|
|
156
|
+
'
|
|
157
|
+
if [ "$MEMBER_COUNT" -gt 10 ]; then
|
|
158
|
+
echo " ... and $((MEMBER_COUNT - 10)) more"
|
|
159
|
+
fi
|
|
160
|
+
echo ""
|
|
161
|
+
|
|
162
|
+
echo -e "${BOLD}${CYAN}Recent Activity (${MESSAGE_COUNT} messages)${NC}"
|
|
163
|
+
echo ""
|
|
164
|
+
|
|
165
|
+
if [ "$MESSAGE_COUNT" -gt 0 ]; then
|
|
166
|
+
echo -e "${BOLD}${CYAN}Latest Messages:${NC}"
|
|
167
|
+
echo "$MESSAGES" | jq -r '
|
|
168
|
+
.[0:5] |
|
|
169
|
+
.[] |
|
|
170
|
+
" [#\(.channel_name)] \(.author): \(.content[0:50])\(if (.content | length) > 50 then "..." else "" end)"
|
|
171
|
+
'
|
|
172
|
+
echo ""
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
echo -e "${BOLD}${CYAN}Quick Actions:${NC}"
|
|
176
|
+
echo ""
|
|
177
|
+
echo -e " ${GREEN}# Send message to a channel${NC}"
|
|
178
|
+
FIRST_CHANNEL=$(echo "$CHANNELS" | jq -r '.[0].id // "CHANNEL_ID"')
|
|
179
|
+
FIRST_CHANNEL_NAME=$(echo "$CHANNELS" | jq -r '.[0].name // "General"')
|
|
180
|
+
echo -e " agent-teams message send \"$FIRST_CHANNEL\" \"Hello!\""
|
|
181
|
+
echo ""
|
|
182
|
+
echo -e " ${GREEN}# List messages in #$FIRST_CHANNEL_NAME${NC}"
|
|
183
|
+
echo -e " agent-teams message list \"$FIRST_CHANNEL\" --limit 10"
|
|
184
|
+
echo ""
|
|
185
|
+
echo -e " ${GREEN}# Get user info${NC}"
|
|
186
|
+
FIRST_USER=$(echo "$MEMBERS" | jq -r '.[0].id // "USER_ID"')
|
|
187
|
+
echo -e " agent-teams user info \"$FIRST_USER\""
|
|
188
|
+
echo ""
|
|
189
|
+
echo -e " ${GREEN}# Switch to another team${NC}"
|
|
190
|
+
echo -e " agent-teams team list"
|
|
191
|
+
echo -e " agent-teams team switch <team-id>"
|
|
192
|
+
echo ""
|
|
193
|
+
echo -e " ${GREEN}# Refresh token (expires in 60-90 min!)${NC}"
|
|
194
|
+
echo -e " agent-teams auth extract"
|
|
195
|
+
echo ""
|
|
196
|
+
|
|
197
|
+
echo -e "${BOLD}${BLUE}=====================================================${NC}"
|
|
198
|
+
echo ""
|
|
199
|
+
|
|
200
|
+
SNAPSHOT_FILE="team-snapshot-$(date +%Y%m%d-%H%M%S).json"
|
|
201
|
+
echo "$SNAPSHOT" > "$SNAPSHOT_FILE"
|
|
202
|
+
echo -e "${GREEN}Full snapshot saved to: $SNAPSHOT_FILE${NC}"
|
|
203
|
+
echo ""
|
|
204
|
+
|
|
205
|
+
# Warn if token is getting old
|
|
206
|
+
if [ "$TOKEN_AGE" != "unknown" ] && [ "${TOKEN_AGE%.*}" -gt 45 ] 2>/dev/null; then
|
|
207
|
+
echo -e "${YELLOW}WARNING: Token is ${TOKEN_AGE} minutes old. Consider refreshing soon!${NC}"
|
|
208
|
+
echo -e "${YELLOW}Run: agent-teams auth extract${NC}"
|
|
209
|
+
echo ""
|
|
210
|
+
fi
|
package/src/cli.ts
CHANGED
|
@@ -24,6 +24,10 @@ program.command('discord', 'Interact with Discord guilds', {
|
|
|
24
24
|
executableFile: join(__dirname, 'platforms', 'discord', 'cli.ts'),
|
|
25
25
|
})
|
|
26
26
|
|
|
27
|
+
program.command('teams', 'Interact with Microsoft Teams', {
|
|
28
|
+
executableFile: join(__dirname, 'platforms', 'teams', 'cli.ts'),
|
|
29
|
+
})
|
|
30
|
+
|
|
27
31
|
program.parse(process.argv)
|
|
28
32
|
|
|
29
33
|
export default program
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises'
|
|
1
2
|
import type {
|
|
2
3
|
DiscordChannel,
|
|
3
4
|
DiscordFile,
|
|
@@ -243,12 +244,11 @@ export class DiscordClient {
|
|
|
243
244
|
}
|
|
244
245
|
|
|
245
246
|
async uploadFile(channelId: string, filePath: string): Promise<DiscordFile> {
|
|
246
|
-
const
|
|
247
|
+
const fileBuffer = await readFile(filePath)
|
|
247
248
|
const filename = filePath.split('/').pop() || 'file'
|
|
248
|
-
const blob = await file.arrayBuffer()
|
|
249
249
|
|
|
250
250
|
const formData = new FormData()
|
|
251
|
-
formData.append('files[0]', new Blob([
|
|
251
|
+
formData.append('files[0]', new Blob([fileBuffer]), filename)
|
|
252
252
|
|
|
253
253
|
interface MessageWithAttachments extends DiscordMessage {
|
|
254
254
|
attachments: DiscordFile[]
|