Add local Suno companion service
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name ChatGPT to Suno Prompt Copier
|
||||
// @namespace local.suno-helper
|
||||
// @version 0.4.3
|
||||
// @version 0.5.0
|
||||
// @description Copy structured ChatGPT song prompt versions into Suno fields.
|
||||
// @author local
|
||||
// @match https://chatgpt.com/*
|
||||
@@ -13,6 +13,8 @@
|
||||
// @connect cdn*.suno.ai
|
||||
// @connect *.suno.com
|
||||
// @connect studio-api-prod.suno.com
|
||||
// @connect 127.0.0.1
|
||||
// @connect localhost
|
||||
// @run-at document-start
|
||||
// @grant GM_addStyle
|
||||
// @grant GM_getValue
|
||||
@@ -953,6 +955,37 @@
|
||||
setStatus(statusTarget, `${preparedTracks.length}곡 manifest 저장. 이제 run_process_suno_library.ps1 실행하면 정리/FLAC 변환돼.`);
|
||||
}
|
||||
|
||||
async function postToCompanion(tracks, statusTarget) {
|
||||
if (!tracks.length) {
|
||||
setStatus(statusTarget, "보낼 곡을 못 찾았어. 라이브러리 곡 감지를 먼저 해줘.");
|
||||
return;
|
||||
}
|
||||
const preparedTracks = [];
|
||||
for (let index = 0; index < tracks.length; index += 1) {
|
||||
const track = { ...tracks[index] };
|
||||
setStatus(statusTarget, `${index + 1}/${tracks.length} WAV 준비 중: ${track.title || track.id}`);
|
||||
track.wavUrl = await requestSunoWavUrl(track);
|
||||
preparedTracks.push(track);
|
||||
}
|
||||
const manifest = {
|
||||
pageUrl: location.href,
|
||||
capturedAt: new Date().toISOString(),
|
||||
count: preparedTracks.length,
|
||||
tracks: preparedTracks,
|
||||
};
|
||||
const response = await fetch("http://127.0.0.1:17873/process", {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify(manifest),
|
||||
});
|
||||
const text = await response.text();
|
||||
if (!response.ok) {
|
||||
throw new Error(text || `${response.status} ${response.statusText}`);
|
||||
}
|
||||
const data = tryParseJson(text) || {};
|
||||
setStatus(statusTarget, `로컬 처리 시작: ${data.jobId || "job"} / ${data.log || "companion console 확인"}`);
|
||||
}
|
||||
|
||||
async function bootSuno() {
|
||||
const body = createPanel("Suno Prompt Paste");
|
||||
const slots = await readSlots();
|
||||
@@ -979,6 +1012,9 @@
|
||||
<div class="cgs-row">
|
||||
<button class="cgs-btn cgs-primary cgs-wide" type="button" data-cgs-export-library>처리용 manifest 저장</button>
|
||||
</div>
|
||||
<div class="cgs-row">
|
||||
<button class="cgs-btn cgs-primary cgs-wide" type="button" data-cgs-send-companion>로컬 프로그램으로 처리</button>
|
||||
</div>
|
||||
<div class="cgs-row">
|
||||
<button class="cgs-btn cgs-wide" type="button" data-cgs-download-library>브라우저 일괄 다운로드</button>
|
||||
</div>
|
||||
@@ -1063,6 +1099,35 @@
|
||||
updateSummary();
|
||||
await exportSunoManifest(libraryTracks, body);
|
||||
});
|
||||
|
||||
body.querySelector("[data-cgs-send-companion]").addEventListener("click", async () => {
|
||||
if (!libraryTracks.length) libraryTracks = scanSunoLibraryTracks();
|
||||
updateSummary();
|
||||
try {
|
||||
await postToCompanion(libraryTracks, body);
|
||||
} catch (error) {
|
||||
setStatus(body, `로컬 프로그램 연결 실패: ${error.message || error}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function safeBootSuno() {
|
||||
try {
|
||||
bootSuno();
|
||||
} catch (error) {
|
||||
console.error("[ChatGPT to Suno]", error);
|
||||
createErrorPanel(error);
|
||||
}
|
||||
}
|
||||
|
||||
function safeBootChatGPT() {
|
||||
try {
|
||||
const versions = parseVersions(getConversationText());
|
||||
if (versions.length) bootChatGPT();
|
||||
} catch (error) {
|
||||
console.error("[ChatGPT to Suno]", error);
|
||||
createErrorPanel(error);
|
||||
}
|
||||
}
|
||||
|
||||
function startApp() {
|
||||
@@ -1071,23 +1136,18 @@
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (isChatGPT) bootChatGPT();
|
||||
if (isSuno) bootSuno();
|
||||
} catch (error) {
|
||||
console.error("[ChatGPT to Suno]", error);
|
||||
createErrorPanel(error);
|
||||
}
|
||||
if (isSuno) safeBootSuno();
|
||||
if (isChatGPT) safeBootChatGPT();
|
||||
|
||||
setInterval(() => {
|
||||
if (!document.querySelector("#cgs-panel")) {
|
||||
try {
|
||||
if (isChatGPT) bootChatGPT();
|
||||
if (isSuno) bootSuno();
|
||||
} catch (error) {
|
||||
console.error("[ChatGPT to Suno]", error);
|
||||
createErrorPanel(error);
|
||||
}
|
||||
if (isSuno && !document.querySelector("#cgs-panel")) {
|
||||
safeBootSuno();
|
||||
}
|
||||
if (isChatGPT) {
|
||||
const hasPanel = Boolean(document.querySelector("#cgs-panel"));
|
||||
const hasVersions = parseVersions(getConversationText()).length > 0;
|
||||
if (hasVersions && !hasPanel) safeBootChatGPT();
|
||||
if (!hasVersions && hasPanel) document.querySelector("#cgs-panel")?.remove();
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user