Update app.js
Browse files
app.js
CHANGED
|
@@ -733,12 +733,15 @@ let localStream = null; // Mikrofon-Stream
|
|
| 733 |
let activeCalls = {}; // { peerId: Call }
|
| 734 |
let activeAudios = {}; // { peerId: <audio> }
|
| 735 |
|
| 736 |
-
// Peer-ID
|
| 737 |
-
// (damit man nach Reload reconnecten kann)
|
| 738 |
function makePeerId(username, vcId) {
|
| 739 |
-
//
|
| 740 |
-
|
| 741 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 742 |
}
|
| 743 |
|
| 744 |
async function joinVoice(vcId, vcName) {
|
|
@@ -760,15 +763,13 @@ async function joinVoice(vcId, vcName) {
|
|
| 760 |
|
| 761 |
const peerId = makePeerId(currentUser.username, vcId);
|
| 762 |
|
| 763 |
-
// Alten Peer aufräumen
|
| 764 |
-
if (myPeer && !myPeer.destroyed) {
|
| 765 |
-
myPeer.destroy();
|
| 766 |
-
myPeer = null;
|
| 767 |
-
}
|
| 768 |
|
| 769 |
-
// PeerJS
|
| 770 |
myPeer = new Peer(peerId, {
|
| 771 |
-
host: 'peerjs
|
|
|
|
| 772 |
secure: true,
|
| 773 |
path: '/',
|
| 774 |
debug: 0,
|
|
@@ -776,6 +777,7 @@ async function joinVoice(vcId, vcName) {
|
|
| 776 |
iceServers: [
|
| 777 |
{ urls: 'stun:stun.l.google.com:19302' },
|
| 778 |
{ urls: 'stun:stun1.l.google.com:19302' },
|
|
|
|
| 779 |
]
|
| 780 |
}
|
| 781 |
});
|
|
@@ -817,17 +819,31 @@ async function joinVoice(vcId, vcName) {
|
|
| 817 |
});
|
| 818 |
|
| 819 |
myPeer.on('error', (err) => {
|
| 820 |
-
|
| 821 |
if (err.type === 'unavailable-id') {
|
| 822 |
-
|
| 823 |
-
|
| 824 |
-
|
| 825 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 826 |
apiSave();
|
| 827 |
-
|
| 828 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 829 |
} else {
|
| 830 |
-
console.warn('[Voice] Peer-Fehler:', err.type, err.message);
|
| 831 |
showToast('🔊 Voice-Fehler: ' + err.type, 'var(--warn)');
|
| 832 |
}
|
| 833 |
});
|
|
|
|
| 733 |
let activeCalls = {}; // { peerId: Call }
|
| 734 |
let activeAudios = {}; // { peerId: <audio> }
|
| 735 |
|
| 736 |
+
// Peer-ID: kurzer Hash damit sie garantiert valid und eindeutig ist
|
|
|
|
| 737 |
function makePeerId(username, vcId) {
|
| 738 |
+
// Nur lowercase alphanumeric + Bindestrich erlaubt
|
| 739 |
+
// Einfacher deterministischer Hash
|
| 740 |
+
const raw = (username + '_' + vcId).toLowerCase();
|
| 741 |
+
let h = 5381;
|
| 742 |
+
for (let i = 0; i < raw.length; i++) h = ((h << 5) + h) ^ raw.charCodeAt(i);
|
| 743 |
+
const hash = Math.abs(h).toString(16).slice(0, 8);
|
| 744 |
+
return 'nc-' + username.toLowerCase().replace(/[^a-z0-9]/g, '') + '-' + hash;
|
| 745 |
}
|
| 746 |
|
| 747 |
async function joinVoice(vcId, vcName) {
|
|
|
|
| 763 |
|
| 764 |
const peerId = makePeerId(currentUser.username, vcId);
|
| 765 |
|
| 766 |
+
// Alten Peer aufräumen
|
| 767 |
+
if (myPeer && !myPeer.destroyed) { myPeer.destroy(); myPeer = null; }
|
|
|
|
|
|
|
|
|
|
| 768 |
|
| 769 |
+
// PeerJS mit dem offiziellen 0.peerjs.com Server
|
| 770 |
myPeer = new Peer(peerId, {
|
| 771 |
+
host: '0.peerjs.com',
|
| 772 |
+
port: 443,
|
| 773 |
secure: true,
|
| 774 |
path: '/',
|
| 775 |
debug: 0,
|
|
|
|
| 777 |
iceServers: [
|
| 778 |
{ urls: 'stun:stun.l.google.com:19302' },
|
| 779 |
{ urls: 'stun:stun1.l.google.com:19302' },
|
| 780 |
+
{ urls: 'stun:stun2.l.google.com:19302' },
|
| 781 |
]
|
| 782 |
}
|
| 783 |
});
|
|
|
|
| 819 |
});
|
| 820 |
|
| 821 |
myPeer.on('error', (err) => {
|
| 822 |
+
console.warn('[Voice] Peer-Fehler:', err.type, err.message);
|
| 823 |
if (err.type === 'unavailable-id') {
|
| 824 |
+
// ID besetzt → zufälligen Suffix anhängen und neu verbinden
|
| 825 |
+
if (myPeer && !myPeer.destroyed) { myPeer.destroy(); myPeer = null; }
|
| 826 |
+
const fallbackId = makePeerId(currentUser.username, vcId) + '-' + Math.random().toString(36).slice(2,6);
|
| 827 |
+
myPeer = new Peer(fallbackId, {
|
| 828 |
+
host: '0.peerjs.com', port: 443, secure: true, path: '/',
|
| 829 |
+
config: { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }
|
| 830 |
+
});
|
| 831 |
+
myPeer.on('open', (id) => {
|
| 832 |
+
if (!DB.voice[vcId]) DB.voice[vcId] = {};
|
| 833 |
+
DB.voice[vcId][currentUser.username] = { name: currentUser.username, peerId: id, muted: false, ts: Date.now() };
|
| 834 |
apiSave();
|
| 835 |
+
const others = Object.entries(DB.voice[vcId] || {}).filter(([u]) => u !== currentUser.username);
|
| 836 |
+
for (const [, data] of others) { if (data.peerId) callPeer(data.peerId); }
|
| 837 |
+
});
|
| 838 |
+
myPeer.on('call', (call) => { call.answer(localStream); handleCallStream(call); });
|
| 839 |
+
myPeer.on('error', (e) => showToast('🔊 Voice-Fehler: ' + e.type, 'var(--warn)'));
|
| 840 |
+
} else if (err.type === 'peer-unavailable') {
|
| 841 |
+
// Anderer Peer nicht erreichbar - ignorieren, wird beim nächsten Poll nochmal versucht
|
| 842 |
+
console.warn('[Voice] Peer nicht erreichbar:', err.message);
|
| 843 |
+
} else if (err.type === 'network' || err.type === 'server-error') {
|
| 844 |
+
showToast('🔊 Voice-Verbindungsfehler, versuche Neuverbindung...', 'var(--warn)');
|
| 845 |
+
setTimeout(() => { if (voiceActive) myPeer?.reconnect(); }, 2000);
|
| 846 |
} else {
|
|
|
|
| 847 |
showToast('🔊 Voice-Fehler: ' + err.type, 'var(--warn)');
|
| 848 |
}
|
| 849 |
});
|