PageSourceSearch

https://gettheminutes.com/v2-assets/release-20260930-realtime/exports.mjs

js gettheminutes.com collected 2026-10-02 01:30:53 UTC 3,809 bytes, 111 lines download raw bytes

1/** Complete, watermarked reader exports. No private assistant or operational fields. */
2export async function completeSnapshot(getPage) {
3  let snapshot = await getPage(0, null),
4    offset = snapshot.next_offset;
5  const rows = [...snapshot.segments];
6  const size = (value) =>
7    new TextEncoder().encode(JSON.stringify(value)).byteLength;
8  let bytes = size(snapshot);
9  if (bytes > 16_000_000 || rows.length > 100000)
10    throw new Error(
11      "Recording exceeds the export limit. No partial file was created.",
12    );
13  const seen = new Set([0]);
14  while (offset !== null) {
15    if (seen.has(offset)) throw new Error("Invalid export pagination");
16    seen.add(offset);
17    const page = await getPage(offset, snapshot.watermark);
18    if (page.watermark !== snapshot.watermark)
19      throw new Error("snapshot_changed");
20    bytes += size(page);
21    if (bytes > 16_000_000 || rows.length + page.segments.length > 100000)
22      throw new Error(
23        "Recording exceeds the export limit. No partial file was created.",
24      );
25    rows.push(...page.segments);
26    offset = page.next_offset;
27  }
28  return {
29    title: snapshot.title,
30    ...(typeof snapshot.minutes === "string" ? { minutes: snapshot.minutes } : {}),
31    segments: rows.map((s) => ({
32      start_seconds: s.start_seconds,
33      end_seconds: s.end_seconds,
34      speaker: s.speaker,
35      text: s.text,
36      language: s.language ?? null,
37      translations: (s.translations || []).map((t) => ({
38        language: t.language,
39        text: t.text,
40      })),
41    })),
42  };
43}
44/** What an export includes: speaker names, timestamps and translations can each be left out. */
45const INCLUDE = { speakers: true, timestamps: true, translations: true };
46export function textExport(snapshot, include = INCLUDE) {
47  const { speakers, timestamps, translations } = { ...INCLUDE, ...include };
48  const stamp = (seconds) =>
49    `${Math.floor(seconds / 60)
50      .toString()
51      .padStart(2, "0")}:${Math.floor(seconds % 60)
52      .toString()
53      .padStart(2, "0")}`;
54  const heading = (s) =>
55    [timestamps ? `[${stamp(s.start_seconds)}]` : "", speakers ? s.speaker : ""].filter(Boolean).join(" ");
56  return (
57    snapshot.title +
58    "\n\n" +
59    (snapshot.minutes ? "Meeting minutes\n" + snapshot.minutes + "\n\n" : "") +
60    snapshot.segments
61      .map(
62        (s) =>
63          (heading(s) ? heading(s) + "\n" : "") +
64          s.text +
65          (translations ? s.translations.map((t) => `\n[${t.language}] ${t.text}`).join("") : ""),
66      )
67      .join("\n\n") +
68    "\n"
69  );
70}
71/** The JSON export, without the fields the person left out. */
72export function jsonExport(snapshot, include = INCLUDE) {
73  const { speakers, timestamps, translations } = { ...INCLUDE, ...include };
74  return JSON.stringify(
75    {
76      ...snapshot,
77      segments: snapshot.segments.map(({ start_seconds, end_seconds, speaker, translations: rows, ...rest }) => ({
78        ...(timestamps ? { start_seconds, end_seconds } : {}),
79        ...(speakers ? { speaker } : {}),
80        ...rest,
81        ...(translations ? { translations: rows } : {}),
82      })),
83    },
84    null,
85    2,
86  );
87}
88export function downloadSnapshot(snapshot, format = "txt", include = INCLUDE) {
89  const body =
90    format === "json"
91      ? jsonExport(snapshot, include)
92      : textExport(snapshot, include);
93  const blob = new Blob([body], {
94    type:
95      format === "json"
96        ? "application/json;charset=utf-8"
97        : "text/plain;charset=utf-8",
98  });
99  const url = URL.createObjectURL(blob),
100    link = document.createElement("a");
101  link.href = url;
102  link.download =
103    (snapshot.title
104      .replace(/[^\p{L}\p{N} _-]/gu, "")
105      .trim()
106      .slice(0, 100) || "recording") +
107    "." +
108    format;
109  link.click();
110  setTimeout(() => URL.revokeObjectURL(url), 1000);
111}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.