"use strict"; (function initPageProbe() { const EVENT_SOURCE = "S3_CAPTURE_PROBE"; const GRAPHQL_URL_FRAGMENT = "surfaces-graphql.splice.com/graphql"; let lastAudioResponseUrl = ""; function emit(kind, payload) { try { window.postMessage( { source: EVENT_SOURCE, kind, payload: payload || {} }, "*" ); } catch (error) { // Ignore probe emission errors. } } function safeString(value) { return typeof value === "string" ? value : ""; } function normalizeUrl(rawUrl) { try { return new URL(rawUrl, window.location.href).toString(); } catch (error) { return ""; } } function normalizeFileName(raw) { if (typeof raw !== "string") { return ""; } const trimmed = raw.trim(); if (!trimmed) { return ""; } const parts = trimmed.split("/"); return parts[parts.length - 1] || trimmed; } function extractSampleIdFromUrl(url) { try { const parsed = new URL(url); const marker = "/audio_samples/"; const idx = parsed.pathname.indexOf(marker); if (idx < 0) { return ""; } const rest = parsed.pathname.slice(idx + marker.length); const parts = rest.split("/").filter(Boolean); const first = (parts[0] || "").replace(/-scrambled$/i, ""); const second = (parts[1] || "").split(".")[0]; const hashRe = /^[a-f0-9]{64}$/i; if (hashRe.test(first)) { return first.toLowerCase(); } if (hashRe.test(second)) { return second.toLowerCase(); } return ""; } catch (error) { return ""; } } function extractCoverImageFromGraphqlItem(item) { if (!item || typeof item !== "object") { return ""; } const ownFiles = Array.isArray(item.files) ? item.files : []; for (const file of ownFiles) { if (!file || typeof file !== "object") { continue; } if (String(file.asset_file_type_slug || "").toLowerCase() !== "cover_image") { continue; } const url = normalizeUrl(file.url || ""); if (url) { return url; } } const parents = item.parents && Array.isArray(item.parents.items) ? item.parents.items : []; for (const parent of parents) { const files = parent && Array.isArray(parent.files) ? parent.files : []; for (const file of files) { if (!file || typeof file !== "object") { continue; } if (String(file.asset_file_type_slug || "").toLowerCase() !== "cover_image") { continue; } const url = normalizeUrl(file.url || ""); if (url) { return url; } } } return ""; } function extractPackNameFromGraphqlItem(item) { if (!item || typeof item !== "object" || !item.parents || !Array.isArray(item.parents.items)) { return ""; } for (const parent of item.parents.items) { if (!parent || typeof parent !== "object") { continue; } const name = typeof parent.name === "string" ? parent.name.trim() : ""; if (name) { return name; } } return ""; } function extractPreviewContextsFromGraphql(json) { const contexts = []; const items = json && json.data && json.data.assetsSearch && Array.isArray(json.data.assetsSearch.items) ? json.data.assetsSearch.items : []; for (const item of items) { if (!item || typeof item !== "object") { continue; } const sampleId = typeof item.uuid === "string" ? item.uuid.toLowerCase() : ""; const itemName = normalizeFileName(String(item.name || "")); const itemKey = typeof item.key === "string" ? item.key.trim().toUpperCase() : ""; const itemBpm = item.bpm == null ? "" : String(item.bpm).trim(); const itemTags = Array.isArray(item.tags) ? Array.from(new Set(item.tags.map((tag) => (tag && tag.label ? String(tag.label).trim() : "")).filter(Boolean))) : []; const itemCoverImageUrl = extractCoverImageFromGraphqlItem(item); const itemPackName = extractPackNameFromGraphqlItem(item); const files = Array.isArray(item.files) ? item.files : []; for (const file of files) { if (!file || typeof file !== "object") { continue; } const typeSlug = String(file.asset_file_type_slug || "").toLowerCase(); const fileUrl = normalizeUrl(file.url || ""); if (typeSlug !== "preview_mp3" || !fileUrl) { continue; } contexts.push({ sampleId: sampleId || extractSampleIdFromUrl(fileUrl), previewUrl: fileUrl, fileName: itemName, key: itemKey, bpm: itemBpm, tags: itemTags, coverImageUrl: itemCoverImageUrl, packName: itemPackName }); } } return contexts; } function emitGraphqlContextsFromJson(json) { const contexts = extractPreviewContextsFromGraphql(json); if (contexts.length) { emit("graphql-contexts", { contexts }); } } function markLastAudioUrl(url, contentType) { const maybeUrl = safeString(url); const maybeType = safeString(contentType).toLowerCase(); if (!maybeUrl) { return; } if (maybeType.startsWith("audio/") || maybeUrl.includes("audio_samples/")) { lastAudioResponseUrl = maybeUrl; } } function patchFetch() { if (typeof window.fetch !== "function") { return; } const currentFetch = window.fetch; if (currentFetch.__s3CapturePatched) { return; } const wrappedFetch = function wrappedFetch(input, init) { const requestUrl = typeof input === "string" ? input : input && typeof input.url === "string" ? input.url : ""; emit("fetch-request", { requestUrl }); return currentFetch.call(this, input, init).then( (response) => { const responseUrl = response && typeof response.url === "string" ? response.url : ""; const contentType = response && response.headers ? response.headers.get("content-type") : ""; markLastAudioUrl(responseUrl, contentType); emit("fetch-response", { requestUrl, responseUrl, status: response ? response.status : 0, contentType: contentType || "" }); if (requestUrl && requestUrl.includes(GRAPHQL_URL_FRAGMENT) && response && typeof response.clone === "function") { response.clone().json().then((json) => { emitGraphqlContextsFromJson(json); }).catch(() => { // Ignore non-JSON GraphQL edge cases. }); } return response; }, (error) => { emit("fetch-error", { requestUrl, error: error && error.message ? error.message : "fetch failed" }); throw error; } ); }; wrappedFetch.__s3CapturePatched = true; window.fetch = wrappedFetch; } function patchXhr() { if (!window.XMLHttpRequest || !window.XMLHttpRequest.prototype) { return; } const proto = window.XMLHttpRequest.prototype; if (proto.open.__s3CapturePatched) { return; } const originalOpen = proto.open; const originalSend = proto.send; proto.open = function patchedOpen(method, url) { this.__s3CaptureRequestUrl = safeString(url); emit("xhr-open", { method: safeString(method), requestUrl: this.__s3CaptureRequestUrl }); return originalOpen.apply(this, arguments); }; proto.open.__s3CapturePatched = true; proto.send = function patchedSend() { const xhr = this; xhr.addEventListener( "loadend", function onLoadEnd() { const responseUrl = safeString(xhr.responseURL); const contentType = safeString(xhr.getResponseHeader("content-type")); markLastAudioUrl(responseUrl || xhr.__s3CaptureRequestUrl, contentType); emit("xhr-response", { requestUrl: safeString(xhr.__s3CaptureRequestUrl), responseUrl, status: xhr.status || 0, contentType }); const requestUrl = safeString(xhr.__s3CaptureRequestUrl); if (!requestUrl || !requestUrl.includes(GRAPHQL_URL_FRAGMENT)) { return; } try { let json = null; if (xhr.responseType === "json" && xhr.response && typeof xhr.response === "object") { json = xhr.response; } else { if (xhr.responseType && xhr.responseType !== "text" && xhr.responseType !== "") { return; } const text = safeString(xhr.responseText); if (!text) { return; } json = JSON.parse(text); } emitGraphqlContextsFromJson(json); } catch (error) { // Ignore non-JSON GraphQL edge cases. } }, { once: true } ); return originalSend.apply(this, arguments); }; } function patchCreateObjectURL() { if (!window.URL || typeof window.URL.createObjectURL !== "function") { return; } const current = window.URL.createObjectURL; if (current.__s3CapturePatched) { return; } const wrapped = function wrappedCreateObjectURL(blob) { const objectUrl = current.call(this, blob); const blobType = blob && typeof blob.type === "string" ? blob.type : ""; const blobSize = blob && typeof blob.size === "number" ? blob.size : 0; emit("blob-created", { blobUrl: objectUrl, blobType, blobSize, linkedUrl: lastAudioResponseUrl }); return objectUrl; }; wrapped.__s3CapturePatched = true; window.URL.createObjectURL = wrapped; } function patchDecodeAudioData(ctor) { if (!ctor || !ctor.prototype || typeof ctor.prototype.decodeAudioData !== "function") { return; } const current = ctor.prototype.decodeAudioData; if (current.__s3CapturePatched) { return; } const wrapped = function wrappedDecodeAudioData(audioData) { const byteLength = audioData && typeof audioData.byteLength === "number" ? audioData.byteLength : 0; emit("decode-audio-data", { byteLength, linkedUrl: lastAudioResponseUrl }); return current.apply(this, arguments); }; wrapped.__s3CapturePatched = true; ctor.prototype.decodeAudioData = wrapped; } patchFetch(); patchXhr(); patchCreateObjectURL(); patchDecodeAudioData(window.AudioContext); patchDecodeAudioData(window.OfflineAudioContext); emit("probe-ready", { href: window.location.href }); })();