Compare commits
2 Commits
8fb7dbb250
...
abcb2e69b7
| Author | SHA1 | Date | |
|---|---|---|---|
| abcb2e69b7 | |||
| 33aa56e571 |
@@ -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.9.8
|
// @version 0.10.0
|
||||||
// @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.9.8";
|
const SCRIPT_VERSION = "0.10.0";
|
||||||
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");
|
||||||
@@ -75,15 +75,18 @@
|
|||||||
|
|
||||||
const originalFetch = page.fetch;
|
const originalFetch = page.fetch;
|
||||||
if (typeof originalFetch === "function") {
|
if (typeof originalFetch === "function") {
|
||||||
page.fetch = async function (...args) {
|
page.fetch = function (...args) {
|
||||||
const response = await originalFetch.apply(this, args);
|
const result = originalFetch.apply(this, args);
|
||||||
const url = args[0]?.url || args[0] || response.url || "";
|
result.then((response) => {
|
||||||
if (/suno/i.test(String(url))) {
|
const url = args[0]?.url || args[0] || response.url || "";
|
||||||
response.clone().text().then((text) => {
|
const urlText = String(url);
|
||||||
rememberSunoResponse(url, tryParseJson(text) || text);
|
if (/suno/i.test(urlText) && !/agg-receiver-service|datadoghq|braze|sprig|cloudflareinsights/i.test(urlText)) {
|
||||||
}).catch(() => {});
|
response.clone().text().then((text) => {
|
||||||
}
|
rememberSunoResponse(url, tryParseJson(text) || text);
|
||||||
return response;
|
}).catch(() => {});
|
||||||
|
}
|
||||||
|
}).catch(() => {});
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -969,7 +972,7 @@
|
|||||||
}) || null;
|
}) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findTrackRowElement(track) {
|
function findTrackRowElementNow(track) {
|
||||||
const rows = getVisibleLibraryRows();
|
const rows = getVisibleLibraryRows();
|
||||||
const index = getTrackVisibleIndex(track, rows);
|
const index = getTrackVisibleIndex(track, rows);
|
||||||
if (index >= 0) return rows[index].element;
|
if (index >= 0) return rows[index].element;
|
||||||
@@ -978,6 +981,42 @@
|
|||||||
return rows.find((row) => row.normalized.includes(title))?.element || null;
|
return rows.find((row) => row.normalized.includes(title))?.element || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPageScroller() {
|
||||||
|
return document.scrollingElement || document.documentElement || document.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function findTrackRowElement(track, statusTarget) {
|
||||||
|
const current = findTrackRowElementNow(track);
|
||||||
|
if (current) return current;
|
||||||
|
|
||||||
|
const scroller = getPageScroller();
|
||||||
|
const originalTop = scroller.scrollTop || window.scrollY || 0;
|
||||||
|
const maxSteps = 50;
|
||||||
|
const step = Math.max(260, Math.floor(window.innerHeight * 0.72));
|
||||||
|
|
||||||
|
setStatus(statusTarget, `SUNO 화면에서 곡 행 찾는 중: ${track.title || track.id}`);
|
||||||
|
scroller.scrollTop = 0;
|
||||||
|
window.scrollTo?.(0, 0);
|
||||||
|
await sleep(450);
|
||||||
|
|
||||||
|
for (let stepIndex = 0; stepIndex <= maxSteps; stepIndex += 1) {
|
||||||
|
const found = findTrackRowElementNow(track);
|
||||||
|
if (found) return found;
|
||||||
|
|
||||||
|
const before = scroller.scrollTop || window.scrollY || 0;
|
||||||
|
scroller.scrollTop = before + step;
|
||||||
|
window.scrollTo?.(0, before + step);
|
||||||
|
await sleep(260);
|
||||||
|
const after = scroller.scrollTop || window.scrollY || 0;
|
||||||
|
if (Math.abs(after - before) < 4) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
scroller.scrollTop = originalTop;
|
||||||
|
window.scrollTo?.(0, originalTop);
|
||||||
|
await sleep(200);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function findMoreButtonInRow(row) {
|
function findMoreButtonInRow(row) {
|
||||||
if (!row) return null;
|
if (!row) return null;
|
||||||
const buttons = [...row.querySelectorAll("button, [role='button']")];
|
const buttons = [...row.querySelectorAll("button, [role='button']")];
|
||||||
@@ -1001,8 +1040,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function clickSunoUiDownload(track, format, statusTarget) {
|
async function clickSunoUiDownload(track, format, statusTarget) {
|
||||||
const row = findTrackRowElement(track);
|
const row = await findTrackRowElement(track, statusTarget);
|
||||||
if (!row) throw new Error("현재 화면에서 곡 행을 못 찾았어. SUNO 목록에서 그 곡이 보이게 스크롤한 뒤 다시 눌러줘.");
|
if (!row) throw new Error("SUNO 화면을 훑어도 곡 행을 못 찾았어. 필터/검색 때문에 목록에 안 보이는지 확인해줘.");
|
||||||
const moreButton = findMoreButtonInRow(row);
|
const moreButton = findMoreButtonInRow(row);
|
||||||
if (!moreButton) throw new Error("곡의 ... 메뉴 버튼을 못 찾았어.");
|
if (!moreButton) throw new Error("곡의 ... 메뉴 버튼을 못 찾았어.");
|
||||||
|
|
||||||
@@ -1814,15 +1853,15 @@
|
|||||||
</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(UI)</button>
|
||||||
<button class="cgs-btn cgs-wide" type="button" data-cgs-process-one-wav>선택 1곡 WAV(UI)</button>
|
<button class="cgs-btn cgs-wide" type="button" data-cgs-process-one-wav>선택 1곡 WAV(UI)</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(UI)</button>
|
||||||
<button class="cgs-btn cgs-primary cgs-wide" type="button" data-cgs-process-selected-wav>선택항목 WAV(UI)</button>
|
<button class="cgs-btn cgs-primary cgs-wide" type="button" data-cgs-process-selected-wav>선택항목 WAV(UI)</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="cgs-row">
|
<div class="cgs-row">
|
||||||
<button class="cgs-btn cgs-wide" type="button" data-cgs-ui-download-mp3>SUNO UI MP3 클릭</button>
|
<button class="cgs-btn cgs-wide" type="button" data-cgs-ui-download-mp3>SUNO UI MP3 재시도</button>
|
||||||
<button class="cgs-btn cgs-wide" type="button" data-cgs-ui-download-wav>SUNO UI WAV 재시도</button>
|
<button class="cgs-btn cgs-wide" type="button" data-cgs-ui-download-wav>SUNO UI WAV 재시도</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="cgs-row">
|
<div class="cgs-row">
|
||||||
@@ -2035,7 +2074,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
body.querySelector("[data-cgs-process-one-mp3]").addEventListener("click", async () => {
|
body.querySelector("[data-cgs-process-one-mp3]").addEventListener("click", async () => {
|
||||||
await processSelectedTrack("mp3");
|
await clickSelectedSunoUiDownloads("mp3", { one: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
body.querySelector("[data-cgs-process-one-wav]").addEventListener("click", async () => {
|
body.querySelector("[data-cgs-process-one-wav]").addEventListener("click", async () => {
|
||||||
@@ -2043,7 +2082,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
body.querySelector("[data-cgs-process-selected-mp3]").addEventListener("click", async () => {
|
body.querySelector("[data-cgs-process-selected-mp3]").addEventListener("click", async () => {
|
||||||
await processSelectedTracks("mp3");
|
await clickSelectedSunoUiDownloads("mp3");
|
||||||
});
|
});
|
||||||
|
|
||||||
body.querySelector("[data-cgs-process-selected-wav]").addEventListener("click", async () => {
|
body.querySelector("[data-cgs-process-selected-wav]").addEventListener("click", async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user