Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
8de112febb
32 changed files with 1109 additions and 285 deletions
|
@ -10,6 +10,7 @@ import { Settings, RoleList } from "./settings.js";
|
|||
import { Role } from "./role.js";
|
||||
import {InfiniteScroller} from "./infiniteScroller.js";
|
||||
import { SnowFlake } from "./snowflake.js";
|
||||
import { channeljson, messagejson, readyjson } from "./jsontypes.js";
|
||||
|
||||
declare global {
|
||||
interface NotificationOptions {
|
||||
|
@ -93,21 +94,31 @@ class Channel{
|
|||
this.infinite=new InfiniteScroller(async function(this:Channel,id:string,offset:number):Promise<string>{
|
||||
const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>;
|
||||
if(offset===1){
|
||||
if(this.idToPrev.get(snowflake)){
|
||||
if(this.idToPrev.has(snowflake)){
|
||||
return this.idToPrev.get(snowflake)?.id;
|
||||
}else{
|
||||
await this.grabBefore(id);
|
||||
return this.idToPrev.get(snowflake)?.id;
|
||||
}
|
||||
}else{
|
||||
return this.idToNext.get(snowflake)?.id;
|
||||
if(this.idToNext.has(snowflake)){
|
||||
return this.idToNext.get(snowflake)?.id;
|
||||
}else if(this.lastmessage.id!==id){
|
||||
await this.grabAfter(id);
|
||||
return this.idToNext.get(snowflake)?.id;
|
||||
}else{
|
||||
console.log("at bottom")
|
||||
}
|
||||
}
|
||||
}.bind(this),
|
||||
function(this:Channel,id:string){
|
||||
async function(this:Channel,id:string){
|
||||
let res:Function;
|
||||
const promise=new Promise(_=>{res=_;}) as Promise<void>;
|
||||
const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>;
|
||||
const html=this.messageids.get(snowflake).buildhtml(this.messageids.get(this.idToPrev.get(snowflake)),promise);
|
||||
const snowflake=SnowFlake.getSnowFlakeFromID(id,Message);
|
||||
if(!snowflake.getObject()){
|
||||
await this.grabArround(id);
|
||||
}
|
||||
const html=snowflake.getObject().buildhtml(this.messageids.get(this.idToPrev.get(snowflake)),promise);
|
||||
ids[id]=res;
|
||||
return html;
|
||||
}.bind(this),
|
||||
|
@ -119,12 +130,11 @@ class Channel{
|
|||
this.readbottom.bind(this)
|
||||
);
|
||||
}
|
||||
constructor(json,owner:Guild){
|
||||
constructor(json:channeljson|-1,owner:Guild){
|
||||
|
||||
if(json===-1){
|
||||
return;
|
||||
}
|
||||
|
||||
this.editing;
|
||||
this.type=json.type;
|
||||
this.owner=owner;
|
||||
|
@ -141,7 +151,7 @@ class Channel{
|
|||
for(const thing of json.permission_overwrites){
|
||||
if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;};
|
||||
this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny));
|
||||
this.permission_overwritesar.push([thing.id,this.permission_overwrites.get(thing.id)]);
|
||||
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id,Role),this.permission_overwrites.get(thing.id)]);
|
||||
}
|
||||
|
||||
this.topic=json.topic;
|
||||
|
@ -163,7 +173,7 @@ class Channel{
|
|||
get info(){
|
||||
return this.owner.info;
|
||||
}
|
||||
readStateInfo(json){
|
||||
readStateInfo(json:readyjson["d"]["read_state"]["entries"][0]){
|
||||
this.lastreadmessageid=SnowFlake.getSnowFlakeFromID(json.last_message_id,Message);
|
||||
this.mentions=json.mention_count;
|
||||
this.mentions??=0;
|
||||
|
@ -540,7 +550,7 @@ class Channel{
|
|||
return;
|
||||
}
|
||||
this.makereplybox();
|
||||
this.buildmessages();
|
||||
await this.buildmessages();
|
||||
history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.snowflake);
|
||||
document.getElementById("channelname").textContent="#"+this.name;
|
||||
console.log(this);
|
||||
|
@ -572,69 +582,114 @@ class Channel{
|
|||
}
|
||||
}
|
||||
}
|
||||
delChannel(json){
|
||||
delChannel(json:channeljson){
|
||||
const build=[];
|
||||
for(const thing of this.children){
|
||||
if(thing.snowflake!==json.id){
|
||||
if(thing.id!==json.id){
|
||||
build.push(thing)
|
||||
}
|
||||
}
|
||||
this.children=build;
|
||||
}
|
||||
async grabBefore(id:string){
|
||||
if(this.allthewayup){
|
||||
async grabAfter(id:string){
|
||||
console.log(id,this.lastmessage.id)
|
||||
if(id===this.lastmessage.id){
|
||||
return;
|
||||
}
|
||||
|
||||
await fetch(this.info.api.toString()+"/channels/"+this.snowflake+"/messages?before="+id+"&limit=100",{
|
||||
await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=100&after="+id,{
|
||||
headers:this.headers
|
||||
}).then((j)=>{return j.json()}).then(response=>{
|
||||
let next:Message;
|
||||
if(response.length===0){
|
||||
this.allthewayup=true;
|
||||
}
|
||||
let previd=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>;
|
||||
let previd:SnowFlake<Message>=SnowFlake.getSnowFlakeFromID(id,Message);
|
||||
for(const i in response){
|
||||
let messager:Message;
|
||||
if(!next){
|
||||
let willbreak=false
|
||||
if(!SnowFlake.hasSnowFlakeFromID(response[i].id,Message)){
|
||||
messager=new Message(response[i],this);
|
||||
}else{
|
||||
messager=next;
|
||||
messager=SnowFlake.getSnowFlakeFromID(response[i].id,Message).getObject();
|
||||
willbreak=true;
|
||||
}
|
||||
if(response[+i+1]!==undefined){
|
||||
next=new Message(response[+i+1],this);
|
||||
}else{
|
||||
next=undefined;
|
||||
console.log("ohno",+i+1);
|
||||
}
|
||||
if(this.messageids.get(messager.snowflake)===undefined){
|
||||
this.idToNext.set(messager.snowflake,previd);
|
||||
this.idToPrev.set(previd,messager.snowflake);
|
||||
previd=messager.snowflake;
|
||||
this.messageids.set(messager.snowflake,messager);
|
||||
}else{
|
||||
console.log("How???")
|
||||
this.idToPrev.set(messager.snowflake,previd);
|
||||
this.idToNext.set(previd,messager.snowflake);
|
||||
previd=messager.snowflake;
|
||||
this.messageids.set(messager.snowflake,messager);
|
||||
if(willbreak){
|
||||
break;
|
||||
}
|
||||
}
|
||||
//out.buildmessages();
|
||||
})
|
||||
return;
|
||||
}
|
||||
topid:SnowFlake<Message>;
|
||||
async grabBefore(id:string){
|
||||
if(this.topid&&id===this.topid.id){
|
||||
return;
|
||||
}
|
||||
|
||||
await fetch(this.info.api.toString()+"/channels/"+this.snowflake+"/messages?before="+id+"&limit=100",{
|
||||
headers:this.headers
|
||||
}).then((j)=>{return j.json()}).then((response:messagejson[])=>{
|
||||
if(response.length<100){
|
||||
this.allthewayup=true;
|
||||
if(response.length===0){
|
||||
this.topid=SnowFlake.getSnowFlakeFromID(id,Message);
|
||||
}
|
||||
}
|
||||
let previd=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake<Message>;
|
||||
for(const i in response){
|
||||
let messager:Message;
|
||||
let willbreak=false;
|
||||
if(!SnowFlake.hasSnowFlakeFromID(response[i].id,Message)){
|
||||
messager=new Message(response[i],this);
|
||||
}else{
|
||||
console.log("flaky")
|
||||
messager=SnowFlake.getSnowFlakeFromID(response[i].id,Message).getObject();
|
||||
willbreak=true;
|
||||
}
|
||||
|
||||
this.idToNext.set(messager.snowflake,previd);
|
||||
this.idToPrev.set(previd,messager.snowflake);
|
||||
previd=messager.snowflake;
|
||||
this.messageids.set(messager.snowflake,messager);
|
||||
|
||||
if(+i===response.length-1&&response.length<100){
|
||||
this.topid=previd;
|
||||
}
|
||||
if(willbreak){
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Please dont use this, its not implemented.
|
||||
**/
|
||||
async grabArround(id:string){//currently unused and no plans to use it yet
|
||||
throw new Error("please don't call this, no one has implmented it :P")
|
||||
}
|
||||
buildmessage(message:Message,next:Message){
|
||||
const built=message.buildhtml(next);
|
||||
document.getElementById("messages").prepend(built);
|
||||
}
|
||||
buildmessages(){
|
||||
async buildmessages(){
|
||||
const messages=document.getElementById("channelw");
|
||||
messages.innerHTML="";
|
||||
let id:SnowFlake<Message>;
|
||||
if(this.messageids.get(this.lastreadmessageid)){
|
||||
if(this.lastreadmessageid&&this.lastreadmessageid.getObject()){
|
||||
id=this.lastreadmessageid;
|
||||
}else if(this.lastmessage.snowflake){
|
||||
id=this.goBackIds(this.lastmessage.snowflake,50);
|
||||
console.log("shouldn't")
|
||||
}
|
||||
messages.append(this.infinite.getDiv(id.id));
|
||||
console.log(this.lastreadmessageid,id.id);
|
||||
messages.append(await this.infinite.getDiv(id.id));
|
||||
this.infinite.updatestuff();
|
||||
this.infinite.watchForChange().then(async _=>{
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
this.infinite.focus(id.id,false);//if someone could figure out how to make this work correctly without this, that's be great :P
|
||||
})
|
||||
}
|
||||
private goBackIds(id:SnowFlake<Message>,back:number):SnowFlake<Message>{
|
||||
while(back!==0){
|
||||
|
@ -649,7 +704,7 @@ class Channel{
|
|||
}
|
||||
return id;
|
||||
}
|
||||
updateChannel(json){
|
||||
updateChannel(json:channeljson){
|
||||
this.type=json.type;
|
||||
this.name=json.name;
|
||||
this.parent_id=new SnowFlake(json.parent_id,undefined);
|
||||
|
@ -661,7 +716,7 @@ class Channel{
|
|||
for(const thing of json.permission_overwrites){
|
||||
if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;};
|
||||
this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny));
|
||||
this.permission_overwritesar.push([thing.id,this.permission_overwrites.get(thing.id)]);
|
||||
this.permission_overwritesar.push([SnowFlake.getSnowFlakeFromID(thing.id,Role),this.permission_overwrites.get(thing.id)]);
|
||||
}
|
||||
this.topic=json.topic;
|
||||
this.nsfw=json.nsfw;
|
||||
|
@ -741,6 +796,7 @@ class Channel{
|
|||
messageCreate(messagep:any):void{
|
||||
if(!this.hasPermission("VIEW_CHANNEL")){return}
|
||||
const messagez=new Message(messagep.d,this);
|
||||
this.lastmessage=messagez;
|
||||
console.log(this.lastmessageid,messagez.snowflake,":3");
|
||||
this.idToNext.set(this.lastmessageid,messagez.snowflake);
|
||||
this.idToPrev.set(messagez.snowflake,this.lastmessageid);
|
||||
|
@ -757,7 +813,9 @@ class Channel{
|
|||
}
|
||||
}
|
||||
this.guild.unreads();
|
||||
this.infinite.addedBottom();
|
||||
if(this===this.localuser.channelfocus){
|
||||
this.infinite.addedBottom();
|
||||
}
|
||||
if(messagez.author===this.localuser.user){
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@ import { Localuser } from "./localuser.js";
|
|||
import {User} from "./user.js";
|
||||
import { Member } from "./member.js";
|
||||
import { SnowFlake } from "./snowflake.js";
|
||||
import { dirrectjson, memberjson } from "./jsontypes.js";
|
||||
|
||||
class Direct extends Guild{
|
||||
constructor(json,owner:Localuser){
|
||||
constructor(json:dirrectjson[],owner:Localuser){
|
||||
super(-1,owner,null);
|
||||
this.message_notifications=0;
|
||||
console.log(json);
|
||||
this.owner=owner;
|
||||
if(!this.localuser){
|
||||
console.error("Owner was not included, please fix")
|
||||
|
@ -44,13 +44,13 @@ class Direct extends Guild{
|
|||
return Number(-result);
|
||||
});
|
||||
}
|
||||
giveMember(member){
|
||||
giveMember(_member:memberjson){
|
||||
console.error("not a real guild, can't give member object")
|
||||
}
|
||||
getRole(ID){
|
||||
getRole(ID:string){
|
||||
return null;
|
||||
}
|
||||
hasRole(r){
|
||||
hasRole(r:string){
|
||||
return false;
|
||||
}
|
||||
isAdmin(){
|
||||
|
@ -64,7 +64,7 @@ class Direct extends Guild{
|
|||
}
|
||||
class Group extends Channel{
|
||||
user:User;
|
||||
constructor(json,owner:Direct){
|
||||
constructor(json:dirrectjson,owner:Direct){
|
||||
super(-1,owner);
|
||||
this.owner=owner;
|
||||
this.headers=this.guild.headers;
|
||||
|
@ -166,13 +166,11 @@ class Group extends Channel{
|
|||
const noti=document.createElement("div");
|
||||
noti.classList.add("unread","notiunread","pinged");
|
||||
noti.textContent=""+this.mentions;
|
||||
console.log(this.mentions)
|
||||
div["noti"]=noti;
|
||||
div.append(noti)
|
||||
const buildpfp=this.user.buildpfp();
|
||||
div["all"]=this;
|
||||
buildpfp.classList.add("mentioned");
|
||||
console.log(this);
|
||||
div.append(buildpfp)
|
||||
sentdms.append(div);
|
||||
div.onclick=_=>{
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import {Fullscreen} from "./fullscreen.js";
|
||||
import {Message} from "./message.js";
|
||||
import {MarkDown} from "./markdown.js";
|
||||
import { embedjson } from "./jsontypes.js";
|
||||
|
||||
class Embed{
|
||||
type:string;
|
||||
owner:Message;
|
||||
json;
|
||||
constructor(json, owner:Message){
|
||||
json:embedjson;
|
||||
constructor(json:embedjson, owner:Message){
|
||||
this.type=this.getType(json);
|
||||
this.owner=owner;
|
||||
this.json=json;
|
||||
}
|
||||
getType(json){
|
||||
getType(json:embedjson){
|
||||
return json.type||"rich";
|
||||
}
|
||||
generateHTML(){
|
||||
|
@ -42,7 +43,6 @@ class Embed{
|
|||
return this.guild.localuser;
|
||||
}
|
||||
generateRich(){
|
||||
console.log(this.json)
|
||||
const div=document.createElement("div");
|
||||
if(this.json.color){
|
||||
div.style.backgroundColor="#"+this.json.color.toString(16);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Message } from "./message.js";
|
||||
import { Fullscreen } from "./fullscreen.js";
|
||||
type filejson= {id:string,filename:string,content_type:string,width:number,height:number,proxy_url:string|undefined,url:string,size:number};
|
||||
import { filejson } from "./jsontypes.js";
|
||||
|
||||
class File{
|
||||
owner:Message;
|
||||
id:string;
|
||||
|
@ -12,7 +13,6 @@ class File{
|
|||
url:string;
|
||||
size:number;
|
||||
constructor(fileJSON:filejson,owner:Message){
|
||||
console.log(fileJSON);
|
||||
this.owner=owner;
|
||||
this.id=fileJSON.id;
|
||||
this.filename=fileJSON.filename;
|
||||
|
|
|
@ -7,6 +7,7 @@ import {Member} from "./member.js";
|
|||
import {Settings,RoleList} from "./settings.js";
|
||||
import {Permissions} from "./permissions.js";
|
||||
import { SnowFlake } from "./snowflake.js";
|
||||
import { channeljson, guildjson } from "./jsontypes.js";
|
||||
class Guild{
|
||||
owner:Localuser;
|
||||
headers:Localuser["headers"];
|
||||
|
@ -79,7 +80,7 @@ class Guild{
|
|||
s1.options.push(new RoleList(permlist,this,this.updateRolePermissions.bind(this)));
|
||||
settings.show();
|
||||
}
|
||||
constructor(json,owner:Localuser,member){
|
||||
constructor(json:guildjson|-1,owner:Localuser,member){
|
||||
if(json===-1){
|
||||
return;
|
||||
}
|
||||
|
@ -404,7 +405,7 @@ class Guild{
|
|||
loadGuild(){
|
||||
this.localuser.loadGuild(this.id);
|
||||
}
|
||||
updateChannel(json){
|
||||
updateChannel(json:channeljson){
|
||||
SnowFlake.getSnowFlakeFromID(json.id,Channel).getObject().updateChannel(json);
|
||||
this.headchannels=[];
|
||||
for(const thing of this.channels){
|
||||
|
@ -417,7 +418,7 @@ class Guild{
|
|||
}
|
||||
this.printServers();
|
||||
}
|
||||
createChannelpac(json){
|
||||
createChannelpac(json:channeljson){
|
||||
const thischannel=new Channel(json,this);
|
||||
this.channelids[json.id]=thischannel;
|
||||
this.channels.push(thischannel);
|
||||
|
@ -470,7 +471,7 @@ class Guild{
|
|||
]);
|
||||
channelselect.show();
|
||||
}
|
||||
delChannel(json){
|
||||
delChannel(json:channeljson){
|
||||
const channel=this.channelids[json.id];
|
||||
delete this.channelids[json.id];
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class InfiniteScroller{
|
||||
readonly getIDFromOffset:(ID:string,offset:number)=>Promise<string>;
|
||||
readonly getHTMLFromID:(ID:string)=>HTMLElement;
|
||||
readonly getHTMLFromID:(ID:string)=>Promise<HTMLElement>;
|
||||
readonly destroyFromID:(ID:string)=>Promise<boolean>;
|
||||
readonly reachesBottom:()=>void;
|
||||
private readonly minDist=3000;
|
||||
|
@ -15,7 +15,7 @@ class InfiniteScroller{
|
|||
this.reachesBottom=reachesBottom;
|
||||
}
|
||||
interval:NodeJS.Timeout;
|
||||
getDiv(initialId:string,bottom=true):HTMLDivElement{
|
||||
async getDiv(initialId:string,bottom=true):Promise<HTMLDivElement>{
|
||||
const div=document.createElement("div");
|
||||
div.classList.add("messagecontainer");
|
||||
//div.classList.add("flexttb")
|
||||
|
@ -30,10 +30,10 @@ class InfiniteScroller{
|
|||
new ResizeObserver(this.watchForChange.bind(this)).observe(div);
|
||||
new ResizeObserver(this.watchForChange.bind(this)).observe(scroll);
|
||||
|
||||
this.firstElement(initialId);
|
||||
await this.firstElement(initialId)
|
||||
this.updatestuff();
|
||||
this.watchForChange().then(_=>{
|
||||
this.scroll.scrollTop=this.scroll.scrollHeight;
|
||||
await this.watchForChange().then(_=>{
|
||||
this.updatestuff();
|
||||
})
|
||||
return div;
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ class InfiniteScroller{
|
|||
}
|
||||
//this.watchForChange();
|
||||
}
|
||||
firstElement(id:string){
|
||||
const html=this.getHTMLFromID(id);
|
||||
async firstElement(id:string){
|
||||
const html=await this.getHTMLFromID(id);
|
||||
this.scroll.append(html);
|
||||
this.HTMLElements.push([html,id]);
|
||||
}
|
||||
|
@ -61,33 +61,20 @@ class InfiniteScroller{
|
|||
this.scroll.scrollTop=this.scroll.scrollHeight;
|
||||
}
|
||||
}
|
||||
async watchForChange():Promise<void>{
|
||||
if(this.currrunning){
|
||||
return;
|
||||
}else{
|
||||
this.currrunning=true;
|
||||
}
|
||||
private async watchForTop():Promise<void>{
|
||||
let again=false;
|
||||
if(!this.div){this.currrunning=false;return}
|
||||
/*
|
||||
if(this.scrollTop===0){
|
||||
this.scrollTop=10;
|
||||
}
|
||||
*/
|
||||
if(this.scrollTop===0){
|
||||
this.scrollTop=1;
|
||||
this.scroll.scrollTop=1;
|
||||
}
|
||||
if(this.scrollTop<this.minDist){
|
||||
|
||||
|
||||
const previd=this.HTMLElements.at(0)[1];
|
||||
const nextid=await this.getIDFromOffset(previd,1);
|
||||
if(!nextid){
|
||||
|
||||
}else{
|
||||
again=true;
|
||||
const html=this.getHTMLFromID(nextid);
|
||||
const html=await this.getHTMLFromID(nextid);
|
||||
this.scroll.prepend(html);
|
||||
this.HTMLElements.unshift([html,nextid]);
|
||||
this.scrollTop+=60;
|
||||
|
@ -100,6 +87,12 @@ class InfiniteScroller{
|
|||
await this.destroyFromID(html[1]);
|
||||
this.scrollTop-=60;
|
||||
}
|
||||
if(again){
|
||||
await this.watchForTop();
|
||||
}
|
||||
}
|
||||
async watchForBottom():Promise<void>{
|
||||
let again=false;
|
||||
const scrollBottom = this.scrollBottom;
|
||||
if(scrollBottom<this.minDist){
|
||||
|
||||
|
@ -109,7 +102,7 @@ class InfiniteScroller{
|
|||
if(!nextid){
|
||||
}else{
|
||||
again=true;
|
||||
const html=this.getHTMLFromID(nextid);
|
||||
const html=await this.getHTMLFromID(nextid);
|
||||
this.scroll.append(html);
|
||||
this.HTMLElements.push([html,nextid]);
|
||||
this.scrollBottom+=60;
|
||||
|
@ -125,13 +118,47 @@ class InfiniteScroller{
|
|||
await this.destroyFromID(html[1]);
|
||||
this.scrollBottom-=60;
|
||||
}
|
||||
|
||||
this.currrunning=false;
|
||||
if(again){
|
||||
await this.watchForChange();
|
||||
await this.watchForBottom();
|
||||
}
|
||||
}
|
||||
async watchForChange():Promise<void>{
|
||||
if(this.currrunning){
|
||||
return;
|
||||
}else{
|
||||
this.currrunning=true;
|
||||
}
|
||||
if(!this.div){this.currrunning=false;return}
|
||||
await Promise.allSettled([this.watchForBottom(),this.watchForTop()])
|
||||
this.currrunning=false;
|
||||
}
|
||||
async focus(id:string,flash=true){
|
||||
let element:HTMLElement;
|
||||
for(const thing of this.HTMLElements){
|
||||
if(thing[1]===id){
|
||||
element=thing[0];
|
||||
}
|
||||
}
|
||||
console.log(element,id,":3");
|
||||
if(element){
|
||||
element.scrollIntoView();
|
||||
if(flash){
|
||||
element.classList.remove("jumped");
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
element.classList.add("jumped");
|
||||
}
|
||||
}else{
|
||||
for(const thing of this.HTMLElements){
|
||||
await this.destroyFromID(thing[1]);
|
||||
}
|
||||
this.HTMLElements=[];
|
||||
await this.firstElement(id);
|
||||
this.updatestuff();
|
||||
await this.watchForChange();
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
await this.focus(id,true);
|
||||
}
|
||||
}
|
||||
async delete():Promise<void>{
|
||||
for(const thing of this.HTMLElements){
|
||||
await this.destroyFromID(thing[1]);
|
||||
|
|
320
webpage/jsontypes.ts
Normal file
320
webpage/jsontypes.ts
Normal file
|
@ -0,0 +1,320 @@
|
|||
type readyjson={
|
||||
op:number;
|
||||
t:string;
|
||||
s:number;
|
||||
d:{
|
||||
v:number;
|
||||
user:mainuserjson;
|
||||
user_settings:{
|
||||
index: number,
|
||||
afk_timeout: number,
|
||||
allow_accessibility_detection: boolean,
|
||||
animate_emoji: boolean,
|
||||
animate_stickers: number,
|
||||
contact_sync_enabled: boolean,
|
||||
convert_emoticons: boolean,
|
||||
custom_status: string,
|
||||
default_guilds_restricted: boolean,
|
||||
detect_platform_accounts: boolean,
|
||||
developer_mode: boolean,
|
||||
disable_games_tab: boolean,
|
||||
enable_tts_command: boolean,
|
||||
explicit_content_filter: 0,
|
||||
friend_discovery_flags: 0,
|
||||
friend_source_flags: {
|
||||
all: boolean
|
||||
},//might be missing things here
|
||||
gateway_connected: boolean,
|
||||
gif_auto_play: boolean,
|
||||
guild_folders: [],//need an example of this not empty
|
||||
guild_positions: [],//need an example of this not empty
|
||||
inline_attachment_media: boolean,
|
||||
inline_embed_media: boolean,
|
||||
locale: string,
|
||||
message_display_compact: boolean,
|
||||
native_phone_integration_enabled: boolean,
|
||||
render_embeds: boolean,
|
||||
render_reactions: boolean,
|
||||
restricted_guilds: [],//need an example of this not empty
|
||||
show_current_game: boolean,
|
||||
status: string,
|
||||
stream_notifications_enabled: boolean,
|
||||
theme: string,
|
||||
timezone_offset: number,
|
||||
view_nsfw_guilds: boolean
|
||||
};
|
||||
guilds:guildjson[];
|
||||
relationships:any[];
|
||||
read_state:{
|
||||
entries:{
|
||||
id: string,
|
||||
channel_id: string,
|
||||
last_message_id: string,
|
||||
last_pin_timestamp: string,
|
||||
mention_count: number //in theory, the server doesn't actually send this as far as I'm aware
|
||||
}[],
|
||||
partial: boolean,
|
||||
version: number
|
||||
};
|
||||
user_guild_settings:{
|
||||
entries:{
|
||||
channel_overrides: unknown[],//will have to find example
|
||||
message_notifications: number,
|
||||
flags: number,
|
||||
hide_muted_channels: boolean,
|
||||
mobile_push: boolean,
|
||||
mute_config: null,
|
||||
mute_scheduled_events: boolean,
|
||||
muted: boolean,
|
||||
notify_highlights: number,
|
||||
suppress_everyone: boolean,
|
||||
suppress_roles: boolean,
|
||||
version: number,
|
||||
guild_id: string
|
||||
}[],
|
||||
partial: boolean,
|
||||
version: number
|
||||
};
|
||||
private_channels:dirrectjson[];
|
||||
session_id:string;
|
||||
country_code:string;
|
||||
users:userjson[];
|
||||
merged_members:memberjson[];
|
||||
sessions:{
|
||||
active: boolean,
|
||||
activities: [],//will need to find example of this
|
||||
client_info: {
|
||||
version: number
|
||||
},
|
||||
session_id: string,
|
||||
status: string
|
||||
}[];
|
||||
resume_gateway_url:string;
|
||||
consents:{
|
||||
personalization: {
|
||||
consented: boolean
|
||||
}
|
||||
};
|
||||
experiments: [],//not sure if I need to do this :P
|
||||
guild_join_requests: [],//need to get examples
|
||||
connected_accounts: [],//need to get examples
|
||||
guild_experiments: [],//need to get examples
|
||||
geo_ordered_rtc_regions: [],//need to get examples
|
||||
api_code_version: number,
|
||||
friend_suggestion_count: number,
|
||||
analytics_token: string,
|
||||
tutorial: boolean,
|
||||
session_type: string,
|
||||
auth_session_id_hash: string,
|
||||
notification_settings: {
|
||||
flags: number
|
||||
}
|
||||
}
|
||||
}
|
||||
type mainuserjson= userjson & {
|
||||
flags: number,
|
||||
mfa_enabled?: boolean,
|
||||
email?: string,
|
||||
phone?: string,
|
||||
verified: boolean,
|
||||
nsfw_allowed: boolean,
|
||||
premium: boolean,
|
||||
purchased_flags: number,
|
||||
premium_usage_flags: number,
|
||||
disabled: boolean
|
||||
}
|
||||
type userjson={
|
||||
username: string,
|
||||
discriminator: string,
|
||||
id: string,
|
||||
public_flags: number,
|
||||
avatar: string,
|
||||
accent_color: string,
|
||||
banner: string,
|
||||
bio: string,
|
||||
bot: boolean,
|
||||
premium_since: string,
|
||||
premium_type: number,
|
||||
theme_colors: string,
|
||||
pronouns: string,
|
||||
badge_ids: string,
|
||||
}
|
||||
type memberjson= {
|
||||
index?:number,
|
||||
id: string,
|
||||
user: userjson,
|
||||
guild_id: string,
|
||||
guild: {
|
||||
id: string
|
||||
},
|
||||
nick: string,
|
||||
roles: string[],
|
||||
joined_at: string,
|
||||
premium_since: string,
|
||||
deaf: boolean,
|
||||
mute: boolean,
|
||||
pending: boolean,
|
||||
last_message_id: boolean
|
||||
}
|
||||
type guildjson={
|
||||
application_command_counts: {[key:string]:number},
|
||||
channels: channeljson[],
|
||||
data_mode: string,
|
||||
emojis: [],
|
||||
guild_scheduled_events: [],
|
||||
id: string,
|
||||
large: boolean,
|
||||
lazy: boolean,
|
||||
member_count: number,
|
||||
premium_subscription_count: number,
|
||||
properties: {
|
||||
name: string,
|
||||
description: string,
|
||||
icon: string,
|
||||
splash: string,
|
||||
banner: string,
|
||||
features: string[],
|
||||
preferred_locale: string,
|
||||
owner_id: string,
|
||||
application_id: string,
|
||||
afk_channel_id: string,
|
||||
afk_timeout: number,
|
||||
system_channel_id: string,
|
||||
verification_level: number,
|
||||
explicit_content_filter: number,
|
||||
default_message_notifications: number,
|
||||
mfa_level: number,
|
||||
vanity_url_code: number,
|
||||
premium_tier: number,
|
||||
premium_progress_bar_enabled: boolean,
|
||||
system_channel_flags: number,
|
||||
discovery_splash: string,
|
||||
rules_channel_id: string,
|
||||
public_updates_channel_id: string,
|
||||
max_video_channel_users: number,
|
||||
max_members: number,
|
||||
nsfw_level: number,
|
||||
hub_type: null,
|
||||
home_header: null,
|
||||
id: string,
|
||||
latest_onboarding_question_id: string,
|
||||
max_stage_video_channel_users: number,
|
||||
nsfw: boolean,
|
||||
safety_alerts_channel_id: string
|
||||
},
|
||||
roles: rolesjson[],
|
||||
stage_instances: [],
|
||||
stickers: [],
|
||||
threads: [],
|
||||
version: string,
|
||||
guild_hashes: {},
|
||||
joined_at: string
|
||||
}
|
||||
type channeljson={
|
||||
id: string,
|
||||
created_at: string,
|
||||
name: string,
|
||||
icon: string,
|
||||
type: number,
|
||||
last_message_id: string,
|
||||
guild_id: string,
|
||||
parent_id: string,
|
||||
last_pin_timestamp: string,
|
||||
default_auto_archive_duration: number,
|
||||
permission_overwrites: {
|
||||
id:string,
|
||||
allow:string,
|
||||
deny:string,
|
||||
}[],
|
||||
video_quality_mode: null,
|
||||
nsfw: boolean,
|
||||
topic: string,
|
||||
retention_policy_id: string,
|
||||
flags: number,
|
||||
default_thread_rate_limit_per_user: number,
|
||||
position: number
|
||||
}
|
||||
type rolesjson={
|
||||
id: string,
|
||||
guild_id: string,
|
||||
color: number,
|
||||
hoist: boolean,
|
||||
managed: boolean,
|
||||
mentionable: boolean,
|
||||
name: string,
|
||||
permissions: string,
|
||||
position: number,
|
||||
icon: string,
|
||||
unicode_emoji: string,
|
||||
flags: number
|
||||
}
|
||||
type dirrectjson={
|
||||
id: string,
|
||||
flags: number,
|
||||
last_message_id: string,
|
||||
type: number,
|
||||
recipients: userjson[],
|
||||
is_spam: boolean
|
||||
}
|
||||
type messagejson={
|
||||
id: string,
|
||||
channel_id: string,
|
||||
guild_id: string,
|
||||
author: userjson,
|
||||
member?: memberjson,
|
||||
content: string,
|
||||
timestamp: string,
|
||||
edited_timestamp: string,
|
||||
tts: boolean,
|
||||
mention_everyone: boolean,
|
||||
mentions: [], //need examples to fix
|
||||
mention_roles: [], //need examples to fix
|
||||
attachments: filejson[],
|
||||
embeds: embedjson[],
|
||||
reactions: [], //ToDo
|
||||
nonce: string,
|
||||
pinned: boolean,
|
||||
type: number
|
||||
}
|
||||
type filejson={
|
||||
id:string,
|
||||
filename:string,
|
||||
content_type:string,
|
||||
width:number,
|
||||
height:number,
|
||||
proxy_url:string|undefined,
|
||||
url:string,
|
||||
size:number
|
||||
};
|
||||
type embedjson={
|
||||
type:string|null,
|
||||
color?:number,
|
||||
author:{
|
||||
icon_url?:string,
|
||||
name?:string,
|
||||
url?:string,
|
||||
title?:string,
|
||||
},
|
||||
title?:string,
|
||||
url?:string,
|
||||
description?:string,
|
||||
fields?:{
|
||||
name:string,
|
||||
value:string,
|
||||
inline:boolean,
|
||||
}[],
|
||||
footer?:{
|
||||
icon_url?:string,
|
||||
text?:string,
|
||||
thumbnail?:string,
|
||||
},
|
||||
timestamp?:string,
|
||||
thumbnail:{
|
||||
proxy_url:string,
|
||||
url:string,
|
||||
},
|
||||
provider:{
|
||||
name:string,
|
||||
}
|
||||
}
|
||||
export {readyjson,dirrectjson,channeljson,guildjson,rolesjson,userjson,memberjson,mainuserjson,messagejson,filejson,embedjson};
|
|
@ -7,6 +7,7 @@ import {Fullscreen} from "./fullscreen.js";
|
|||
import {setTheme, Specialuser} from "./login.js";
|
||||
import { SnowFlake } from "./snowflake.js";
|
||||
import { Message } from "./message.js";
|
||||
import { channeljson, readyjson, userjson } from "./jsontypes.js";
|
||||
|
||||
const wsCodesRetry=new Set([4000,4003,4005,4007,4008,4009]);
|
||||
|
||||
|
@ -21,7 +22,7 @@ class Localuser{
|
|||
usersettings:Fullscreen;
|
||||
userConnections:Fullscreen;
|
||||
devPortal:Fullscreen;
|
||||
ready;
|
||||
ready:readyjson;
|
||||
guilds:Guild[];
|
||||
guildids:Map<string,Guild>;
|
||||
user:User;
|
||||
|
@ -42,7 +43,7 @@ class Localuser{
|
|||
this.info=this.serverurls;
|
||||
this.headers={"Content-type": "application/json; charset=UTF-8",Authorization:this.userinfo.token};
|
||||
}
|
||||
gottenReady(ready):void{
|
||||
gottenReady(ready:readyjson):void{
|
||||
this.usersettings=null;
|
||||
this.initialized=true;
|
||||
this.ready=ready;
|
||||
|
@ -90,8 +91,8 @@ class Localuser{
|
|||
this.typing=[];
|
||||
}
|
||||
outoffocus():void{
|
||||
document.getElementById("servers").textContent="";
|
||||
document.getElementById("channels").textContent="";
|
||||
document.getElementById("servers").innerHTML="";
|
||||
document.getElementById("channels").innerHTML="";
|
||||
if(this.channelfocus){
|
||||
this.channelfocus.infinite.delete();
|
||||
}
|
||||
|
@ -104,7 +105,7 @@ class Localuser{
|
|||
this.outoffocus();
|
||||
this.guilds=[];
|
||||
this.guildids=new Map();
|
||||
this.ws.close(4000)
|
||||
this.ws.close(4001)
|
||||
}
|
||||
async initwebsocket():Promise<void>{
|
||||
let returny=null
|
||||
|
@ -119,7 +120,7 @@ class Localuser{
|
|||
"capabilities": 16381,
|
||||
"properties": {
|
||||
"browser": "Jank Client",
|
||||
"client_build_number": 0,
|
||||
"client_build_number": 0,//might update this eventually lol
|
||||
"release_channel": "Custom",
|
||||
"browser_user_agent": navigator.userAgent
|
||||
},
|
||||
|
@ -154,7 +155,7 @@ class Localuser{
|
|||
SnowFlake.getSnowFlakeFromID(temp.d.id,Message).getObject().deleteEvent();
|
||||
break;
|
||||
case "READY":
|
||||
this.gottenReady(temp);
|
||||
this.gottenReady(temp as readyjson);
|
||||
this.genusersettings();
|
||||
returny();
|
||||
break;
|
||||
|
@ -226,7 +227,6 @@ class Localuser{
|
|||
this.unload();
|
||||
document.getElementById("loading").classList.remove("doneloading");
|
||||
document.getElementById("loading").classList.add("loading");
|
||||
|
||||
if (((event.code>1000 && event.code<1016) || wsCodesRetry.has(event.code))) {
|
||||
if (this.connectionSucceed!==0 && Date.now()>this.connectionSucceed+20000) this.errorBackoff=0;
|
||||
else this.errorBackoff++;
|
||||
|
@ -258,24 +258,24 @@ class Localuser{
|
|||
}
|
||||
return undefined;
|
||||
}
|
||||
updateChannel(json):void{
|
||||
updateChannel(json:channeljson):void{
|
||||
SnowFlake.getSnowFlakeFromID(json.guild_id,Guild).getObject().updateChannel(json);
|
||||
if(json.guild_id===this.lookingguild.id){
|
||||
this.loadGuild(json.guild_id);
|
||||
}
|
||||
}
|
||||
createChannel(json):void{
|
||||
createChannel(json:channeljson):void{
|
||||
json.guild_id??="@me";
|
||||
SnowFlake.getSnowFlakeFromID(json.guild_id,Guild).getObject().createChannelpac(json);
|
||||
if(json.guild_id===this.lookingguild.id){
|
||||
this.loadGuild(json.guild_id);
|
||||
}
|
||||
}
|
||||
delChannel(json):void{
|
||||
delChannel(json:channeljson):void{
|
||||
json.guild_id??="@me";
|
||||
this.guildids.get(json.guild_id).delChannel(json);
|
||||
|
||||
if(json.guild_id===this.lookingguild.snowflake){
|
||||
if(json.guild_id===this.lookingguild.id){
|
||||
this.loadGuild(json.guild_id);
|
||||
}
|
||||
}
|
||||
|
@ -302,7 +302,6 @@ class Localuser{
|
|||
if(!guild){
|
||||
guild=this.guildids.get("@me");
|
||||
}
|
||||
console.log(this.guildids,id,guild);
|
||||
if(this.lookingguild){
|
||||
this.lookingguild.html.classList.remove("serveropen");
|
||||
}
|
||||
|
@ -363,7 +362,6 @@ class Localuser{
|
|||
div.classList.add("home","servericon")
|
||||
serverlist.appendChild(div)
|
||||
div.onclick=_=>{
|
||||
console.log("clicked :3")
|
||||
this.createGuild();
|
||||
}
|
||||
|
||||
|
@ -376,7 +374,6 @@ class Localuser{
|
|||
});
|
||||
|
||||
}
|
||||
console.log("test");
|
||||
this.unreads();
|
||||
}
|
||||
createGuild(){
|
||||
|
@ -390,7 +387,6 @@ class Localuser{
|
|||
"Invite Link/Code",
|
||||
"",
|
||||
function(){
|
||||
console.log(this)
|
||||
inviteurl=this.value;
|
||||
}
|
||||
],
|
||||
|
@ -410,7 +406,6 @@ class Localuser{
|
|||
method:"POST",
|
||||
headers:this.headers,
|
||||
}).then(r=>r.json()).then(_=>{
|
||||
console.log(_);
|
||||
if(_.message){
|
||||
error.textContent=_.message;
|
||||
}
|
||||
|
@ -492,11 +487,9 @@ class Localuser{
|
|||
this.unreads();
|
||||
}
|
||||
unreads():void{
|
||||
console.log(this.guildhtml)
|
||||
for(const thing of this.guilds){
|
||||
if(thing.id==="@me"){continue;}
|
||||
const html=this.guildhtml.get(thing.id);
|
||||
console.log(html);
|
||||
thing.unreads(html);
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +525,6 @@ class Localuser{
|
|||
updatepfp(file:Blob):void{
|
||||
var reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
console.log(this.headers);
|
||||
reader.onload = ()=>{
|
||||
fetch(this.info.api.toString()+"/users/@me",{
|
||||
method:"PATCH",
|
||||
|
@ -541,7 +533,6 @@ class Localuser{
|
|||
avatar:reader.result,
|
||||
})
|
||||
});
|
||||
console.log(reader.result);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -585,7 +576,6 @@ class Localuser{
|
|||
}else{
|
||||
build+=" is typing";
|
||||
}
|
||||
console.log(typingtext.classList);
|
||||
if(showing){
|
||||
typingtext.classList.remove("hidden");
|
||||
document.getElementById("typingtext").textContent=build;
|
||||
|
@ -598,7 +588,7 @@ class Localuser{
|
|||
let file=null;
|
||||
let newprouns=null;
|
||||
let newbio=null;
|
||||
let hypouser=new User(this.user,this,true);
|
||||
let hypouser=this.user.clone();
|
||||
function regen(){
|
||||
hypotheticalProfile.textContent="";
|
||||
const hypoprofile=hypouser.buildprofile(-1,-1);
|
||||
|
@ -652,9 +642,9 @@ class Localuser{
|
|||
["vdiv",
|
||||
["html",hypotheticalProfile]
|
||||
]
|
||||
],_=>{},function(){
|
||||
],_=>{},function(this:Localuser){
|
||||
console.log(this);
|
||||
hypouser=new User(this.user,this);
|
||||
hypouser=this.user.clone();
|
||||
regen();
|
||||
file=null;
|
||||
newprouns=null;
|
||||
|
|
|
@ -173,15 +173,21 @@ async function login(username:string, password:string, captcha:string){
|
|||
console.log(response);
|
||||
|
||||
if(response.captcha_sitekey){
|
||||
const capt=document.getElementById("h-captcha");
|
||||
const capty=document.createElement("div");
|
||||
capty.classList.add("h-captcha");
|
||||
|
||||
capty.setAttribute("data-sitekey", response.captcha_sitekey);
|
||||
const script=document.createElement("script");
|
||||
script.src="https://js.hcaptcha.com/1/api.js";
|
||||
capt.append(script);
|
||||
capt.append(capty);
|
||||
const capt=document.getElementById("h-captcha");
|
||||
if(!capt.children.length){
|
||||
const capty=document.createElement("div");
|
||||
capty.classList.add("h-captcha");
|
||||
|
||||
capty.setAttribute("data-sitekey", response.captcha_sitekey);
|
||||
const script=document.createElement("script");
|
||||
script.src="https://js.hcaptcha.com/1/api.js";
|
||||
capt.append(script);
|
||||
capt.append(capty);
|
||||
}else{
|
||||
eval("hcaptcha.reset()");
|
||||
}
|
||||
return;
|
||||
}else{
|
||||
adduser({serverurls:JSON.parse(localStorage.getItem("instanceinfo")),email:username,token:response.token});
|
||||
window.location.href = '/channels/@me';
|
||||
|
|
|
@ -3,6 +3,7 @@ import {Role} from "./role.js";
|
|||
import {Guild} from "./guild.js";
|
||||
import { Contextmenu } from "./contextmenu.js";
|
||||
import { SnowFlake } from "./snowflake.js";
|
||||
import { memberjson, userjson } from "./jsontypes.js";
|
||||
|
||||
class Member{
|
||||
static already={};
|
||||
|
@ -10,6 +11,7 @@ class Member{
|
|||
user:User;
|
||||
roles:Role[];
|
||||
error:boolean;
|
||||
id:string;
|
||||
static contextmenu:Contextmenu=new Contextmenu("User Menu");
|
||||
static setUpContextMenu(){
|
||||
this.contextmenu.addbutton("Copy user id",function(){
|
||||
|
@ -23,17 +25,18 @@ class Member{
|
|||
});
|
||||
});
|
||||
}
|
||||
constructor(memberjson,owner:Guild,error=false){
|
||||
constructor(memberjson:memberjson|User|{guild_member:memberjson,user:userjson},owner:Guild,error=false){
|
||||
this.error=error;
|
||||
this.owner=owner;
|
||||
let membery=memberjson;
|
||||
this.roles=[];
|
||||
if(!error){
|
||||
if(memberjson.guild_member){
|
||||
if(memberjson["guild_member"]){
|
||||
memberjson=memberjson as {guild_member:memberjson,user:userjson};
|
||||
membery=memberjson.guild_member;
|
||||
this.user=memberjson.user;
|
||||
}
|
||||
}
|
||||
membery=membery as User|memberjson;
|
||||
for(const thing of Object.keys(membery)){
|
||||
if(thing==="guild"){continue}
|
||||
if(thing==="owner"){continue}
|
||||
|
@ -49,7 +52,11 @@ class Member{
|
|||
if(error){
|
||||
this.user=memberjson as User;
|
||||
}else{
|
||||
this.user=new User(this.user,owner.localuser);
|
||||
if(SnowFlake.getSnowFlakeFromID(this?.id,User)){
|
||||
this.user=SnowFlake.getSnowFlakeFromID(this.id,User).getObject();
|
||||
return;
|
||||
}
|
||||
this.user=new User((membery as memberjson).user,owner.localuser);
|
||||
}
|
||||
}
|
||||
get guild(){
|
||||
|
@ -61,7 +68,7 @@ class Member{
|
|||
get info(){
|
||||
return this.owner.info;
|
||||
}
|
||||
static async resolve(unkown:User|object|string,guild:Guild):Promise<Member>{
|
||||
static async resolve(unkown:User|memberjson|string,guild:Guild):Promise<Member>{
|
||||
if(!(guild instanceof Guild)){
|
||||
console.error(guild)
|
||||
}
|
||||
|
@ -73,7 +80,7 @@ class Member{
|
|||
}else if(typeof unkown===typeof ""){
|
||||
id=new SnowFlake(unkown as string,undefined);
|
||||
}else{
|
||||
return new Member(unkown,guild);
|
||||
return new Member(unkown as User|memberjson,guild);
|
||||
}
|
||||
if(guild.id==="@me"){return null}
|
||||
if(!Member.already[guild.id]){
|
||||
|
|
|
@ -8,6 +8,7 @@ import {Localuser} from "./localuser.js";
|
|||
import { Role } from "./role.js";
|
||||
import {File} from "./file.js";
|
||||
import { SnowFlake } from "./snowflake.js";
|
||||
import { messagejson } from "./jsontypes.js";
|
||||
|
||||
class Message{
|
||||
static contextmenu=new Contextmenu("message menu");
|
||||
|
@ -26,6 +27,7 @@ class Message{
|
|||
static del:Promise<void>;
|
||||
static resolve:Function;
|
||||
div:HTMLDivElement;
|
||||
member:Member;
|
||||
get id(){
|
||||
return this.snowflake.id;
|
||||
}
|
||||
|
@ -47,7 +49,7 @@ class Message{
|
|||
this.channel.setReplying(this);
|
||||
});
|
||||
Message.contextmenu.addbutton("Copy message id",function(){
|
||||
navigator.clipboard.writeText(this.id.id);
|
||||
navigator.clipboard.writeText(this.id);
|
||||
});
|
||||
Message.contextmenu.addbutton("Edit",function(){
|
||||
this.channel.editing=this;
|
||||
|
@ -59,13 +61,13 @@ class Message{
|
|||
this.delete();
|
||||
},null,_=>{return _.canDelete()})
|
||||
}
|
||||
constructor(messagejson,owner:Channel){
|
||||
constructor(messagejson:messagejson,owner:Channel){
|
||||
this.owner=owner;
|
||||
this.headers=this.owner.headers;
|
||||
this.giveData(messagejson);
|
||||
|
||||
}
|
||||
giveData(messagejson){
|
||||
giveData(messagejson:messagejson){
|
||||
for(const thing of Object.keys(messagejson)){
|
||||
if(thing==="attachments"){
|
||||
this.attachments=[];
|
||||
|
@ -79,16 +81,29 @@ class Message{
|
|||
}else if(thing ==="id"){
|
||||
this.snowflake=new SnowFlake(messagejson.id,this);
|
||||
continue;
|
||||
}else if(thing==="member"){
|
||||
this.member=new Member(messagejson.member,this.guild);
|
||||
continue;
|
||||
}else if(thing ==="embeds"){
|
||||
this.embeds=[];
|
||||
for(const thing in messagejson.embeds){
|
||||
console.log(thing,messagejson.embeds)
|
||||
this.embeds[thing]=new Embed(messagejson.embeds[thing],this);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
this[thing]=messagejson[thing];
|
||||
}
|
||||
for(const thing in this.embeds){
|
||||
console.log(thing,this.embeds)
|
||||
this.embeds[thing]=new Embed(this.embeds[thing],this);
|
||||
|
||||
|
||||
this.author=new User(messagejson.author,this.localuser);
|
||||
for(const thing in messagejson.mentions){
|
||||
this.mentions[thing]=new User(messagejson.mentions[thing],this.localuser);
|
||||
}
|
||||
this.author=new User(this.author,this.localuser);
|
||||
for(const thing in this.mentions){
|
||||
this.mentions[thing]=new User(this.mentions[thing],this.localuser);
|
||||
if(!this.member&&this.guild.id!=="@me"){
|
||||
this.author.resolvemember(this.guild).then(_=>{
|
||||
this.member=_;
|
||||
})
|
||||
}
|
||||
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)
|
||||
|
@ -231,6 +246,10 @@ class Message{
|
|||
username.textContent=author.username;
|
||||
author.bind(username);
|
||||
});
|
||||
reply.onclick=_=>{
|
||||
console.log("this got clicked :3")
|
||||
this.channel.infinite.focus(this.message_reference.message_id);
|
||||
}
|
||||
div.appendChild(replyline);
|
||||
}
|
||||
build.classList.add("message");
|
||||
|
@ -304,6 +323,7 @@ class Message{
|
|||
messagedwrap.appendChild(attach)
|
||||
}
|
||||
if(this.embeds.length){
|
||||
console.log(this.embeds);
|
||||
const embeds = document.createElement("div")
|
||||
embeds.classList.add("flexltr");
|
||||
for(const thing of this.embeds){
|
||||
|
|
|
@ -8,30 +8,45 @@
|
|||
<div id="logindiv">
|
||||
<h1>Create an account</h1><br>
|
||||
<form id="register" submit="registertry(e)">
|
||||
<label for="instance"><b>Instance:</b></label><br>
|
||||
<p id="verify"></p>
|
||||
<input type="text" placeholder="Instance URL" name="instance" value="https://spacebar.chat/" id="instancein" required><br><br>
|
||||
<div>
|
||||
<label for="instance"><b>Instance:</b></label><br>
|
||||
<p id="verify"></p>
|
||||
<input type="text" placeholder="Instance URL" name="instance" value="https://spacebar.chat/" id="instancein" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="uname"><b>Email:</b></label><br>
|
||||
<input type="text" placeholder="Enter Email" name="email" required>
|
||||
</div>
|
||||
|
||||
<label for="uname"><b>Email:</b></label><br>
|
||||
<input type="text" placeholder="Enter Email" name="email" required><br><br>
|
||||
<div>
|
||||
<label for="uname"><b>Username:</b></label><br>
|
||||
<input type="text" placeholder="Enter Username" name="uname" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="psw"><b>Password:</b></label><br>
|
||||
<input type="password" placeholder="Enter Password" name="psw" required>
|
||||
</div>
|
||||
|
||||
<label for="uname"><b>Username:</b></label><br>
|
||||
<input type="text" placeholder="Enter Username" name="uname" required><br><br>
|
||||
<div>
|
||||
<label for="psw2"><b>Enter password again:</b></label><br>
|
||||
<input type="password" placeholder="Enter Password Again" name="psw2" required>
|
||||
</div>
|
||||
|
||||
<label for="psw"><b>Password:</b></label><br>
|
||||
<input type="password" placeholder="Enter Password" name="psw" required><br><br>
|
||||
<div>
|
||||
<label for="date"><b>Date of birth:</b></label><br>
|
||||
<input type="date" id="start" name="date"/>
|
||||
</div>
|
||||
|
||||
<label for="psw2"><b>Enter password again:</b></label><br>
|
||||
<input type="password" placeholder="Enter Password Again" name="psw2" required><br><br>
|
||||
<div>
|
||||
<b id="TOSbox">I agree to the <a href="" id="TOSa">Terms of Service</a>:</b>
|
||||
<input type="checkbox" id="TOS" name="TOS"/>
|
||||
</div>
|
||||
|
||||
<label for="date"><b>Date of birth:</b></label><br>
|
||||
<input type="date" id="start" name="date"/><br><br>
|
||||
<p class="wrongred" id="wrong"></p>
|
||||
<div id="h-captcha">
|
||||
|
||||
|
||||
<b id="TOSbox">I agree to the <a href="" id="TOSa">Terms of Service</a>:</b>
|
||||
<input type="checkbox" id="TOS" name="TOS"/><br>
|
||||
<p class="wrongred" id="wrong"></p><br>
|
||||
<button type="submit">Create account</button>
|
||||
</div>
|
||||
<button type="submit" class="dontgrow">Create account</button>
|
||||
</form>
|
||||
<a href="/login.html">Already have an account?</a>
|
||||
</div>
|
||||
|
|
|
@ -16,13 +16,14 @@ async function registertry(e){
|
|||
const dateofbirth=elements[5].value;
|
||||
const apiurl=new URL(JSON.parse(localStorage.getItem("instanceinfo")).api)
|
||||
|
||||
fetch(apiurl+"/auth/register",{
|
||||
await fetch(apiurl+"/auth/register",{
|
||||
body:JSON.stringify({
|
||||
date_of_birth:dateofbirth,
|
||||
email:email,
|
||||
username:username,
|
||||
password:password,
|
||||
consent:elements[6].checked,
|
||||
captcha_key:elements[7]?.value
|
||||
}),
|
||||
headers:{
|
||||
"content-type": "application/json"
|
||||
|
@ -30,9 +31,37 @@ async function registertry(e){
|
|||
method:"POST"
|
||||
}).then(e=>{
|
||||
e.json().then(e=>{
|
||||
if(e.captcha_sitekey){
|
||||
const capt=document.getElementById("h-captcha");
|
||||
if(!capt.children.length){
|
||||
const capty=document.createElement("div");
|
||||
capty.classList.add("h-captcha");
|
||||
|
||||
capty.setAttribute("data-sitekey", e.captcha_sitekey);
|
||||
const script=document.createElement("script");
|
||||
script.src="https://js.hcaptcha.com/1/api.js";
|
||||
capt.append(script);
|
||||
capt.append(capty);
|
||||
}else{
|
||||
eval("hcaptcha.reset()");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(!e.token){
|
||||
console.log(e);
|
||||
document.getElementById("wrong").textContent=e.errors[Object.keys(e.errors)[0]]._errors[0].message;
|
||||
if(e.errors.consent){
|
||||
error(elements[6],e.errors.consent._errors[0].message);
|
||||
}else if(e.errors.password){
|
||||
error(elements[3],"Password: "+e.errors.password._errors[0].message);
|
||||
}else if(e.errors.username){
|
||||
error(elements[2],"Username: "+e.errors.username._errors[0].message);
|
||||
}else if(e.errors.email){
|
||||
error(elements[1],"Email: "+e.errors.email._errors[0].message);
|
||||
}else if(e.errors.date_of_birth){
|
||||
error(elements[5],"Date of Birth: "+e.errors.date_of_birth._errors[0].message);
|
||||
}else{
|
||||
document.getElementById("wrong").textContent=e.errors[Object.keys(e.errors)[0]]._errors[0].message;
|
||||
}
|
||||
}else{
|
||||
localStorage.setItem("token",e.token);
|
||||
window.location.href = '/channels/@me';
|
||||
|
@ -42,6 +71,20 @@ async function registertry(e){
|
|||
//document.getElementById("wrong").textContent=h;
|
||||
// console.log(h);
|
||||
}
|
||||
function error(e:HTMLFormElement,message:string){
|
||||
const p=e.parentElement;
|
||||
let element=p.getElementsByClassName("suberror")[0] as HTMLElement;
|
||||
if(!element){
|
||||
const div=document.createElement("div");
|
||||
div.classList.add("suberror","suberrora");
|
||||
p.append(div);
|
||||
element=div;
|
||||
}else{
|
||||
element.classList.remove("suberror");
|
||||
setTimeout(_=>{element.classList.add("suberror")},100);
|
||||
}
|
||||
element.textContent=message;
|
||||
}
|
||||
let TOSa=document.getElementById("TOSa");
|
||||
async function tosLogic(){
|
||||
const apiurl=new URL(JSON.parse(localStorage.getItem("instanceinfo")).api)
|
||||
|
|
|
@ -3,6 +3,7 @@ import {Permissions} from "./permissions.js";
|
|||
import {Localuser} from "./localuser.js";
|
||||
import {Guild} from "./guild.js";
|
||||
import { SnowFlake } from "./snowflake.js";
|
||||
import { rolesjson } from "./jsontypes.js";
|
||||
class Role{
|
||||
permissions:Permissions;
|
||||
owner:Guild;
|
||||
|
@ -18,7 +19,7 @@ class Role{
|
|||
get id(){
|
||||
return this.snowflake.id;
|
||||
}
|
||||
constructor(json, owner:Guild){
|
||||
constructor(json:rolesjson, owner:Guild){
|
||||
this.headers=owner.headers;
|
||||
this.info=owner.info;
|
||||
for(const thing of Object.keys(json)){
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class SnowFlake<x>{
|
||||
class SnowFlake<x extends WeakKey>{
|
||||
public readonly id:string;
|
||||
private static readonly SnowFlakes:Map<any,Map<string,WeakRef<SnowFlake<any>>>>=new Map();
|
||||
private static readonly FinalizationRegistry=new FinalizationRegistry((a:[string,any])=>{
|
||||
private static readonly FinalizationRegistry=new FinalizationRegistry((a:[string,WeakKey])=>{
|
||||
SnowFlake.SnowFlakes.get(a[1]).delete(a[0]);
|
||||
});
|
||||
private obj:x;
|
||||
|
@ -15,8 +15,12 @@ class SnowFlake<x>{
|
|||
}
|
||||
if(SnowFlake.SnowFlakes.get(obj.constructor).get(id)){
|
||||
const snowflake=SnowFlake.SnowFlakes.get(obj.constructor).get(id).deref();
|
||||
snowflake.obj=obj;
|
||||
return snowflake;
|
||||
if(snowflake){
|
||||
snowflake.obj=obj;
|
||||
return snowflake;
|
||||
}else{
|
||||
SnowFlake.SnowFlakes.get(obj.constructor).delete(id);
|
||||
}
|
||||
}
|
||||
this.id=id;
|
||||
SnowFlake.SnowFlakes.get(obj.constructor).set(id,new WeakRef(this));
|
||||
|
@ -33,7 +37,12 @@ class SnowFlake<x>{
|
|||
}
|
||||
const snowflake=SnowFlake.SnowFlakes.get(type).get(id);
|
||||
if(snowflake){
|
||||
return snowflake.deref();
|
||||
const obj=snowflake.deref();
|
||||
if(obj){
|
||||
return obj;
|
||||
}else{
|
||||
SnowFlake.SnowFlakes.get(type).delete(id);
|
||||
}
|
||||
}
|
||||
{
|
||||
const snowflake=new SnowFlake(id,undefined);
|
||||
|
@ -44,6 +53,22 @@ class SnowFlake<x>{
|
|||
return snowflake;
|
||||
}
|
||||
}
|
||||
static hasSnowFlakeFromID(id:string,type:any){
|
||||
if(!SnowFlake.SnowFlakes.get(type)){
|
||||
return false;
|
||||
}
|
||||
const flake=SnowFlake.SnowFlakes.get(type).get(id);
|
||||
if(flake){
|
||||
const flake2=flake.deref()?.getObject();
|
||||
if(flake2){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
getUnixTime():number{
|
||||
return Number((BigInt(this.id)>>22n)+1420070400000n);
|
||||
}
|
||||
|
|
|
@ -74,6 +74,22 @@ th {
|
|||
.messagediv:hover {
|
||||
background-color: var(--message-bg-hover);
|
||||
}
|
||||
|
||||
.jumped{
|
||||
animation-duration: .5s;
|
||||
animation-name: jumped;
|
||||
}
|
||||
@keyframes jumped{
|
||||
0% {
|
||||
background-color: transparent;
|
||||
}
|
||||
50% {
|
||||
background-color: var(--message-jump);
|
||||
}
|
||||
100% {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.messagediv{
|
||||
overflow: hidden;
|
||||
max-width:100%;
|
||||
|
@ -83,7 +99,7 @@ th {
|
|||
flex-wrap: nowrap;
|
||||
flex-direction: column;
|
||||
max-height: 20in;
|
||||
padding: .02in .2in 0 .1in;
|
||||
padding: .02in .1in 0 .1in;
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
@ -546,7 +562,7 @@ hr {
|
|||
.replypfp {
|
||||
border-radius: 50%;
|
||||
width: .2in;
|
||||
height: 2.in;
|
||||
height: .2in;
|
||||
padding: .05in;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
|
@ -567,6 +583,7 @@ hr {
|
|||
/* display: inline-block !important; */
|
||||
width: 25vw;
|
||||
grid-column: 2;
|
||||
cursor: pointer;
|
||||
}
|
||||
.replytext pre {
|
||||
/* padding: 0 .05in; */
|
||||
|
@ -837,6 +854,10 @@ select{
|
|||
border-style: solid;
|
||||
border-color: var(--login-border);
|
||||
text-align: center;
|
||||
height: 90%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#logindiv input {
|
||||
|
@ -1398,7 +1419,7 @@ span {
|
|||
.messagediv .flexttb{
|
||||
display:flex;
|
||||
overflow: hidden;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
max-height:100in;
|
||||
|
@ -1441,3 +1462,56 @@ span {
|
|||
content:'You can\'t chat here';
|
||||
color:color-mix(in hsl, var(--primary-bg),var(--primary-text));
|
||||
}
|
||||
.scroller{
|
||||
padding-bottom: .2in;
|
||||
}
|
||||
.suberror{
|
||||
animation: goout 6s forwards;
|
||||
}
|
||||
.suberrora{
|
||||
background:var(--channel-hover);
|
||||
border-radius:.1in;
|
||||
position:absolute;
|
||||
border:solid var(--primary-text) .02in;
|
||||
color:color-mix(in hsl,var(--yellow),var(--red));
|
||||
font-weight:bold;
|
||||
opacity:0;
|
||||
cursor:default;
|
||||
/* height: .4in; */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: space-evenly;
|
||||
padding: .075in;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@keyframes goout {
|
||||
0%{
|
||||
opacity:0;
|
||||
}
|
||||
5%{
|
||||
opacity:1;
|
||||
}
|
||||
90%{
|
||||
opacity:1;
|
||||
}
|
||||
100%{
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
|
||||
#register{
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.dontgrow{
|
||||
flex-grow:0;
|
||||
width: 1.6in;
|
||||
text-align: center;
|
||||
}
|
||||
form div{
|
||||
width:100%;
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
/* Default value */
|
||||
--red: red;
|
||||
--green: green;
|
||||
--yellow:yellow;
|
||||
}
|
||||
.Dark-theme { /* thanks to TomatoCake for the updated CSS vars and such*/
|
||||
color-scheme: dark;
|
||||
|
@ -51,6 +52,7 @@
|
|||
--embed: #1a1823;
|
||||
--link: #8888ff;
|
||||
--discovery-bg: #37373b;
|
||||
--message-jump:#7678b0;
|
||||
}
|
||||
.WHITE-theme {
|
||||
color-scheme: light;
|
||||
|
@ -101,6 +103,7 @@
|
|||
--embed: #f2f3f5;
|
||||
--link: #3333ee;
|
||||
--discovery-bg: #c6c6d8;
|
||||
--message-jump:#52558a;
|
||||
}
|
||||
.Light-theme {
|
||||
color-scheme: light;
|
||||
|
@ -159,4 +162,5 @@
|
|||
--embed: #cdccd1;
|
||||
--link: #5566cc;
|
||||
--discovery-bg: #c6c6d8;
|
||||
--message-jump:#52558a;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import {Contextmenu} from "./contextmenu.js";
|
|||
import {Localuser} from "./localuser.js";
|
||||
import {Guild} from "./guild.js";
|
||||
import { SnowFlake } from "./snowflake.js";
|
||||
import { userjson } from "./jsontypes.js";
|
||||
|
||||
class User{
|
||||
static userids={};
|
||||
|
@ -17,6 +18,31 @@ class User{
|
|||
discriminator:string;
|
||||
pronouns:string;
|
||||
bot:boolean;
|
||||
public_flags: number;
|
||||
accent_color: string;
|
||||
banner: string;
|
||||
premium_since: string;
|
||||
premium_type: number;
|
||||
theme_colors: string;
|
||||
badge_ids: string;
|
||||
clone(){
|
||||
return new User({
|
||||
username:this.username,
|
||||
id:this.id+"#clone",
|
||||
public_flags:this.public_flags,
|
||||
discriminator:this.discriminator,
|
||||
avatar:this.avatar,
|
||||
accent_color:this.accent_color,
|
||||
banner:this.banner,
|
||||
bio:this.bio.rawString,
|
||||
premium_since:this.premium_since,
|
||||
premium_type:this.premium_type,
|
||||
bot:this.bot,
|
||||
theme_colors:this.theme_colors,
|
||||
pronouns:this.pronouns,
|
||||
badge_ids:this.badge_ids
|
||||
},this.owner)
|
||||
}
|
||||
get id(){
|
||||
return this.snowflake.id;
|
||||
}
|
||||
|
@ -33,12 +59,12 @@ class User{
|
|||
});
|
||||
})
|
||||
}
|
||||
static checkuser(userjson,owner:Localuser){
|
||||
if(User.userids[userjson.id]){
|
||||
return User.userids[userjson.id];
|
||||
static checkuser(user:User|userjson,owner:Localuser):User{
|
||||
if(User.userids[user.id]){
|
||||
return User.userids[user.id];
|
||||
}else{
|
||||
const tempuser=new User(userjson,owner,true)
|
||||
User.userids[userjson.id]=tempuser;
|
||||
const tempuser=new User(user as userjson,owner,true)
|
||||
User.userids[user.id]=tempuser;
|
||||
return tempuser;
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +74,7 @@ class User{
|
|||
get localuser(){
|
||||
return this.owner;
|
||||
}
|
||||
constructor(userjson,owner:Localuser,dontclone=false){
|
||||
constructor(userjson:userjson,owner:Localuser,dontclone=false){
|
||||
this.owner=owner;
|
||||
if(!owner){console.error("missing localuser")}
|
||||
if(dontclone){
|
||||
|
@ -69,7 +95,7 @@ class User{
|
|||
}
|
||||
}
|
||||
async resolvemember(guild:Guild){
|
||||
await Member.resolve(this,guild);
|
||||
return await Member.resolve(this,guild);
|
||||
}
|
||||
buildpfp(){
|
||||
const pfp=document.createElement('img');
|
||||
|
@ -78,7 +104,7 @@ class User{
|
|||
pfp.classList.add("userid:"+this.id);
|
||||
return pfp;
|
||||
}
|
||||
userupdate(json){
|
||||
userupdate(json:userjson){
|
||||
if(json.avatar!==this.avatar){
|
||||
console.log
|
||||
this.changepfp(json.avatar);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue