TS conversion

This commit is contained in:
MathMan05 2024-06-27 11:27:38 -05:00
parent 75fa9d0844
commit 845c7f6612
44 changed files with 6225 additions and 611 deletions

View file

@ -1,6 +1,15 @@
class voice{
constructor(wave,freq,volume=1){
this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
import {getBulkInfo} from "./login.js";
class Voice{
audioCtx:AudioContext;
info:{wave:string|Function,freq:number};
playing:boolean;
myArrayBuffer:AudioBuffer;
gainNode:GainNode;
buffer:Float32Array;
source:AudioBufferSourceNode;
constructor(wave:string|Function,freq:number,volume=1){
this.audioCtx = new (window.AudioContext)();
this.info={wave:wave,freq:freq}
this.playing=false;
this.myArrayBuffer=this.audioCtx.createBuffer(
@ -16,61 +25,61 @@ class voice{
this.source.buffer = this.myArrayBuffer;
this.source.loop=true;
this.source.start();
this.updateWave(freq);
this.updateWave();
}
get wave(){
get wave():string|Function{
return this.info.wave;
}
get freq(){
get freq():number{
return this.info.freq;
}
set wave(wave){
set wave(wave:string|Function){
this.info.wave=wave;
this.updateWave()
this.updateWave();
}
set freq(freq){
set freq(freq:number){
this.info.freq=freq;
this.updateWave()
this.updateWave();
}
updateWave(){
updateWave():void{
const func=this.waveFucnion();
for (let i = 0; i < this.buffer.length; i++) {
this.buffer[i]=func(i/this.audioCtx.sampleRate,this.freq);
}
}
waveFucnion(){
waveFucnion():Function{
if(typeof this.wave === 'function'){
return this.wave;
}
switch(this.wave){
case "sin":
return (t,freq)=>{
return (t:number,freq:number)=>{
return Math.sin(t*Math.PI*2*freq);
}
case "triangle":
return (t,freq)=>{
return (t:number,freq:number)=>{
return Math.abs((4*t*freq)%4-2)-1;
}
case "sawtooth":
return (t,freq)=>{
return (t:number,freq:number)=>{
return ((t*freq)%1)*2-1;
}
case "square":
return (t,freq)=>{
return (t:number,freq:number)=>{
return (t*freq)%2<1?1:-1;
}
case "white":
return (t,freq)=>{
return (_t:number,_freq:number)=>{
return Math.random()*2-1;
}
case "noise":
return (t,freq)=>{
return (_t:number,_freq:number)=>{
return 0;
}
}
}
play(){
play():void{
if(this.playing){
return;
}
@ -78,16 +87,16 @@ class voice{
this.playing=true;
}
stop(){
stop():void{
if(this.playing){
this.source.disconnect();
this.playing=false;
}
}
static noises(noise){
static noises(noise:string):void{
switch(noise){
case "three":{
const voicy=new voice("sin",800);
const voicy=new Voice("sin",800);
voicy.play();
setTimeout(_=>{voicy.freq=1000},50);
setTimeout(_=>{voicy.freq=1300},100);
@ -95,7 +104,7 @@ class voice{
break;
}
case "zip":{
const voicy=new voice((t,freq)=>{
const voicy=new Voice((t:number,freq:number)=>{
return Math.sin(((t+2)**(Math.cos(t*4)))*Math.PI*2*freq);
},700);
voicy.play();
@ -103,7 +112,7 @@ class voice{
break;
}
case "square":{
const voicy=new voice("square",600,.4);
const voicy=new Voice("square",600,.4);
voicy.play()
setTimeout(_=>{voicy.freq=800},50);
setTimeout(_=>{voicy.freq=1000},100);
@ -111,7 +120,7 @@ class voice{
break;
}
case "beep":{
const voicy=new voice("sin",800);
const voicy=new Voice("sin",800);
voicy.play();
setTimeout(_=>{voicy.stop()},50);
setTimeout(_=>{voicy.play();},100);
@ -123,7 +132,7 @@ class voice{
static get sounds(){
return ["three","zip","square","beep"];
}
static setNotificationSound(sound){
static setNotificationSound(sound:string){
let userinfos=getBulkInfo();
userinfos.preferances.notisound=sound;
localStorage.setItem("userinfos",JSON.stringify(userinfos));
@ -133,3 +142,4 @@ class voice{
return userinfos.preferances.notisound;
}
}
export {Voice as Voice};

View file

@ -1,31 +1,69 @@
"use strict"
class channel{
static contextmenu=new contextmenu("channel menu");
import { Message } from "./message.js";
import {Voice} from "./audio.js";
import {Contextmenu} from "./contextmenu.js";
import {Fullscreen} from "./fullscreen.js";
import {markdown} from "./markdown.js";
import {Guild} from "./guild.js";
import { Localuser } from "./localuser.js";
import { Permissions } from "./permissions.js";
declare global {
interface NotificationOptions {
image?: string
}
}
class Channel{
editing:Message;
type:number;
owner:Guild;
headers:Localuser["headers"];
messages:Message[];
name:string;
id:string;
parent_id:string;
parrent:Channel;
children:Channel[];
guild_id:string;
messageids:{[key : string]:Message};
permission_overwrites:{[key:string]:Permissions};
topic:string;
nsfw:boolean;
position:number;
lastreadmessageid:string;
lastmessageid:string;
mentions:number;
lastpin:string;
move_id:string;
typing:number;
message_notifications:number;
allthewayup:boolean;
static contextmenu=new Contextmenu("channel menu");
static setupcontextmenu(){
channel.contextmenu.addbutton("Copy channel id",function(){
Channel.contextmenu.addbutton("Copy channel id",function(){
console.log(this)
navigator.clipboard.writeText(this.id);
});
channel.contextmenu.addbutton("Mark as read",function(){
Channel.contextmenu.addbutton("Mark as read",function(){
console.log(this)
this.readbottom();
});
channel.contextmenu.addbutton("Delete channel",function(){
Channel.contextmenu.addbutton("Delete channel",function(){
console.log(this)
this.deleteChannel();
},null,_=>{console.log(_);return _.isAdmin()});
channel.contextmenu.addbutton("Edit channel",function(){
editchannelf(this);
Channel.contextmenu.addbutton("Edit channel",function(){
this.editChannel(this);
},null,_=>{return _.isAdmin()});
}
constructor(JSON,owner){
constructor(JSON,owner:Guild){
if(JSON===-1){
return;
}
this.editing;
this.type=JSON.type;
this.owner=owner;
this.headers=this.owner.headers;
@ -37,7 +75,11 @@ class channel{
this.children=[];
this.guild_id=JSON.guild_id;
this.messageids={};
this.permission_overwrites=JSON.permission_overwrites;
this.permission_overwrites={};
for(const thing of JSON.permission_overwrites){
this.permission_overwrites[thing.id]=new Permissions(thing.allow,thing.deny);
}
console.log(this.permission_overwrites)
this.topic=JSON.topic;
this.nsfw=JSON.nsfw;
this.position=JSON.position;
@ -53,6 +95,9 @@ class channel{
get localuser(){
return this.guild.localuser;
}
get info(){
return this.owner.info;
}
readStateInfo(json){
this.lastreadmessageid=json.last_message_id;
this.mentions=json.mention_count;
@ -63,8 +108,13 @@ class channel{
return this.lastmessageid!==this.lastreadmessageid&&this.type!==4;
}
get canMessage(){
for(const thing of this.permission_overwrites){
if(this.guild.hasRole(thing.id)&&thing.deny&(1<<11)){
console.log("this should run");
for(const thing of Object.entries(this.permission_overwrites)){
const perm=thing[1].getPermision("SEND_MESSAGES");
if(perm===1){
return true
}
if(perm===-1){
return false;
}
}
@ -73,7 +123,7 @@ class channel{
sortchildren(){
this.children.sort((a,b)=>{return a.position-b.position});
}
resolveparent(guild){
resolveparent(guild:Guild){
this.parrent=guild.channelids[this.parent_id];
this.parrent??=null;
if(this.parrent!==null){
@ -85,7 +135,7 @@ class channel{
let position=-1;
let build=[];
for(const thing of this.children){
const thisthing={id:thing.id}
const thisthing={id:thing.id,position:undefined,parent_id:undefined};
if(thing.position<position){
thing.position=thisthing.position=position+1;
}
@ -105,10 +155,10 @@ class channel{
static dragged=[];
createguildHTML(admin=false){
const div=document.createElement("div");
div.all=this;
div["all"]=this;
div.draggable=admin;
div.addEventListener("dragstart",(e)=>{channel.dragged=[this,div];e.stopImmediatePropagation()})
div.addEventListener("dragend",()=>{channel.dragged=[]})
div.addEventListener("dragstart",(e)=>{Channel.dragged=[this,div];e.stopImmediatePropagation()})
div.addEventListener("dragend",()=>{Channel.dragged=[]})
if(this.type===4){
this.sortchildren();
const caps=document.createElement("div");
@ -129,17 +179,17 @@ class channel{
addchannel.classList.add("addchannel");
caps.appendChild(addchannel);
addchannel.onclick=function(){
createchannels(this.createChannel.bind(this));
this.guild.createchannels(this.createChannel.bind(this));
}.bind(this);
this.coatDropDiv(decdiv,this,childrendiv);
this.coatDropDiv(decdiv,childrendiv);
}
div.appendChild(caps)
caps.classList.add("capsflex")
decdiv.classList.add("channeleffects");
decdiv.classList.add("channel");
channel.contextmenu.bind(decdiv,this);
decdiv.all=this;
Channel.contextmenu.bind(decdiv,this);
decdiv["all"]=this;
for(const channel of this.children){
@ -164,9 +214,9 @@ class channel{
if(this.hasunreads){
div.classList.add("cunread");
}
channel.contextmenu.bind(div,this);
if(admin){this.coatDropDiv(div,this);}
div.all=this;
Channel.contextmenu.bind(div,this);
if(admin){this.coatDropDiv(div);}
div["all"]=this;
const myhtml=document.createElement("span");
myhtml.textContent=this.name;
if(this.type===0){
@ -188,9 +238,8 @@ class channel{
console.log(this.type)
}
div.appendChild(myhtml);
div.myinfo=this;
div.onclick=function(){
this.myinfo.getHTML();
div.onclick=_=>{
this.getHTML();
}
}
return div;
@ -201,9 +250,9 @@ class channel{
return null
}else if(this.parrent){
for(const thing of search){
if(thing.all===this.parrent){
if(thing["all"]===this.parrent){
for(const thing2 of thing.children[1].children){
if(thing2.all===this){
if(thing2["all"]===this){
return thing2;
}
}
@ -211,7 +260,7 @@ class channel{
}
}else{
for(const thing of search){
if(thing.all===this){
if(thing["all"]===this){
return thing;
}
}
@ -222,7 +271,7 @@ class channel{
if(!this.hasunreads){
return;
}
fetch(info.api.toString()+"/v9/channels/"+this.id+"/messages/"+this.lastmessageid+"/ack",{
fetch(this.info.api.toString()+"/v9/channels/"+this.id+"/messages/"+this.lastmessageid+"/ack",{
method:"POST",
headers:this.headers,
body:JSON.stringify({})
@ -233,7 +282,7 @@ class channel{
this.myhtml.classList.remove("cunread");
}
}
coatDropDiv(div,that,container=false){
coatDropDiv(div:HTMLDivElement,container:HTMLElement|boolean=false){
div.addEventListener("dragenter", (event) => {
console.log("enter")
event.preventDefault();
@ -244,7 +293,7 @@ class channel{
});
div.addEventListener("drop", (event) => {
const that=channel.dragged[0];
const that=Channel.dragged[0];
event.preventDefault();
if(container){
that.move_id=this.id;
@ -252,10 +301,10 @@ class channel{
that.parrent.children.splice(that.parrent.children.indexOf(that),1);
}
that.parrent=this;
container.prepend(channel.dragged[1]);
(container as HTMLElement).prepend(Channel.dragged[1]);
this.children.unshift(that);
}else{
console.log(this,channel.dragged);
console.log(this,Channel.dragged);
that.move_id=this.parent_id;
if(that.parrent){
that.parrent.children.splice(that.parrent.children.indexOf(that),1);
@ -282,15 +331,15 @@ class channel{
}
this.guild.headchannels=build;
}
div.after(channel.dragged[1]);
div.after(Channel.dragged[1]);
}
this.guild.calculateReorder()
});
return div;
}
createChannel(name,type){
fetch(info.api.toString()+"/guilds/"+this.guild.id+"/channels",{
createChannel(name:string,type:number){
fetch(this.info.api.toString()+"/guilds/"+this.guild.id+"/channels",{
method:"Post",
headers:this.headers,
body:JSON.stringify({
@ -307,14 +356,14 @@ class channel{
let nsfw=this.nsfw;
const thisid=this.id;
const thistype=this.type;
const full=new fullscreen(
const full=new Fullscreen(
["hdiv",
["vdiv",
["textbox","Channel name:",this.name,function(){name=this.value}],
["mdbox","Channel topic:",this.topic,function(){topic=this.value}],
["checkbox","NSFW Channel",this.nsfw,function(){nsfw=this.checked}],
["button","","submit",function(){
fetch(info.api.toString()+"/v9/channels/"+thisid,{
fetch(this.info.api.toString()+"/v9/channels/"+thisid,{
method:"PATCH",
headers:this.headers,
body:JSON.stringify({
@ -338,7 +387,7 @@ class channel{
console.log(full)
}
deleteChannel(){
fetch(info.api.toString()+"/v9/channels/"+this.id,{
fetch(this.info.api.toString()+"/v9/channels/"+this.id,{
method:"DELETE",
headers:this.headers
})
@ -352,18 +401,18 @@ class channel{
this.putmessages();
history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.id);
document.getElementById("channelname").textContent="#"+this.name;
console.log(this);
(document.getElementById("typebox") as HTMLInputElement).disabled=!this.canMessage;
}
putmessages(){
const out=this;
fetch(info.api.toString()+"/channels/"+this.id+"/messages?limit=100",{
fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=100",{
method: 'GET',
headers: this.headers,
}).then((j)=>{return j.json()}).then(responce=>{
messages.innerHTML = '';
//responce.reverse()
messagelist=[];
document.getElementById("messages").innerHTML = '';
for(const thing of responce){
const messager=new cmessage(thing,this)
const messager=new Message(thing,this)
if(out.messageids[messager.id]==undefined){
out.messageids[messager.id]=messager;
out.messages.push(messager);
@ -387,25 +436,25 @@ class channel{
}
const out=this;
await fetch(info.api.toString()+"/channels/"+this.id+"/messages?before="+this.messages[this.messages.length-1].id+"&limit=100",{
await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?before="+this.messages[this.messages.length-1].id+"&limit=100",{
method:"GET",
headers:this.headers
}).then((j)=>{return j.json()}).then(responce=>{
//messages.innerHTML = '';
//responce.reverse()
let next
let next:Message;
if(responce.length===0){
out.allthewayup=true;
}
for(const i in responce){
let messager
let messager:Message;
if(!next){
messager=new cmessage(responce[i],this)
messager=new Message(responce[i],this)
}else{
messager=next;
}
if(responce[+i+1]!==undefined){
next=new cmessage(responce[+i+1],this);
next=new Message(responce[+i+1],this);
}else{
next=undefined;
console.log("ohno",+i+1)
@ -422,15 +471,15 @@ class channel{
})
return;
}
buildmessage(message,next){
buildmessage(message:Message,next:Message){
const built=message.buildhtml(next);
messages.prepend(built);
document.getElementById("messages").prepend(built);
}
buildmessages(){
for(const i in this.messages){
const prev=this.messages[(+i)+1];
const built=this.messages[i].buildhtml(prev);
messages.prepend(built);
document.getElementById("messages").prepend(built);
}
document.getElementById("messagecontainer").scrollTop = document.getElementById("messagecontainer").scrollHeight;
@ -452,7 +501,7 @@ class channel{
return;
}
this.typing=new Date().getTime()+6000;
fetch(info.api.toString()+"/channels/"+this.id+"/typing",{
fetch(this.info.api.toString()+"/channels/"+this.id+"/typing",{
method:"POST",
headers:this.headers
})
@ -472,8 +521,8 @@ class channel{
return "default";
}
}
async sendMessage(content,{attachments=[],embeds=[],replyingto=false}){
let replyjson=false;
async sendMessage(content:string,{attachments=[],embeds=[],replyingto=null}){
let replyjson:any;
if(replyingto){
replyjson=
{
@ -481,17 +530,18 @@ class channel{
"channel_id": replyingto.channel.id,
"message_id": replyingto.id,
};
}
};
if(attachments.length===0){
const body={
content:content,
nonce:Math.floor(Math.random()*1000000000)
nonce:Math.floor(Math.random()*1000000000),
message_reference:undefined
};
if(replyjson){
body.message_reference=replyjson;
}
console.log(body)
return await fetch(info.api.toString()+"/channels/"+this.id+"/messages",{
return await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages",{
method:"POST",
headers:this.headers,
body:JSON.stringify(body)
@ -501,6 +551,7 @@ class channel{
const body={
content:content,
nonce:Math.floor(Math.random()*1000000000),
message_reference:undefined
}
if(replyjson){
body.message_reference=replyjson;
@ -510,15 +561,15 @@ class channel{
console.log(attachments[i])
formData.append("files["+i+"]",attachments[i]);
}
return await fetch(info.api.toString()+"/channels/"+this.id+"/messages", {
return await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages", {
method: 'POST',
body: formData,
headers:{"Authorization":this.headers.Authorization}
});
}
}
messageCreate(messagep,focus){
const messagez=new cmessage(messagep.d,this);
messageCreate(messagep:any):void{
const messagez=new Message(messagep.d,this);
this.lastmessageid=messagez.id;
if(messagez.author===this.localuser.user){
this.lastreadmessageid=messagez.id;
@ -536,7 +587,7 @@ class channel{
this.messageids[messagez.id]=messagez;
if(this.localuser.lookingguild.prevchannel===this){
var shouldScroll=scrolly.scrollTop+scrolly.clientHeight>scrolly.scrollHeight-20;
messages.appendChild(messagez.buildhtml(this.messages[1]));
document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1]));
}
if(shouldScroll){
scrolly.scrollTop = scrolly.scrollHeight;
@ -553,11 +604,11 @@ class channel{
this.notify(messagez);
}
}
notititle(message){
notititle(message:Message):string{
return message.author.username+" > "+this.guild.properties.name+" > "+this.name;
}
notify(message,deep=0){
voice.noises(voice.getNotificationSound());
notify(message:Message,deep=0){
Voice.noises(Voice.getNotificationSound());
if (!("Notification" in window)) {
} else if (Notification.permission === "granted") {
@ -584,11 +635,12 @@ class channel{
this.getHTML();
})
} else if (Notification.permission !== "denied") {
Notification.requestPermission().then((permission) => {
Notification.requestPermission().then(() => {
if(deep===3){return};
this.notify(message,deep+1);
});
}
}
}
channel.setupcontextmenu();
Channel.setupcontextmenu();
export {Channel};

View file

@ -1,14 +1,29 @@
class contextmenu{
constructor(name){
class Contextmenu{
static currentmenu;
name:string;
buttons:[string,Function,string,Function,Function][];
div:HTMLDivElement;
static setup(){
Contextmenu.currentmenu="";
document.addEventListener('click', function(event) {
if(Contextmenu.currentmenu==""){
return;
}
if (!Contextmenu.currentmenu.contains(event.target)) {
Contextmenu.currentmenu.remove();
Contextmenu.currentmenu="";
}
});
}
constructor(name:string){
this.name=name;
this.buttons=[]
}
addbutton(text,onclick,img=null,shown=_=>true,enabled=_=>true){
addbutton(text:string,onclick:Function,img=null,shown=_=>true,enabled=_=>true){
this.buttons.push([text,onclick,img,shown,enabled])
return {};
}
makemenu(x,y,addinfo,obj){
makemenu(x:number,y:number,addinfo:any,obj:HTMLElement){
const div=document.createElement("table");
div.classList.add("contextmenu");
for(const thing of this.buttons){
@ -16,7 +31,7 @@ class contextmenu{
const textb=document.createElement("tr");
const intext=document.createElement("button")
intext.disabled=!thing[4]();
textb.button=intext;
textb["button"]=intext;
intext.classList.add("contextbutton")
intext.textContent=thing[0]
textb.appendChild(intext)
@ -24,17 +39,17 @@ class contextmenu{
intext.onclick=thing[1].bind(addinfo,obj);
div.appendChild(textb);
}
if(currentmenu!=""){
currentmenu.remove();
if(Contextmenu.currentmenu!=""){
Contextmenu.currentmenu.remove();
}
div.style.top = y+'px';
div.style.left = x+'px';
document.body.appendChild(div);
console.log(div)
currentmenu=div;
Contextmenu.currentmenu=div;
return this.div;
}
bind(obj,addinfo){
bind(obj:HTMLElement,addinfo:any=undefined){
obj.addEventListener("contextmenu", (event) => {
event.preventDefault();
event.stopImmediatePropagation();
@ -42,3 +57,5 @@ class contextmenu{
});
}
}
Contextmenu.setup();
export {Contextmenu as Contextmenu}

View file

@ -1,6 +1,12 @@
class direct extends guild{
constructor(JSON,owner){
super(-1);
import {Guild} from "./guild.js";
import { Channel } from "./channel.js";
import { Message } from "./message.js";
import { Localuser } from "./localuser.js";
import {User} from "./user.js";
class Direct extends Guild{
constructor(JSON,owner:Localuser){
super(-1,owner);
this.message_notifications=0;
console.log(JSON);
this.owner=owner;
@ -17,14 +23,14 @@ class direct extends guild{
this.prevchannel=undefined;
this.properties.name="Dirrect Messages";
for(const thing of JSON){
const temp=new group(thing,this);
const temp=new Group(thing,this);
this.channels.push(temp);
this.channelids[temp.id]=temp;
}
this.headchannels=this.channels;
}
createChannelpac(JSON){
const thischannel=new group(JSON,this);
const thischannel=new Group(JSON,this);
this.channelids[JSON.id]=thischannel;
this.channels.push(thischannel);
this.calculateReorder();
@ -50,19 +56,20 @@ class direct extends guild{
}
unreaddms(){
for(const thing of this.channels){
thing.unreads();
(thing as Group).unreads();
}
}
}
class group extends channel{
constructor(JSON,owner){
super(-1);
class Group extends Channel{
user:User;
constructor(JSON,owner:Direct){
super(-1,owner);
this.owner=owner;
this.headers=this.guild.headers;
this.messages=[];
this.name=JSON.recipients[0]?.username;
if(JSON.recipients[0]){
this.user=new user(JSON.recipients[0]);
this.user=new User(JSON.recipients[0],this.localuser);
}else{
this.user=this.localuser.user;
}
@ -73,9 +80,9 @@ class group extends channel{
this.children=[];
this.guild_id="@me";
this.messageids={};
this.permission_overwrites=[];
this.permission_overwrites={};
this.lastmessageid=JSON.last_message_id;
this.lastmessageid??=0;
this.lastmessageid??="0";
this.mentions=0;
}
createguildHTML(){
@ -85,9 +92,9 @@ class group extends channel{
myhtml.textContent=this.name;
div.appendChild(this.user.buildpfp());
div.appendChild(myhtml);
div.myinfo=this;
div.onclick=function(){
this.myinfo.getHTML();
div["myinfo"]=this;
div.onclick=_=>{
this.getHTML();
}
return div;
}
@ -98,8 +105,8 @@ class group extends channel{
history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.id);
document.getElementById("channelname").textContent="@"+this.name;
}
messageCreate(messagep,focus){
const messagez=new cmessage(messagep.d,this);
messageCreate(messagep){
const messagez=new Message(messagep.d,this);
this.lastmessageid=messagez.id;
if(messagez.author===this.localuser.user){
this.lastreadmessageid=messagez.id;
@ -109,7 +116,7 @@ class group extends channel{
this.messageids[messagez.id]=messagez;
if(this.localuser.lookingguild.prevchannel===this){
var shouldScroll=scrolly.scrollTop+scrolly.clientHeight>scrolly.scrollHeight-20;
messages.appendChild(messagez.buildhtml(this.messages[1]));
document.getElementById("messages").appendChild(messagez.buildhtml(this.messages[1]));
}
if(shouldScroll){
scrolly.scrollTop = scrolly.scrollHeight;
@ -118,12 +125,10 @@ class group extends channel{
if(this.localuser.lookingguild===this.guild){
const channellist=document.getElementById("channels").children[0]
for(const thing of channellist.children){
if(thing.myinfo===this){
if(thing["myinfo"]===this){
channellist.prepend(thing);
console.log(thing.myinfo);
break;
}
console.log(thing.myinfo,this,thing.myinfo===this);
}
}
this.unreads();
@ -147,8 +152,7 @@ class group extends channel{
const sentdms=document.getElementById("sentdms");
let current=null;
for(const thing of sentdms.children){
console.log(thing.all)
if(thing.all===this){
if(thing["all"]===this){
current=thing;
}
}
@ -158,19 +162,19 @@ class group extends channel{
div.classList.add("servernoti");
const noti=document.createElement("div");
noti.classList.add("unread","notiunread","pinged");
noti.textContent=this.mentions;
noti.textContent=""+this.mentions;
console.log(this.mentions)
div.noti=noti;
div["noti"]=noti;
div.append(noti)
const buildpfp=this.user.buildpfp();
div.all=this;
div["all"]=this;
buildpfp.classList.add("mentioned");
console.log(this);
div.append(buildpfp)
sentdms.append(div);
div.onclick=function(){
this.all.guild.loadGuild();
this.all.getHTML();
this["noti"].guild.loadGuild();
this["noti"].getHTML();
}
}else if(current){
@ -180,3 +184,4 @@ class group extends channel{
}
}
}
export {Direct, Group};

View file

@ -1,6 +1,10 @@
class embed{
constructor(json, owner){
import {Fullscreen} from "./fullscreen.js";
import {Message} from "./message.js";
class Embed{
type:string;
owner:Message;
json;
constructor(json, owner:Message){
this.type=this.getType(json);
this.owner=owner;
this.json=json;
@ -116,7 +120,7 @@ class embed{
const img=document.createElement("img");
img.classList.add("messageimg")
img.onclick=function(){
const full=new fullscreen(["img",img.src,["fit"]]);
const full=new Fullscreen(["img",img.src,["fit"]]);
full.show();
}
img.src=this.json.thumbnail.proxy_url;
@ -141,7 +145,7 @@ class embed{
if(this.json.thumbnail){
img.classList.add("embedimg");
img.onclick=function(){
const full=new fullscreen(["img",img.src,["fit"]]);
const full=new Fullscreen(["img",img.src,["fit"]]);
full.show();
}
img.src=this.json.thumbnail.proxy_url;
@ -184,7 +188,7 @@ class embed{
const img=document.createElement("img");
img.classList.add("bigembedimg");
img.onclick=function(){
const full=new fullscreen(["img",img.src,["fit"]]);
const full=new Fullscreen(["img",img.src,["fit"]]);
full.show();
}
img.src=this.json.thumbnail.proxy_url;
@ -194,3 +198,4 @@ class embed{
return colordiv;
}
}
export {Embed};

BIN
webpage/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -1,4 +1,10 @@
class fullscreen{
export {Fullscreen};
class Fullscreen{
layout;
onclose: Function;
onopen: Function;
html:HTMLDivElement;
background: HTMLDivElement;
constructor(layout,onclose=_=>{},onopen=_=>{}){
this.layout=layout;
this.onclose=onclose;
@ -134,8 +140,9 @@ class fullscreen{
if(i===0){
continue;
}
if(thing.children[0].children[0].checked){
array[3](thing.children[0].children[0].value);
const checkbox = thing.children[0].children[0] as HTMLInputElement;
if(checkbox.checked){
array[3](checkbox.value);
}
}
});

View file

@ -1,30 +1,52 @@
class guild{
static contextmenu=new contextmenu("guild menu");
import { Channel } from "./channel.js";
import { Localuser } from "./localuser.js";
import {Contextmenu} from "./contextmenu.js";
import {Role} from "./role.js";
import {Fullscreen} from "./fullscreen.js";
import {Member} from "./member.js";
class Guild{
owner:Localuser;
headers:Localuser["headers"];
channels:Channel[];
channelids:{[key:string]:Channel};
id:string;
properties
roles:Role[];
roleids:{[key:string]:Role};
prevchannel:Channel;
message_notifications
headchannels:Channel[];
position:number;
parent_id:string;
member:Member;
html:HTMLUnknownElement;
static contextmenu=new Contextmenu("guild menu");
static setupcontextmenu(){
guild.contextmenu.addbutton("Copy Guild id",function(){
Guild.contextmenu.addbutton("Copy Guild id",function(){
console.log(this)
navigator.clipboard.writeText(this.id);
});
guild.contextmenu.addbutton("Mark as read",function(){
Guild.contextmenu.addbutton("Mark as read",function(){
console.log(this)
this.markAsRead();
});
guild.contextmenu.addbutton("Notifications",function(){
Guild.contextmenu.addbutton("Notifications",function(){
console.log(this)
this.setnotifcation();
});
guild.contextmenu.addbutton("Leave guild",function(){
Guild.contextmenu.addbutton("Leave guild",function(){
this.confirmleave();
},null,function(_){return _.properties.owner_id!==_.member.user.id});
guild.contextmenu.addbutton("Delete guild",function(){
Guild.contextmenu.addbutton("Delete guild",function(){
this.confirmDelete();
},null,function(_){return _.properties.owner_id===_.member.user.id});
guild.contextmenu.addbutton("Create invite",function(){
Guild.contextmenu.addbutton("Create invite",function(){
console.log(this);
},null,_=>true,_=>false);
/* -----things left for later-----
@ -38,7 +60,7 @@ class guild{
},null,_=>{return thisuser.isAdmin()})
*/
}
constructor(JSON,owner){
constructor(JSON,owner:Localuser){
if(JSON===-1){
return;
@ -57,12 +79,12 @@ class guild{
this.prevchannel=undefined;
this.message_notifications=0;
for(const roley of JSON.roles){
const roleh=new role(roley);
const roleh=new Role(roley,this);
this.roles.push(roleh)
this.roleids[roleh.id]=roleh;
}
for(const thing of JSON.channels){
const temp=new channel(thing,this);
const temp=new Channel(thing,this);
this.channels.push(temp);
this.channelids[temp.id]=temp;
}
@ -78,7 +100,7 @@ class guild{
}
setnotifcation(){
let noti=this.message_notifications
const notiselect=new fullscreen(
const notiselect=new Fullscreen(
["vdiv",
["radio","select notifications type",
["all","only mentions","none"],
@ -88,7 +110,7 @@ class guild{
noti
],
["button","","submit",_=>{
fetch(info.api.toString()+"/v9/users/@me/guilds/settings",{
fetch(this.info.api.toString()+"/v9/users/@me/guilds/settings",{
method:"PATCH",
headers:this.headers,
body:JSON.stringify({
@ -105,7 +127,7 @@ class guild{
notiselect.show();
}
confirmleave(){
const full= new fullscreen([
const full= new Fullscreen([
"vdiv",
["title",
"Are you sure you want to leave?"
@ -133,7 +155,7 @@ class guild{
full.show();
}
async leave(){
return fetch(info.api.toString()+"/users/@me/guilds/"+this.id,{
return fetch(this.info.api.toString()+"/users/@me/guilds/"+this.id,{
method:"DELETE",
headers:this.headers
})
@ -152,7 +174,7 @@ class guild{
let position=-1;
let build=[];
for(const thing of this.headchannels){
const thisthing={id:thing.id}
const thisthing={id:thing.id,position:undefined,parent_id:undefined}
if(thing.position<=position){
thing.position=(thisthing.position=position+1);
}
@ -181,14 +203,14 @@ class guild{
if(serverbug){
for(const thing of build){
console.log(build,thing)
fetch(info.api.toString()+"/v9/guilds/"+this.id+"/channels",{
fetch(this.info.api.toString()+"/v9/guilds/"+this.id+"/channels",{
method:"PATCH",
headers:this.headers,
body:JSON.stringify([thing])
});
}
}else{
fetch(info.api.toString()+"/v9/guilds/"+this.id+"/channels",{
fetch(this.info.api.toString()+"/v9/guilds/"+this.id+"/channels",{
method:"PATCH",
headers:this.headers,
body:JSON.stringify(build)
@ -199,9 +221,8 @@ class guild{
get localuser(){
return this.owner;
}
loadChannel(id){
this.localuser.channelfocus=this.channelids[id];
this.channelids[id].getHTML();
get info(){
return this.owner.info;
}
sortchannels(){
this.headchannels.sort((a,b)=>{return a.position-b.position;});
@ -217,14 +238,14 @@ class guild{
if(this.properties.icon!=null){
const img=document.createElement("img");
img.classList.add("pfp","servericon");
img.src=info.cdn.toString()+"icons/"+this.properties.id+"/"+this.properties.icon+".png";
img.src=this.info.cdn.toString()+"icons/"+this.properties.id+"/"+this.properties.icon+".png";
divy.appendChild(img)
img.onclick=()=>{
console.log(this.loadGuild)
this.loadGuild();
this.loadChannel();
}
guild.contextmenu.bind(img,this);
Guild.contextmenu.bind(img,this);
}else{
const div=document.createElement("div");
let build="";
@ -238,13 +259,13 @@ class guild{
this.loadGuild();
this.loadChannel();
}
guild.contextmenu.bind(div,this)
Guild.contextmenu.bind(div,this)
}
return divy;
}
confirmDelete(){
let confirmname="";
const full= new fullscreen([
const full= new Fullscreen([
"vdiv",
["title",
"Are you sure you want to delete "+this.properties.name+"?"
@ -284,12 +305,12 @@ class guild{
full.show();
}
async delete(){
return fetch(info.api.toString()+"/guilds/"+this.id+"/delete",{
return fetch(this.info.api.toString()+"/guilds/"+this.id+"/delete",{
method:"POST",
headers:this.headers,
})
}
unreads(html){
unreads(html=undefined){
if(html){
this.html=html;
}else{
@ -333,13 +354,13 @@ class guild{
}
}
this.unreads();
fetch(info.api.toString()+"/v9/read-states/ack-bulk",{
fetch(this.info.api.toString()+"/v9/read-states/ack-bulk",{
method:"POST",
headers:this.headers,
body:JSON.stringify(build)
})
}
fillMember(member){
fillMember(member:Member){
const realroles=[];
for(const thing of member.roles){
realroles.push(this.getRole(thing));
@ -347,20 +368,21 @@ class guild{
member.roles=realroles;
return member;
}
giveMember(member){
giveMember(member:Member){
this.fillMember(member);
this.member=member;
}
getRole(ID){
return this.roleids[ID];
}
hasRole(r){
hasRole(r:Role|string){
console.log("this should run");
if((typeof r)!==(typeof "")){
r=r.id;
r=(r as Role).id;
}
return this.member.hasRole(r);
return this.member.hasRole(r as string);
}
loadChannel(ID){
loadChannel(ID=undefined){
if(ID&&this.channelids[ID]){
this.channelids[ID].getHTML();
return;
@ -394,7 +416,7 @@ class guild{
this.printServers();
}
createChannelpac(JSON){
const thischannel=new channel(JSON,this);
const thischannel=new Channel(JSON,this);
this.channelids[JSON.id]=thischannel;
this.channels.push(thischannel);
thischannel.resolveparent(this);
@ -404,26 +426,82 @@ class guild{
this.calculateReorder();
this.printServers();
}
createchannels(func=this.createChannel){
let name="";
let category=0;
const channelselect=new Fullscreen(
["vdiv",
["radio","select channel type",
["voice","text","announcement"],
function(e){
console.log(e)
category={"text":0,"voice":2,"announcement":5,"category":4}[e]
},
1
],
["textbox","Name of channel","",function(){
console.log(this)
name=this.value
}],
["button","","submit",function(){
console.log(name,category)
func(name,category);
channelselect.hide();
}.bind(this)]
]);
channelselect.show();
}
createcategory(){
let name="";
let category=4;
const channelselect=new Fullscreen(
["vdiv",
["textbox","Name of category","",function(){
console.log(this);
name=this.value;
}],
["button","","submit",function(){
console.log(name,category)
this.createChannel(name,category);
channelselect.hide();
}]
]);
channelselect.show();
}
delChannel(JSON){
const channel=this.channelids[JSON.id];
delete this.channelids[JSON.id];
this.channels.splice(this.channels.indexOf(channel),1);
const indexy=this.headchannels.indexOf(channel);
if(indexy!==-1){
this.headchannels.splice(indexy,1);
}
/*
const build=[];
for(const thing of this.channels){
if(thing.id!==JSON.id){
console.log(thing.id);
if(thing!==channel){
build.push(thing)
}else{
console.log("fail");
if(thing.parrent){
thing.parrent.delChannel(JSON);
}
}
}
this.channels=build;
*/
this.printServers();
}
createChannel(name,type){
fetch(info.api.toString()+"/guilds/"+this.id+"/channels",{
createChannel(name:string,type:number){
fetch(this.info.api.toString()+"/guilds/"+this.id+"/channels",{
method:"Post",
headers:this.headers,
body:JSON.stringify({name: name, type: type})
})
}
}
guild.setupcontextmenu();
Guild.setupcontextmenu();
export { Guild };

View file

@ -10,21 +10,28 @@
</head>
<body class="Dark-theme">
<script src="/login.js"></script>
<script src="/contextmenu.js"></script>
<script src="/member.js"></script>
<script src="/user.js"></script>
<script src="/embed.js"></script>
<script src="/message.js"></script>
<script src="/channel.js"></script>
<script src="/permissions.js"></script>
<script src="/role.js"></script>
<script src="/guild.js"></script>
<script src="/direct.js"></script>
<script src="/localuser.js"></script>
<script src="/markdown.js"></script>
<script src="/fullscreen.js"></script>
<script src="/audio.js"></script>
<script type="importmap">
{
"imports": {
"localuser": "/localuser.js",
"guild": "/guild.js",
"direct": "/direct.js",
"channel":"/channel.js",
"message":"/message.js",
"audio":"/audio.js",
"user":"/user.js",
"member":"/member.js",
"markdown":"/markdown.js",
"embed":"/embed.js",
"contextmenu":"/contextmenu.js",
"role":"/role.js",
"permissions":"/permissions.js",
"fullscreen":"/fullscreen.js",
"login":"/login.js"
}
}
</script>
<script src="/index.js" type="module"></script>
<div id="loading" class="loading"><div id="centerdiv"><img src="/bitmap.svg" width="1in" height="1in"><h1>Jank Client is loading</h1><h2>This shouldn't take long</h2></div></div>
<table id="page" cellspacing="0" cellpadding="0">
@ -58,7 +65,7 @@
</td>
</tr></table></td>
<td>
<h2 id="settings" onclick="userSettings()"></h2>
<h2 id="settings"></h2>
</td>
</tr>
</table>
@ -86,6 +93,5 @@
</td>
</tr>
</table>
<script src="/index.js"></script>
</body>
</html>

View file

@ -1,3 +1,16 @@
import { Localuser } from "./localuser.js";
import {Contextmenu} from "./contextmenu.js";
import {mobile, getBulkUsers,setTheme, Specialuser} from "./login.js";
async function waitforload(){
let res
new Promise(r=>{res=r});
document.addEventListener("DOMContentLoaded", function(){
res();
});
await res;
}
await waitforload();
function setDynamicHeight() {
var servertdHeight = document.getElementById('servertd').offsetHeight+document.getElementById('typebox').offsetHeight+document.getElementById('pasteimage').offsetHeight;
document.documentElement.style.setProperty('--servertd-height', servertdHeight + 'px');
@ -18,7 +31,7 @@ var info=users.users[users.currentuser].serverurls;
let token=users.users[users.currentuser].token;
let READY;
let thisuser=new localuser(users.users[users.currentuser]);
let thisuser=new Localuser(users.users[users.currentuser]);
thisuser.initwebsocket().then(_=>{
thisuser.loaduser();
thisuser.init();
@ -32,7 +45,8 @@ thisuser.initwebsocket().then(_=>{
userinfo.addEventListener("click",function(event){
const table=document.createElement("table");
for(const thing of Object.values(users.users)){
console.log(thing.pfpsrc)
const specialuser=thing as Specialuser;
console.log(specialuser.pfpsrc)
const tr=document.createElement("tr");
const td=document.createElement("td");
@ -49,14 +63,14 @@ thisuser.initwebsocket().then(_=>{
row.append(usertd);
const user=document.createElement("div");
usertd.append(user);
user.append(thing.username);
user.append(specialuser.username);
user.append(document.createElement("br"));
const span=document.createElement("span");
span.textContent=thing.serverurls.wellknown.hostname;
span.textContent=specialuser.serverurls.wellknown.hostname;
user.append(span);
span.classList.add("serverURL")
pfp.src=thing.pfpsrc;
pfp.src=specialuser.pfpsrc;
pfp.classList.add("pfp");
td.append(userinfo)
@ -66,9 +80,8 @@ thisuser.initwebsocket().then(_=>{
thisuser.unload();
document.getElementById("loading").classList.remove("doneloading");
document.getElementById("loading").classList.add("loading");
thisuser=new localuser(thing);
window.info =thing.serverurls;
users.currentuser=thing.uid;
thisuser=new Localuser(specialuser);
users["currentuser"]=specialuser.uid;
localStorage.setItem("userinfos",JSON.stringify(users));
thisuser.initwebsocket().then(_=>{
thisuser.loaduser();
@ -91,178 +104,50 @@ thisuser.initwebsocket().then(_=>{
table.append(tr);
}
table.classList.add("accountSwitcher");
if(currentmenu!=""){
currentmenu.remove();
if(Contextmenu.currentmenu!=""){
Contextmenu.currentmenu.remove();
}
currentmenu=table;
Contextmenu.currentmenu=table;
console.log(table);
userdock.append(table);
event.stopImmediatePropagation();
})
}
var currentmenu="";
document.addEventListener('click', function(event) {
if(currentmenu==""){
return;
}
if (!currentmenu.contains(event.target)) {
currentmenu.remove();
currentmenu="";
}
});
let replyingto=null;
{
const menu=new contextmenu("create rightclick");
const menu=new Contextmenu("create rightclick");
menu.addbutton("Create channel",function(){
createchannels(thisuser.lookingguild.createChannel.bind(thisuser.lookingguild));
thisuser.lookingguild.createchannels();
},null,_=>{return thisuser.isAdmin()})
menu.addbutton("Create category",function(){
createcategory(thisuser.lookingguild.createChannel.bind(thisuser.lookingguild));
thisuser.lookingguild.createcategory();
},null,_=>{return thisuser.isAdmin()})
menu.bind(document.getElementById("channels"))
}
function createchannels(fincall){
let name="";
let category=0;
console.log(fincall);
channelselect=new fullscreen(
["vdiv",
["radio","select channel type",
["voice","text","announcement"],
function(e){
console.log(e)
category={"text":0,"voice":2,"announcement":5,"category":4}[e]
},
1
],
["textbox","Name of channel","",function(){
console.log(this)
name=this.value
}],
["button","","submit",function(){
console.log(name,category)
fincall(name,category);
channelselect.hide();
}]
]);
channelselect.show();
}
function createcategory(fincall){
let name="";
let category=4;
console.log(fincall);
channelselect=new fullscreen(
["vdiv",
["textbox","Name of category","",function(){
console.log(this)
name=this.value
}],
["button","","submit",function(){
console.log(name,category)
fincall(name,category);
channelselect.hide();
}]
]);
channelselect.show();
}
function editchannelf(channel){channel.editChannel();}
let messagelist=[];
function buildprofile(x,y,user,type="author"){
if(currentmenu!=""){
currentmenu.remove();
}
let nickname, username, discriminator, bio, bot, pronouns, id, avatar
if(type=="author"){
console.log(user)
username=nickname=user.username;
bio=user.bio;
id=user.id;
discriminator=user.discriminator;
pronouns=user.pronouns;
bot=user.bot;
avatar=user.avatar;
}
const div=document.createElement("table");
if(x!==-1){
div.style.left=x+"px";
div.style.top=y+"px";
div.classList.add("profile");
}else{
div.classList.add("hypoprofile");
}
{
const pfp=user.buildpfp();
const pfprow=document.createElement("tr");
div.appendChild(pfprow);
pfprow.appendChild(pfp);
}
{
const userbody=document.createElement("tr");
userbody.classList.add("infosection");
div.appendChild(userbody);
const usernamehtml=document.createElement("h2");
usernamehtml.textContent=nickname;
userbody.appendChild(usernamehtml);
const discrimatorhtml=document.createElement("h3");
discrimatorhtml.classList.add("tag");
discrimatorhtml.textContent=username+"#"+discriminator;
userbody.appendChild(discrimatorhtml)
const pronounshtml=document.createElement("p");
pronounshtml.textContent=pronouns;
pronounshtml.classList.add("pronouns");
userbody.appendChild(pronounshtml)
const rule=document.createElement("hr");
userbody.appendChild(rule);
const biohtml=markdown(bio);
userbody.appendChild(biohtml);
}
console.log(div);
if(x!==-1){
currentmenu=div;
document.body.appendChild(div)
}
return div
}
function profileclick(obj,author){
obj.onclick=function(e){
console.log(e.clientX,e.clientY,author);
buildprofile(e.clientX,e.clientY,author);
e.stopPropagation();
}
}
var editing=false;
const typebox=document.getElementById("typebox")
typebox.addEventListener("keyup",enter);
typebox.addEventListener("keydown",event=>{
if(event.key === "Enter"&&!event.shiftKey) event.preventDefault();
});
console.log(typebox)
typebox.onclick=console.log;
const pasteimage=document.getElementById("pasteimage");
let replyingto=null;
async function enter(event){
thisuser.channelfocus.typingstart();
const channel=thisuser.channelfocus
channel.typingstart();
if(event.key === "Enter"&&!event.shiftKey){
event.preventDefault();
if(editing){
editing.edit(typebox.value);
editing=false;
if(channel.editing){
channel.editing.edit((typebox).value);
channel.editing=null;
}else{
let replying=replyingto?.all;
if(replyingto){
replyingto.classList.remove("replying");
}
replyingto=false;
thisuser.channelfocus.sendMessage(typebox.value,{
channel.sendMessage(typebox.value,{
attachments:images,
replyingto:replying,
})
@ -276,7 +161,17 @@ async function enter(event){
}
}
let packets=1;
const typebox=document.getElementById("typebox") as HTMLInputElement;
typebox.addEventListener("keyup",enter);
typebox.addEventListener("keydown",event=>{
if(event.key === "Enter"&&!event.shiftKey) event.preventDefault();
});
console.log(typebox)
typebox.onclick=console.log;
let serverz=0;
let serverid=[];
@ -289,13 +184,13 @@ let cchanel=0;
function getguildinfo(){
const path=window.location.pathname.split("/");
const channel=path[3];
ws.send(JSON.stringify({op: 14, d: {guild_id: path[2], channels: {[channel]: [[0, 99]]}}}));
this.ws.send(JSON.stringify({op: 14, d: {guild_id: path[2], channels: {[channel]: [[0, 99]]}}}));
}
const images=[];
const imageshtml=[];
function createunknown(fname,fsize,src){
function createunknown(fname,fsize){
const div=document.createElement("table");
div.classList.add("unknownfile");
const nametr=document.createElement("tr");
@ -304,14 +199,9 @@ function createunknown(fname,fsize,src){
nametr.append(fileicon);
fileicon.append("🗎");
fileicon.classList.add("fileicon");
fileicon.rowSpan="2";
fileicon.rowSpan=2;
const nametd=document.createElement("td");
if(src){
const a=document.createElement("a");
a.href=src;
a.textContent=fname;
nametd.append(a);
}else{
{
nametd.textContent=fname;
}
@ -362,6 +252,7 @@ setTheme();
function userSettings(){
thisuser.usersettings.show();
}
document.getElementById("settings").onclick=userSettings;
let triggered=false;
document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{
const messagecontainer=document.getElementById("messagecontainer")
@ -384,13 +275,13 @@ document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{
})
if(mobile){
document.getElementById("channelw").onclick=function(){
document.getElementById("channels").parentNode.classList.add("collapse");
(document.getElementById("channels").parentNode as HTMLElement).classList.add("collapse");
document.getElementById("servertd").classList.add("collapse");
document.getElementById("servers").classList.add("collapse");
}
document.getElementById("mobileback").textContent="#";
document.getElementById("mobileback").onclick=function(){
document.getElementById("channels").parentNode.classList.remove("collapse");
(document.getElementById("channels").parentNode as HTMLElement).classList.remove("collapse");
document.getElementById("servertd").classList.remove("collapse");
document.getElementById("servers").classList.remove("collapse");
}

View file

@ -1,18 +1,48 @@
class localuser{
constructor(userinfo){
import {Guild} from "./guild.js";
import {Channel} from "./channel.js";
import {Direct} from "./direct.js";
import {Voice} from "./audio.js";
import {User} from "./user.js";
import {Member} from "./member.js";
import {markdown} from "./markdown.js";
import {Fullscreen} from "./fullscreen.js";
import {setTheme, Specialuser} from "./login.js";
class Localuser{
packets:number;
token:string;
userinfo:Specialuser;
serverurls;
initialized:boolean;
info;
headers:{"Content-type":string,Authorization:string};
usersettings:Fullscreen;
ready;
guilds:Guild[];
guildids:{ [key: string]: Guild };
user:User;
status:string;
channelfocus:Channel;
lookingguild:Guild;
guildhtml:Record<string, HTMLDivElement>;
ws:WebSocket;
typing:[string,number][];
wsinterval:NodeJS.Timeout;
constructor(userinfo:Specialuser){
this.packets=1;
this.token=userinfo.token;
this.userinfo=userinfo;
this.serverurls=this.userinfo.serverurls;
this.initialized=false;
this.info=this.serverurls;
this.headers={"Content-type": "application/json; charset=UTF-8",Authorization:this.userinfo.token};
}
gottenReady(ready){
gottenReady(ready):void{
this.usersettings=null;
this.initialized=true;
this.ready=ready;
this.guilds=[];
this.guildids={};
this.user=new user(ready.d.user);
this.user=new User(ready.d.user,this);
this.userinfo.username=this.user.username;
this.userinfo.pfpsrc=this.user.getpfpsrc();
this.status=this.ready.d.user_settings.status;
@ -20,12 +50,12 @@ class localuser{
this.lookingguild=null;
this.guildhtml={};
for(const thing of ready.d.guilds){
const temp=new guild(thing,this);
const temp=new Guild(thing,this);
this.guilds.push(temp);
this.guildids[temp.id]=temp;
}
{
const temp=new direct(ready.d.private_channels,this);
const temp=new Direct(ready.d.private_channels,this);
this.guilds.push(temp);
this.guildids[temp.id]=temp;
}
@ -35,11 +65,11 @@ class localuser{
}
for(const thing of ready.d.merged_members){
const guild=this.guildids[thing[0].guild_id]
const temp=new member(thing[0],guild);
const temp=new Member(thing[0],guild);
guild.giveMember(temp);
}
for(const thing of ready.d.read_state.entries){
const guild=this.resolveGuildidFromChannelID(thing.id)
const guild=this.resolveChannelFromID(thing.id).guild;
if(guild===undefined){
continue
}
@ -48,14 +78,14 @@ class localuser{
}
this.typing=[];
}
outoffocus(){
outoffocus():void{
document.getElementById("servers").textContent="";
document.getElementById("channels").textContent="";
document.getElementById("messages").textContent="";
this.lookingguild=null;
this.channelfocus=null;
}
unload(){
unload():void{
this.initialized=false;
clearInterval(this.wsinterval);
this.outoffocus();
@ -63,7 +93,7 @@ class localuser{
this.guildids={};
this.ws.close(4000)
}
async initwebsocket(){
async initwebsocket():Promise<void>{
let returny=null
const promise=new Promise((res)=>{returny=res});
this.ws = new WebSocket(this.serverurls.gateway.toString());
@ -106,22 +136,25 @@ class localuser{
break;
case "READY":
this.gottenReady(temp);
READY=temp;
this.genusersettings();
returny();
break;
case "MESSAGE_UPDATE":
if(this.initialized){
if(window.location.pathname.split("/")[3]==temp.d.channel_id){
if(this.channelfocus.id===temp.d.channel_id){
const find=temp.d.id;
const messagelist=document.getElementById("messages").children;
for(const message of messagelist){
if(message.all.id===find){
message.all.content=temp.d.content;
message.txt.innerHTML=markdown(temp.d.content).innerHTML;
const all = message["all"];
if(all.id===find){
all.content=temp.d.content;
message["txt"].innerHTML=markdown(temp.d.content).innerHTML;
break;
}
}
}
}else{
this.resolveChannelFromID(temp.d.channel_id).messages.find(e=>e.id===temp.d.channel_id).content=temp.d.content;
}
}
break;
case "TYPING_START":
@ -131,7 +164,7 @@ class localuser{
break;
case "USER_UPDATE":
if(this.initialized){
const users=user.userids[temp.d.id];
const users=User.userids[temp.d.id];
console.log(users,temp.d.id)
if(users){
users.userupdate(temp.d);
@ -163,7 +196,7 @@ class localuser{
}
case "GUILD_CREATE":
{
const guildy=new guild(temp.d,this);
const guildy=new Guild(temp.d,this);
this.guilds.push(guildy);
this.guildids[guildy.id]=guildy;
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(),document.getElementById("bottomseperator"));
@ -173,11 +206,11 @@ class localuser{
}else if(temp.op===10){
console.log("heartbeat down")
this.wsinterval=setInterval(_=>{
this.ws.send(JSON.stringify({op:1,d:packets}))
this.ws.send(JSON.stringify({op:1,d:this.packets}))
},temp.d.heartbeat_interval)
packets=1;
this.packets=1;
}else if(temp.op!=11){
packets++
this.packets++
}
}catch(error){
console.error(error)
@ -189,13 +222,13 @@ class localuser{
clearInterval(this.wsinterval);
console.log('WebSocket closed');
console.warn(event);
if(event.code!==4000&&thisuser===this){
if(event.code!==4000&&this===this){
this.unload();
document.getElementById("loading").classList.remove("doneloading");
document.getElementById("loading").classList.add("loading");
this.initwebsocket().then(_=>{
thisuser.loaduser();
thisuser.init();
this.loaduser();
this.init();
document.getElementById("loading").classList.add("doneloading");
document.getElementById("loading").classList.remove("loading");
console.log("done loading")
@ -205,32 +238,34 @@ class localuser{
await promise;
return;
}
resolveGuildidFromChannelID(ID){
let resolve=this.guilds.find(guild => guild.channelids[ID])
resolveChannelFromID(ID:string):Channel{
console.log(this.guilds.find(guild => guild.channelids[ID]).channelids)
let resolve=this.guilds.find(guild => guild.channelids[ID]).channelids[ID];
resolve??=undefined;
return resolve;
}
updateChannel(JSON){
updateChannel(JSON):void{
this.guildids[JSON.guild_id].updateChannel(JSON);
if(JSON.guild_id===this.lookingguild.id){
this.loadGuild(JSON.guild_id);
}
}
createChannel(JSON){
createChannel(JSON):void{
JSON.guild_id??="@me";
this.guildids[JSON.guild_id].createChannelpac(JSON);
if(JSON.guild_id===this.lookingguild.id){
this.loadGuild(JSON.guild_id);
}
}
delChannel(JSON){
delChannel(JSON):void{
JSON.guild_id??="@me";
this.guildids[JSON.guild_id].delChannel(JSON);
if(JSON.guild_id===this.lookingguild.id){
this.loadGuild(JSON.guild_id);
}
}
init(){
init():void{
const location=window.location.href.split("/");
if(location[3]==="channels"){
const guild=this.loadGuild(location[4]);
@ -239,15 +274,15 @@ class localuser{
}
this.buildservers();
}
loaduser(){
document.getElementById("username").textContent=this.user.username
document.getElementById("userpfp").src=this.user.getpfpsrc()
loaduser():void{
document.getElementById("username").textContent=this.user.username;
(document.getElementById("userpfp") as HTMLImageElement).src=this.user.getpfpsrc();
document.getElementById("status").textContent=this.status;
}
isAdmin(){
isAdmin():boolean{
return this.lookingguild.isAdmin();
}
loadGuild(id){
loadGuild(id:string):Guild{
let guild=this.guildids[id];
if(!guild){
guild=this.guildids["@me"];
@ -259,17 +294,17 @@ class localuser{
document.getElementById("channels").appendChild(guild.getHTML());
return guild;
}
buildservers(){
buildservers():void{
const serverlist=document.getElementById("servers");//
const div=document.createElement("div");
div.textContent="⌂";
div.classList.add("home","servericon")
div.all=this.guildids["@me"];
div["all"]=this.guildids["@me"];
serverlist.appendChild(div)
div.onclick=function(){
this.all.loadGuild();
this.all.loadChannel();
this["all"].loadGuild();
this["all"].loadChannel();
}
const sentdms=document.createElement("div");
sentdms.classList.add("sentdms");
@ -280,8 +315,8 @@ class localuser{
br.classList.add("lightbr");
serverlist.appendChild(br)
for(const thing of this.guilds){
if(thing instanceof direct){
thing.unreaddms();
if(thing instanceof Direct){
(thing as Direct).unreaddms();
continue;
}
const divy=thing.generateGuildIcon();
@ -309,7 +344,7 @@ class localuser{
let inviteurl="";
const error=document.createElement("span");
const full=new fullscreen(["tabs",[
const full=new Fullscreen(["tabs",[
["Join using invite",[
"vdiv",
["textbox",
@ -332,7 +367,7 @@ class localuser{
}else{
parsed=inviteurl;
}
fetch(info.api.toString()+"/v9/invites/"+parsed,{
fetch(this.info.api.toString()+"/v9/invites/"+parsed,{
method:"POST",
headers:this.headers,
}).then(r=>r.json()).then(_=>{
@ -351,19 +386,19 @@ class localuser{
]])
full.show();
}
messageCreate(messagep){
messageCreate(messagep):void{
messagep.d.guild_id??="@me";
this.guildids[messagep.d.guild_id].channelids[messagep.d.channel_id].messageCreate(messagep,this.channelfocus.id===messagep.d.channel_id);
this.guildids[messagep.d.guild_id].channelids[messagep.d.channel_id].messageCreate(messagep);
this.unreads();
}
unreads(){
unreads():void{
console.log(this.guildhtml)
for(const thing of this.guilds){
if(thing.id==="@me"){continue;}
thing.unreads(this.guildhtml[thing.id]);
}
}
typeingStart(typing){
typeingStart(typing):void{
if(this.channelfocus.id===typing.d.channel_id){
const memb=typing.d.member;
let name;
@ -392,12 +427,12 @@ class localuser{
this.rendertyping();
}
}
updatepfp(file){
updatepfp(file:Blob):void{
var reader = new FileReader();
reader.readAsDataURL(file);
console.log(this.headers);
reader.onload = ()=>{
fetch(info.api.toString()+"/v9/users/@me",{
fetch(this.info.api.toString()+"/v9/users/@me",{
method:"PATCH",
headers:this.headers,
body:JSON.stringify({
@ -408,8 +443,8 @@ class localuser{
};
}
updatepronouns(pronouns){
fetch(info.api.toString()+"/v9/users/@me/profile",{
updatepronouns(pronouns:string):void{
fetch(this.info.api.toString()+"/v9/users/@me/profile",{
method:"PATCH",
headers:this.headers,
body:JSON.stringify({
@ -417,8 +452,8 @@ class localuser{
})
});
}
updatebio(bio){
fetch(info.api.toString()+"/v9/users/@me/profile",{
updatebio(bio:string):void{
fetch(this.info.api.toString()+"/v9/users/@me/profile",{
method:"PATCH",
headers:this.headers,
body:JSON.stringify({
@ -426,7 +461,7 @@ class localuser{
})
});
}
rendertyping(){
rendertyping():void{
const typingtext=document.getElementById("typing")
let build="";
const array2=[];
@ -456,20 +491,20 @@ class localuser{
typingtext.classList.add("hidden");
}
}
genusersettings(){
genusersettings():void{
const hypothetcialprofie=document.createElement("div");
let file=null;
let newprouns=null;
let newbio=null;
let hypouser=new user(thisuser.user,true);
let hypouser=new User(this.user,this,true);
function regen(){
hypothetcialprofie.textContent="";
const hypoprofile=buildprofile(-1,-1,hypouser);
const hypoprofile=hypouser.buildprofile(-1,-1);
hypothetcialprofie.appendChild(hypoprofile)
}
regen();
this.usersettings=new fullscreen(
this.usersettings=new Fullscreen(
["hdiv",
["vdiv",
["fileupload","upload pfp:",function(e){
@ -480,13 +515,13 @@ class localuser{
hypouser.hypotheticalpfp=true;
regen();
}],
["textbox","Pronouns:",thisuser.user.pronouns,function(e){
["textbox","Pronouns:",this.user.pronouns,function(e){
console.log(this.value);
hypouser.pronouns=this.value;
newprouns=this.value;
regen();
}],
["mdbox","Bio:",thisuser.user.bio,function(e){
["mdbox","Bio:",this.user.bio,function(e){
console.log(this.value);
hypouser.bio=this.value;
newbio=this.value;
@ -494,33 +529,35 @@ class localuser{
}],
["button","update user content:","submit",function(){
if(file!==null){
thisuser.updatepfp(file);
this.updatepfp(file);
}
if(newprouns!==null){
thisuser.updatepronouns(newprouns);
this.updatepronouns(newprouns);
}
if(newbio!==null){
thisuser.updatebio(newbio);
this.updatebio(newbio);
}
}],
["select","Theme:",["Dark","Light","WHITE"],e=>{
localStorage.setItem("theme",["Dark","Light","WHITE"][e.target.selectedIndex]);
setTheme();
},["Dark","Light","WHITE"].indexOf(localStorage.getItem("theme"))],
["select","Notification sound:",voice.sounds,e=>{
voice.setNotificationSound(voice.sounds[e.target.selectedIndex]);
voice.noises(voice.sounds[e.target.selectedIndex]);
},voice.sounds.indexOf(voice.getNotificationSound())]
["select","Notification sound:",Voice.sounds,e=>{
Voice.setNotificationSound(Voice.sounds[e.target.selectedIndex]);
Voice.noises(Voice.sounds[e.target.selectedIndex]);
},Voice.sounds.indexOf(Voice.getNotificationSound())]
],
["vdiv",
["html",hypothetcialprofie]
]
],_=>{},function(){
hypouser=new user(thisuser.user);
console.log(this);
hypouser=new User(this.user,this);
regen();
file=null;
newprouns=null;
newbio=null;
})
}.bind(this))
}
}
export {Localuser};

View file

@ -22,5 +22,5 @@
</form>
<a href="/register.html">Don't have an account?</a>
</div>
<script src="/login.js"></script>
<script src="/login.js" type="module"></script>
</body>

View file

@ -1,4 +1,5 @@
const mobile=isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
const mobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
export {mobile, getBulkUsers,getBulkInfo,setTheme,Specialuser}
function setTheme(){
const name=localStorage.getItem("theme");
if(!name){
@ -11,7 +12,7 @@ setTheme();
function getBulkUsers(){
const json=getBulkInfo()
for(const thing in json.users){
json.users[thing]=new specialuser(json.users[thing]);
json.users[thing]=new Specialuser(json.users[thing]);
}
return json;
}
@ -48,9 +49,14 @@ function setDefaults(){
localStorage.setItem("userinfos",JSON.stringify(userinfos));
}
setDefaults();
class specialuser{
class Specialuser{
serverurls;
email:string;
token:string;
loggedin;
json;
constructor(json){
if(json instanceof specialuser){
if(json instanceof Specialuser){
console.error("specialuser can't construct from another specialuser");
}
this.serverurls=json.serverurls;
@ -94,21 +100,23 @@ class specialuser{
}
}
function adduser(user){
user=new specialuser(user);
user=new Specialuser(user);
const info=getBulkInfo();
info.users[user.uid]=user;
info.currentuser=user.uid;
localStorage.setItem("userinfos",JSON.stringify(info));
}
const instancein=document.getElementById("instancein");
let timeout=0;
let timeout;
let instanceinfo;
async function checkInstance(e){
const verify=document.getElementById("verify");;
try{
verify.textContent="Checking Instance";
instanceinfo=await setInstance(instancein.value);
const instanceinfo=await setInstance((instancein as HTMLInputElement).value);
localStorage.setItem("instanceinfo",JSON.stringify(instanceinfo));
verify.textContent="Instance is all good"
if(checkInstance.alt){checkInstance.alt();}
if(checkInstance["alt"]){checkInstance["alt"]();}
setTimeout(_=>{
console.log(verify.textContent)
verify.textContent="";
@ -128,7 +136,7 @@ if(instancein){
timeout=setTimeout(checkInstance,1000);
});
if(localStorage.getItem("instanceinfo")){
instancein.value=JSON.parse(localStorage.getItem("instanceinfo")).wellknown
(instancein as HTMLInputElement).value=JSON.parse(localStorage.getItem("instanceinfo")).wellknown
}else{
checkInstance("https://spacebar.chat/");
}
@ -148,7 +156,7 @@ async function login(username, password){
}}
try{
const info=JSON.parse(localStorage.getItem("instanceinfo"));
url=new URL(info.login);
const url=new URL(info.login);
return await fetch(url.origin+'/api/auth/login',options).then(responce=>responce.json())
.then((response) => {
console.log(response,response.message)

View file

@ -1,7 +1,10 @@
"use strict";
function markdown(txt,keep=false){
if((typeof txt)===(typeof "")){
return markdown(txt.split(""),keep);
export {markdown};
function markdown(text : string|string[],keep=false){
let txt : string[];
if((typeof txt)==="string"){
txt=(text as string).split("");
}else{
txt=(text as string[]);
}
const span=document.createElement("span");
let current=document.createElement("span");
@ -19,7 +22,7 @@ function markdown(txt,keep=false){
i--;
}
let element=null;
let keepys=false;
let keepys="";
if(txt[i+1]==="#"){
console.log("test");
@ -151,7 +154,7 @@ function markdown(txt,keep=false){
if(txt[j]==="*"){
find++;
}else{
build+=txt[j];
build.push(txt[j]);
if(find!==0){
build=build.concat(new Array(find).fill("*"));
find=0;
@ -205,7 +208,7 @@ function markdown(txt,keep=false){
if(txt[j]==="_"){
find++;
}else{
build+=txt[j];
build.push(txt[j]);
if(find!==0){
build=build.concat(new Array(find).fill("_"));
find=0;
@ -251,7 +254,7 @@ function markdown(txt,keep=false){
if(txt[j]==="~"){
find++;
}else{
build+=txt[j];
build.push(txt[j]);
if(find!==0){
build=build.concat(new Array(find).fill("~"));
find=0;
@ -281,7 +284,7 @@ function markdown(txt,keep=false){
if(txt[j]==="|"){
find++;
}else{
build+=txt[j];
build.push(txt[j]);
if(find!==0){
build=build.concat(new Array(find).fill("~"));
find=0;
@ -309,8 +312,9 @@ function markdown(txt,keep=false){
appendcurrent();
return span;
}
markdown.unspoil=function(e){
markdown.unspoil=function(e:any) : void{
//console.log("undone")
e.target.classList.remove("spoiler")
e.target.classList.add("unspoiled")
}

View file

@ -1,6 +1,12 @@
class member{
import {User} from "./user.js";
import {Role} from "./role.js";
import {Guild} from "./guild.js";
class Member{
static already={};
constructor(memberjson,owner){
owner:Guild;
user:User;
roles:Role[];
constructor(memberjson,owner:Guild){
if(!owner){console.error("Guild not included in the creation of a member object")}
this.owner=owner;
let membery=memberjson;
@ -12,7 +18,7 @@ class member{
if(thing==="guild"){continue}
this[thing]=membery[thing];
}
this.user=new user(this.user);
this.user=new User(this.user,owner.localuser);
}
get guild(){
return this.owner;
@ -20,27 +26,32 @@ class member{
get localuser(){
return this.guild.localuser;
}
static async resolve(user,guild){
if(!member.already[guild.id]){
member.already[guild.id]={};
}else if(member.already[guild.id][user.id]){
const memb=member.already[guild.id][user.id]
get info(){
return this.owner.info;
}
static async resolve(user:User,guild:Guild){
if(guild.id==="@me"){return null}
if(!Member.already[guild.id]){
Member.already[guild.id]={};
}else if(Member.already[guild.id][user.id]){
const memb=Member.already[guild.id][user.id]
if(memb instanceof Promise){
return await memb;
}
return memb;
}
const promoise= fetch(info.api.toString()+"/v9/users/"+user.id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.id,{headers:guild.headers}).then(_=>_.json()).then(json=>{
const memb=new member(json,guild);
member.already[guild.id][user.id]=memb;
const promoise= fetch(guild.info.api.toString()+"/v9/users/"+user.id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.id,{headers:guild.headers}).then(_=>_.json()).then(json=>{
const memb=new Member(json,guild);
Member.already[guild.id][user.id]=memb;
guild.fillMember(memb);
console.log("resolved")
return memb
});
member.already[guild.id][user.id]=promoise;
Member.already[guild.id][user.id]=promoise;
return await promoise;
}
hasRole(ID){
hasRole(ID:string){
console.log(this.roles,ID);
for(const thing of this.roles){
if(thing.id===ID){
return true;
@ -62,3 +73,4 @@ class member{
}
}
export {Member};

View file

@ -1,34 +1,56 @@
class cmessage{
static contextmenu=new contextmenu("message menu");
import {Contextmenu} from "./contextmenu.js";
import {User} from "./user.js";
import {Member} from "./member.js";
import {markdown} from "./markdown.js";
import {Embed} from "./embed.js";
import {Fullscreen} from "./fullscreen.js";
import { Channel } from "./channel.js";
import {Localuser} from "./localuser.js";
import { Role } from "./role.js";
class Message{
static contextmenu=new Contextmenu("message menu");
owner:Channel;
headers:Localuser["headers"];
embeds:Embed[];
author:User;
mentions:User[];
mention_roles:Role[];
attachments;
id:string;
message_reference;
type:number;
timestamp:number;
content;
static setupcmenu(){
cmessage.contextmenu.addbutton("Copy raw text",function(){
Message.contextmenu.addbutton("Copy raw text",function(){
navigator.clipboard.writeText(this.content);
});
cmessage.contextmenu.addbutton("Reply",function(div){
if(replyingto){
replyingto.classList.remove("replying");
Message.contextmenu.addbutton("Reply",function(div){
if(this.channel.replyingto){
this.channel.replyingto.classList.remove("replying");
}
replyingto=div;
this.channel.replyingto=div;
console.log(div);
replyingto.classList.add("replying");
this.channel.replyingto.classList.add("replying");
});
cmessage.contextmenu.addbutton("Copy message id",function(){
Message.contextmenu.addbutton("Copy message id",function(){
navigator.clipboard.writeText(this.id);
});
cmessage.contextmenu.addbutton("Copy user id",function(){
Message.contextmenu.addbutton("Copy user id",function(){
navigator.clipboard.writeText(this.author.id);
});
cmessage.contextmenu.addbutton("Message user",function(){
fetch(info.api.toString()+"/v9/users/@me/channels",
Message.contextmenu.addbutton("Message user",function(){
fetch(this.info.api.toString()+"/v9/users/@me/channels",
{method:"POST",
body:JSON.stringify({"recipients":[this.author.id]}),
headers: {"Content-type": "application/json; charset=UTF-8",Authorization:token}
headers: this.headers
});
})
cmessage.contextmenu.addbutton("Edit",function(){
editing=this;
document.getElementById("typebox").value=this.content;
},null,_=>{return _.author.id==READY.d.user.id});
Message.contextmenu.addbutton("Edit",function(){
this.channel.editing=this;
(document.getElementById("typebox") as HTMLInputElement).value=this.content;
},null,_=>{return _.author.id===_.localuser.user.id});
}
constructor(messagejson,owner){
this.owner=owner;
@ -38,11 +60,11 @@ class cmessage{
}
for(const thing in this.embeds){
console.log(thing,this.embeds)
this.embeds[thing]=new embed(this.embeds[thing],this);
this.embeds[thing]=new Embed(this.embeds[thing],this);
}
this.author=new user(this.author);
this.author=new User(this.author,this.localuser);
for(const thing in this.mentions){
this.mentions[thing]=new user(this.mentions[thing]);
this.mentions[thing]=new User(this.mentions[thing],this.localuser);
}
if(this.mentions.length||this.mention_roles.length){//currently mention_roles isn't implemented on the spacebar servers
console.log(this.mentions,this.mention_roles)
@ -60,14 +82,17 @@ class cmessage{
get localuser(){
return this.owner.localuser;
}
get info(){
return this.owner.info;
}
messageevents(obj){
cmessage.contextmenu.bind(obj,this)
Message.contextmenu.bind(obj,this)
obj.classList.add("messagediv")
}
mentionsuser(userd){
if(userd instanceof user){
if(userd instanceof User){
return this.mentions.includes(userd);
}else if(userd instanceof member){
}else if(userd instanceof Member){
return this.mentions.includes(userd.user);
}
}
@ -81,7 +106,7 @@ class cmessage{
return build;
}
async edit(content){
return await fetch(info.api.toString()+"/channels/"+this.channel.id+"/messages/"+this.id,{
return await fetch(this.info.api.toString()+"/channels/"+this.channel.id+"/messages/"+this.id,{
method: "PATCH",
headers: this.headers,
body:JSON.stringify({content:content})
@ -104,7 +129,7 @@ class cmessage{
const reply=document.createElement("div");
username.classList.add("username");
member.resolve(this.author,this.guild).then(_=>{
Member.resolve(this.author,this.guild).then(_=>{
username.style.color=_.getColor();
});
@ -115,21 +140,20 @@ class cmessage{
line2.classList.add("reply");
line.classList.add("startreply");
replyline.classList.add("replyflex")
fetch(info.api.toString()+"/v9/channels/"+this.message_reference.channel_id+"/messages?limit=1&around="+this.message_reference.message_id,{headers:this.headers}).then(responce=>responce.json()).then(responce=>{
const author=new user(responce[0].author);
fetch(this.info.api.toString()+"/v9/channels/"+this.message_reference.channel_id+"/messages?limit=1&around="+this.message_reference.message_id,{headers:this.headers}).then(responce=>responce.json()).then(responce=>{
const author=new User(responce[0].author,this.localuser);
reply.appendChild(markdown(responce[0].content));
minipfp.src=author.getpfpsrc()
profileclick(minipfp,author)
author.profileclick(minipfp)
username.textContent=author.username;
profileclick(username,author)
author.profileclick(username)
});
div.appendChild(replyline);
}
this.messageevents(div);
messagelist.push(div)
build.classList.add("message");
div.appendChild(build);
if({0:true,19:true}[this.type]||this.attachments.length!==0){
@ -145,13 +169,13 @@ class cmessage{
const newt=(new Date(this.timestamp).getTime())/1000;
current=(newt-old)>600;
}
const combine=(premessage?.userid!=this.author.id&premessage?.author?.id!=this.author.id)||(current)||this.message_reference
const combine=(premessage?.userid!=this.author.id&&premessage?.author?.id!=this.author.id)||(current)||this.message_reference
if(combine){
const pfp=this.author.buildpfp();
profileclick(pfp,this.author);
this.author.profileclick(pfp);
pfpRow.appendChild(pfp);
}else{
div.pfpparent=pfpparent;
div["pfpparent"]=pfpparent;
}
pfpRow.classList.add("pfprow")
build.appendChild(pfpRow);
@ -163,8 +187,9 @@ class cmessage{
if(combine){
const username=document.createElement("span");
username.classList.add("username")
profileclick(username,this.author);
member.resolve(this.author,this.guild).then(_=>{
this.author.profileclick(username);
Member.resolve(this.author,this.guild).then(_=>{
if(!_){return}
username.style.color=_.getColor();
})
username.textContent=this.author.username;
@ -184,28 +209,29 @@ class cmessage{
texttxt.appendChild(userwrap)
}
const messaged=markdown(this.content);
div.txt=messaged;
div["txt"]=messaged;
const messagedwrap=document.createElement("tr")
messagedwrap.appendChild(messaged)
texttxt.appendChild(messagedwrap)
build.appendChild(text)
if(this.attachments.length){
console.log(this.attachments)
const attatch = document.createElement("tr")
for(const thing of this.attachments){
const array=thing.url.split("/");array.shift();array.shift();array.shift();
const src=info.cdn.toString()+array.join("/");
const src=this.info.cdn.toString()+array.join("/");
if(thing.content_type.startsWith('image/')){
const img=document.createElement("img");
img.classList.add("messageimg")
img.onclick=function(){
const full=new fullscreen(["img",img.src,["fit"]]);
const full=new Fullscreen(["img",img.src,["fit"]]);
full.show();
}
img.src=src;
attatch.appendChild(img)
}else{
attatch.appendChild(createunknown(thing.filename,thing.size,src))
attatch.appendChild(this.createunknown(thing.filename,thing.size,src))
}
}
@ -228,7 +254,7 @@ class cmessage{
build.appendChild(text)
const messaged=document.createElement("p");
div.txt=messaged;
div["txt"]=messaged;
messaged.textContent="welcome: "+this.author.username;
const messagedwrap=document.createElement("tr")
messagedwrap.appendChild(messaged);
@ -240,10 +266,44 @@ class cmessage{
texttxt.appendChild(messagedwrap)
}
div.userid=this.author.id;
div.all=this;
div["userid"]=this.author.id;
div["all"]=this;
return(div)
}
createunknown(fname,fsize,src){
const div=document.createElement("table");
div.classList.add("unknownfile");
const nametr=document.createElement("tr");
div.append(nametr);
const fileicon=document.createElement("td");
nametr.append(fileicon);
fileicon.append("🗎");
fileicon.classList.add("fileicon");
fileicon.rowSpan=2;
const nametd=document.createElement("td");
if(src){
const a=document.createElement("a");
a.href=src;
a.textContent=fname;
nametd.append(a);
}else{
nametd.textContent=fname;
}
nametd.classList.add("filename");
nametr.append(nametd);
const sizetr=document.createElement("tr");
const size=document.createElement("td");
sizetr.append(size);
size.textContent="Size:"+this.filesizehuman(fsize);
size.classList.add("filesize");
div.appendChild(sizetr)
return div;
}
filesizehuman(fsize){
var i = fsize == 0 ? 0 : Math.floor(Math.log(fsize) / Math.log(1024));
return +((fsize / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', 'Terabytes'][i];
}
}
function formatTime(date) {
@ -268,4 +328,5 @@ function formatTime(date) {
return `${date.toLocaleDateString()} at ${formatTime(date)}`;
}
}
cmessage.setupcmenu();
Message.setupcmenu();
export { Message };

View file

@ -1,18 +1,24 @@
class permissions{
constructor(b){
this.permissions=BigInt(b);
export {Permissions};
class Permissions{
allow:bigint;
deny:bigint;
constructor(allow:string,deny:string=""){
this.allow=BigInt(allow);
this.deny=BigInt(deny);
}
getPermisionbit(b){
return Boolean((this.permissions>>BigInt(b))&1n);
getPermisionbit(b:number,big:bigint) : boolean{
return Boolean((big>>BigInt(b))&1n);
}
setPermisionbit(b,state){
setPermisionbit(b:number,state:boolean,big:bigint) : bigint{
const bit=1n<<BigInt(b);
this.permissions=(this.permissions & ~bit) | (BigInt(state) << BigInt(b));//thanks to geotale for this code :3
return (big & ~bit) | (BigInt(state) << BigInt(b));//thanks to geotale for this code :3
}
static map
static info
static map:{
[key:number|string]:{"name":string,"readableName":string,"description":string}|number,
}
static info:{"name":string,"readableName":string,"description":string}[];
static makeMap(){
permissions.info=[//for people in the future, do not reorder these, the creation of the map realize on the order
Permissions.info=[//for people in the future, do not reorder these, the creation of the map realize on the order
{
name:"CREATE_INSTANT_INVITE",
readableName:"Create instance invite",
@ -219,16 +225,22 @@ class permissions{
description:"Allows the user to time out other users to prevent them from sending or reacting to messages in chat and threads, and from speaking in voice and stage channels"
},
];
permissions.map={};
Permissions.map={};
let i=0;
for(const thing of permissions.info){
permissions.map[i]=thing;
permissions.map[thing.name]=i;
for(const thing of Permissions.info){
Permissions.map[i]=thing;
Permissions.map[thing.name]=i;
i++;
}
}
getPermision(name){
return this.getPermisionbit(permissions.map[name]);
getPermision(name:string):number{
if(this.getPermisionbit(Permissions.map[name] as number,this.allow)){
return 1;
}else if(this.getPermisionbit(Permissions.map[name] as number,this.deny)){
return -1;
}else{
return 0;
}
}
}
permissions.makeMap();
Permissions.makeMap();

View file

@ -1,20 +0,0 @@
class role{
constructor(JSON, owner){
for(const thing of Object.keys(JSON)){
this[thing]=JSON[thing];
}
this.permissions=new permissions(JSON.permissions);
this.owner=owner;
}
get guild(){
return this.owner;
}
get localuser(){
return this.guild.localuser;
}
getColor(){
if(this.color===0){return null};
return `#${this.color.toString(16)}`;
}
}

28
webpage/role.ts Normal file
View file

@ -0,0 +1,28 @@
export {Role};
import {Permissions} from "./permissions.js";
import {Localuser} from "./localuser.js";
import {Guild} from "./guild.js";
class Role{
permissions:Permissions;
owner:Guild;
color:number;
id:string;
constructor(JSON, owner:Guild){
for(const thing of Object.keys(JSON)){
this[thing]=JSON[thing];
}
this.permissions=new Permissions(JSON.permissions);
this.owner=owner;
}
get guild():Guild{
return this.owner;
}
get localuser():Localuser{
return this.guild.localuser;
}
getColor():string{
if(this.color===0){return null};
return `#${this.color.toString(16)}`;
}
}

View file

@ -24,13 +24,13 @@ async function checkCache(){
if(checkedrecently){
return;
}
promise=await caches.match("/getupdates");
const promise=await caches.match("/getupdates");
if(promise){
lastcache= await promise.text();
}
console.log(lastcache);
fetch("/getupdates").then(async data=>{
text=await data.clone().text();
const text=await data.clone().text();
console.log(text,lastcache)
if(lastcache!==text){
deleteoldcache();
@ -80,8 +80,8 @@ async function getfile(event){
return responseFromNetwork;
}catch(e){console.error(e)}
}
self.addEventListener('fetch', (event) => {
self.addEventListener('fetch', (event:any) => {
try{
event.respondWith(getfile(event));
event.respondWith(getfile(event));
}catch(e){console.error(e)}
})

View file

@ -1,61 +0,0 @@
//const usercache={};
class user{
static userids={};
static checkuser(userjson){
if(user.userids[userjson.id]){
return user.userids[userjson.id];
}else{
const tempuser=new user(userjson,true)
user.userids[userjson.id]=tempuser;
return tempuser;
}
}
constructor(userjson,dontclone=false){
if(dontclone){
for(const thing of Object.keys(userjson)){
this[thing]=userjson[thing];
}
this.hypotheticalpfp=false;
}else{
return user.checkuser(userjson);
}
}
async resolvemember(guild){
await member.resolve(this,guild);
}
buildpfp(){
const pfp=document.createElement('img');
pfp.src=this.getpfpsrc(this.id,this.avatar);
pfp.classList.add("pfp");
pfp.classList.add("userid:"+this.id);
return pfp;
}
userupdate(json){
if(json.avatar!==this.avatar){
console.log
this.changepfp(json.avatar);
}
}
changepfp(update){
this.avatar=update;
this.hypotheticalpfp=false;
const src=this.getpfpsrc();
console.log(src)
for(thing of document.getElementsByClassName("userid:"+this.id)){
thing.src=src;
}
}
getpfpsrc(){
if(this.hypotheticalpfp){
return this.avatar;
}
if(this.avatar!=null){
return info.cdn.toString()+"avatars/"+this.id+"/"+this.avatar+".png";
}else{
return info.cdn.toString()+"embed/avatars/3.png";
}
}
createjankpromises(){
new Promise(_=>{})
}
}

141
webpage/user.ts Normal file
View file

@ -0,0 +1,141 @@
//const usercache={};
import {Member} from "./member.js";
import {markdown} from "./markdown.js";
import {Contextmenu} from "./contextmenu.js";
import {Localuser} from "./localuser.js";
import {Guild} from "./guild.js";
class User{
static userids={};
owner:Localuser;
hypotheticalpfp:boolean;
id:string;
avatar:string;
username:string;
bio:string;
discriminator:string;
pronouns:string;
bot:boolean;
static checkuser(userjson,owner:Localuser){
if(User.userids[userjson.id]){
return User.userids[userjson.id];
}else{
const tempuser=new User(userjson,owner,true)
User.userids[userjson.id]=tempuser;
return tempuser;
}
}
get info(){
return this.owner.info;
}
get localuser(){
return this.owner;
}
constructor(userjson,owner:Localuser,dontclone=false){
this.owner=owner;
if(!owner){console.error("missing localuser")}
if(dontclone){
for(const thing of Object.keys(userjson)){
this[thing]=userjson[thing];
}
this.hypotheticalpfp=false;
}else{
return User.checkuser(userjson,owner);
}
}
async resolvemember(guild:Guild){
await Member.resolve(this,guild);
}
buildpfp(){
const pfp=document.createElement('img');
pfp.src=this.getpfpsrc();
pfp.classList.add("pfp");
pfp.classList.add("userid:"+this.id);
return pfp;
}
userupdate(json){
if(json.avatar!==this.avatar){
console.log
this.changepfp(json.avatar);
}
}
changepfp(update:string){
this.avatar=update;
this.hypotheticalpfp=false;
const src=this.getpfpsrc();
console.log(src)
for(const thing of document.getElementsByClassName("userid:"+this.id)){
(thing as HTMLImageElement).src=src;
}
}
getpfpsrc(){
if(this.hypotheticalpfp){
return this.avatar;
}
if(this.avatar!=null){
return this.info.cdn.toString()+"avatars/"+this.id+"/"+this.avatar+".png";
}else{
return this.info.cdn.toString()+"embed/avatars/3.png";
}
}
createjankpromises(){
new Promise(_=>{})
}
buildprofile(x:number,y:number){
if(Contextmenu.currentmenu!=""){
Contextmenu.currentmenu.remove();
}
const div=document.createElement("table");
if(x!==-1){
div.style.left=x+"px";
div.style.top=y+"px";
div.classList.add("profile");
}else{
div.classList.add("hypoprofile");
}
{
const pfp=this.buildpfp();
const pfprow=document.createElement("tr");
div.appendChild(pfprow);
pfprow.appendChild(pfp);
}
{
const userbody=document.createElement("tr");
userbody.classList.add("infosection");
div.appendChild(userbody);
const usernamehtml=document.createElement("h2");
usernamehtml.textContent=this.username;
userbody.appendChild(usernamehtml);
const discrimatorhtml=document.createElement("h3");
discrimatorhtml.classList.add("tag");
discrimatorhtml.textContent=this.username+"#"+this.discriminator;
userbody.appendChild(discrimatorhtml)
const pronounshtml=document.createElement("p");
pronounshtml.textContent=this.pronouns;
pronounshtml.classList.add("pronouns");
userbody.appendChild(pronounshtml)
const rule=document.createElement("hr");
userbody.appendChild(rule);
const biohtml=markdown(this.bio);
userbody.appendChild(biohtml);
}
console.log(div);
if(x!==-1){
Contextmenu.currentmenu=div;
document.body.appendChild(div)
}
return div;
}
profileclick(obj:HTMLElement){
obj.onclick=e=>{
this.buildprofile(e.clientX,e.clientY);
e.stopPropagation();
}
}
}
export {User};