teams-api-mcp 0.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/LICENSE +21 -0
- package/README.md +406 -0
- package/SKILL.md +130 -0
- package/dist/actions.d.ts +49 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +842 -0
- package/dist/actions.js.map +1 -0
- package/dist/api.d.ts +111 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +630 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.d.ts +53 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +479 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +13 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +178 -0
- package/dist/cli.js.map +1 -0
- package/dist/mcp-server.d.ts +35 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +144 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/teams-client.d.ts +197 -0
- package/dist/teams-client.d.ts.map +1 -0
- package/dist/teams-client.js +545 -0
- package/dist/teams-client.js.map +1 -0
- package/dist/token-store.d.ts +14 -0
- package/dist/token-store.d.ts.map +1 -0
- package/dist/token-store.js +79 -0
- package/dist/token-store.js.map +1 -0
- package/dist/types.d.ts +245 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/package.json +69 -0
package/dist/api.js
ADDED
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Low-level REST API layer for Teams Chat Service.
|
|
4
|
+
*
|
|
5
|
+
* All HTTP calls to {region}.ng.msg.teams.microsoft.com/v1 are here.
|
|
6
|
+
* This module is stateless — every function takes a TeamsToken explicitly.
|
|
7
|
+
*
|
|
8
|
+
* Higher-level orchestration (pagination, search) lives in teams-client.ts.
|
|
9
|
+
*/
|
|
10
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
11
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.ApiRateLimitError = exports.ApiAuthError = void 0;
|
|
15
|
+
exports.fetchConversations = fetchConversations;
|
|
16
|
+
exports.fetchMessagesPage = fetchMessagesPage;
|
|
17
|
+
exports.fetchMembers = fetchMembers;
|
|
18
|
+
exports.fetchProfiles = fetchProfiles;
|
|
19
|
+
exports.postMessage = postMessage;
|
|
20
|
+
exports.fetchUserProperties = fetchUserProperties;
|
|
21
|
+
exports.parseRawMessage = parseRawMessage;
|
|
22
|
+
exports.extractTranscriptUrl = extractTranscriptUrl;
|
|
23
|
+
exports.extractMeetingTitle = extractMeetingTitle;
|
|
24
|
+
exports.isSuccessfulRecording = isSuccessfulRecording;
|
|
25
|
+
exports.parseVtt = parseVtt;
|
|
26
|
+
exports.fetchTranscriptVtt = fetchTranscriptVtt;
|
|
27
|
+
exports.fetchTranscript = fetchTranscript;
|
|
28
|
+
exports.searchPeople = searchPeople;
|
|
29
|
+
exports.searchChats = searchChats;
|
|
30
|
+
const markdown_it_1 = __importDefault(require("markdown-it"));
|
|
31
|
+
const markdownRenderer = new markdown_it_1.default({ html: true, breaks: true });
|
|
32
|
+
class ApiAuthError extends Error {
|
|
33
|
+
constructor(message) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.name = "ApiAuthError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.ApiAuthError = ApiAuthError;
|
|
39
|
+
class ApiRateLimitError extends Error {
|
|
40
|
+
retryAfterMilliseconds;
|
|
41
|
+
constructor(message, retryAfterMilliseconds) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = "ApiRateLimitError";
|
|
44
|
+
this.retryAfterMilliseconds = retryAfterMilliseconds;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.ApiRateLimitError = ApiRateLimitError;
|
|
48
|
+
const MAX_RETRY_ATTEMPTS = 5;
|
|
49
|
+
const INITIAL_BACKOFF_MILLISECONDS = 2_000;
|
|
50
|
+
function parseRetryAfter(response) {
|
|
51
|
+
const retryAfterHeader = response.headers.get("Retry-After");
|
|
52
|
+
if (!retryAfterHeader) {
|
|
53
|
+
return INITIAL_BACKOFF_MILLISECONDS;
|
|
54
|
+
}
|
|
55
|
+
const seconds = Number(retryAfterHeader);
|
|
56
|
+
if (!Number.isNaN(seconds) && seconds > 0) {
|
|
57
|
+
return seconds * 1_000;
|
|
58
|
+
}
|
|
59
|
+
return INITIAL_BACKOFF_MILLISECONDS;
|
|
60
|
+
}
|
|
61
|
+
function delay(milliseconds) {
|
|
62
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Wrapper around `fetch` that automatically retries on 429 (rate limit) responses.
|
|
66
|
+
*
|
|
67
|
+
* Uses the `Retry-After` header when present; otherwise applies exponential backoff
|
|
68
|
+
* starting at 2 seconds. Retries up to 5 times before throwing `ApiRateLimitError`.
|
|
69
|
+
*/
|
|
70
|
+
async function fetchWithRetry(input, init) {
|
|
71
|
+
for (let attempt = 0; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
|
|
72
|
+
const response = await fetch(input, init);
|
|
73
|
+
if (response.status !== 429) {
|
|
74
|
+
return response;
|
|
75
|
+
}
|
|
76
|
+
if (attempt === MAX_RETRY_ATTEMPTS) {
|
|
77
|
+
const errorText = await response.text();
|
|
78
|
+
throw new ApiRateLimitError(`Rate limit exceeded after ${MAX_RETRY_ATTEMPTS + 1} attempts: ${response.status} ${errorText}`, parseRetryAfter(response));
|
|
79
|
+
}
|
|
80
|
+
const retryAfterMilliseconds = parseRetryAfter(response);
|
|
81
|
+
const backoffMilliseconds = retryAfterMilliseconds * Math.pow(2, attempt);
|
|
82
|
+
await delay(backoffMilliseconds);
|
|
83
|
+
}
|
|
84
|
+
throw new Error("Unreachable: fetchWithRetry loop exited unexpectedly");
|
|
85
|
+
}
|
|
86
|
+
const chatServiceBase = (region) => `https://${region}.ng.msg.teams.microsoft.com/v1`;
|
|
87
|
+
function authHeaders(token) {
|
|
88
|
+
return {
|
|
89
|
+
Authentication: `skypetoken=${token.skypeToken}`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Fetch conversations from the Teams Chat Service.
|
|
94
|
+
* Returns one page of conversations (no built-in pagination).
|
|
95
|
+
*/
|
|
96
|
+
async function fetchConversations(token, pageSize) {
|
|
97
|
+
const url = `${chatServiceBase(token.region)}/users/ME/conversations?view=mychats&pageSize=${pageSize}`;
|
|
98
|
+
const response = await fetchWithRetry(url, { headers: authHeaders(token) });
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
if (response.status === 401) {
|
|
101
|
+
throw new ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
|
|
102
|
+
}
|
|
103
|
+
throw new Error(`Failed to fetch conversations: ${response.status} ${response.statusText}`);
|
|
104
|
+
}
|
|
105
|
+
const data = (await response.json());
|
|
106
|
+
return (data.conversations ?? []).map((conversation) => ({
|
|
107
|
+
id: conversation.id,
|
|
108
|
+
topic: conversation.threadProperties?.topic ??
|
|
109
|
+
conversation.properties?.displayName ??
|
|
110
|
+
"",
|
|
111
|
+
threadType: conversation.threadProperties?.threadType ?? "chat",
|
|
112
|
+
version: conversation.version,
|
|
113
|
+
lastMessageTime: conversation.properties?.lastimreceivedtime ?? null,
|
|
114
|
+
memberCount: conversation.threadProperties?.memberCount
|
|
115
|
+
? Number(conversation.threadProperties.memberCount)
|
|
116
|
+
: null,
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Fetch one page of messages from a conversation.
|
|
121
|
+
*/
|
|
122
|
+
async function fetchMessagesPage(token, conversationId, pageSize, backwardLink) {
|
|
123
|
+
const url = backwardLink ??
|
|
124
|
+
`${chatServiceBase(token.region)}/users/ME/conversations/${encodeURIComponent(conversationId)}/messages?pageSize=${pageSize}`;
|
|
125
|
+
const response = await fetchWithRetry(url, { headers: authHeaders(token) });
|
|
126
|
+
if (!response.ok) {
|
|
127
|
+
if (response.status === 401) {
|
|
128
|
+
throw new ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
|
|
129
|
+
}
|
|
130
|
+
throw new Error(`Failed to fetch messages: ${response.status} ${response.statusText}`);
|
|
131
|
+
}
|
|
132
|
+
const data = (await response.json());
|
|
133
|
+
const messages = (data.messages ?? []).map(parseRawMessage);
|
|
134
|
+
return {
|
|
135
|
+
messages,
|
|
136
|
+
backwardLink: data._metadata?.backwardLink ?? null,
|
|
137
|
+
syncState: data._metadata?.syncState ?? null,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Fetch members of a conversation.
|
|
142
|
+
*/
|
|
143
|
+
async function fetchMembers(token, conversationId) {
|
|
144
|
+
const url = `${chatServiceBase(token.region)}/threads/${encodeURIComponent(conversationId)}/members`;
|
|
145
|
+
const response = await fetchWithRetry(url, { headers: authHeaders(token) });
|
|
146
|
+
if (!response.ok) {
|
|
147
|
+
if (response.status === 401) {
|
|
148
|
+
throw new ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
|
|
149
|
+
}
|
|
150
|
+
throw new Error(`Failed to fetch members: ${response.status} ${response.statusText}`);
|
|
151
|
+
}
|
|
152
|
+
const data = (await response.json());
|
|
153
|
+
return (data.members ?? []).map((member) => ({
|
|
154
|
+
id: member.id,
|
|
155
|
+
displayName: member.userDisplayName ?? "",
|
|
156
|
+
role: member.role ?? "member",
|
|
157
|
+
memberType: member.id.startsWith("28:")
|
|
158
|
+
? "bot"
|
|
159
|
+
: "person",
|
|
160
|
+
}));
|
|
161
|
+
}
|
|
162
|
+
const MIDDLE_TIER_BASE = "https://teams.cloud.microsoft/api/mt";
|
|
163
|
+
/**
|
|
164
|
+
* Resolve display names for a batch of MRIs via the Teams middle-tier profile endpoint.
|
|
165
|
+
*
|
|
166
|
+
* Requires a Bearer token (api.spaces.skype.com audience). Returns an empty array
|
|
167
|
+
* if the token is unavailable or the request fails.
|
|
168
|
+
*/
|
|
169
|
+
async function fetchProfiles(token, mris) {
|
|
170
|
+
if (!token.bearerToken || mris.length === 0) {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
const url = `${MIDDLE_TIER_BASE}/${token.region}/beta/users/fetchShortProfile?isMailAddress=false&enableGuest=true&skypeTeamsInfo=true`;
|
|
174
|
+
const response = await fetchWithRetry(url, {
|
|
175
|
+
method: "POST",
|
|
176
|
+
headers: {
|
|
177
|
+
"Content-Type": "application/json",
|
|
178
|
+
Authorization: `Bearer ${token.bearerToken}`,
|
|
179
|
+
},
|
|
180
|
+
body: JSON.stringify(mris),
|
|
181
|
+
});
|
|
182
|
+
if (!response.ok) {
|
|
183
|
+
if (response.status === 401) {
|
|
184
|
+
throw new ApiAuthError(`Profile resolution authentication failed: ${response.status} ${response.statusText}`);
|
|
185
|
+
}
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
const data = (await response.json());
|
|
189
|
+
return (data.value ?? []).map((profile) => ({
|
|
190
|
+
mri: profile.mri ?? "",
|
|
191
|
+
displayName: profile.displayName ?? "",
|
|
192
|
+
email: profile.email ?? "",
|
|
193
|
+
jobTitle: profile.jobTitle ?? "",
|
|
194
|
+
userType: profile.userType ?? "",
|
|
195
|
+
}));
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Convert content to the appropriate format for the Teams API.
|
|
199
|
+
*
|
|
200
|
+
* - "text": sent as-is with messagetype "Text"
|
|
201
|
+
* - "markdown": converted from Markdown to HTML, sent as "RichText/Html"
|
|
202
|
+
* - "html": sent as-is with messagetype "RichText/Html"
|
|
203
|
+
*/
|
|
204
|
+
function resolveMessageContent(content, format) {
|
|
205
|
+
switch (format) {
|
|
206
|
+
case "text":
|
|
207
|
+
return {
|
|
208
|
+
resolvedContent: content,
|
|
209
|
+
messagetype: "Text",
|
|
210
|
+
contenttype: "text",
|
|
211
|
+
};
|
|
212
|
+
case "html":
|
|
213
|
+
return {
|
|
214
|
+
resolvedContent: content,
|
|
215
|
+
messagetype: "RichText/Html",
|
|
216
|
+
contenttype: "text",
|
|
217
|
+
};
|
|
218
|
+
case "markdown": {
|
|
219
|
+
const htmlContent = markdownRenderer.render(content);
|
|
220
|
+
return {
|
|
221
|
+
resolvedContent: htmlContent,
|
|
222
|
+
messagetype: "RichText/Html",
|
|
223
|
+
contenttype: "text",
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Send a message to a conversation.
|
|
230
|
+
*
|
|
231
|
+
* The `format` parameter controls how `content` is interpreted:
|
|
232
|
+
* - `"text"` — plain text, sent as-is
|
|
233
|
+
* - `"markdown"` (default) — converted from Markdown to HTML
|
|
234
|
+
* - `"html"` — raw HTML, sent as-is
|
|
235
|
+
*/
|
|
236
|
+
async function postMessage(token, conversationId, content, senderDisplayName, format = "markdown") {
|
|
237
|
+
const url = `${chatServiceBase(token.region)}/users/ME/conversations/${encodeURIComponent(conversationId)}/messages`;
|
|
238
|
+
const clientMessageId = String(Date.now());
|
|
239
|
+
const { resolvedContent, messagetype, contenttype } = resolveMessageContent(content, format);
|
|
240
|
+
const body = {
|
|
241
|
+
content: resolvedContent,
|
|
242
|
+
messagetype,
|
|
243
|
+
contenttype,
|
|
244
|
+
clientmessageid: clientMessageId,
|
|
245
|
+
imdisplayname: senderDisplayName,
|
|
246
|
+
properties: {
|
|
247
|
+
importance: "",
|
|
248
|
+
subject: null,
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
const response = await fetchWithRetry(url, {
|
|
252
|
+
method: "POST",
|
|
253
|
+
headers: {
|
|
254
|
+
...authHeaders(token),
|
|
255
|
+
"Content-Type": "application/json",
|
|
256
|
+
},
|
|
257
|
+
body: JSON.stringify(body),
|
|
258
|
+
});
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
if (response.status === 401) {
|
|
261
|
+
throw new ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
|
|
262
|
+
}
|
|
263
|
+
const errorText = await response.text();
|
|
264
|
+
throw new Error(`Failed to send message: ${response.status} ${response.statusText} — ${errorText}`);
|
|
265
|
+
}
|
|
266
|
+
const data = (await response.json());
|
|
267
|
+
return {
|
|
268
|
+
messageId: data.id ?? clientMessageId,
|
|
269
|
+
arrivalTime: data.OriginalArrivalTime,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Fetch user properties for the authenticated user.
|
|
274
|
+
* Returns raw properties — display name may or may not be present.
|
|
275
|
+
*/
|
|
276
|
+
async function fetchUserProperties(token) {
|
|
277
|
+
const url = `${chatServiceBase(token.region)}/users/ME/properties`;
|
|
278
|
+
const response = await fetchWithRetry(url, { headers: authHeaders(token) });
|
|
279
|
+
if (!response.ok) {
|
|
280
|
+
if (response.status === 401) {
|
|
281
|
+
throw new ApiAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
|
|
282
|
+
}
|
|
283
|
+
throw new Error(`Failed to fetch user properties: ${response.status} ${response.statusText}`);
|
|
284
|
+
}
|
|
285
|
+
return (await response.json());
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Parse a raw API message object into the public Message type.
|
|
289
|
+
*/
|
|
290
|
+
function parseRawMessage(raw) {
|
|
291
|
+
const properties = (raw.properties ?? {});
|
|
292
|
+
const reactions = parseReactions(properties.emotions);
|
|
293
|
+
const mentions = parseMentions(properties.mentions);
|
|
294
|
+
let quotedMessageId = null;
|
|
295
|
+
const content = String(raw.content ?? "");
|
|
296
|
+
const quoteMatch = content.match(/itemtype="http:\/\/schema\.skype\.com\/Reply"\s+itemid="(\d+)"/);
|
|
297
|
+
if (quoteMatch) {
|
|
298
|
+
quotedMessageId = quoteMatch[1];
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
id: String(raw.id ?? ""),
|
|
302
|
+
messageType: String(raw.messagetype ?? ""),
|
|
303
|
+
senderMri: String(raw.from ?? ""),
|
|
304
|
+
senderDisplayName: String(raw.imdisplayname ?? ""),
|
|
305
|
+
content,
|
|
306
|
+
originalArrivalTime: String(raw.originalarrivaltime ?? ""),
|
|
307
|
+
composeTime: String(raw.composetime ?? ""),
|
|
308
|
+
editTime: properties.edittime ? String(properties.edittime) : null,
|
|
309
|
+
subject: properties.subject ? String(properties.subject) : null,
|
|
310
|
+
isDeleted: raw.messagetype === "MessageDelete" ||
|
|
311
|
+
String(properties.deletetime ?? "") !== "",
|
|
312
|
+
reactions,
|
|
313
|
+
mentions,
|
|
314
|
+
quotedMessageId,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function parseReactions(rawEmotions) {
|
|
318
|
+
if (typeof rawEmotions === "string") {
|
|
319
|
+
try {
|
|
320
|
+
return JSON.parse(rawEmotions);
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
return [];
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (Array.isArray(rawEmotions)) {
|
|
327
|
+
return rawEmotions;
|
|
328
|
+
}
|
|
329
|
+
return [];
|
|
330
|
+
}
|
|
331
|
+
function parseMentions(rawMentions) {
|
|
332
|
+
let parsed;
|
|
333
|
+
if (typeof rawMentions === "string") {
|
|
334
|
+
try {
|
|
335
|
+
parsed = JSON.parse(rawMentions);
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
return [];
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
else if (Array.isArray(rawMentions)) {
|
|
342
|
+
parsed = rawMentions;
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
return [];
|
|
346
|
+
}
|
|
347
|
+
return parsed.map((mention) => ({
|
|
348
|
+
id: mention.id ?? "",
|
|
349
|
+
displayName: mention.displayName ?? "",
|
|
350
|
+
}));
|
|
351
|
+
}
|
|
352
|
+
// ── Transcript helpers ────────────────────────────────────────────────
|
|
353
|
+
/**
|
|
354
|
+
* Extract the AMS transcript URL from a `RichText/Media_CallRecording` message.
|
|
355
|
+
*
|
|
356
|
+
* The message content is XML containing `<item type="amsTranscript" uri="...">`.
|
|
357
|
+
* Returns null if no transcript URL is found.
|
|
358
|
+
*/
|
|
359
|
+
function extractTranscriptUrl(messageContent) {
|
|
360
|
+
const match = messageContent.match(/<item\s+[^>]*type="amsTranscript"[^>]*\buri="([^"]+)"/);
|
|
361
|
+
return match?.[1] ?? null;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Extract the meeting title from a `RichText/Media_CallRecording` message.
|
|
365
|
+
*
|
|
366
|
+
* The title is in the `<OriginalName>` element inside the XML content.
|
|
367
|
+
*/
|
|
368
|
+
function extractMeetingTitle(messageContent) {
|
|
369
|
+
const match = messageContent.match(/<OriginalName\b[^>]*v="([^"]*)"[^>]*\/>/);
|
|
370
|
+
return match?.[1] ?? "Unknown Meeting";
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Check whether a `RichText/Media_CallRecording` message represents
|
|
374
|
+
* a successful recording (as opposed to started/failed).
|
|
375
|
+
*/
|
|
376
|
+
function isSuccessfulRecording(messageContent) {
|
|
377
|
+
return /<RecordingStatus\b[^>]*status="Success"/.test(messageContent);
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Decode HTML entities to plain text (used for VTT content).
|
|
381
|
+
*/
|
|
382
|
+
function decodeVttEntities(text) {
|
|
383
|
+
return text
|
|
384
|
+
.replace(/&/g, "&")
|
|
385
|
+
.replace(/</g, "<")
|
|
386
|
+
.replace(/>/g, ">")
|
|
387
|
+
.replace(/"/g, '"')
|
|
388
|
+
.replace(/&#(\d+);/g, (_, code) => String.fromCharCode(Number(code)));
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Parse VTT content into structured transcript entries.
|
|
392
|
+
*
|
|
393
|
+
* Handles the Teams VTT format with `<v Speaker Name>text</v>` tags
|
|
394
|
+
* and HTML entities.
|
|
395
|
+
*/
|
|
396
|
+
function parseVtt(vttContent) {
|
|
397
|
+
const entries = [];
|
|
398
|
+
const lines = vttContent.split("\n");
|
|
399
|
+
let currentStartTime = "";
|
|
400
|
+
let currentEndTime = "";
|
|
401
|
+
for (const line of lines) {
|
|
402
|
+
// Match timestamp lines: "00:00:00.000 --> 00:00:05.000"
|
|
403
|
+
const timestampMatch = line.match(/^(\d{2}:\d{2}:\d{2}\.\d{3})\s+-->\s+(\d{2}:\d{2}:\d{2}\.\d{3})/);
|
|
404
|
+
if (timestampMatch) {
|
|
405
|
+
currentStartTime = timestampMatch[1];
|
|
406
|
+
currentEndTime = timestampMatch[2];
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
// Match speaker lines: "<v Speaker Name>text</v>"
|
|
410
|
+
const speakerMatch = line.match(/^<v\s+([^>]+)>(.+)<\/v>\s*$/);
|
|
411
|
+
if (speakerMatch && currentStartTime) {
|
|
412
|
+
entries.push({
|
|
413
|
+
speaker: decodeVttEntities(speakerMatch[1]),
|
|
414
|
+
startTime: currentStartTime,
|
|
415
|
+
endTime: currentEndTime,
|
|
416
|
+
text: decodeVttEntities(speakerMatch[2]),
|
|
417
|
+
});
|
|
418
|
+
currentStartTime = "";
|
|
419
|
+
currentEndTime = "";
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return entries;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Fetch a transcript from the AMS (Async Media Service).
|
|
426
|
+
*
|
|
427
|
+
* Uses `Authorization: skype_token <token>` header (note: different format
|
|
428
|
+
* from the Chat Service `Authentication: skypetoken=<token>` header).
|
|
429
|
+
*/
|
|
430
|
+
async function fetchTranscriptVtt(token, amsTranscriptUrl) {
|
|
431
|
+
const response = await fetchWithRetry(amsTranscriptUrl, {
|
|
432
|
+
headers: {
|
|
433
|
+
Authorization: `skype_token ${token.skypeToken}`,
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
if (!response.ok) {
|
|
437
|
+
if (response.status === 401) {
|
|
438
|
+
throw new ApiAuthError(`Transcript fetch authentication failed: ${response.status} ${response.statusText}`);
|
|
439
|
+
}
|
|
440
|
+
throw new Error(`Failed to fetch transcript: ${response.status} ${response.statusText}`);
|
|
441
|
+
}
|
|
442
|
+
return response.text();
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Fetch and parse the transcript for a conversation.
|
|
446
|
+
*
|
|
447
|
+
* 1. Fetches messages from the conversation
|
|
448
|
+
* 2. Finds the latest `RichText/Media_CallRecording` message with status="Success"
|
|
449
|
+
* 3. Extracts the AMS transcript URL from the XML content
|
|
450
|
+
* 4. Fetches the VTT content from AMS
|
|
451
|
+
* 5. Parses the VTT into structured entries
|
|
452
|
+
*/
|
|
453
|
+
async function fetchTranscript(token, conversationId) {
|
|
454
|
+
// Fetch messages to find the recording message
|
|
455
|
+
const pageSize = 200;
|
|
456
|
+
const maxPages = 20;
|
|
457
|
+
let backwardLink;
|
|
458
|
+
let amsTranscriptUrl = null;
|
|
459
|
+
let meetingTitle = "Unknown Meeting";
|
|
460
|
+
for (let pageIndex = 0; pageIndex < maxPages; pageIndex++) {
|
|
461
|
+
const page = await fetchMessagesPage(token, conversationId, pageSize, backwardLink);
|
|
462
|
+
for (const message of page.messages) {
|
|
463
|
+
if (message.messageType === "RichText/Media_CallRecording" &&
|
|
464
|
+
isSuccessfulRecording(message.content)) {
|
|
465
|
+
const transcriptUrl = extractTranscriptUrl(message.content);
|
|
466
|
+
if (transcriptUrl) {
|
|
467
|
+
amsTranscriptUrl = transcriptUrl;
|
|
468
|
+
meetingTitle = extractMeetingTitle(message.content);
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (amsTranscriptUrl || !page.backwardLink)
|
|
474
|
+
break;
|
|
475
|
+
backwardLink = page.backwardLink;
|
|
476
|
+
}
|
|
477
|
+
if (!amsTranscriptUrl) {
|
|
478
|
+
throw new Error("No meeting transcript found in this conversation. " +
|
|
479
|
+
"Make sure the conversation contains a recorded meeting with a transcript.");
|
|
480
|
+
}
|
|
481
|
+
const rawVtt = await fetchTranscriptVtt(token, amsTranscriptUrl);
|
|
482
|
+
const entries = parseVtt(rawVtt);
|
|
483
|
+
return { meetingTitle, rawVtt, entries };
|
|
484
|
+
}
|
|
485
|
+
// ── Substrate search API ──────────────────────────────────────────────
|
|
486
|
+
const SUBSTRATE_SEARCH_BASE = "https://substrate.office.com";
|
|
487
|
+
/**
|
|
488
|
+
* Search for people by name using the Substrate suggestions API.
|
|
489
|
+
*
|
|
490
|
+
* Requires a Substrate Bearer token (substrate.office.com audience).
|
|
491
|
+
* Returns matching people with their MRIs, emails, job titles, etc.
|
|
492
|
+
*/
|
|
493
|
+
async function searchPeople(token, query, maxResults = 10) {
|
|
494
|
+
if (!token.substrateToken) {
|
|
495
|
+
return [];
|
|
496
|
+
}
|
|
497
|
+
const url = `${SUBSTRATE_SEARCH_BASE}/search/api/v1/suggestions?scenario=peoplepicker.newChat`;
|
|
498
|
+
const body = {
|
|
499
|
+
EntityRequests: [
|
|
500
|
+
{
|
|
501
|
+
Query: {
|
|
502
|
+
QueryString: query,
|
|
503
|
+
DisplayQueryString: query,
|
|
504
|
+
},
|
|
505
|
+
EntityType: "People",
|
|
506
|
+
Size: maxResults,
|
|
507
|
+
Fields: [
|
|
508
|
+
"Id",
|
|
509
|
+
"MRI",
|
|
510
|
+
"DisplayName",
|
|
511
|
+
"EmailAddresses",
|
|
512
|
+
"PeopleType",
|
|
513
|
+
"PeopleSubtype",
|
|
514
|
+
"UserPrincipalName",
|
|
515
|
+
"GivenName",
|
|
516
|
+
"Surname",
|
|
517
|
+
"JobTitle",
|
|
518
|
+
"Department",
|
|
519
|
+
"ExternalDirectoryObjectId",
|
|
520
|
+
],
|
|
521
|
+
Filter: {
|
|
522
|
+
And: [
|
|
523
|
+
{
|
|
524
|
+
Or: [
|
|
525
|
+
{ Term: { PeopleType: "Person" } },
|
|
526
|
+
{ Term: { PeopleType: "Other" } },
|
|
527
|
+
],
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
Or: [
|
|
531
|
+
{ Term: { PeopleSubtype: "OrganizationUser" } },
|
|
532
|
+
{ Term: { PeopleSubtype: "MTOUser" } },
|
|
533
|
+
{ Term: { PeopleSubtype: "Guest" } },
|
|
534
|
+
],
|
|
535
|
+
},
|
|
536
|
+
{ Or: [{ Term: { Flags: "NonHidden" } }] },
|
|
537
|
+
],
|
|
538
|
+
},
|
|
539
|
+
Provenances: ["Mailbox", "Directory"],
|
|
540
|
+
From: 0,
|
|
541
|
+
},
|
|
542
|
+
],
|
|
543
|
+
Scenario: { Name: "peoplepicker.newChat" },
|
|
544
|
+
AppName: "Microsoft Teams",
|
|
545
|
+
};
|
|
546
|
+
const response = await fetchWithRetry(url, {
|
|
547
|
+
method: "POST",
|
|
548
|
+
headers: {
|
|
549
|
+
"Content-Type": "application/json",
|
|
550
|
+
Authorization: `Bearer ${token.substrateToken}`,
|
|
551
|
+
},
|
|
552
|
+
body: JSON.stringify(body),
|
|
553
|
+
});
|
|
554
|
+
if (!response.ok) {
|
|
555
|
+
if (response.status === 401) {
|
|
556
|
+
throw new ApiAuthError(`Substrate search authentication failed: ${response.status} ${response.statusText}`);
|
|
557
|
+
}
|
|
558
|
+
return [];
|
|
559
|
+
}
|
|
560
|
+
const data = (await response.json());
|
|
561
|
+
const peopleGroup = data.Groups?.find((group) => group.Type === "People");
|
|
562
|
+
if (!peopleGroup?.Suggestions)
|
|
563
|
+
return [];
|
|
564
|
+
return peopleGroup.Suggestions.map((suggestion) => ({
|
|
565
|
+
displayName: suggestion.DisplayName ?? "",
|
|
566
|
+
mri: suggestion.MRI ?? "",
|
|
567
|
+
email: suggestion.EmailAddresses?.[0] ?? suggestion.UserPrincipalName ?? "",
|
|
568
|
+
jobTitle: suggestion.JobTitle ?? "",
|
|
569
|
+
department: suggestion.Department ?? "",
|
|
570
|
+
objectId: suggestion.ExternalDirectoryObjectId ?? "",
|
|
571
|
+
}));
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Search for chats by name or member using the Substrate suggestions API.
|
|
575
|
+
*
|
|
576
|
+
* Requires a Substrate Bearer token (substrate.office.com audience).
|
|
577
|
+
* Returns matching chats with their thread IDs, members, etc.
|
|
578
|
+
*/
|
|
579
|
+
async function searchChats(token, query, maxResults = 10) {
|
|
580
|
+
if (!token.substrateToken) {
|
|
581
|
+
return [];
|
|
582
|
+
}
|
|
583
|
+
const url = `${SUBSTRATE_SEARCH_BASE}/search/api/v1/suggestions?scenario=peoplepicker.newChat`;
|
|
584
|
+
const body = {
|
|
585
|
+
EntityRequests: [
|
|
586
|
+
{
|
|
587
|
+
Query: {
|
|
588
|
+
QueryString: query,
|
|
589
|
+
},
|
|
590
|
+
EntityType: "Chat",
|
|
591
|
+
Size: maxResults,
|
|
592
|
+
},
|
|
593
|
+
],
|
|
594
|
+
Scenario: { Name: "peoplepicker.newChat" },
|
|
595
|
+
AppName: "Microsoft Teams",
|
|
596
|
+
};
|
|
597
|
+
const response = await fetchWithRetry(url, {
|
|
598
|
+
method: "POST",
|
|
599
|
+
headers: {
|
|
600
|
+
"Content-Type": "application/json",
|
|
601
|
+
Authorization: `Bearer ${token.substrateToken}`,
|
|
602
|
+
},
|
|
603
|
+
body: JSON.stringify(body),
|
|
604
|
+
});
|
|
605
|
+
if (!response.ok) {
|
|
606
|
+
if (response.status === 401) {
|
|
607
|
+
throw new ApiAuthError(`Substrate search authentication failed: ${response.status} ${response.statusText}`);
|
|
608
|
+
}
|
|
609
|
+
return [];
|
|
610
|
+
}
|
|
611
|
+
const data = (await response.json());
|
|
612
|
+
const chatGroup = data.Groups?.find((group) => group.Type === "Chat");
|
|
613
|
+
if (!chatGroup?.Suggestions)
|
|
614
|
+
return [];
|
|
615
|
+
return chatGroup.Suggestions.map((suggestion) => ({
|
|
616
|
+
name: suggestion.Name ?? "",
|
|
617
|
+
threadId: suggestion.ThreadId ?? "",
|
|
618
|
+
threadType: suggestion.ThreadType ?? "",
|
|
619
|
+
matchingMembers: (suggestion.MatchingMembers ?? []).map((member) => ({
|
|
620
|
+
displayName: member.DisplayName ?? "",
|
|
621
|
+
mri: member.MRI ?? "",
|
|
622
|
+
})),
|
|
623
|
+
chatMembers: (suggestion.ChatMembers ?? []).map((member) => ({
|
|
624
|
+
displayName: member.DisplayName ?? "",
|
|
625
|
+
mri: member.MRI ?? "",
|
|
626
|
+
})),
|
|
627
|
+
totalMemberCount: suggestion.TotalChatMembersCount ?? 0,
|
|
628
|
+
}));
|
|
629
|
+
}
|
|
630
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|