agent-messenger 2.8.0 → 2.10.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-plugin/plugin.json +1 -1
- package/README.md +0 -11
- package/dist/package.json +1 -1
- package/dist/src/platforms/channeltalk/commands/snapshot.d.ts +4 -2
- package/dist/src/platforms/channeltalk/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/channeltalk/commands/snapshot.js +86 -31
- package/dist/src/platforms/channeltalk/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/snapshot.d.ts +3 -1
- package/dist/src/platforms/channeltalkbot/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/channeltalkbot/commands/snapshot.js +110 -60
- package/dist/src/platforms/channeltalkbot/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/discord/commands/snapshot.d.ts +1 -0
- package/dist/src/platforms/discord/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/discord/commands/snapshot.js +48 -34
- package/dist/src/platforms/discord/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/discordbot/commands/snapshot.d.ts +2 -0
- package/dist/src/platforms/discordbot/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/discordbot/commands/snapshot.js +46 -34
- package/dist/src/platforms/discordbot/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/slack/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/slack/commands/snapshot.js +75 -55
- package/dist/src/platforms/slack/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/teams/client.d.ts +9 -1
- package/dist/src/platforms/teams/client.d.ts.map +1 -1
- package/dist/src/platforms/teams/client.js +69 -18
- package/dist/src/platforms/teams/client.js.map +1 -1
- package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/auth.js +7 -2
- package/dist/src/platforms/teams/commands/auth.js.map +1 -1
- package/dist/src/platforms/teams/commands/channel.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/channel.js +18 -3
- package/dist/src/platforms/teams/commands/channel.js.map +1 -1
- package/dist/src/platforms/teams/commands/file.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/file.js +18 -3
- package/dist/src/platforms/teams/commands/file.js.map +1 -1
- package/dist/src/platforms/teams/commands/message.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/message.js +24 -4
- package/dist/src/platforms/teams/commands/message.js.map +1 -1
- package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/reaction.js +12 -2
- package/dist/src/platforms/teams/commands/reaction.js.map +1 -1
- package/dist/src/platforms/teams/commands/snapshot.d.ts +1 -0
- package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/snapshot.js +50 -32
- package/dist/src/platforms/teams/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/teams/commands/team.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/team.js +6 -1
- package/dist/src/platforms/teams/commands/team.js.map +1 -1
- package/dist/src/platforms/teams/commands/user.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/user.js +18 -3
- package/dist/src/platforms/teams/commands/user.js.map +1 -1
- package/dist/src/platforms/teams/commands/whoami.d.ts.map +1 -1
- package/dist/src/platforms/teams/commands/whoami.js +6 -1
- package/dist/src/platforms/teams/commands/whoami.js.map +1 -1
- package/dist/src/platforms/teams/credential-manager.d.ts +3 -1
- package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/teams/credential-manager.js +6 -1
- package/dist/src/platforms/teams/credential-manager.js.map +1 -1
- package/dist/src/platforms/teams/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/teams/ensure-auth.js +7 -2
- package/dist/src/platforms/teams/ensure-auth.js.map +1 -1
- package/dist/src/platforms/teams/token-extractor.d.ts +3 -1
- package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/teams/token-extractor.js +67 -10
- package/dist/src/platforms/teams/token-extractor.js.map +1 -1
- package/dist/src/platforms/teams/types.d.ts +17 -0
- package/dist/src/platforms/teams/types.d.ts.map +1 -1
- package/dist/src/platforms/teams/types.js +2 -0
- package/dist/src/platforms/teams/types.js.map +1 -1
- package/dist/src/platforms/webex/client.d.ts +3 -0
- package/dist/src/platforms/webex/client.d.ts.map +1 -1
- package/dist/src/platforms/webex/client.js +58 -13
- package/dist/src/platforms/webex/client.js.map +1 -1
- package/dist/src/platforms/webex/commands/auth.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/auth.js +61 -10
- package/dist/src/platforms/webex/commands/auth.js.map +1 -1
- package/dist/src/platforms/webex/commands/snapshot.d.ts +1 -0
- package/dist/src/platforms/webex/commands/snapshot.d.ts.map +1 -1
- package/dist/src/platforms/webex/commands/snapshot.js +14 -7
- package/dist/src/platforms/webex/commands/snapshot.js.map +1 -1
- package/dist/src/platforms/webex/credential-manager.d.ts.map +1 -1
- package/dist/src/platforms/webex/credential-manager.js +18 -6
- package/dist/src/platforms/webex/credential-manager.js.map +1 -1
- package/dist/src/platforms/webex/encryption.d.ts.map +1 -1
- package/dist/src/platforms/webex/encryption.js +3 -1
- package/dist/src/platforms/webex/encryption.js.map +1 -1
- package/dist/src/platforms/webex/ensure-auth.d.ts.map +1 -1
- package/dist/src/platforms/webex/ensure-auth.js +10 -2
- package/dist/src/platforms/webex/ensure-auth.js.map +1 -1
- package/dist/src/platforms/webex/token-extractor.d.ts +1 -0
- package/dist/src/platforms/webex/token-extractor.d.ts.map +1 -1
- package/dist/src/platforms/webex/token-extractor.js +21 -4
- package/dist/src/platforms/webex/token-extractor.js.map +1 -1
- package/docs/content/docs/agent-skills.mdx +0 -10
- package/docs/content/docs/cli/channeltalk.mdx +18 -8
- package/docs/content/docs/cli/channeltalkbot.mdx +16 -6
- package/docs/content/docs/cli/discord.mdx +23 -7
- package/docs/content/docs/cli/discordbot.mdx +23 -7
- package/docs/content/docs/cli/slack.mdx +24 -7
- package/docs/content/docs/cli/teams.mdx +24 -8
- package/docs/content/docs/cli/webex.mdx +15 -2
- package/e2e/webex.e2e.test.ts +57 -0
- package/package.json +1 -1
- package/skills/agent-channeltalk/SKILL.md +19 -9
- package/skills/agent-channeltalk/references/common-patterns.md +10 -9
- package/skills/agent-channeltalkbot/SKILL.md +19 -9
- package/skills/agent-channeltalkbot/references/common-patterns.md +10 -9
- package/skills/agent-discord/SKILL.md +18 -9
- package/skills/agent-discord/references/common-patterns.md +8 -7
- package/skills/agent-discordbot/SKILL.md +18 -9
- package/skills/agent-instagram/SKILL.md +1 -1
- package/skills/agent-kakaotalk/SKILL.md +1 -1
- package/skills/agent-line/SKILL.md +1 -1
- package/skills/agent-slack/SKILL.md +19 -10
- package/skills/agent-slack/references/common-patterns.md +4 -7
- package/skills/agent-slackbot/SKILL.md +1 -1
- package/skills/agent-teams/SKILL.md +18 -9
- package/skills/agent-teams/references/common-patterns.md +9 -7
- package/skills/agent-telegram/SKILL.md +1 -1
- package/skills/agent-webex/SKILL.md +13 -4
- package/skills/agent-webex/references/common-patterns.md +8 -2
- package/skills/agent-wechatbot/SKILL.md +1 -1
- package/skills/agent-whatsapp/SKILL.md +1 -1
- package/skills/agent-whatsappbot/SKILL.md +1 -1
- package/src/platforms/channeltalk/commands/snapshot.test.ts +58 -26
- package/src/platforms/channeltalk/commands/snapshot.ts +107 -33
- package/src/platforms/channeltalkbot/commands/snapshot.test.ts +26 -8
- package/src/platforms/channeltalkbot/commands/snapshot.ts +131 -64
- package/src/platforms/discord/commands/snapshot.test.ts +1 -1
- package/src/platforms/discord/commands/snapshot.ts +58 -42
- package/src/platforms/discordbot/commands/snapshot.test.ts +40 -18
- package/src/platforms/discordbot/commands/snapshot.ts +54 -37
- package/src/platforms/slack/commands/snapshot.test.ts +63 -8
- package/src/platforms/slack/commands/snapshot.ts +98 -66
- package/src/platforms/teams/client.test.ts +34 -30
- package/src/platforms/teams/client.ts +92 -20
- package/src/platforms/teams/commands/auth.test.ts +6 -2
- package/src/platforms/teams/commands/auth.ts +7 -2
- package/src/platforms/teams/commands/channel.test.ts +6 -6
- package/src/platforms/teams/commands/channel.ts +18 -3
- package/src/platforms/teams/commands/file.ts +18 -3
- package/src/platforms/teams/commands/message.ts +24 -4
- package/src/platforms/teams/commands/reaction.ts +12 -2
- package/src/platforms/teams/commands/snapshot.test.ts +1 -1
- package/src/platforms/teams/commands/snapshot.ts +59 -39
- package/src/platforms/teams/commands/team.test.ts +2 -2
- package/src/platforms/teams/commands/team.ts +6 -1
- package/src/platforms/teams/commands/user.ts +18 -3
- package/src/platforms/teams/commands/whoami.ts +6 -1
- package/src/platforms/teams/credential-manager.test.ts +25 -0
- package/src/platforms/teams/credential-manager.ts +13 -3
- package/src/platforms/teams/ensure-auth.test.ts +6 -1
- package/src/platforms/teams/ensure-auth.ts +7 -2
- package/src/platforms/teams/token-extractor.ts +77 -12
- package/src/platforms/teams/types.test.ts +17 -0
- package/src/platforms/teams/types.ts +6 -0
- package/src/platforms/webex/client.test.ts +157 -13
- package/src/platforms/webex/client.ts +64 -15
- package/src/platforms/webex/commands/auth.test.ts +122 -1
- package/src/platforms/webex/commands/auth.ts +72 -17
- package/src/platforms/webex/commands/snapshot.test.ts +14 -1
- package/src/platforms/webex/commands/snapshot.ts +17 -9
- package/src/platforms/webex/credential-manager.test.ts +63 -0
- package/src/platforms/webex/credential-manager.ts +22 -8
- package/src/platforms/webex/encryption.test.ts +54 -0
- package/src/platforms/webex/encryption.ts +3 -1
- package/src/platforms/webex/ensure-auth.ts +10 -2
- package/src/platforms/webex/token-extractor.test.ts +32 -3
- package/src/platforms/webex/token-extractor.ts +26 -5
|
@@ -2,7 +2,15 @@ import { readFile } from 'node:fs/promises'
|
|
|
2
2
|
import { basename } from 'node:path'
|
|
3
3
|
|
|
4
4
|
import { TeamsCredentialManager } from './credential-manager'
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
TeamsAccountType,
|
|
7
|
+
TeamsChannel,
|
|
8
|
+
TeamsFile,
|
|
9
|
+
TeamsMessage,
|
|
10
|
+
TeamsRegion,
|
|
11
|
+
TeamsTeam,
|
|
12
|
+
TeamsUser,
|
|
13
|
+
} from './types'
|
|
6
14
|
import { TeamsError } from './types'
|
|
7
15
|
|
|
8
16
|
interface RateLimitBucket {
|
|
@@ -10,18 +18,28 @@ interface RateLimitBucket {
|
|
|
10
18
|
resetAt: number
|
|
11
19
|
}
|
|
12
20
|
|
|
13
|
-
const
|
|
21
|
+
const PERSONAL_MSG_API_BASE = 'https://msgapi.teams.live.com/v1'
|
|
14
22
|
const CSA_API_BASE = 'https://teams.microsoft.com/api'
|
|
15
23
|
const MAX_RETRIES = 3
|
|
16
24
|
const BASE_BACKOFF_MS = 100
|
|
25
|
+
const DEFAULT_REGION: TeamsRegion = 'amer'
|
|
26
|
+
const REGIONS: TeamsRegion[] = ['amer', 'emea', 'apac']
|
|
17
27
|
|
|
18
28
|
export class TeamsClient {
|
|
19
29
|
private token: string | null = null
|
|
20
30
|
private tokenExpiresAt?: Date
|
|
31
|
+
private isPersonalAccount: boolean = false
|
|
32
|
+
private region: TeamsRegion = DEFAULT_REGION
|
|
33
|
+
private regionDiscovered: boolean = false
|
|
21
34
|
private buckets: Map<string, RateLimitBucket> = new Map()
|
|
22
35
|
private globalRateLimitUntil: number = 0
|
|
23
36
|
|
|
24
|
-
async login(credentials?: {
|
|
37
|
+
async login(credentials?: {
|
|
38
|
+
token: string
|
|
39
|
+
tokenExpiresAt?: string
|
|
40
|
+
accountType?: TeamsAccountType
|
|
41
|
+
region?: TeamsRegion
|
|
42
|
+
}): Promise<this> {
|
|
25
43
|
if (credentials) {
|
|
26
44
|
if (!credentials.token) {
|
|
27
45
|
throw new TeamsError('Token is required', 'missing_token')
|
|
@@ -30,6 +48,11 @@ export class TeamsClient {
|
|
|
30
48
|
if (credentials.tokenExpiresAt) {
|
|
31
49
|
this.tokenExpiresAt = new Date(credentials.tokenExpiresAt)
|
|
32
50
|
}
|
|
51
|
+
this.isPersonalAccount = credentials.accountType === 'personal'
|
|
52
|
+
if (credentials.region) {
|
|
53
|
+
this.region = credentials.region
|
|
54
|
+
this.regionDiscovered = true
|
|
55
|
+
}
|
|
33
56
|
return this
|
|
34
57
|
}
|
|
35
58
|
|
|
@@ -43,7 +66,16 @@ export class TeamsClient {
|
|
|
43
66
|
'no_credentials',
|
|
44
67
|
)
|
|
45
68
|
}
|
|
46
|
-
return this.login({
|
|
69
|
+
return this.login({
|
|
70
|
+
token: creds.token,
|
|
71
|
+
tokenExpiresAt: creds.tokenExpiresAt,
|
|
72
|
+
accountType: creds.accountType,
|
|
73
|
+
region: creds.region,
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
getRegion(): TeamsRegion {
|
|
78
|
+
return this.region
|
|
47
79
|
}
|
|
48
80
|
|
|
49
81
|
private ensureAuth(): string {
|
|
@@ -108,12 +140,47 @@ export class TeamsClient {
|
|
|
108
140
|
return new Promise((resolve) => setTimeout(resolve, ms))
|
|
109
141
|
}
|
|
110
142
|
|
|
111
|
-
private
|
|
143
|
+
private getMsgApiBase(): string {
|
|
144
|
+
if (this.isPersonalAccount) return PERSONAL_MSG_API_BASE
|
|
145
|
+
return `https://${this.region}.ng.msg.teams.microsoft.com/v1`
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private async discoverRegion(): Promise<void> {
|
|
149
|
+
if (this.isPersonalAccount) {
|
|
150
|
+
this.regionDiscovered = true
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const token = this.ensureAuth()
|
|
155
|
+
|
|
156
|
+
for (const region of REGIONS) {
|
|
157
|
+
try {
|
|
158
|
+
const response = await fetch(`https://${region}.ng.msg.teams.microsoft.com/v1/users/ME/properties`, {
|
|
159
|
+
headers: {
|
|
160
|
+
'X-Skypetoken': token,
|
|
161
|
+
},
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
if (response.ok || response.status !== 403) {
|
|
165
|
+
this.region = region
|
|
166
|
+
break
|
|
167
|
+
}
|
|
168
|
+
} catch {}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
this.regionDiscovered = true
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private async request<T>(method: string, path: string, body?: unknown, baseUrl?: string): Promise<T> {
|
|
112
175
|
if (this.isTokenExpired()) {
|
|
113
176
|
throw new TeamsError('Token has expired. Run "auth extract" to refresh.', 'token_expired')
|
|
114
177
|
}
|
|
115
178
|
|
|
116
|
-
|
|
179
|
+
if (baseUrl === undefined && !this.regionDiscovered) {
|
|
180
|
+
await this.discoverRegion()
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const url = `${baseUrl ?? this.getMsgApiBase()}${path}`
|
|
117
184
|
const bucketKey = this.getBucketKey(method, path)
|
|
118
185
|
|
|
119
186
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
@@ -144,7 +211,7 @@ export class TeamsClient {
|
|
|
144
211
|
const errorBody = (await response.json().catch(() => null)) as {
|
|
145
212
|
message?: string
|
|
146
213
|
} | null
|
|
147
|
-
throw new TeamsError(errorBody?.message
|
|
214
|
+
throw new TeamsError(errorBody?.message || 'Rate limited', 'rate_limited')
|
|
148
215
|
}
|
|
149
216
|
|
|
150
217
|
if (response.status >= 500 && attempt < MAX_RETRIES) {
|
|
@@ -158,7 +225,7 @@ export class TeamsClient {
|
|
|
158
225
|
code?: string | number
|
|
159
226
|
} | null
|
|
160
227
|
throw new TeamsError(
|
|
161
|
-
errorBody?.message
|
|
228
|
+
errorBody?.message || `HTTP ${response.status}`,
|
|
162
229
|
errorBody?.code?.toString() ?? `http_${response.status}`,
|
|
163
230
|
)
|
|
164
231
|
}
|
|
@@ -173,12 +240,16 @@ export class TeamsClient {
|
|
|
173
240
|
throw new TeamsError('Request failed after retries', 'max_retries')
|
|
174
241
|
}
|
|
175
242
|
|
|
176
|
-
private async requestFormData<T>(path: string, formData: FormData, baseUrl
|
|
243
|
+
private async requestFormData<T>(path: string, formData: FormData, baseUrl?: string): Promise<T> {
|
|
177
244
|
if (this.isTokenExpired()) {
|
|
178
245
|
throw new TeamsError('Token has expired. Run "auth extract" to refresh.', 'token_expired')
|
|
179
246
|
}
|
|
180
247
|
|
|
181
|
-
|
|
248
|
+
if (baseUrl === undefined && !this.regionDiscovered) {
|
|
249
|
+
await this.discoverRegion()
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const url = `${baseUrl ?? this.getMsgApiBase()}${path}`
|
|
182
253
|
const bucketKey = this.getBucketKey('POST', path)
|
|
183
254
|
|
|
184
255
|
await this.waitForRateLimit(bucketKey)
|
|
@@ -199,7 +270,7 @@ export class TeamsClient {
|
|
|
199
270
|
code?: string | number
|
|
200
271
|
} | null
|
|
201
272
|
throw new TeamsError(
|
|
202
|
-
errorBody?.message
|
|
273
|
+
errorBody?.message || `HTTP ${response.status}`,
|
|
203
274
|
errorBody?.code?.toString() ?? `http_${response.status}`,
|
|
204
275
|
)
|
|
205
276
|
}
|
|
@@ -210,13 +281,14 @@ export class TeamsClient {
|
|
|
210
281
|
async testAuth(): Promise<TeamsUser> {
|
|
211
282
|
interface UserProperties {
|
|
212
283
|
userDetails?: string
|
|
284
|
+
primaryMemberName?: string
|
|
213
285
|
locale?: string
|
|
214
286
|
}
|
|
215
287
|
const props = await this.request<UserProperties>('GET', '/users/ME/properties')
|
|
216
288
|
const userDetails = props.userDetails ? JSON.parse(props.userDetails) : {}
|
|
217
289
|
return {
|
|
218
290
|
id: 'ME',
|
|
219
|
-
displayName: userDetails.name || 'Teams User',
|
|
291
|
+
displayName: userDetails.name || props.primaryMemberName || 'Teams User',
|
|
220
292
|
}
|
|
221
293
|
}
|
|
222
294
|
|
|
@@ -272,7 +344,7 @@ export class TeamsClient {
|
|
|
272
344
|
async sendMessage(teamId: string, channelId: string, content: string): Promise<TeamsMessage> {
|
|
273
345
|
return this.request<TeamsMessage>(
|
|
274
346
|
'POST',
|
|
275
|
-
`/csa/
|
|
347
|
+
`/csa/${this.region}/api/v2/teams/${teamId}/channels/${channelId}/messages`,
|
|
276
348
|
{ content },
|
|
277
349
|
CSA_API_BASE,
|
|
278
350
|
)
|
|
@@ -281,7 +353,7 @@ export class TeamsClient {
|
|
|
281
353
|
async getMessages(teamId: string, channelId: string, limit: number = 50): Promise<TeamsMessage[]> {
|
|
282
354
|
return this.request<TeamsMessage[]>(
|
|
283
355
|
'GET',
|
|
284
|
-
`/csa/
|
|
356
|
+
`/csa/${this.region}/api/v2/teams/${teamId}/channels/${channelId}/messages?limit=${limit}`,
|
|
285
357
|
undefined,
|
|
286
358
|
CSA_API_BASE,
|
|
287
359
|
)
|
|
@@ -290,7 +362,7 @@ export class TeamsClient {
|
|
|
290
362
|
async getMessage(teamId: string, channelId: string, messageId: string): Promise<TeamsMessage> {
|
|
291
363
|
return this.request<TeamsMessage>(
|
|
292
364
|
'GET',
|
|
293
|
-
`/csa/
|
|
365
|
+
`/csa/${this.region}/api/v2/teams/${teamId}/channels/${channelId}/messages/${messageId}`,
|
|
294
366
|
undefined,
|
|
295
367
|
CSA_API_BASE,
|
|
296
368
|
)
|
|
@@ -299,7 +371,7 @@ export class TeamsClient {
|
|
|
299
371
|
async deleteMessage(teamId: string, channelId: string, messageId: string): Promise<void> {
|
|
300
372
|
return this.request<void>(
|
|
301
373
|
'DELETE',
|
|
302
|
-
`/csa/
|
|
374
|
+
`/csa/${this.region}/api/v2/teams/${teamId}/channels/${channelId}/messages/${messageId}`,
|
|
303
375
|
undefined,
|
|
304
376
|
CSA_API_BASE,
|
|
305
377
|
)
|
|
@@ -308,7 +380,7 @@ export class TeamsClient {
|
|
|
308
380
|
async addReaction(teamId: string, channelId: string, messageId: string, emoji: string): Promise<void> {
|
|
309
381
|
return this.request<void>(
|
|
310
382
|
'POST',
|
|
311
|
-
`/csa/
|
|
383
|
+
`/csa/${this.region}/api/v2/teams/${teamId}/channels/${channelId}/messages/${messageId}/reactions`,
|
|
312
384
|
{ emoji },
|
|
313
385
|
CSA_API_BASE,
|
|
314
386
|
)
|
|
@@ -317,7 +389,7 @@ export class TeamsClient {
|
|
|
317
389
|
async removeReaction(teamId: string, channelId: string, messageId: string, emoji: string): Promise<void> {
|
|
318
390
|
return this.request<void>(
|
|
319
391
|
'DELETE',
|
|
320
|
-
`/csa/
|
|
392
|
+
`/csa/${this.region}/api/v2/teams/${teamId}/channels/${channelId}/messages/${messageId}/reactions/${emoji}`,
|
|
321
393
|
undefined,
|
|
322
394
|
CSA_API_BASE,
|
|
323
395
|
)
|
|
@@ -339,7 +411,7 @@ export class TeamsClient {
|
|
|
339
411
|
formData.append('file', new Blob([fileBuffer]), filename)
|
|
340
412
|
|
|
341
413
|
return this.requestFormData<TeamsFile>(
|
|
342
|
-
`/csa/
|
|
414
|
+
`/csa/${this.region}/api/v2/teams/${teamId}/channels/${channelId}/files`,
|
|
343
415
|
formData,
|
|
344
416
|
CSA_API_BASE,
|
|
345
417
|
)
|
|
@@ -348,7 +420,7 @@ export class TeamsClient {
|
|
|
348
420
|
async listFiles(teamId: string, channelId: string): Promise<TeamsFile[]> {
|
|
349
421
|
return this.request<TeamsFile[]>(
|
|
350
422
|
'GET',
|
|
351
|
-
`/csa/
|
|
423
|
+
`/csa/${this.region}/api/v2/teams/${teamId}/channels/${channelId}/files`,
|
|
352
424
|
undefined,
|
|
353
425
|
CSA_API_BASE,
|
|
354
426
|
)
|
|
@@ -12,6 +12,7 @@ let credManagerLoadConfigSpy: ReturnType<typeof spyOn>
|
|
|
12
12
|
let credManagerSaveConfigSpy: ReturnType<typeof spyOn>
|
|
13
13
|
let credManagerClearCredentialsSpy: ReturnType<typeof spyOn>
|
|
14
14
|
let credManagerIsTokenExpiredSpy: ReturnType<typeof spyOn>
|
|
15
|
+
let clientGetRegionSpy: ReturnType<typeof spyOn>
|
|
15
16
|
|
|
16
17
|
beforeEach(() => {
|
|
17
18
|
extractorExtractSpy = spyOn(TeamsTokenExtractor.prototype, 'extract').mockResolvedValue([
|
|
@@ -29,6 +30,8 @@ beforeEach(() => {
|
|
|
29
30
|
{ id: 'team-2', name: 'Team Two' },
|
|
30
31
|
])
|
|
31
32
|
|
|
33
|
+
clientGetRegionSpy = spyOn(TeamsClient.prototype, 'getRegion').mockReturnValue('emea')
|
|
34
|
+
|
|
32
35
|
credManagerLoadConfigSpy = spyOn(TeamsCredentialManager.prototype, 'loadConfig').mockResolvedValue(null)
|
|
33
36
|
|
|
34
37
|
credManagerSaveConfigSpy = spyOn(TeamsCredentialManager.prototype, 'saveConfig').mockResolvedValue(undefined)
|
|
@@ -48,6 +51,7 @@ afterEach(() => {
|
|
|
48
51
|
credManagerSaveConfigSpy?.mockRestore()
|
|
49
52
|
credManagerClearCredentialsSpy?.mockRestore()
|
|
50
53
|
credManagerIsTokenExpiredSpy?.mockRestore()
|
|
54
|
+
clientGetRegionSpy?.mockRestore()
|
|
51
55
|
})
|
|
52
56
|
|
|
53
57
|
test('extract: calls TeamsTokenExtractor', async () => {
|
|
@@ -59,7 +63,7 @@ test('extract: calls TeamsTokenExtractor', async () => {
|
|
|
59
63
|
})
|
|
60
64
|
|
|
61
65
|
test('extract: validates token with TeamsClient', async () => {
|
|
62
|
-
const client = await new TeamsClient().login({ token: 'test-skype-token-123' })
|
|
66
|
+
const client = await new TeamsClient().login({ token: 'test-skype-token-123', region: 'emea' })
|
|
63
67
|
const authInfo = await client.testAuth()
|
|
64
68
|
expect(authInfo).toBeDefined()
|
|
65
69
|
expect(authInfo.id).toBe('user-123')
|
|
@@ -67,7 +71,7 @@ test('extract: validates token with TeamsClient', async () => {
|
|
|
67
71
|
})
|
|
68
72
|
|
|
69
73
|
test('extract: discovers teams', async () => {
|
|
70
|
-
const client = await new TeamsClient().login({ token: 'test-skype-token-123' })
|
|
74
|
+
const client = await new TeamsClient().login({ token: 'test-skype-token-123', region: 'emea' })
|
|
71
75
|
const teams = await client.listTeams()
|
|
72
76
|
expect(teams).toHaveLength(2)
|
|
73
77
|
expect(teams[0].id).toBe('team-1')
|
|
@@ -16,7 +16,8 @@ export async function extractAction(options: { pretty?: boolean; debug?: boolean
|
|
|
16
16
|
return
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const
|
|
19
|
+
const debugLog = options.debug ? (msg: string) => debug(`[debug] ${msg}`) : undefined
|
|
20
|
+
const extractor = new TeamsTokenExtractor(undefined, undefined, debugLog)
|
|
20
21
|
|
|
21
22
|
if (process.platform === 'darwin') {
|
|
22
23
|
console.log('')
|
|
@@ -72,7 +73,7 @@ export async function extractAction(options: { pretty?: boolean; debug?: boolean
|
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
try {
|
|
75
|
-
const client = await new TeamsClient().login({ token })
|
|
76
|
+
const client = await new TeamsClient().login({ token, accountType })
|
|
76
77
|
const authInfo = await client.testAuth()
|
|
77
78
|
const teams = await client.listTeams()
|
|
78
79
|
|
|
@@ -88,6 +89,7 @@ export async function extractAction(options: { pretty?: boolean; debug?: boolean
|
|
|
88
89
|
const account: TeamsAccount = {
|
|
89
90
|
token,
|
|
90
91
|
token_expires_at: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
|
|
92
|
+
region: client.getRegion(),
|
|
91
93
|
account_type: accountType,
|
|
92
94
|
user_name: authInfo.displayName,
|
|
93
95
|
current_team: teams[0]?.id ?? null,
|
|
@@ -191,6 +193,7 @@ async function extractManualToken(token: string, options: { pretty?: boolean; de
|
|
|
191
193
|
const account: TeamsAccount = {
|
|
192
194
|
token,
|
|
193
195
|
token_expires_at: new Date(Date.now() + 60 * 60 * 1000).toISOString(),
|
|
196
|
+
region: client.getRegion(),
|
|
194
197
|
account_type: accountType,
|
|
195
198
|
user_name: authInfo.displayName,
|
|
196
199
|
current_team: teams[0].id,
|
|
@@ -295,6 +298,8 @@ export async function statusAction(options: { pretty?: boolean }): Promise<void>
|
|
|
295
298
|
const client = await new TeamsClient().login({
|
|
296
299
|
token: account.token,
|
|
297
300
|
tokenExpiresAt: account.token_expires_at ?? undefined,
|
|
301
|
+
accountType: account.account_type,
|
|
302
|
+
region: account.region,
|
|
298
303
|
})
|
|
299
304
|
const authInfo = await client.testAuth()
|
|
300
305
|
displayName = authInfo.displayName
|
|
@@ -67,7 +67,7 @@ afterEach(() => {
|
|
|
67
67
|
|
|
68
68
|
test('list: returns channels from team', async () => {
|
|
69
69
|
// given
|
|
70
|
-
const client = await new TeamsClient().login({ token: 'test-token' })
|
|
70
|
+
const client = await new TeamsClient().login({ token: 'test-token', region: 'emea' })
|
|
71
71
|
|
|
72
72
|
// when
|
|
73
73
|
const channels = await client.listChannels('team-1')
|
|
@@ -80,7 +80,7 @@ test('list: returns channels from team', async () => {
|
|
|
80
80
|
|
|
81
81
|
test('list: includes channel metadata', async () => {
|
|
82
82
|
// given
|
|
83
|
-
const client = await new TeamsClient().login({ token: 'test-token' })
|
|
83
|
+
const client = await new TeamsClient().login({ token: 'test-token', region: 'emea' })
|
|
84
84
|
const channels = await client.listChannels('team-1')
|
|
85
85
|
|
|
86
86
|
// when
|
|
@@ -95,7 +95,7 @@ test('list: includes channel metadata', async () => {
|
|
|
95
95
|
|
|
96
96
|
test('info: returns channel details', async () => {
|
|
97
97
|
// given
|
|
98
|
-
const client = await new TeamsClient().login({ token: 'test-token' })
|
|
98
|
+
const client = await new TeamsClient().login({ token: 'test-token', region: 'emea' })
|
|
99
99
|
|
|
100
100
|
// when
|
|
101
101
|
const channel = await client.getChannel('team-1', 'ch-1')
|
|
@@ -108,7 +108,7 @@ test('info: returns channel details', async () => {
|
|
|
108
108
|
|
|
109
109
|
test('info: throws error for non-existent channel', async () => {
|
|
110
110
|
// given
|
|
111
|
-
const client = await new TeamsClient().login({ token: 'test-token' })
|
|
111
|
+
const client = await new TeamsClient().login({ token: 'test-token', region: 'emea' })
|
|
112
112
|
|
|
113
113
|
// when/then
|
|
114
114
|
try {
|
|
@@ -121,7 +121,7 @@ test('info: throws error for non-existent channel', async () => {
|
|
|
121
121
|
|
|
122
122
|
test('history: returns messages', async () => {
|
|
123
123
|
// given
|
|
124
|
-
const client = await new TeamsClient().login({ token: 'test-token' })
|
|
124
|
+
const client = await new TeamsClient().login({ token: 'test-token', region: 'emea' })
|
|
125
125
|
|
|
126
126
|
// when
|
|
127
127
|
const messages = await client.getMessages('team-1', 'ch-1', 50)
|
|
@@ -136,7 +136,7 @@ test('history: returns messages', async () => {
|
|
|
136
136
|
|
|
137
137
|
test('history: includes message metadata', async () => {
|
|
138
138
|
// given
|
|
139
|
-
const client = await new TeamsClient().login({ token: 'test-token' })
|
|
139
|
+
const client = await new TeamsClient().login({ token: 'test-token', region: 'emea' })
|
|
140
140
|
const messages = await client.getMessages('team-1', 'ch-1', 50)
|
|
141
141
|
|
|
142
142
|
// when
|
|
@@ -16,7 +16,12 @@ export async function listAction(teamId: string, options: { pretty?: boolean }):
|
|
|
16
16
|
process.exit(1)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const client = await new TeamsClient().login({
|
|
19
|
+
const client = await new TeamsClient().login({
|
|
20
|
+
token: cred.token,
|
|
21
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
22
|
+
accountType: cred.accountType,
|
|
23
|
+
region: cred.region,
|
|
24
|
+
})
|
|
20
25
|
const channels = await client.listChannels(teamId)
|
|
21
26
|
|
|
22
27
|
const output = channels.map((ch) => ({
|
|
@@ -42,7 +47,12 @@ export async function infoAction(teamId: string, channelId: string, options: { p
|
|
|
42
47
|
process.exit(1)
|
|
43
48
|
}
|
|
44
49
|
|
|
45
|
-
const client = await new TeamsClient().login({
|
|
50
|
+
const client = await new TeamsClient().login({
|
|
51
|
+
token: cred.token,
|
|
52
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
53
|
+
accountType: cred.accountType,
|
|
54
|
+
region: cred.region,
|
|
55
|
+
})
|
|
46
56
|
const channel = await client.getChannel(teamId, channelId)
|
|
47
57
|
|
|
48
58
|
const output = {
|
|
@@ -72,7 +82,12 @@ export async function historyAction(
|
|
|
72
82
|
process.exit(1)
|
|
73
83
|
}
|
|
74
84
|
|
|
75
|
-
const client = await new TeamsClient().login({
|
|
85
|
+
const client = await new TeamsClient().login({
|
|
86
|
+
token: cred.token,
|
|
87
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
88
|
+
accountType: cred.accountType,
|
|
89
|
+
region: cred.region,
|
|
90
|
+
})
|
|
76
91
|
const messages = await client.getMessages(teamId, channelId, options.limit || 50)
|
|
77
92
|
|
|
78
93
|
const output = messages.map((msg) => ({
|
|
@@ -24,7 +24,12 @@ export async function uploadAction(
|
|
|
24
24
|
process.exit(1)
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const client = await new TeamsClient().login({
|
|
27
|
+
const client = await new TeamsClient().login({
|
|
28
|
+
token: cred.token,
|
|
29
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
30
|
+
accountType: cred.accountType,
|
|
31
|
+
region: cred.region,
|
|
32
|
+
})
|
|
28
33
|
const filePath = resolve(path)
|
|
29
34
|
const file = await client.uploadFile(teamId, channelId, filePath)
|
|
30
35
|
|
|
@@ -52,7 +57,12 @@ export async function listAction(teamId: string, channelId: string, options: { p
|
|
|
52
57
|
process.exit(1)
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
const client = await new TeamsClient().login({
|
|
60
|
+
const client = await new TeamsClient().login({
|
|
61
|
+
token: cred.token,
|
|
62
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
63
|
+
accountType: cred.accountType,
|
|
64
|
+
region: cred.region,
|
|
65
|
+
})
|
|
56
66
|
const files = await client.listFiles(teamId, channelId)
|
|
57
67
|
|
|
58
68
|
const output = files.map((file: TeamsFile) => ({
|
|
@@ -84,7 +94,12 @@ export async function infoAction(
|
|
|
84
94
|
process.exit(1)
|
|
85
95
|
}
|
|
86
96
|
|
|
87
|
-
const client = await new TeamsClient().login({
|
|
97
|
+
const client = await new TeamsClient().login({
|
|
98
|
+
token: cred.token,
|
|
99
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
100
|
+
accountType: cred.accountType,
|
|
101
|
+
region: cred.region,
|
|
102
|
+
})
|
|
88
103
|
const files = await client.listFiles(teamId, channelId)
|
|
89
104
|
const fileData = files.find((f) => f.id === fileId)
|
|
90
105
|
|
|
@@ -22,7 +22,12 @@ export async function sendAction(
|
|
|
22
22
|
process.exit(1)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const client = await new TeamsClient().login({
|
|
25
|
+
const client = await new TeamsClient().login({
|
|
26
|
+
token: cred.token,
|
|
27
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
28
|
+
accountType: cred.accountType,
|
|
29
|
+
region: cred.region,
|
|
30
|
+
})
|
|
26
31
|
const message = await client.sendMessage(teamId, channelId, content)
|
|
27
32
|
|
|
28
33
|
const output = {
|
|
@@ -52,7 +57,12 @@ export async function listAction(
|
|
|
52
57
|
process.exit(1)
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
const client = await new TeamsClient().login({
|
|
60
|
+
const client = await new TeamsClient().login({
|
|
61
|
+
token: cred.token,
|
|
62
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
63
|
+
accountType: cred.accountType,
|
|
64
|
+
region: cred.region,
|
|
65
|
+
})
|
|
56
66
|
const limit = options.limit || 50
|
|
57
67
|
const messages = await client.getMessages(teamId, channelId, limit)
|
|
58
68
|
|
|
@@ -84,7 +94,12 @@ export async function getAction(
|
|
|
84
94
|
process.exit(1)
|
|
85
95
|
}
|
|
86
96
|
|
|
87
|
-
const client = await new TeamsClient().login({
|
|
97
|
+
const client = await new TeamsClient().login({
|
|
98
|
+
token: cred.token,
|
|
99
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
100
|
+
accountType: cred.accountType,
|
|
101
|
+
region: cred.region,
|
|
102
|
+
})
|
|
88
103
|
const message = await client.getMessage(teamId, channelId, messageId)
|
|
89
104
|
|
|
90
105
|
if (!message) {
|
|
@@ -125,7 +140,12 @@ export async function deleteAction(
|
|
|
125
140
|
process.exit(0)
|
|
126
141
|
}
|
|
127
142
|
|
|
128
|
-
const client = await new TeamsClient().login({
|
|
143
|
+
const client = await new TeamsClient().login({
|
|
144
|
+
token: cred.token,
|
|
145
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
146
|
+
accountType: cred.accountType,
|
|
147
|
+
region: cred.region,
|
|
148
|
+
})
|
|
129
149
|
await client.deleteMessage(teamId, channelId, messageId)
|
|
130
150
|
|
|
131
151
|
console.log(formatOutput({ deleted: messageId }, options.pretty))
|
|
@@ -23,7 +23,12 @@ export async function addAction(
|
|
|
23
23
|
return
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
const client = await new TeamsClient().login({
|
|
26
|
+
const client = await new TeamsClient().login({
|
|
27
|
+
token: cred.token,
|
|
28
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
29
|
+
accountType: cred.accountType,
|
|
30
|
+
region: cred.region,
|
|
31
|
+
})
|
|
27
32
|
await client.addReaction(teamId, channelId, messageId, emoji)
|
|
28
33
|
|
|
29
34
|
console.log(
|
|
@@ -60,7 +65,12 @@ export async function removeAction(
|
|
|
60
65
|
return
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
const client = await new TeamsClient().login({
|
|
68
|
+
const client = await new TeamsClient().login({
|
|
69
|
+
token: cred.token,
|
|
70
|
+
tokenExpiresAt: cred.tokenExpiresAt,
|
|
71
|
+
accountType: cred.accountType,
|
|
72
|
+
region: cred.region,
|
|
73
|
+
})
|
|
64
74
|
await client.removeReaction(teamId, channelId, messageId, emoji)
|
|
65
75
|
|
|
66
76
|
console.log(
|
|
@@ -8,7 +8,7 @@ test('snapshot: command is defined', () => {
|
|
|
8
8
|
})
|
|
9
9
|
|
|
10
10
|
test('snapshot: command has correct description', () => {
|
|
11
|
-
expect(snapshotCommand.description()).toContain('team
|
|
11
|
+
expect(snapshotCommand.description()).toContain('team overview')
|
|
12
12
|
})
|
|
13
13
|
|
|
14
14
|
test('snapshot: command has --channels-only option', () => {
|