compressed web socket support

This commit is contained in:
MathMan05
2024-07-30 20:01:03 -05:00
parent b9f1bb5e53
commit 44294c6ea9
5 changed files with 241 additions and 162 deletions

View File

@@ -106,7 +106,7 @@ class Localuser {
async initwebsocket() { async initwebsocket() {
let returny = null; let returny = null;
const promise = new Promise((res) => { returny = res; }); const promise = new Promise((res) => { returny = res; });
this.ws = new WebSocket(this.serverurls.gateway.toString()); this.ws = new WebSocket(this.serverurls.gateway.toString() + "?encoding=json&v=9" + (DecompressionStream ? "&compress=zlib-stream" : ""));
this.ws.addEventListener('open', (event) => { this.ws.addEventListener('open', (event) => {
console.log('WebSocket connected'); console.log('WebSocket connected');
this.ws.send(JSON.stringify({ this.ws.send(JSON.stringify({
@@ -120,7 +120,7 @@ class Localuser {
"release_channel": "Custom", "release_channel": "Custom",
"browser_user_agent": navigator.userAgent "browser_user_agent": navigator.userAgent
}, },
"compress": false, "compress": !!DecompressionStream,
"presence": { "presence": {
"status": "online", "status": "online",
"since": new Date().getTime(), "since": new Date().getTime(),
@@ -130,85 +130,46 @@ class Localuser {
} }
})); }));
}); });
this.ws.addEventListener('message', (event) => { const ds = new DecompressionStream("deflate");
const temp = JSON.parse(event.data); const w = ds.writable.getWriter();
console.log(temp); const r = ds.readable.getReader();
if (temp.s) let arr = new Uint8Array();
this.lastSequence = temp.s; let build = "";
if (temp.op == 0) { this.ws.addEventListener('message', async (event) => {
switch (temp.t) { let temp;
case "MESSAGE_CREATE": if (event.data instanceof Blob) {
if (this.initialized) { const buff = await event.data.arrayBuffer();
this.messageCreate(temp); const array = new Uint8Array(buff);
} const temparr = new Uint8Array(array.length + arr.length);
break; temparr.set(arr, 0);
case "MESSAGE_DELETE": temparr.set(array, arr.length);
console.log(temp.d); arr = temparr;
SnowFlake.getSnowFlakeFromID(temp.d.id, Message).getObject().deleteEvent(); const len = array.length;
break; if (!(array[len - 1] === 255 && array[len - 2] === 255 && array[len - 3] === 0 && array[len - 4] === 0)) {
case "READY": return;
this.gottenReady(temp); }
this.genusersettings(); w.write(arr.buffer);
returny(); arr = new Uint8Array();
break; //console.log(data,test);
case "MESSAGE_UPDATE": const read = (await r.read());
const message = SnowFlake.getSnowFlakeFromID(temp.d.id, Message).getObject(); const data = new TextDecoder().decode(read.value);
message.giveData(temp.d); build += data;
break; console.log("temp");
case "TYPING_START": try {
if (this.initialized) { temp = JSON.parse(build);
this.typingStart(temp); build = "";
} }
break; catch {
case "USER_UPDATE": return;
if (this.initialized) {
const users = SnowFlake.getSnowFlakeFromID(temp.d.id, User).getObject();
console.log(users, temp.d.id);
if (users) {
users.userupdate(temp.d);
}
}
break;
case "CHANNEL_UPDATE":
if (this.initialized) {
this.updateChannel(temp.d);
}
break;
case "CHANNEL_CREATE":
if (this.initialized) {
this.createChannel(temp.d);
}
break;
case "CHANNEL_DELETE":
if (this.initialized) {
this.delChannel(temp.d);
}
break;
case "GUILD_DELETE":
{
const guildy = this.guildids.get(temp.d.id);
this.guildids.delete(temp.d.id);
this.guilds.splice(this.guilds.indexOf(guildy), 1);
guildy.html.remove();
break;
}
case "GUILD_CREATE":
{
const guildy = new Guild(temp.d, this, this.user);
this.guilds.push(guildy);
this.guildids.set(guildy.id, guildy);
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(), document.getElementById("bottomseparator"));
}
} }
} }
else if (temp.op === 10) { else {
console.log("heartbeat down"); temp = JSON.parse(event.data);
this.wsinterval = setInterval(_ => {
if (this.connectionSucceed === 0)
this.connectionSucceed = Date.now();
this.ws.send(JSON.stringify({ op: 1, d: this.lastSequence }));
}, temp.d.heartbeat_interval);
} }
if (temp.op === 0 && temp.t === "READY") {
returny();
}
this.handleEvent(temp);
}); });
this.ws.addEventListener("close", event => { this.ws.addEventListener("close", event => {
console.log("WebSocket closed with code " + event.code); console.log("WebSocket closed with code " + event.code);
@@ -241,6 +202,84 @@ class Localuser {
await promise; await promise;
return; return;
} }
handleEvent(temp) {
console.debug(temp);
if (temp.s)
this.lastSequence = temp.s;
if (temp.op == 0) {
switch (temp.t) {
case "MESSAGE_CREATE":
if (this.initialized) {
this.messageCreate(temp);
}
break;
case "MESSAGE_DELETE":
console.log(temp.d);
SnowFlake.getSnowFlakeFromID(temp.d.id, Message).getObject().deleteEvent();
break;
case "READY":
this.gottenReady(temp);
this.genusersettings();
break;
case "MESSAGE_UPDATE":
const message = SnowFlake.getSnowFlakeFromID(temp.d.id, Message).getObject();
message.giveData(temp.d);
break;
case "TYPING_START":
if (this.initialized) {
this.typingStart(temp);
}
break;
case "USER_UPDATE":
if (this.initialized) {
const users = SnowFlake.getSnowFlakeFromID(temp.d.id, User).getObject();
console.log(users, temp.d.id);
if (users) {
users.userupdate(temp.d);
}
}
break;
case "CHANNEL_UPDATE":
if (this.initialized) {
this.updateChannel(temp.d);
}
break;
case "CHANNEL_CREATE":
if (this.initialized) {
this.createChannel(temp.d);
}
break;
case "CHANNEL_DELETE":
if (this.initialized) {
this.delChannel(temp.d);
}
break;
case "GUILD_DELETE":
{
const guildy = this.guildids.get(temp.d.id);
this.guildids.delete(temp.d.id);
this.guilds.splice(this.guilds.indexOf(guildy), 1);
guildy.html.remove();
break;
}
case "GUILD_CREATE":
{
const guildy = new Guild(temp.d, this, this.user);
this.guilds.push(guildy);
this.guildids.set(guildy.id, guildy);
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(), document.getElementById("bottomseparator"));
}
}
}
else if (temp.op === 10) {
console.log("heartbeat down");
this.wsinterval = setInterval(_ => {
if (this.connectionSucceed === 0)
this.connectionSucceed = Date.now();
this.ws.send(JSON.stringify({ op: 1, d: this.lastSequence }));
}, temp.d.heartbeat_interval);
}
}
resolveChannelFromID(ID) { resolveChannelFromID(ID) {
let resolve = this.guilds.find(guild => guild.channelids[ID]); let resolve = this.guilds.find(guild => guild.channelids[ID]);
if (resolve) { if (resolve) {

View File

@@ -99,7 +99,9 @@ class Member {
} }
return memb; return memb;
} }
const promoise = fetch(guild.info.api.toString() + "/users/" + id + "/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id=" + guild.snowflake, { headers: guild.headers }).then(_ => _.json()).then(json => { const prom1 = fetch(guild.info.api.toString() + "/users/" + id + "/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id=" + guild.snowflake, { headers: guild.headers });
prom1.catch(_ => { console.log(_); });
const promoise = prom1.then(_ => _.json()).then(json => {
const memb = new Member(json, guild); const memb = new Member(json, guild);
Member.already[guild.id][id] = memb; Member.already[guild.id][id] = memb;
console.log("resolved"); console.log("resolved");

View File

@@ -112,7 +112,7 @@ class Localuser{
async initwebsocket():Promise<void>{ async initwebsocket():Promise<void>{
let returny=null let returny=null
const promise=new Promise((res)=>{returny=res}); const promise=new Promise((res)=>{returny=res});
this.ws = new WebSocket(this.serverurls.gateway.toString()); this.ws = new WebSocket(this.serverurls.gateway.toString()+"?encoding=json&v=9"+(DecompressionStream?"&compress=zlib-stream":""));
this.ws.addEventListener('open', (event) => { this.ws.addEventListener('open', (event) => {
console.log('WebSocket connected'); console.log('WebSocket connected');
this.ws.send(JSON.stringify({ this.ws.send(JSON.stringify({
@@ -126,7 +126,7 @@ class Localuser{
"release_channel": "Custom", "release_channel": "Custom",
"browser_user_agent": navigator.userAgent "browser_user_agent": navigator.userAgent
}, },
"compress": false, "compress": !!DecompressionStream,
"presence": { "presence": {
"status": "online", "status": "online",
"since": new Date().getTime(), "since": new Date().getTime(),
@@ -136,90 +136,46 @@ class Localuser{
} }
})) }))
}); });
const ds = new DecompressionStream("deflate");
const w= ds.writable.getWriter();
const r=ds.readable.getReader();
let arr=new Uint8Array();
let build="";
this.ws.addEventListener('message', async (event) => {
let temp:{op:number,t:string};
if(event.data instanceof Blob){
const buff=await event.data.arrayBuffer()
const array=new Uint8Array(buff);
this.ws.addEventListener('message', (event) => { const temparr=new Uint8Array(array.length+arr.length);
temparr.set(arr, 0);
temparr.set(array, arr.length);
arr=temparr;
const len=array.length;
if(!(array[len-1]===255&&array[len-2]===255&&array[len-3]===0&&array[len-4]===0)){
const temp=JSON.parse(event.data); return;
console.log(temp)
if (temp.s) this.lastSequence=temp.s;
if(temp.op==0){
switch(temp.t){
case "MESSAGE_CREATE":
if(this.initialized){
this.messageCreate(temp);
}
break;
case "MESSAGE_DELETE":
console.log(temp.d);
SnowFlake.getSnowFlakeFromID(temp.d.id,Message).getObject().deleteEvent();
break;
case "READY":
this.gottenReady(temp as readyjson);
this.genusersettings();
returny();
break;
case "MESSAGE_UPDATE":
const message=SnowFlake.getSnowFlakeFromID(temp.d.id,Message).getObject();
message.giveData(temp.d);
break;
case "TYPING_START":
if(this.initialized){
this.typingStart(temp);
}
break;
case "USER_UPDATE":
if(this.initialized){
const users=SnowFlake.getSnowFlakeFromID(temp.d.id,User).getObject() as User;
console.log(users,temp.d.id)
if(users){
users.userupdate(temp.d);
}
}
break
case "CHANNEL_UPDATE":
if(this.initialized){
this.updateChannel(temp.d);
}
break;
case "CHANNEL_CREATE":
if(this.initialized){
this.createChannel(temp.d);
}
break;
case "CHANNEL_DELETE":
if(this.initialized){
this.delChannel(temp.d);
}
break;
case "GUILD_DELETE":
{
const guildy=this.guildids.get(temp.d.id);
this.guildids.delete(temp.d.id);
this.guilds.splice(this.guilds.indexOf(guildy),1);
guildy.html.remove();
break;
}
case "GUILD_CREATE":
{
const guildy=new Guild(temp.d,this,this.user);
this.guilds.push(guildy);
this.guildids.set(guildy.id,guildy);
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(),document.getElementById("bottomseparator"));
}
} }
w.write(arr.buffer);
}else if(temp.op===10){ arr=new Uint8Array();
console.log("heartbeat down") //console.log(data,test);
this.wsinterval=setInterval(_=>{ const read=(await r.read());
if (this.connectionSucceed===0) this.connectionSucceed=Date.now() const data=new TextDecoder().decode(read.value);
build+=data;
this.ws.send(JSON.stringify({op:1,d:this.lastSequence})) console.log("temp");
},temp.d.heartbeat_interval) try{
temp=JSON.parse(build);
build="";
}catch{
return;
}
}else{
temp=JSON.parse(event.data);
} }
if(temp.op===0&&temp.t==="READY"){
returny();
}
this.handleEvent(temp);
}); });
this.ws.addEventListener("close", event => { this.ws.addEventListener("close", event => {
@@ -253,6 +209,83 @@ class Localuser{
await promise; await promise;
return; return;
} }
handleEvent(temp){
console.debug(temp);
if (temp.s) this.lastSequence=temp.s;
if(temp.op==0){
switch(temp.t){
case "MESSAGE_CREATE":
if(this.initialized){
this.messageCreate(temp);
}
break;
case "MESSAGE_DELETE":
console.log(temp.d);
SnowFlake.getSnowFlakeFromID(temp.d.id,Message).getObject().deleteEvent();
break;
case "READY":
this.gottenReady(temp as readyjson);
this.genusersettings();
break;
case "MESSAGE_UPDATE":
const message=SnowFlake.getSnowFlakeFromID(temp.d.id,Message).getObject();
message.giveData(temp.d);
break;
case "TYPING_START":
if(this.initialized){
this.typingStart(temp);
}
break;
case "USER_UPDATE":
if(this.initialized){
const users=SnowFlake.getSnowFlakeFromID(temp.d.id,User).getObject() as User;
console.log(users,temp.d.id)
if(users){
users.userupdate(temp.d);
}
}
break
case "CHANNEL_UPDATE":
if(this.initialized){
this.updateChannel(temp.d);
}
break;
case "CHANNEL_CREATE":
if(this.initialized){
this.createChannel(temp.d);
}
break;
case "CHANNEL_DELETE":
if(this.initialized){
this.delChannel(temp.d);
}
break;
case "GUILD_DELETE":
{
const guildy=this.guildids.get(temp.d.id);
this.guildids.delete(temp.d.id);
this.guilds.splice(this.guilds.indexOf(guildy),1);
guildy.html.remove();
break;
}
case "GUILD_CREATE":
{
const guildy=new Guild(temp.d,this,this.user);
this.guilds.push(guildy);
this.guildids.set(guildy.id,guildy);
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(),document.getElementById("bottomseparator"));
}
}
}else if(temp.op===10){
console.log("heartbeat down")
this.wsinterval=setInterval(_=>{
if (this.connectionSucceed===0) this.connectionSucceed=Date.now()
this.ws.send(JSON.stringify({op:1,d:this.lastSequence}))
},temp.d.heartbeat_interval)
}
}
resolveChannelFromID(ID:string):Channel{ resolveChannelFromID(ID:string):Channel{
let resolve=this.guilds.find(guild => guild.channelids[ID]); let resolve=this.guilds.find(guild => guild.channelids[ID]);
if(resolve){ if(resolve){

View File

@@ -92,7 +92,9 @@ class Member{
} }
return memb; return memb;
} }
const promoise= fetch(guild.info.api.toString()+"/users/"+id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.snowflake,{headers:guild.headers}).then(_=>_.json()).then(json=>{ const prom1= fetch(guild.info.api.toString()+"/users/"+id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.snowflake,{headers:guild.headers})
prom1.catch(_=>{console.log(_)})
const promoise=prom1.then(_=>_.json()).then(json=>{
const memb=new Member(json,guild); const memb=new Member(json,guild);
Member.already[guild.id][id]=memb; Member.already[guild.id][id]=memb;
console.log("resolved") console.log("resolved")

View File

@@ -944,6 +944,7 @@ span {
text-align: center; text-align: center;
transition: transform .2s; transition: transform .2s;
vertical-align: middle; vertical-align: middle;
display: flex;
} }
#centerdiv { #centerdiv {
@@ -951,6 +952,8 @@ span {
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
display: flex;
flex-direction: column;
} }
#loading.doneloading { #loading.doneloading {