114 lines
3.7 KiB
JavaScript
114 lines
3.7 KiB
JavaScript
let fingerprint = null;
|
|
|
|
const OriginalRTC = window.RTCPeerConnection;
|
|
const OriginalSend = WebSocket.prototype.send;
|
|
|
|
window.RTCPeerConnection = function (...args) {
|
|
const pc = new OriginalRTC(...args);
|
|
const originalCreateOffer = pc.createOffer.bind(pc);
|
|
|
|
pc.createOffer = async function (options) {
|
|
const offer = await originalCreateOffer(options);
|
|
|
|
if (offer.sdp) {
|
|
const lines = offer.sdp.split("\n");
|
|
for (const line of lines) {
|
|
if (line.includes("a=fingerprint")) {
|
|
fingerprint = line.split("a=fingerprint:")[1]?.trim() ?? null;
|
|
}
|
|
}
|
|
}
|
|
|
|
return offer;
|
|
};
|
|
|
|
return pc;
|
|
};
|
|
|
|
Object.setPrototypeOf(window.RTCPeerConnection, OriginalRTC);
|
|
Object.setPrototypeOf(window.RTCPeerConnection.prototype, OriginalRTC.prototype);
|
|
|
|
WebSocket.prototype.send = function (data) {
|
|
try {
|
|
let parsed = JSON.parse(data);
|
|
|
|
if (parsed.d && typeof parsed.d === "object") {
|
|
for (const [key, value] of Object.entries(parsed.d)) {
|
|
if (typeof value === "string" && (value.includes("a=extmap") || value.includes("a=ice-") || value.includes("a=rtpmap"))) {
|
|
if (!value.includes("a=fingerprint")) {
|
|
parsed.d[key] = addFingerprintToSdp(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return OriginalSend.call(this, JSON.stringify(parsed));
|
|
}
|
|
} catch (e) {}
|
|
|
|
return OriginalSend.call(this, data);
|
|
};
|
|
|
|
function addFingerprintToSdp(sdp) {
|
|
if (!fingerprint) return sdp;
|
|
|
|
const lines = sdp.split("\n");
|
|
const result = [];
|
|
let added = false;
|
|
|
|
for (const line of lines) {
|
|
result.push(line);
|
|
if (!added && line.includes("a=ice-pwd:")) {
|
|
result.push(`a=fingerprint:${fingerprint}`);
|
|
added = true;
|
|
}
|
|
}
|
|
|
|
return result.join("\n");
|
|
}
|
|
|
|
if (window.location.pathname.startsWith("/channel")) {
|
|
const observer = new MutationObserver(() => {
|
|
const screenshareButton = document.querySelector('[aria-label="Share your screen"]');
|
|
if (screenshareButton) {
|
|
screenshareButton.addEventListener("click", async () => {
|
|
try {
|
|
const displayStream = await navigator.mediaDevices.getDisplayMedia({
|
|
video: {
|
|
width: { ideal: 1920 },
|
|
height: { ideal: 1080 },
|
|
frameRate: { ideal: 30 }
|
|
},
|
|
audio: false
|
|
});
|
|
|
|
const audioStream = await navigator.mediaDevices.getUserMedia({
|
|
audio: {
|
|
echoCancellation: { ideal: true },
|
|
autoGainControl: { ideal: true },
|
|
noiseSuppression: { ideal: true }
|
|
}
|
|
});
|
|
|
|
const combinedStream = new MediaStream();
|
|
|
|
displayStream.getVideoTracks().forEach(track => {
|
|
combinedStream.addTrack(track);
|
|
});
|
|
|
|
audioStream.getAudioTracks().forEach(track => {
|
|
combinedStream.addTrack(track);
|
|
});
|
|
|
|
displayStream.getVideoTracks()[0].onended = () => {
|
|
audioStream.getTracks().forEach(track => track.stop());
|
|
};
|
|
} catch (error) {
|
|
console.error("Screenshare failed:", error);
|
|
}
|
|
}, { once: true });
|
|
observer.disconnect();
|
|
}
|
|
});
|
|
|
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
} |