more VC work
This commit is contained in:
parent
152ea41b6a
commit
5cdb4d2184
6 changed files with 279 additions and 127 deletions
|
@ -14,6 +14,7 @@ import{channeljson,embedjson,messageCreateJson,messagejson,readyjson,startTyping
|
||||||
import{ MarkDown }from"./markdown.js";
|
import{ MarkDown }from"./markdown.js";
|
||||||
import{ Member }from"./member.js";
|
import{ Member }from"./member.js";
|
||||||
import { Voice } from "./voice.js";
|
import { Voice } from "./voice.js";
|
||||||
|
import { User } from "./user.js";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface NotificationOptions {
|
interface NotificationOptions {
|
||||||
|
@ -332,8 +333,9 @@ class Channel extends SnowFlake{
|
||||||
}
|
}
|
||||||
this.setUpInfiniteScroller();
|
this.setUpInfiniteScroller();
|
||||||
this.perminfo ??= {};
|
this.perminfo ??= {};
|
||||||
if(this.type===2){
|
if(this.type===2&&this.localuser.voiceFactory){
|
||||||
this.voice=new Voice(this);
|
this.voice=this.localuser.voiceFactory.makeVoice(this.guild.id,this.id,{bitrate:this.bitrate});
|
||||||
|
this.setUpVoice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
get perminfo(){
|
get perminfo(){
|
||||||
|
@ -456,6 +458,7 @@ class Channel extends SnowFlake{
|
||||||
get visable(){
|
get visable(){
|
||||||
return this.hasPermission("VIEW_CHANNEL");
|
return this.hasPermission("VIEW_CHANNEL");
|
||||||
}
|
}
|
||||||
|
voiceUsers=new WeakRef(document.createElement("div"));
|
||||||
createguildHTML(admin = false): HTMLDivElement{
|
createguildHTML(admin = false): HTMLDivElement{
|
||||||
const div = document.createElement("div");
|
const div = document.createElement("div");
|
||||||
this.html = new WeakRef(div);
|
this.html = new WeakRef(div);
|
||||||
|
@ -562,6 +565,7 @@ class Channel extends SnowFlake{
|
||||||
const decoration = document.createElement("span");
|
const decoration = document.createElement("span");
|
||||||
div.appendChild(decoration);
|
div.appendChild(decoration);
|
||||||
decoration.classList.add("space", "svgtheme", "svg-voice");
|
decoration.classList.add("space", "svgtheme", "svg-voice");
|
||||||
|
|
||||||
}else if(this.type === 5){
|
}else if(this.type === 5){
|
||||||
//
|
//
|
||||||
const decoration = document.createElement("span");
|
const decoration = document.createElement("span");
|
||||||
|
@ -574,9 +578,51 @@ class Channel extends SnowFlake{
|
||||||
div.onclick = _=>{
|
div.onclick = _=>{
|
||||||
this.getHTML();
|
this.getHTML();
|
||||||
};
|
};
|
||||||
|
if(this.type===2){
|
||||||
|
const voiceUsers=document.createElement("div");
|
||||||
|
div.append(voiceUsers);
|
||||||
|
this.voiceUsers=new WeakRef(voiceUsers);
|
||||||
|
this.updateVoiceUsers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return div;
|
return div;
|
||||||
}
|
}
|
||||||
|
async setUpVoice(){
|
||||||
|
if(!this.voice) return;
|
||||||
|
this.voice.onMemberChange=async (memb,joined)=>{
|
||||||
|
console.log(memb,joined);
|
||||||
|
if(typeof memb!=="string"){
|
||||||
|
await Member.new(memb,this.guild);
|
||||||
|
}
|
||||||
|
this.updateVoiceUsers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async updateVoiceUsers(){
|
||||||
|
const voiceUsers=this.voiceUsers.deref();
|
||||||
|
if(!voiceUsers||!this.voice) return;
|
||||||
|
console.warn(this.voice.userids)
|
||||||
|
|
||||||
|
const html=(await Promise.all(this.voice.userids.entries().toArray().map(async _=>{
|
||||||
|
const user=await User.resolve(_[0],this.localuser);
|
||||||
|
console.log(user);
|
||||||
|
const member=await Member.resolveMember(user,this.guild);
|
||||||
|
const array=[member,_[1]] as [Member, typeof _[1]];
|
||||||
|
return array;
|
||||||
|
}))).flatMap(([member,_obj])=>{
|
||||||
|
if(!member){
|
||||||
|
console.warn("This is weird, member doesn't exist :P");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const div=document.createElement("div");
|
||||||
|
const span=document.createElement("span");
|
||||||
|
span.textContent=member.name;
|
||||||
|
div.append(span);
|
||||||
|
return div;
|
||||||
|
});
|
||||||
|
|
||||||
|
voiceUsers.innerHTML="";
|
||||||
|
voiceUsers.append(...html);
|
||||||
|
}
|
||||||
get myhtml(){
|
get myhtml(){
|
||||||
if(this.html){
|
if(this.html){
|
||||||
return this.html.deref();
|
return this.html.deref();
|
||||||
|
@ -840,8 +886,7 @@ class Channel extends SnowFlake{
|
||||||
this.rendertyping();
|
this.rendertyping();
|
||||||
this.localuser.getSidePannel();
|
this.localuser.getSidePannel();
|
||||||
if(this.voice){
|
if(this.voice){
|
||||||
this.voice.onSatusChange=console.warn;
|
this.localuser.joinVoice(this);
|
||||||
this.voice.join();
|
|
||||||
}
|
}
|
||||||
await this.putmessages();
|
await this.putmessages();
|
||||||
await prom;
|
await prom;
|
||||||
|
@ -1329,11 +1374,7 @@ class Channel extends SnowFlake{
|
||||||
}
|
}
|
||||||
notititle(message: Message): string{
|
notititle(message: Message): string{
|
||||||
return(
|
return(
|
||||||
message.author.username +
|
message.author.username + " > " + this.guild.properties.name + " > " + this.name
|
||||||
" > " +
|
|
||||||
this.guild.properties.name +
|
|
||||||
" > " +
|
|
||||||
this.name
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
notify(message: Message, deep = 0){
|
notify(message: Message, deep = 0){
|
||||||
|
|
|
@ -35,18 +35,23 @@
|
||||||
<h2 id="serverName">Server Name</h2>
|
<h2 id="serverName">Server Name</h2>
|
||||||
</div>
|
</div>
|
||||||
<div id="channels"></div>
|
<div id="channels"></div>
|
||||||
<div class="flexltr" id="userdock">
|
<div class="flexttb" style="flex-shrink: 0;">
|
||||||
<div class="flexltr" id="userinfo">
|
<div class="flexltr" id="VoiceBox">
|
||||||
<img id="userpfp" class="pfp">
|
<span id="VoiceStatus"></span>
|
||||||
|
|
||||||
<div class="userflex">
|
|
||||||
<p id="username">USERNAME</p>
|
|
||||||
<p id="status">STATUS</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flexltr" id="userdock">
|
||||||
|
<div class="flexltr" id="userinfo">
|
||||||
|
<img id="userpfp" class="pfp">
|
||||||
|
|
||||||
<div id="user-actions">
|
<div class="userflex">
|
||||||
<span id="settings" class="svgtheme svg-settings"></span>
|
<p id="username">USERNAME</p>
|
||||||
|
<p id="status">STATUS</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="user-actions">
|
||||||
|
<span id="settings" class="svgtheme svg-settings"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,13 +5,13 @@ import{ AVoice }from"./audio.js";
|
||||||
import{ User }from"./user.js";
|
import{ User }from"./user.js";
|
||||||
import{ Dialog }from"./dialog.js";
|
import{ Dialog }from"./dialog.js";
|
||||||
import{ getapiurls, getBulkInfo, setTheme, Specialuser }from"./login.js";
|
import{ getapiurls, getBulkInfo, setTheme, Specialuser }from"./login.js";
|
||||||
import{channeljson,guildjson,mainuserjson,memberjson,memberlistupdatejson,messageCreateJson,presencejson,readyjson,startTypingjson,voiceupdate,wsjson,}from"./jsontypes.js";
|
import{channeljson,guildjson,mainuserjson,memberjson,memberlistupdatejson,messageCreateJson,presencejson,readyjson,startTypingjson,wsjson,}from"./jsontypes.js";
|
||||||
import{ Member }from"./member.js";
|
import{ Member }from"./member.js";
|
||||||
import{ Form, FormError, Options, Settings }from"./settings.js";
|
import{ Form, FormError, Options, Settings }from"./settings.js";
|
||||||
import{ MarkDown }from"./markdown.js";
|
import{ MarkDown }from"./markdown.js";
|
||||||
import { Bot } from "./bot.js";
|
import { Bot } from "./bot.js";
|
||||||
import { Role } from "./role.js";
|
import { Role } from "./role.js";
|
||||||
import { Voice } from "./voice.js";
|
import { VoiceFactory } from "./voice.js";
|
||||||
|
|
||||||
const wsCodesRetry = new Set([4000, 4003, 4005, 4007, 4008, 4009]);
|
const wsCodesRetry = new Set([4000, 4003, 4005, 4007, 4008, 4009]);
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ class Localuser{
|
||||||
errorBackoff = 0;
|
errorBackoff = 0;
|
||||||
channelids: Map<string, Channel> = new Map();
|
channelids: Map<string, Channel> = new Map();
|
||||||
readonly userMap: Map<string, User> = new Map();
|
readonly userMap: Map<string, User> = new Map();
|
||||||
|
voiceFactory?:VoiceFactory;
|
||||||
instancePing = {
|
instancePing = {
|
||||||
name: "Unknown",
|
name: "Unknown",
|
||||||
};
|
};
|
||||||
|
@ -74,6 +75,9 @@ class Localuser{
|
||||||
this.guildids = new Map();
|
this.guildids = new Map();
|
||||||
this.user = new User(ready.d.user, this);
|
this.user = new User(ready.d.user, this);
|
||||||
this.user.setstatus("online");
|
this.user.setstatus("online");
|
||||||
|
|
||||||
|
this.voiceFactory=new VoiceFactory({id:this.user.id});
|
||||||
|
this.handleVoice();
|
||||||
this.mfa_enabled = ready.d.user.mfa_enabled as boolean;
|
this.mfa_enabled = ready.d.user.mfa_enabled as boolean;
|
||||||
this.userinfo.username = this.user.username;
|
this.userinfo.username = this.user.username;
|
||||||
this.userinfo.pfpsrc = this.user.getpfpsrc();
|
this.userinfo.pfpsrc = this.user.getpfpsrc();
|
||||||
|
@ -117,6 +121,7 @@ class Localuser{
|
||||||
|
|
||||||
this.pingEndpoint();
|
this.pingEndpoint();
|
||||||
this.userinfo.updateLocal();
|
this.userinfo.updateLocal();
|
||||||
|
|
||||||
}
|
}
|
||||||
outoffocus(): void{
|
outoffocus(): void{
|
||||||
const servers = document.getElementById("servers") as HTMLDivElement;
|
const servers = document.getElementById("servers") as HTMLDivElement;
|
||||||
|
@ -477,15 +482,14 @@ class Localuser{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "VOICE_STATE_UPDATE":
|
case "VOICE_STATE_UPDATE":
|
||||||
if(this.waitingForVoice){
|
if(this.voiceFactory){
|
||||||
this.waitingForVoice(temp);
|
this.voiceFactory.voiceStateUpdate(temp)
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "VOICE_SERVER_UPDATE":
|
case "VOICE_SERVER_UPDATE":
|
||||||
if(this.currentVoice){
|
if(this.voiceFactory){
|
||||||
Voice.url=temp.d.endpoint;
|
this.voiceFactory.voiceServerUpdate(temp)
|
||||||
Voice.gotUrl();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -504,32 +508,30 @@ class Localuser{
|
||||||
}, this.heartbeat_interval);
|
}, this.heartbeat_interval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waitingForVoice?:((arg:voiceupdate|undefined)=>void);
|
get currentVoice(){
|
||||||
currentVoice?:Voice;
|
return this.voiceFactory?.currentVoice;
|
||||||
async joinVoice(voice:Voice){
|
}
|
||||||
if(this.currentVoice){
|
async joinVoice(channel:Channel){
|
||||||
this.currentVoice.leave();
|
if(!this.voiceFactory) return;
|
||||||
}
|
if(!this.ws) return;
|
||||||
this.currentVoice=voice;
|
this.ws.send(JSON.stringify(this.voiceFactory.joinVoice(channel.id,channel.guild.id)));
|
||||||
if(this.ws){
|
|
||||||
this.ws.send(JSON.stringify({
|
|
||||||
d:{
|
|
||||||
guild_id: voice.guild.id,
|
|
||||||
channel_id: voice.channel.id,
|
|
||||||
self_mute: true,//todo
|
|
||||||
self_deaf: false,//todo
|
|
||||||
self_video: false,//What is this? I have some guesses
|
|
||||||
flags: 2//?????
|
|
||||||
},
|
|
||||||
op:4
|
|
||||||
}));
|
|
||||||
if(this.waitingForVoice){
|
|
||||||
this.waitingForVoice(undefined);
|
|
||||||
}
|
|
||||||
return await new Promise<voiceupdate|undefined>((res)=>{this.waitingForVoice=res;})
|
|
||||||
}
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
changeVCStatus(status:string){
|
||||||
|
const statuselm=document.getElementById("VoiceStatus");
|
||||||
|
if(!statuselm) throw new Error("Missing status element");
|
||||||
|
statuselm.textContent=status;
|
||||||
|
}
|
||||||
|
handleVoice(){
|
||||||
|
if(this.voiceFactory){
|
||||||
|
this.voiceFactory.onJoin=voice=>{
|
||||||
|
voice.onSatusChange=status=>{
|
||||||
|
this.changeVCStatus(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
heartbeat_interval: number = 0;
|
heartbeat_interval: number = 0;
|
||||||
updateChannel(json: channeljson): void{
|
updateChannel(json: channeljson): void{
|
||||||
const guild = this.guildids.get(json.guild_id);
|
const guild = this.guildids.get(json.guild_id);
|
||||||
|
|
|
@ -2267,4 +2267,18 @@ form div{
|
||||||
>div{
|
>div{
|
||||||
opacity:.4;
|
opacity:.4;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#VoiceBox{
|
||||||
|
padding: .05in;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
align-content: center;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: .1in .1in 0 0;
|
||||||
|
border: solid .01in var(--black);
|
||||||
|
}
|
||||||
|
#VoiceStatus{
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
|
@ -301,7 +301,7 @@ class User extends SnowFlake{
|
||||||
localuser.info.api.toString() + "/users/" + id + "/profile",
|
localuser.info.api.toString() + "/users/" + id + "/profile",
|
||||||
{ headers: localuser.headers }
|
{ headers: localuser.headers }
|
||||||
).then(res=>res.json());
|
).then(res=>res.json());
|
||||||
return new User(json, localuser);
|
return new User(json.user, localuser);
|
||||||
}
|
}
|
||||||
|
|
||||||
changepfp(update: string | null): void{
|
changepfp(update: string | null): void{
|
||||||
|
|
|
@ -1,11 +1,80 @@
|
||||||
import { Channel } from "./channel.js";
|
import { memberjson, sdpback, voiceserverupdate, voiceupdate, webRTCSocket } from "./jsontypes.js";
|
||||||
import { sdpback, webRTCSocket } from "./jsontypes.js";
|
|
||||||
|
class VoiceFactory{
|
||||||
|
settings:{id:string};
|
||||||
|
constructor(usersettings:VoiceFactory["settings"]){
|
||||||
|
this.settings=usersettings;
|
||||||
|
}
|
||||||
|
voices=new Map<string,Map<string,Voice>>();
|
||||||
|
voiceChannels=new Map<string,Voice>();
|
||||||
|
currentVoice?:Voice;
|
||||||
|
guildUrlMap=new Map<string,{url?:string,geturl:Promise<void>,gotUrl:()=>void}>();
|
||||||
|
makeVoice(guildid:string,channelId:string,settings:Voice["settings"]){
|
||||||
|
let guild=this.voices.get(guildid);
|
||||||
|
if(!guild){
|
||||||
|
this.setUpGuild(guildid);
|
||||||
|
guild=new Map();
|
||||||
|
this.voices.set(guildid,guild);
|
||||||
|
}
|
||||||
|
const urlobj=this.guildUrlMap.get(guildid);
|
||||||
|
if(!urlobj) throw new Error("url Object doesn't exist (InternalError)");
|
||||||
|
const voice=new Voice(this.settings.id,settings,urlobj);
|
||||||
|
this.voiceChannels.set(channelId,voice);
|
||||||
|
guild.set(channelId,voice);
|
||||||
|
return voice;
|
||||||
|
}
|
||||||
|
onJoin=(_voice:Voice)=>{};
|
||||||
|
onLeave=(_voice:Voice)=>{};
|
||||||
|
joinVoice(channelId:string,guildId:string){
|
||||||
|
if(this.currentVoice){
|
||||||
|
this.currentVoice.leave();
|
||||||
|
}
|
||||||
|
const voice=this.voiceChannels.get(channelId);
|
||||||
|
if(!voice) throw new Error(`Voice ${channelId} does not exist`);
|
||||||
|
voice.join();
|
||||||
|
this.currentVoice=voice;
|
||||||
|
this.onJoin(voice);
|
||||||
|
return {
|
||||||
|
d:{
|
||||||
|
guild_id: guildId,
|
||||||
|
channel_id: channelId,
|
||||||
|
self_mute: true,//todo
|
||||||
|
self_deaf: false,//todo
|
||||||
|
self_video: false,//What is this? I have some guesses
|
||||||
|
flags: 2//?????
|
||||||
|
},
|
||||||
|
op:4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
userMap=new Map<string,Voice>();
|
||||||
|
voiceStateUpdate(update:voiceupdate){
|
||||||
|
|
||||||
|
const prev=this.userMap.get(update.d.user_id);
|
||||||
|
console.log(prev,this.userMap);
|
||||||
|
if(prev){
|
||||||
|
prev.disconnect(update.d.user_id);
|
||||||
|
this.onLeave(prev);
|
||||||
|
}
|
||||||
|
const voice=this.voiceChannels.get(update.d.channel_id);
|
||||||
|
if(voice){
|
||||||
|
this.userMap.set(update.d.user_id,voice);
|
||||||
|
voice.voiceupdate(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private setUpGuild(id:string){
|
||||||
|
const obj:{url?:string,geturl?:Promise<void>,gotUrl?:()=>void}={};
|
||||||
|
obj.geturl=new Promise<void>(res=>{obj.gotUrl=res});
|
||||||
|
this.guildUrlMap.set(id,obj as {geturl:Promise<void>,gotUrl:()=>void});
|
||||||
|
}
|
||||||
|
voiceServerUpdate(update:voiceserverupdate){
|
||||||
|
const obj=this.guildUrlMap.get(update.d.guild_id);
|
||||||
|
if(!obj) return;
|
||||||
|
obj.url=update.d.endpoint;
|
||||||
|
obj.gotUrl();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Voice{
|
class Voice{
|
||||||
owner:Channel;
|
|
||||||
static url?:string;
|
|
||||||
static gotUrl:()=>void;
|
|
||||||
static geturl=new Promise<void>(res=>{this.gotUrl=res})
|
|
||||||
private pstatus:string="not connected";
|
private pstatus:string="not connected";
|
||||||
public onSatusChange:(e:string)=>unknown=()=>{};
|
public onSatusChange:(e:string)=>unknown=()=>{};
|
||||||
set status(e:string){
|
set status(e:string){
|
||||||
|
@ -15,17 +84,13 @@ class Voice{
|
||||||
get status(){
|
get status(){
|
||||||
return this.pstatus;
|
return this.pstatus;
|
||||||
}
|
}
|
||||||
get channel(){
|
readonly userid:string;
|
||||||
return this.owner;
|
settings:{bitrate:number};
|
||||||
}
|
urlobj:{url?:string,geturl:Promise<void>,gotUrl:()=>void};
|
||||||
get guild(){
|
constructor(userid:string,settings:Voice["settings"],urlobj:Voice["urlobj"]){
|
||||||
return this.owner.owner;
|
this.userid=userid;
|
||||||
}
|
this.settings=settings;
|
||||||
get localuser(){
|
this.urlobj=urlobj;
|
||||||
return this.owner.localuser;
|
|
||||||
}
|
|
||||||
constructor(owner:Channel){
|
|
||||||
this.owner=owner;
|
|
||||||
}
|
}
|
||||||
pc?:RTCPeerConnection;
|
pc?:RTCPeerConnection;
|
||||||
ws?:WebSocket;
|
ws?:WebSocket;
|
||||||
|
@ -40,7 +105,28 @@ class Voice{
|
||||||
}
|
}
|
||||||
readonly users= new Map<number,string>();
|
readonly users= new Map<number,string>();
|
||||||
readonly speakingMap= new Map<string,number>();
|
readonly speakingMap= new Map<string,number>();
|
||||||
onSpeakingChange=(_:string,_2:number)=>{};
|
onSpeakingChange=(_userid:string,_speaking:number)=>{};
|
||||||
|
disconnect(userid:string){
|
||||||
|
console.warn(userid);
|
||||||
|
if(userid===this.userid){
|
||||||
|
this.leave();
|
||||||
|
}
|
||||||
|
const ssrc=this.speakingMap.get(userid);
|
||||||
|
|
||||||
|
if(ssrc){
|
||||||
|
this.users.delete(ssrc);
|
||||||
|
for(const thing of this.ssrcMap){
|
||||||
|
if(thing[1]===ssrc){
|
||||||
|
this.ssrcMap.delete(thing[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.speakingMap.delete(userid);
|
||||||
|
this.userids.delete(userid);
|
||||||
|
console.log(this.userids,userid);
|
||||||
|
//there's more for sure, but this is "good enough" for now
|
||||||
|
this.onMemberChange(userid,false);
|
||||||
|
}
|
||||||
packet(message:MessageEvent){
|
packet(message:MessageEvent){
|
||||||
const data=message.data
|
const data=message.data
|
||||||
if(typeof data === "string"){
|
if(typeof data === "string"){
|
||||||
|
@ -89,14 +175,7 @@ class Voice{
|
||||||
console.log(bundles);
|
console.log(bundles);
|
||||||
|
|
||||||
if(!this.offer) throw new Error("Offer is missing :P");
|
if(!this.offer) throw new Error("Offer is missing :P");
|
||||||
let cline:string|undefined;
|
let cline=sdp.split("\n").find(line=>line.startsWith("c="));
|
||||||
console.log(sdp);
|
|
||||||
for(const line of sdp.split("\n")){
|
|
||||||
if(line.startsWith("c=")){
|
|
||||||
cline=line;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!cline) throw new Error("c line wasn't found");
|
if(!cline) throw new Error("c line wasn't found");
|
||||||
const parsed1=Voice.parsesdp(sdp).medias[0];
|
const parsed1=Voice.parsesdp(sdp).medias[0];
|
||||||
//const parsed2=Voice.parsesdp(this.offer);
|
//const parsed2=Voice.parsesdp(this.offer);
|
||||||
|
@ -168,7 +247,6 @@ a=rtcp-mux\r`;
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
build+="\n";
|
build+="\n";
|
||||||
console.log(build);
|
|
||||||
return build;
|
return build;
|
||||||
}
|
}
|
||||||
counter?:string;
|
counter?:string;
|
||||||
|
@ -298,18 +376,19 @@ a=rtcp-mux\r`;
|
||||||
pc.addTransceiver("audio",{
|
pc.addTransceiver("audio",{
|
||||||
direction:"recvonly",
|
direction:"recvonly",
|
||||||
streams:[],
|
streams:[],
|
||||||
sendEncodings:[{active:true,maxBitrate:this.channel.bitrate}]
|
sendEncodings:[{active:true,maxBitrate:this.settings.bitrate}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for(let i=0;i<10;i++){
|
for(let i=0;i<10;i++){
|
||||||
pc.addTransceiver("video",{
|
pc.addTransceiver("video",{
|
||||||
direction:"recvonly",
|
direction:"recvonly",
|
||||||
streams:[],
|
streams:[],
|
||||||
sendEncodings:[{active:true,maxBitrate:this.channel.bitrate}]
|
sendEncodings:[{active:true,maxBitrate:this.settings.bitrate}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.counter=data.d.sdp;
|
this.counter=data.d.sdp;
|
||||||
pc.ontrack = async (e) => {
|
pc.ontrack = async (e) => {
|
||||||
|
this.status="Done";
|
||||||
if(e.track.kind==="video"){
|
if(e.track.kind==="video"){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -496,58 +575,69 @@ a=rtcp-mux\r`;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
open=false;
|
||||||
async join(){
|
async join(){
|
||||||
console.warn("Joining");
|
console.warn("Joining");
|
||||||
|
this.open=true
|
||||||
this.status="waiting for main WS";
|
this.status="waiting for main WS";
|
||||||
const json = await this.localuser.joinVoice(this);
|
}
|
||||||
if(!json) {
|
onMemberChange=(_member:memberjson|string,_joined:boolean)=>{};
|
||||||
this.status="bad responce from WS";
|
userids=new Map<string,{}>();
|
||||||
return;
|
async voiceupdate(update:voiceupdate){
|
||||||
};
|
console.log("Update!");
|
||||||
if(!Voice.url){
|
this.userids.set(update.d.member.id,{deaf:update.d.deaf,muted:update.d.mute});
|
||||||
this.status="waiting for Voice URL";
|
this.onMemberChange(update.d.member,true);
|
||||||
await Voice.geturl;
|
if(update.d.member.id===this.userid&&this.open){
|
||||||
}
|
if(!update) {
|
||||||
if(this.localuser.currentVoice!==this){this.status="closed";return}
|
this.status="bad responce from WS";
|
||||||
const ws=new WebSocket("ws://"+Voice.url as string);
|
return;
|
||||||
this.ws=ws;
|
};
|
||||||
ws.onclose=()=>{
|
if(!this.urlobj.url){
|
||||||
this.leave();
|
this.status="waiting for Voice URL";
|
||||||
}
|
await this.urlobj.geturl;
|
||||||
this.status="waiting for WS to open";
|
if(!this.open){this.leave();return}
|
||||||
ws.addEventListener("message",(m)=>{
|
|
||||||
this.packet(m);
|
|
||||||
})
|
|
||||||
await new Promise<void>(res=>{
|
|
||||||
ws.addEventListener("open",()=>{
|
|
||||||
res()
|
|
||||||
})
|
|
||||||
});
|
|
||||||
this.status="waiting for WS to authorize";
|
|
||||||
ws.send(JSON.stringify({
|
|
||||||
"op": 0,
|
|
||||||
"d": {
|
|
||||||
server_id: this.guild.id,
|
|
||||||
user_id: json.d.user_id,
|
|
||||||
session_id: json.d.session_id,
|
|
||||||
token: json.d.token,
|
|
||||||
video: false,
|
|
||||||
"streams": [
|
|
||||||
{
|
|
||||||
type: "video",
|
|
||||||
rid: "100",
|
|
||||||
quality: 100
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}));
|
|
||||||
/*
|
const ws=new WebSocket("ws://"+this.urlobj.url as string);
|
||||||
const pc=new RTCPeerConnection();
|
this.ws=ws;
|
||||||
this.pc=pc;
|
ws.onclose=()=>{
|
||||||
//pc.setRemoteDescription({sdp:json.d.token,type:""})
|
this.leave();
|
||||||
*/
|
}
|
||||||
|
this.status="waiting for WS to open";
|
||||||
|
ws.addEventListener("message",(m)=>{
|
||||||
|
this.packet(m);
|
||||||
|
})
|
||||||
|
await new Promise<void>(res=>{
|
||||||
|
ws.addEventListener("open",()=>{
|
||||||
|
res()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
if(!this.ws){
|
||||||
|
this.leave();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.status="waiting for WS to authorize";
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
"op": 0,
|
||||||
|
"d": {
|
||||||
|
server_id: update.d.guild_id,
|
||||||
|
user_id: update.d.user_id,
|
||||||
|
session_id: update.d.session_id,
|
||||||
|
token: update.d.token,
|
||||||
|
video: false,
|
||||||
|
"streams": [
|
||||||
|
{
|
||||||
|
type: "video",
|
||||||
|
rid: "100",
|
||||||
|
quality: 100
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async leave(){
|
async leave(){
|
||||||
|
this.open=false;
|
||||||
this.status="Left voice chat";
|
this.status="Left voice chat";
|
||||||
if(this.ws){
|
if(this.ws){
|
||||||
this.ws.close();
|
this.ws.close();
|
||||||
|
@ -559,4 +649,4 @@ a=rtcp-mux\r`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export {Voice};
|
export {Voice,VoiceFactory};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue