Restore MP3 auto and show visible Suno tracks

This commit is contained in:
DESKTOP-KSVGT20\shkim
2026-05-02 02:32:22 +09:00
parent d6a7e50ad3
commit a77a40695c
+33 -23
View File
@@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name ChatGPT to Suno Prompt Copier // @name ChatGPT to Suno Prompt Copier
// @namespace local.suno-helper // @namespace local.suno-helper
// @version 0.10.1 // @version 0.10.3
// @description Copy structured ChatGPT song prompt versions into Suno fields. // @description Copy structured ChatGPT song prompt versions into Suno fields.
// @author local // @author local
// @match https://chatgpt.com/* // @match https://chatgpt.com/*
@@ -30,7 +30,7 @@
(function () { (function () {
"use strict"; "use strict";
const SCRIPT_VERSION = "0.10.1"; const SCRIPT_VERSION = "0.10.3";
const STORAGE_KEY = "chatgptSunoPromptSlots"; const STORAGE_KEY = "chatgptSunoPromptSlots";
const SLOT_COUNT = 2; const SLOT_COUNT = 2;
const isChatGPT = location.hostname.includes("chatgpt.com") || location.hostname.includes("chat.openai.com"); const isChatGPT = location.hostname.includes("chatgpt.com") || location.hostname.includes("chat.openai.com");
@@ -1878,11 +1878,11 @@
</div> </div>
<div class="cgs-track-list" data-cgs-track-list></div> <div class="cgs-track-list" data-cgs-track-list></div>
<div class="cgs-row"> <div class="cgs-row">
<button class="cgs-btn cgs-wide" type="button" data-cgs-process-one-mp3>선택 1곡 MP3 대기</button> <button class="cgs-btn cgs-wide" type="button" data-cgs-process-one-mp3>선택 1곡 MP3 자동</button>
<button class="cgs-btn cgs-wide" type="button" data-cgs-process-one-wav>선택 1곡 WAV 대기</button> <button class="cgs-btn cgs-wide" type="button" data-cgs-process-one-wav>선택 1곡 WAV 대기</button>
</div> </div>
<div class="cgs-row"> <div class="cgs-row">
<button class="cgs-btn cgs-primary cgs-wide" type="button" data-cgs-process-selected-mp3>선택항목 MP3 대기</button> <button class="cgs-btn cgs-primary cgs-wide" type="button" data-cgs-process-selected-mp3>선택항목 MP3 자동</button>
<button class="cgs-btn cgs-primary cgs-wide" type="button" data-cgs-process-selected-wav>선택항목 WAV 대기</button> <button class="cgs-btn cgs-primary cgs-wide" type="button" data-cgs-process-selected-wav>선택항목 WAV 대기</button>
</div> </div>
<div class="cgs-row"> <div class="cgs-row">
@@ -1910,12 +1910,14 @@
const slotSelect = body.querySelector("[data-cgs-slot]"); const slotSelect = body.querySelector("[data-cgs-slot]");
const trackList = body.querySelector("[data-cgs-track-list]"); const trackList = body.querySelector("[data-cgs-track-list]");
let libraryTracks = []; let libraryTracks = [];
let visibleTrackIds = new Set();
const libraryTrackMap = new Map(); const libraryTrackMap = new Map();
const selectedTrackIds = new Set(); const selectedTrackIds = new Set();
let lastSelectedIndex = -1; let lastSelectedIndex = -1;
let autoScanTimer = 0; let autoScanTimer = 0;
const getSelectedTracks = () => libraryTracks.filter((track) => selectedTrackIds.has(track.id)); const getVisibleTracks = () => libraryTracks.filter((track) => visibleTrackIds.has(track.id));
const getSelectedTracks = () => getVisibleTracks().filter((track) => selectedTrackIds.has(track.id));
const mergeLibraryTracks = (tracks) => { const mergeLibraryTracks = (tracks) => {
for (const track of tracks) { for (const track of tracks) {
if (!track.id) continue; if (!track.id) continue;
@@ -1929,24 +1931,25 @@
}; };
const renderLibraryTrackList = () => { const renderLibraryTrackList = () => {
try { try {
const visibleTracks = getVisibleTracks();
for (const id of [...selectedTrackIds]) { for (const id of [...selectedTrackIds]) {
if (!libraryTrackMap.has(id)) selectedTrackIds.delete(id); if (!visibleTrackIds.has(id)) selectedTrackIds.delete(id);
} }
const selectedCount = selectedTrackIds.size; const selectedCount = selectedTrackIds.size;
selectionSummary.textContent = libraryTracks.length selectionSummary.textContent = visibleTracks.length
? `누적 ${libraryTracks.length}곡 / 선택 ${selectedCount}` ? `현재 화면 ${visibleTracks.length}곡 / 선택 ${selectedCount} / 누적 ${libraryTracks.length}`
: "누적된 곡 없음. 스크롤하면서 곡 감지를 눌러줘."; : `현재 화면 감지 없음 / 누적 ${libraryTracks.length}`;
const nodes = []; const nodes = [];
if (!libraryTracks.length) { if (!visibleTracks.length) {
const empty = document.createElement("div"); const empty = document.createElement("div");
empty.className = "cgs-track-item"; empty.className = "cgs-track-item";
empty.innerHTML = `<div></div><div class="cgs-track-meta">감지된 곡 없음</div><div></div>`; empty.innerHTML = `<div></div><div class="cgs-track-meta">현재 화면에 감지된 곡 없음</div><div></div>`;
trackList.replaceChildren(empty); trackList.replaceChildren(empty);
return; return;
} }
libraryTracks.forEach((track, index) => { visibleTracks.forEach((track, index) => {
const row = document.createElement("div"); const row = document.createElement("div");
row.className = `cgs-track-item ${selectedTrackIds.has(track.id) ? "cgs-selected" : ""}`; row.className = `cgs-track-item ${selectedTrackIds.has(track.id) ? "cgs-selected" : ""}`;
row.dataset.cgsTrackIndex = String(index); row.dataset.cgsTrackIndex = String(index);
@@ -1984,15 +1987,17 @@
}; };
const setSelectedRange = (from, to) => { const setSelectedRange = (from, to) => {
const start = Math.max(0, Math.min(from, to)); const start = Math.max(0, Math.min(from, to));
const end = Math.min(libraryTracks.length - 1, Math.max(from, to)); const visibleTracks = getVisibleTracks();
const end = Math.min(visibleTracks.length - 1, Math.max(from, to));
for (let index = start; index <= end; index += 1) { for (let index = start; index <= end; index += 1) {
if (libraryTracks[index]?.id) selectedTrackIds.add(libraryTracks[index].id); if (visibleTracks[index]?.id) selectedTrackIds.add(visibleTracks[index].id);
} }
}; };
const scanAndMergeVisibleTracks = () => { const scanAndMergeVisibleTracks = () => {
const scannedTracks = scanSunoLibraryTracks(); const scannedTracks = scanSunoLibraryTracks();
const before = libraryTracks.length; const before = libraryTracks.length;
mergeLibraryTracks(scannedTracks); mergeLibraryTracks(scannedTracks);
visibleTrackIds = new Set(scannedTracks.map((track) => track.id).filter(Boolean));
renderLibraryTrackList(); renderLibraryTrackList();
updateSummary(); updateSummary();
return { scannedTracks, added: libraryTracks.length - before }; return { scannedTracks, added: libraryTracks.length - before };
@@ -2062,7 +2067,8 @@
const item = event.target.closest("[data-cgs-track-index]"); const item = event.target.closest("[data-cgs-track-index]");
if (!item) return; if (!item) return;
const index = Number(item.getAttribute("data-cgs-track-index")); const index = Number(item.getAttribute("data-cgs-track-index"));
const track = libraryTracks[index]; const visibleTracks = getVisibleTracks();
const track = visibleTracks[index];
if (!track?.id) return; if (!track?.id) return;
if (event.shiftKey && lastSelectedIndex >= 0) { if (event.shiftKey && lastSelectedIndex >= 0) {
setSelectedRange(lastSelectedIndex, index); setSelectedRange(lastSelectedIndex, index);
@@ -2085,7 +2091,7 @@
renderLibraryTrackList(); renderLibraryTrackList();
} }
updateSummary(); updateSummary();
const track = getSelectedTracks()[0] || libraryTracks[0]; const track = getSelectedTracks()[0] || getVisibleTracks()[0];
if (!track) { if (!track) {
setStatus(body, "선택할 감지 곡이 없어. 곡 감지를 먼저 눌러줘."); setStatus(body, "선택할 감지 곡이 없어. 곡 감지를 먼저 눌러줘.");
return; return;
@@ -2099,7 +2105,7 @@
}; };
body.querySelector("[data-cgs-process-one-mp3]").addEventListener("click", async () => { body.querySelector("[data-cgs-process-one-mp3]").addEventListener("click", async () => {
await registerSelectedManualDownloads("mp3", { one: true }); await processSelectedTrack("mp3");
}); });
body.querySelector("[data-cgs-process-one-wav]").addEventListener("click", async () => { body.querySelector("[data-cgs-process-one-wav]").addEventListener("click", async () => {
@@ -2107,7 +2113,7 @@
}); });
body.querySelector("[data-cgs-process-selected-mp3]").addEventListener("click", async () => { body.querySelector("[data-cgs-process-selected-mp3]").addEventListener("click", async () => {
await registerSelectedManualDownloads("mp3"); await processSelectedTracks("mp3");
}); });
body.querySelector("[data-cgs-process-selected-wav]").addEventListener("click", async () => { body.querySelector("[data-cgs-process-selected-wav]").addEventListener("click", async () => {
@@ -2115,7 +2121,7 @@
}); });
const registerSelectedManualDownloads = async (format, options = {}) => { const registerSelectedManualDownloads = async (format, options = {}) => {
if (!libraryTracks.length) { if (!getVisibleTracks().length) {
mergeLibraryTracks(scanSunoLibraryTracks()); mergeLibraryTracks(scanSunoLibraryTracks());
renderLibraryTrackList(); renderLibraryTrackList();
} }
@@ -2132,7 +2138,7 @@
}; };
const clickSelectedSunoUiDownloads = async (format, options = {}) => { const clickSelectedSunoUiDownloads = async (format, options = {}) => {
if (!libraryTracks.length) { if (!getVisibleTracks().length) {
mergeLibraryTracks(scanSunoLibraryTracks()); mergeLibraryTracks(scanSunoLibraryTracks());
renderLibraryTrackList(); renderLibraryTrackList();
} }
@@ -2165,20 +2171,24 @@
}); });
const processLibraryTracks = async (format) => { const processLibraryTracks = async (format) => {
if (!libraryTracks.length) { if (!getVisibleTracks().length) {
mergeLibraryTracks(scanSunoLibraryTracks()); mergeLibraryTracks(scanSunoLibraryTracks());
renderLibraryTrackList(); renderLibraryTrackList();
} }
updateSummary(); updateSummary();
try { try {
await uploadTracksToCompanion(libraryTracks, body, format); if (format === "wav") {
await expectManualDownloads(libraryTracks, body, "wav");
} else {
await uploadTracksToCompanion(libraryTracks, body, format);
}
} catch (error) { } catch (error) {
setStatus(body, `${format.toUpperCase()} 일괄 처리 실패: ${error.message || error}`); setStatus(body, `${format.toUpperCase()} 일괄 처리 실패: ${error.message || error}`);
} }
}; };
const processSelectedTracks = async (format) => { const processSelectedTracks = async (format) => {
if (!libraryTracks.length) { if (!getVisibleTracks().length) {
mergeLibraryTracks(scanSunoLibraryTracks()); mergeLibraryTracks(scanSunoLibraryTracks());
renderLibraryTrackList(); renderLibraryTrackList();
} }