Untitled
javascript
8 hours ago
4.4 KB
2
Indexable
(function () {
const OBS_URL = "ws://127.0.0.1:4455";
const OBS_PASSWORD = "";
const TRIGGER = "Roundabout";
const TARGET_SCENE = "Jantar";
const MAX_START_PROGRESS = 15000;
const DEBUG = true;
const DEBUG_LINES = 12;
let socket;
let identified = false;
let requestSeq = 0;
let reconnectDelay = 1000;
let reconnecting = false;
let firedTrack = "";
const lines = [];
let panel = null;
function debug(message) {
if (!DEBUG) return;
lines.push(new Date().toLocaleTimeString() + " " + message);
if (lines.length > DEBUG_LINES) lines.shift();
if (!document.body) return;
if (!panel) {
panel = document.createElement("div");
panel.style.cssText =
"position:fixed;top:8px;left:8px;z-index:99999;max-width:560px;" +
"padding:8px 10px;border-radius:6px;background:rgba(0,0,0,.75);" +
"color:#4ade80;font:12px/1.5 monospace;white-space:pre;pointer-events:none";
document.body.appendChild(panel);
}
panel.textContent = lines.join("\n");
}
function sha256(text) {
return crypto.subtle
.digest("SHA-256", new TextEncoder().encode(text))
.then(digest => btoa(String.fromCharCode(...new Uint8Array(digest))));
}
function buildAuth(salt, challenge) {
return sha256(OBS_PASSWORD + salt).then(secret => sha256(secret + challenge));
}
function send(data) {
socket.send(JSON.stringify(data));
}
function setScene(sceneName) {
send({
op: 6,
d: {
requestType: "SetCurrentProgramScene",
requestId: `req-${++requestSeq}`,
requestData: { sceneName },
},
});
}
function connect() {
reconnecting = false;
socket = new WebSocket(OBS_URL);
debug("conectando em " + OBS_URL);
socket.onmessage = async ({ data }) => {
const message = JSON.parse(data);
if (message.op === 0) {
const auth = message.d.authentication;
send({
op: 1,
d: {
rpcVersion: 1,
eventSubscriptions: 0,
authentication: auth && (await buildAuth(auth.salt, auth.challenge)),
},
});
}
if (message.op === 2) {
identified = true;
reconnectDelay = 1000;
debug("identificado no OBS");
}
if (message.op === 7 && !message.d.requestStatus.result) {
debug("erro: " + message.d.requestType + " — " + message.d.requestStatus.code);
}
};
socket.onclose = () => {
if (reconnecting) return;
reconnecting = true;
debug("desconectado — retry em " + reconnectDelay + "ms");
setTimeout(connect, reconnectDelay);
reconnectDelay = Math.min(reconnectDelay * 2, 30000);
};
}
connect();
window.spotify.onUpdate(state => {
const track = state.trackId || state.trackName;
if (!track || !state.isPlaying || track === firedTrack) return;
if (!state.trackName?.includes(TRIGGER)) return;
debug(state.trackName + " em " + Math.round(state.progressMs / 1000) + "s");
if (state.progressMs > MAX_START_PROGRESS) {
debug("já em andamento — não troca");
return;
}
if (!identified) {
debug("gatilho perdido — OBS offline");
return;
}
firedTrack = track;
debug("trocando pra cena " + TARGET_SCENE);
setScene(TARGET_SCENE);
});
})();Editor is loading...
Leave a Comment