Filter Suno library detection to visible rows
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name ChatGPT to Suno Prompt Copier
|
||||
// @namespace local.suno-helper
|
||||
// @version 0.4.0
|
||||
// @version 0.4.1
|
||||
// @description Copy structured ChatGPT song prompt versions into Suno fields.
|
||||
// @author local
|
||||
// @match https://chatgpt.com/*
|
||||
@@ -620,6 +620,60 @@
|
||||
return target;
|
||||
}
|
||||
|
||||
function normalizeMatchText(value) {
|
||||
return String(value || "")
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, " ")
|
||||
.trim();
|
||||
}
|
||||
|
||||
function getVisibleLibraryRows() {
|
||||
const rows = [];
|
||||
const seen = new Set();
|
||||
const mediaNodes = [...document.querySelectorAll("img, [style*='background-image']")];
|
||||
for (const node of mediaNodes) {
|
||||
const rect = node.getBoundingClientRect();
|
||||
if (rect.width < 30 || rect.height < 30 || rect.bottom < 0 || rect.top > window.innerHeight) continue;
|
||||
let current = node;
|
||||
for (let depth = 0; depth < 8 && current; depth += 1) {
|
||||
const text = (current.innerText || current.textContent || "").trim();
|
||||
const currentRect = current.getBoundingClientRect();
|
||||
if (
|
||||
text.length > 20 &&
|
||||
text.length < 1800 &&
|
||||
currentRect.width > 250 &&
|
||||
currentRect.height > 45 &&
|
||||
/v\d|BPM|Korean|rock|pop|metal|랩|가사|female|male|vocal|Suno/i.test(text)
|
||||
) {
|
||||
const key = normalizeMatchText(text);
|
||||
if (!seen.has(key)) {
|
||||
seen.add(key);
|
||||
rows.push({
|
||||
text,
|
||||
normalized: key,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
current = current.parentElement;
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
function trackMatchesVisibleRows(track, rows) {
|
||||
if (!rows.length) return true;
|
||||
const title = normalizeMatchText(track.title);
|
||||
const style = normalizeMatchText(track.style || track.lyrics || "");
|
||||
if (!title || title.length > 160) return false;
|
||||
return rows.some((row) => {
|
||||
if (!row.normalized.includes(title)) return false;
|
||||
if (!style) return true;
|
||||
const styleNeedle = style.slice(0, Math.min(42, style.length));
|
||||
return styleNeedle.length < 16 || row.normalized.includes(styleNeedle);
|
||||
});
|
||||
}
|
||||
|
||||
function scanSunoLibraryTracks() {
|
||||
const sources = readSunoDataSources();
|
||||
const objects = sources.flatMap((item) => flattenObjects(item));
|
||||
@@ -651,17 +705,18 @@
|
||||
});
|
||||
}
|
||||
|
||||
const visibleRows = getVisibleLibraryRows();
|
||||
return [...tracks.values()]
|
||||
.filter((track) => track.id || track.audioUrl || track.imageUrl)
|
||||
.filter((track) => trackMatchesVisibleRows(track, visibleRows))
|
||||
.sort((a, b) => String(a.title).localeCompare(String(b.title), "ko"));
|
||||
}
|
||||
|
||||
function visibleSunoRowsHint() {
|
||||
const titles = [...document.querySelectorAll("a, h1, h2, h3, [role='button'], div, span")]
|
||||
.map((node) => (node.innerText || node.textContent || "").trim())
|
||||
.filter((text) => text && text.length < 80 && !/^(Songs|Playlists|Workspaces|Studio Projects|Voices|Cover Art|Hooks|History|Search|Newest|Liked|Public|Uploads)$/i.test(text));
|
||||
const likelyTitles = titles.filter((text, index) => titles.indexOf(text) === index).slice(0, 5);
|
||||
return likelyTitles;
|
||||
return getVisibleLibraryRows()
|
||||
.map((row) => row.text.split("\n").map((line) => line.trim()).filter(Boolean)[0])
|
||||
.filter((text, index, list) => text && list.indexOf(text) === index)
|
||||
.slice(0, 5);
|
||||
}
|
||||
|
||||
function findCurrentSunoTrack() {
|
||||
@@ -893,7 +948,8 @@
|
||||
updateSummary();
|
||||
const sample = libraryTracks.slice(0, 3).map((track) => track.title || track.id).join(", ");
|
||||
if (libraryTracks.length) {
|
||||
setStatus(body, `${libraryTracks.length}곡 감지: ${sample}`);
|
||||
const visibleCount = getVisibleLibraryRows().length;
|
||||
setStatus(body, `${libraryTracks.length}곡 감지: ${sample} / 화면 행 ${visibleCount}개 기준`);
|
||||
return;
|
||||
}
|
||||
const visibleHints = visibleSunoRowsHint();
|
||||
|
||||
Reference in New Issue
Block a user