fireflies-api 0.5.1 → 0.6.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.
Files changed (36) hide show
  1. package/dist/cli/index.cjs +1435 -217
  2. package/dist/cli/index.cjs.map +1 -1
  3. package/dist/cli/index.js +1436 -222
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/index.cjs +1372 -392
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.cts +462 -3
  8. package/dist/index.d.ts +462 -3
  9. package/dist/index.js +1357 -393
  10. package/dist/index.js.map +1 -1
  11. package/dist/middleware/express.cjs +459 -16
  12. package/dist/middleware/express.cjs.map +1 -1
  13. package/dist/middleware/express.d.cts +2 -2
  14. package/dist/middleware/express.d.ts +2 -2
  15. package/dist/middleware/express.js +459 -16
  16. package/dist/middleware/express.js.map +1 -1
  17. package/dist/middleware/fastify.cjs +459 -16
  18. package/dist/middleware/fastify.cjs.map +1 -1
  19. package/dist/middleware/fastify.d.cts +2 -2
  20. package/dist/middleware/fastify.d.ts +2 -2
  21. package/dist/middleware/fastify.js +459 -16
  22. package/dist/middleware/fastify.js.map +1 -1
  23. package/dist/middleware/hono.cjs +459 -16
  24. package/dist/middleware/hono.cjs.map +1 -1
  25. package/dist/middleware/hono.d.cts +2 -2
  26. package/dist/middleware/hono.d.ts +2 -2
  27. package/dist/middleware/hono.js +459 -16
  28. package/dist/middleware/hono.js.map +1 -1
  29. package/dist/templates/digest/compact.md +8 -0
  30. package/dist/templates/digest/default.md +44 -0
  31. package/dist/templates/digest/executive.md +22 -0
  32. package/dist/{types-CaHcwnKw.d.ts → types-BMzVSd6w.d.ts} +1 -1
  33. package/dist/{types-BX-3JcRI.d.cts → types-BeXRmVD7.d.cts} +1 -1
  34. package/dist/{types-DIPZmUl3.d.ts → types-D2XsCR5R.d.ts} +120 -1
  35. package/dist/{types-C_XxdRd1.d.cts → types-zVGqyFzP.d.cts} +120 -1
  36. package/package.json +6 -1
@@ -291,8 +291,8 @@ async function retry(fn, options) {
291
291
  if (attempt >= maxRetries || !shouldRetry(error, attempt)) {
292
292
  throw error;
293
293
  }
294
- const delay = calculateDelay(error, attempt, baseDelay, maxDelay);
295
- await sleep(delay);
294
+ const delay2 = calculateDelay(error, attempt, baseDelay, maxDelay);
295
+ await sleep(delay2);
296
296
  }
297
297
  }
298
298
  throw lastError;
@@ -441,9 +441,9 @@ var GraphQLClient = class {
441
441
  if (!this.rateLimitTracker || !this.rateLimitConfig?.throttle) {
442
442
  return;
443
443
  }
444
- const delay = this.rateLimitTracker.getThrottleDelay(this.rateLimitConfig.throttle);
445
- if (delay > 0) {
446
- await sleep2(delay);
444
+ const delay2 = this.rateLimitTracker.getThrottleDelay(this.rateLimitConfig.throttle);
445
+ if (delay2 > 0) {
446
+ await sleep2(delay2);
447
447
  }
448
448
  }
449
449
  /**
@@ -1097,6 +1097,46 @@ function buildAggregatedResult(items, transcriptsProcessed, transcriptsWithItems
1097
1097
  };
1098
1098
  }
1099
1099
 
1100
+ // src/helpers/batch.ts
1101
+ async function* batch(items, processor, options = {}) {
1102
+ const { delayMs = 100, handleRateLimit = true, maxRateLimitRetries = 3 } = options;
1103
+ let isFirst = true;
1104
+ for await (const item of items) {
1105
+ if (!isFirst && delayMs > 0) {
1106
+ await delay(delayMs);
1107
+ }
1108
+ isFirst = false;
1109
+ yield await processWithRetry(item, processor, {
1110
+ handleRateLimit,
1111
+ maxRateLimitRetries
1112
+ });
1113
+ }
1114
+ }
1115
+ async function processWithRetry(item, processor, options) {
1116
+ const { handleRateLimit, maxRateLimitRetries } = options;
1117
+ let retries = 0;
1118
+ while (true) {
1119
+ try {
1120
+ const result = await processor(item);
1121
+ return { item, result };
1122
+ } catch (err) {
1123
+ if (handleRateLimit && err instanceof RateLimitError && retries < maxRateLimitRetries) {
1124
+ const waitTime = err.retryAfter ?? 1e3;
1125
+ await delay(waitTime);
1126
+ retries++;
1127
+ continue;
1128
+ }
1129
+ return {
1130
+ item,
1131
+ error: err instanceof Error ? err : new Error(String(err))
1132
+ };
1133
+ }
1134
+ }
1135
+ }
1136
+ function delay(ms) {
1137
+ return new Promise((resolve) => setTimeout(resolve, ms));
1138
+ }
1139
+
1100
1140
  // src/helpers/domain-utils.ts
1101
1141
  function extractDomain(email) {
1102
1142
  const atIndex = email.indexOf("@");
@@ -1112,6 +1152,332 @@ function hasExternalParticipants(participants, internalDomain) {
1112
1152
  });
1113
1153
  }
1114
1154
 
1155
+ // src/helpers/markdown.ts
1156
+ var DEFAULT_OPTIONS2 = {
1157
+ includeMetadata: true,
1158
+ includeSummary: true,
1159
+ includeActionItems: true,
1160
+ actionItemFormat: "checkbox",
1161
+ includeTimestamps: false,
1162
+ speakerFormat: "bold",
1163
+ groupBySpeaker: true
1164
+ };
1165
+ async function transcriptToMarkdown(transcript, options = {}) {
1166
+ const opts = { ...DEFAULT_OPTIONS2, ...options };
1167
+ const sections = [];
1168
+ if (opts.includeMetadata) {
1169
+ sections.push(formatMetadata(transcript));
1170
+ }
1171
+ if (opts.includeSummary && transcript.summary) {
1172
+ sections.push(formatSummary(transcript.summary, opts));
1173
+ }
1174
+ if (transcript.sentences && transcript.sentences.length > 0) {
1175
+ sections.push(formatTranscript(transcript.sentences, opts));
1176
+ }
1177
+ const content = sections.join("\n\n---\n\n");
1178
+ await writeIfOutputPath(content, options.outputPath);
1179
+ return content;
1180
+ }
1181
+ function formatMetadata(transcript) {
1182
+ const lines = [`# ${transcript.title || "Untitled Meeting"}`];
1183
+ if (transcript.dateString) {
1184
+ lines.push(`
1185
+ **Date:** ${formatDate(transcript.dateString)}`);
1186
+ }
1187
+ const duration = calculateDuration(transcript);
1188
+ if (duration > 0) {
1189
+ lines.push(`**Duration:** ${formatDuration(duration)}`);
1190
+ }
1191
+ const participants = getParticipantNames(transcript);
1192
+ if (participants.length > 0) {
1193
+ lines.push(`**Participants:** ${participants.join(", ")}`);
1194
+ }
1195
+ return lines.join("\n");
1196
+ }
1197
+ function calculateDuration(transcript) {
1198
+ if (transcript.sentences && transcript.sentences.length > 0) {
1199
+ const lastSentence = transcript.sentences[transcript.sentences.length - 1];
1200
+ if (lastSentence) {
1201
+ return parseFloat(lastSentence.end_time);
1202
+ }
1203
+ }
1204
+ return transcript.duration || 0;
1205
+ }
1206
+ function formatSummary(summary, opts) {
1207
+ const sections = ["## Summary"];
1208
+ if (summary.gist) {
1209
+ sections.push("", summary.gist);
1210
+ }
1211
+ if (summary.bullet_gist) {
1212
+ const bullets = parseMultilineField(summary.bullet_gist);
1213
+ if (bullets.length > 0) {
1214
+ sections.push("", "### Key Points");
1215
+ sections.push(bullets.map((p) => `- ${p}`).join("\n"));
1216
+ }
1217
+ }
1218
+ if (opts.includeActionItems && summary.action_items) {
1219
+ const items = parseMultilineField(summary.action_items);
1220
+ if (items.length > 0) {
1221
+ sections.push("", "### Action Items");
1222
+ const prefix = opts.actionItemFormat === "checkbox" ? "- [ ] " : "- ";
1223
+ sections.push(items.map((a) => `${prefix}${a}`).join("\n"));
1224
+ }
1225
+ }
1226
+ return sections.join("\n");
1227
+ }
1228
+ function formatTranscript(sentences, opts) {
1229
+ const lines = ["## Transcript"];
1230
+ if (opts.groupBySpeaker) {
1231
+ const groups = groupSentencesBySpeaker(sentences);
1232
+ for (const group of groups) {
1233
+ lines.push("", formatSpeakerGroup(group, opts));
1234
+ }
1235
+ } else {
1236
+ for (const sentence of sentences) {
1237
+ lines.push("", formatSentence(sentence, opts));
1238
+ }
1239
+ }
1240
+ return lines.join("\n");
1241
+ }
1242
+ function groupSentencesBySpeaker(sentences) {
1243
+ const groups = [];
1244
+ let current = null;
1245
+ for (const sentence of sentences) {
1246
+ if (!current || current.speakerName !== sentence.speaker_name) {
1247
+ current = { speakerName: sentence.speaker_name, sentences: [] };
1248
+ groups.push(current);
1249
+ }
1250
+ current.sentences.push(sentence);
1251
+ }
1252
+ return groups;
1253
+ }
1254
+ function formatSpeakerGroup(group, opts) {
1255
+ const speaker = formatSpeakerName(group.speakerName, opts.speakerFormat);
1256
+ const text = group.sentences.map((s) => s.text).join(" ");
1257
+ const firstSentence = group.sentences[0];
1258
+ if (opts.includeTimestamps && firstSentence) {
1259
+ const timestamp = formatTimestamp(firstSentence.start_time);
1260
+ return `${timestamp} ${speaker} ${text}`;
1261
+ }
1262
+ return `${speaker} ${text}`;
1263
+ }
1264
+ function formatSentence(sentence, opts) {
1265
+ const speaker = formatSpeakerName(sentence.speaker_name, opts.speakerFormat);
1266
+ if (opts.includeTimestamps) {
1267
+ const timestamp = formatTimestamp(sentence.start_time);
1268
+ return `${timestamp} ${speaker} ${sentence.text}`;
1269
+ }
1270
+ return `${speaker} ${sentence.text}`;
1271
+ }
1272
+ function formatSpeakerName(name, format) {
1273
+ switch (format) {
1274
+ case "bold":
1275
+ return `**${name}:**`;
1276
+ case "plain":
1277
+ return `${name}:`;
1278
+ }
1279
+ }
1280
+ function formatTimestamp(startTime) {
1281
+ const seconds = parseFloat(startTime);
1282
+ const mins = Math.floor(seconds / 60);
1283
+ const secs = Math.floor(seconds % 60);
1284
+ return `[${mins}:${secs.toString().padStart(2, "0")}]`;
1285
+ }
1286
+ function formatDuration(seconds) {
1287
+ const hours = Math.floor(seconds / 3600);
1288
+ const mins = Math.floor(seconds % 3600 / 60);
1289
+ if (hours > 0) {
1290
+ return `${hours}h ${mins}m`;
1291
+ }
1292
+ return `${mins} minutes`;
1293
+ }
1294
+ function formatDate(isoString) {
1295
+ return new Date(isoString).toLocaleDateString("en-US", {
1296
+ weekday: "long",
1297
+ year: "numeric",
1298
+ month: "long",
1299
+ day: "numeric"
1300
+ });
1301
+ }
1302
+ function getParticipantNames(transcript) {
1303
+ if (transcript.meeting_attendees?.length) {
1304
+ return transcript.meeting_attendees.map((a) => a.displayName || a.name || a.email).filter(Boolean);
1305
+ }
1306
+ return transcript.speakers?.map((s) => s.name) || [];
1307
+ }
1308
+ function parseMultilineField(value) {
1309
+ return value.split(/\n/).map((line) => line.trim()).filter((line) => line.length > 0);
1310
+ }
1311
+ async function writeIfOutputPath(content, outputPath) {
1312
+ if (outputPath) {
1313
+ const { writeFile } = await import('fs/promises');
1314
+ await writeFile(outputPath, content, "utf-8");
1315
+ }
1316
+ }
1317
+
1318
+ // src/helpers/export-formats.ts
1319
+ var DEFAULT_TEXT_OPTIONS = {
1320
+ includeTimestamps: false,
1321
+ includeMetadata: true
1322
+ };
1323
+ var DEFAULT_CSV_OPTIONS = {
1324
+ includeHeader: true,
1325
+ delimiter: ","
1326
+ };
1327
+ function transcriptToText(transcript, options = {}) {
1328
+ const opts = { ...DEFAULT_TEXT_OPTIONS, ...options };
1329
+ const sections = [];
1330
+ if (opts.includeMetadata) {
1331
+ sections.push(formatTextMetadata(transcript));
1332
+ }
1333
+ if (transcript.sentences && transcript.sentences.length > 0) {
1334
+ sections.push(formatTextTranscript(transcript.sentences, opts));
1335
+ }
1336
+ return sections.join("\n\n");
1337
+ }
1338
+ function transcriptToCsv(transcript, options = {}) {
1339
+ const opts = { ...DEFAULT_CSV_OPTIONS, ...options };
1340
+ const d = opts.delimiter;
1341
+ const lines = [];
1342
+ if (opts.includeHeader) {
1343
+ lines.push(`timestamp${d}speaker${d}text${d}is_question${d}is_task`);
1344
+ }
1345
+ for (const sentence of transcript.sentences) {
1346
+ const isQuestion = Boolean(sentence.ai_filters?.question);
1347
+ const isTask = Boolean(sentence.ai_filters?.task);
1348
+ const row = [
1349
+ sentence.start_time,
1350
+ escapeCsvField(sentence.speaker_name, d),
1351
+ escapeCsvField(sentence.text, d),
1352
+ String(isQuestion),
1353
+ String(isTask)
1354
+ ];
1355
+ lines.push(row.join(d));
1356
+ }
1357
+ return lines.join("\n");
1358
+ }
1359
+ function sanitizeFilename(title) {
1360
+ if (!title.trim()) {
1361
+ return "untitled";
1362
+ }
1363
+ return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 100);
1364
+ }
1365
+ function generateExportFilename(transcript, extension) {
1366
+ const sanitizedTitle = sanitizeFilename(transcript.title);
1367
+ let datePrefix = "";
1368
+ if (transcript.dateString) {
1369
+ try {
1370
+ const date = new Date(transcript.dateString);
1371
+ if (!Number.isNaN(date.getTime())) {
1372
+ datePrefix = `${date.toISOString().slice(0, 10)}-`;
1373
+ }
1374
+ } catch {
1375
+ }
1376
+ }
1377
+ return `${datePrefix}${sanitizedTitle}.${extension}`;
1378
+ }
1379
+ async function exportTranscript(transcript, format) {
1380
+ switch (format) {
1381
+ case "markdown":
1382
+ return transcriptToMarkdown(transcript);
1383
+ case "json":
1384
+ return JSON.stringify(transcript, null, 2);
1385
+ case "txt":
1386
+ return transcriptToText(transcript);
1387
+ case "csv":
1388
+ return transcriptToCsv(transcript);
1389
+ }
1390
+ }
1391
+ async function createZipArchive(files) {
1392
+ const archiver = await import('archiver');
1393
+ const { Writable } = await import('stream');
1394
+ return new Promise((resolve, reject) => {
1395
+ const chunks = [];
1396
+ const archive = archiver.default("zip", { zlib: { level: 9 } });
1397
+ const writable = new Writable({
1398
+ write(chunk, _encoding, callback) {
1399
+ chunks.push(chunk);
1400
+ callback();
1401
+ }
1402
+ });
1403
+ writable.on("finish", () => {
1404
+ resolve(Buffer.concat(chunks));
1405
+ });
1406
+ archive.on("error", reject);
1407
+ archive.pipe(writable);
1408
+ for (const file of files) {
1409
+ archive.append(file.content, { name: file.filename });
1410
+ }
1411
+ archive.finalize();
1412
+ });
1413
+ }
1414
+ function formatTextMetadata(transcript) {
1415
+ const lines = [];
1416
+ lines.push(transcript.title || "Untitled Meeting");
1417
+ if (transcript.dateString) {
1418
+ lines.push(`Date: ${formatDate2(transcript.dateString)}`);
1419
+ }
1420
+ const participants = getParticipantNames2(transcript);
1421
+ if (participants.length > 0) {
1422
+ lines.push(`Participants: ${participants.join(", ")}`);
1423
+ }
1424
+ return lines.join("\n");
1425
+ }
1426
+ function formatTextTranscript(sentences, opts) {
1427
+ const groups = groupSentencesBySpeaker2(sentences);
1428
+ const lines = [];
1429
+ for (const group of groups) {
1430
+ const text = group.sentences.map((s) => s.text).join(" ");
1431
+ const speaker = group.speakerName || "Unknown";
1432
+ const firstSentence = group.sentences[0];
1433
+ if (opts.includeTimestamps && firstSentence) {
1434
+ const timestamp = formatTimestamp2(firstSentence.start_time);
1435
+ lines.push(`${timestamp} ${speaker}: ${text}`);
1436
+ } else {
1437
+ lines.push(`${speaker}: ${text}`);
1438
+ }
1439
+ }
1440
+ return lines.join("\n");
1441
+ }
1442
+ function groupSentencesBySpeaker2(sentences) {
1443
+ const groups = [];
1444
+ let current = null;
1445
+ for (const sentence of sentences) {
1446
+ if (!current || current.speakerName !== sentence.speaker_name) {
1447
+ current = { speakerName: sentence.speaker_name, sentences: [] };
1448
+ groups.push(current);
1449
+ }
1450
+ current.sentences.push(sentence);
1451
+ }
1452
+ return groups;
1453
+ }
1454
+ function formatTimestamp2(startTime) {
1455
+ const seconds = parseFloat(startTime);
1456
+ const mins = Math.floor(seconds / 60);
1457
+ const secs = Math.floor(seconds % 60);
1458
+ return `[${mins}:${secs.toString().padStart(2, "0")}]`;
1459
+ }
1460
+ function formatDate2(isoString) {
1461
+ return new Date(isoString).toLocaleDateString("en-US", {
1462
+ weekday: "long",
1463
+ year: "numeric",
1464
+ month: "long",
1465
+ day: "numeric"
1466
+ });
1467
+ }
1468
+ function getParticipantNames2(transcript) {
1469
+ if (transcript.meeting_attendees?.length) {
1470
+ return transcript.meeting_attendees.map((a) => a.displayName || a.name || a.email).filter(Boolean);
1471
+ }
1472
+ return transcript.speakers?.map((s) => s.name) || [];
1473
+ }
1474
+ function escapeCsvField(field, delimiter) {
1475
+ if (field.includes('"') || field.includes(delimiter) || field.includes("\n")) {
1476
+ return `"${field.replace(/"/g, '""')}"`;
1477
+ }
1478
+ return field;
1479
+ }
1480
+
1115
1481
  // src/helpers/meeting-insights.ts
1116
1482
  function analyzeMeetings(transcripts, options = {}) {
1117
1483
  const { speakers, groupBy, topSpeakersCount = 10, topParticipantsCount = 10 } = options;
@@ -1585,6 +1951,21 @@ var TRANSCRIPT_LIST_FIELDS = `
1585
1951
  summary_status
1586
1952
  }
1587
1953
  `;
1954
+ function buildListFields(params) {
1955
+ const includeSentences = params?.includeSentences === true;
1956
+ const includeSummary = params?.includeSummary === true;
1957
+ if (!includeSentences && !includeSummary) {
1958
+ return TRANSCRIPT_LIST_FIELDS;
1959
+ }
1960
+ let fields = TRANSCRIPT_BASE_FIELDS;
1961
+ if (includeSentences) {
1962
+ fields += SENTENCES_FIELDS;
1963
+ }
1964
+ if (includeSummary) {
1965
+ fields += SUMMARY_FIELDS;
1966
+ }
1967
+ return fields;
1968
+ }
1588
1969
  function createTranscriptsAPI(client) {
1589
1970
  return {
1590
1971
  async get(id, params) {
@@ -1600,6 +1981,7 @@ function createTranscriptsAPI(client) {
1600
1981
  return normalizeTranscript(data.transcript);
1601
1982
  },
1602
1983
  async list(params) {
1984
+ const fields = buildListFields(params);
1603
1985
  const query = `
1604
1986
  query ListTranscripts(
1605
1987
  $keyword: String
@@ -1637,13 +2019,23 @@ function createTranscriptsAPI(client) {
1637
2019
  participant_email: $participant_email
1638
2020
  date: $date
1639
2021
  ) {
1640
- ${TRANSCRIPT_LIST_FIELDS}
2022
+ ${fields}
1641
2023
  }
1642
2024
  }
1643
2025
  `;
2026
+ let internalDomain;
2027
+ if (params?.external) {
2028
+ const userQuery = "query { user { email } }";
2029
+ const userData = await client.execute(userQuery);
2030
+ internalDomain = extractDomain(userData.user.email);
2031
+ }
1644
2032
  const variables = buildListVariables(params);
1645
2033
  const data = await client.execute(query, variables);
1646
- return data.transcripts.map(normalizeTranscript);
2034
+ let results = data.transcripts.map(normalizeTranscript);
2035
+ if (internalDomain) {
2036
+ results = results.filter((t) => hasExternalParticipants(t.participants, internalDomain));
2037
+ }
2038
+ return results;
1647
2039
  },
1648
2040
  async getSummary(id) {
1649
2041
  const query = `
@@ -1690,9 +2082,10 @@ function createTranscriptsAPI(client) {
1690
2082
  } = params;
1691
2083
  const transcripts = [];
1692
2084
  for await (const t of this.listAll({
2085
+ ...listParams,
1693
2086
  keyword: query,
1694
2087
  scope,
1695
- ...listParams
2088
+ includeSentences: true
1696
2089
  })) {
1697
2090
  transcripts.push(t);
1698
2091
  if (limit && transcripts.length >= limit) break;
@@ -1700,8 +2093,7 @@ function createTranscriptsAPI(client) {
1700
2093
  const allMatches = [];
1701
2094
  let transcriptsWithMatches = 0;
1702
2095
  for (const t of transcripts) {
1703
- const full = await this.get(t.id, { includeSentences: true });
1704
- const matches = searchTranscript(full, {
2096
+ const matches = searchTranscript(t, {
1705
2097
  query,
1706
2098
  caseSensitive,
1707
2099
  speakers,
@@ -1753,13 +2145,13 @@ function createTranscriptsAPI(client) {
1753
2145
  organizers,
1754
2146
  participants,
1755
2147
  user_id,
1756
- channel_id
2148
+ channel_id,
2149
+ includeSentences: true
1757
2150
  })) {
1758
2151
  if (internalDomain && !hasExternalParticipants(t.participants, internalDomain)) {
1759
2152
  continue;
1760
2153
  }
1761
- const full = await this.get(t.id, { includeSentences: true, includeSummary: false });
1762
- transcripts.push(full);
2154
+ transcripts.push(t);
1763
2155
  if (limit && transcripts.length >= limit) break;
1764
2156
  }
1765
2157
  return analyzeMeetings(transcripts, {
@@ -1777,13 +2169,20 @@ function createTranscriptsAPI(client) {
1777
2169
  toDate,
1778
2170
  mine,
1779
2171
  organizers,
1780
- participants
2172
+ participants,
2173
+ includeSummary: true
1781
2174
  })) {
1782
- const full = await this.get(t.id, { includeSentences: false, includeSummary: true });
1783
- transcripts.push(full);
2175
+ transcripts.push(t);
1784
2176
  if (limit && transcripts.length >= limit) break;
1785
2177
  }
1786
2178
  return aggregateActionItems(transcripts, {}, filterOptions);
2179
+ },
2180
+ async bulkExport(params = {}) {
2181
+ const { format = "markdown", asZip = false, onProgress } = params;
2182
+ const transcriptIds = await collectTranscriptIds(client, this, params);
2183
+ const files = await convertTranscripts(this, transcriptIds, format, onProgress);
2184
+ const zip = asZip ? await createZipArchive(files) : void 0;
2185
+ return { files, zip, format, totalExported: files.length };
1787
2186
  }
1788
2187
  };
1789
2188
  }
@@ -1862,6 +2261,50 @@ function buildListVariables(params) {
1862
2261
  date: params.date
1863
2262
  };
1864
2263
  }
2264
+ async function collectTranscriptIds(client, api, params) {
2265
+ const { ids, fromDate, toDate, mine, organizers, participants, external, limit } = params;
2266
+ if (ids?.length) {
2267
+ return ids;
2268
+ }
2269
+ let internalDomain;
2270
+ if (external) {
2271
+ const userQuery = "query { user { email } }";
2272
+ const userData = await client.execute(userQuery);
2273
+ internalDomain = extractDomain(userData.user.email);
2274
+ }
2275
+ const result = [];
2276
+ for await (const t of api.listAll({ fromDate, toDate, mine, organizers, participants })) {
2277
+ if (internalDomain && !hasExternalParticipants(t.participants, internalDomain)) {
2278
+ continue;
2279
+ }
2280
+ result.push(t.id);
2281
+ if (limit && result.length >= limit) break;
2282
+ }
2283
+ return result;
2284
+ }
2285
+ async function convertTranscripts(api, transcriptIds, format, onProgress) {
2286
+ const files = [];
2287
+ const extension = format === "markdown" ? "md" : format;
2288
+ let completed = 0;
2289
+ const total = transcriptIds.length;
2290
+ for await (const result of batch(
2291
+ transcriptIds,
2292
+ async (id) => {
2293
+ const transcript = await api.get(id);
2294
+ const content = await exportTranscript(transcript, format);
2295
+ const filename = generateExportFilename(transcript, extension);
2296
+ return { id, title: transcript.title, filename, content };
2297
+ },
2298
+ { delayMs: 100 }
2299
+ )) {
2300
+ if (!result.error) {
2301
+ files.push(result.result);
2302
+ }
2303
+ completed++;
2304
+ onProgress?.(completed, total);
2305
+ }
2306
+ return files;
2307
+ }
1865
2308
 
1866
2309
  // src/graphql/queries/users.ts
1867
2310
  var USER_FIELDS = `