Capturing pack and cover

This commit is contained in:
2026-08-05 22:41:04 -05:00
parent 235f76a124
commit 47871d4bc5
6 changed files with 490 additions and 86 deletions

View File

@@ -2,6 +2,7 @@
(function initPageProbe() {
const EVENT_SOURCE = "S3_CAPTURE_PROBE";
const GRAPHQL_URL_FRAGMENT = "surfaces-graphql.splice.com/graphql";
let lastAudioResponseUrl = "";
function emit(kind, payload) {
@@ -23,6 +24,156 @@
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();
@@ -64,6 +215,13 @@
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) => {
@@ -117,6 +275,28 @@
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 }
);