import{ Channel }from"./channel.js"; import{ Localuser }from"./localuser.js"; import{Contextmenu}from"./contextmenu.js"; import{Role,RoleList}from"./role.js"; import{Dialog}from"./dialog.js"; import{Member}from"./member.js"; import{Settings}from"./settings.js"; import{Permissions}from"./permissions.js"; import{ SnowFlake }from"./snowflake.js"; import{ channeljson, guildjson, emojijson, memberjson, invitejson }from"./jsontypes.js"; import{ User }from"./user.js"; class Guild extends SnowFlake{ owner:Localuser; headers:Localuser["headers"]; channels:Channel[]; properties:guildjson["properties"]; member_count:number; roles:Role[]; roleids:Map; prevchannel:Channel|undefined; message_notifications:number; headchannels:Channel[]; position:number; parent_id:string; member:Member; html:HTMLElement; emojis:emojijson[]; large:boolean; static contextmenu=new Contextmenu("guild menu"); static setupcontextmenu(){ Guild.contextmenu.addbutton("Copy Guild id",function(this:Guild){ navigator.clipboard.writeText(this.id); }); Guild.contextmenu.addbutton("Mark as read",function(this:Guild){ this.markAsRead(); }); Guild.contextmenu.addbutton("Notifications",function(this:Guild){ this.setnotifcation(); }); Guild.contextmenu.addbutton("Leave guild",function(this:Guild){ this.confirmleave(); },null,function(_){ return this.properties.owner_id!==this.member.user.id; }); Guild.contextmenu.addbutton("Delete guild",function(this:Guild){ this.confirmDelete(); },null,function(_){ return this.properties.owner_id===this.member.user.id; }); Guild.contextmenu.addbutton("Create invite",function(this:Guild){ },null,_=>true,_=>false); Guild.contextmenu.addbutton("Settings",function(this:Guild){ this.generateSettings(); }); /* -----things left for later----- guild.contextmenu.addbutton("Leave Guild",function(){ console.log(this) this.deleteChannel(); },null,_=>{return thisuser.isAdmin()}) guild.contextmenu.addbutton("Mute Guild",function(){ editchannelf(this); },null,_=>{return thisuser.isAdmin()}) */ } generateSettings(){ const settings=new Settings("Settings for "+this.properties.name); { const overview=settings.addButton("Overview"); const form=overview.addForm("",_=>{},{ headers:this.headers, traditionalSubmit:true, fetchURL:this.info.api+"/guilds/"+this.id, method:"PATCH" }) form.addTextInput("Name:","name",{initText:this.properties.name}); form.addMDInput("Description:","description",{initText:this.properties.description}); form.addFileInput("Banner:","banner",{clear:true}); form.addFileInput("Icon:","icon",{clear:true}); let region=this.properties.region; if(!region){ region=""; } form.addTextInput("Region:","region",{initText:region}); } const s1=settings.addButton("roles"); const permlist:[Role,Permissions][]=[]; for(const thing of this.roles){ permlist.push([thing,thing.permissions]); } s1.options.push(new RoleList(permlist,this,this.updateRolePermissions.bind(this))); settings.show(); } constructor(json:guildjson|-1,owner:Localuser,member:memberjson|User|null){ if(json===-1||member===null){ super("@me"); return; } if(json.stickers.length){ console.log(json.stickers,":3"); } super(json.id); this.large=json.large; this.member_count=json.member_count; this.emojis = json.emojis; this.owner=owner; this.headers=this.owner.headers; this.channels=[]; this.properties=json.properties; this.roles=[]; this.roleids=new Map(); this.message_notifications=0; for(const roley of json.roles){ const roleh=new Role(roley,this); this.roles.push(roleh); this.roleids.set(roleh.id,roleh); } if(member instanceof User){ Member.resolveMember(member,this).then(_=>{ if(_){ this.member=_; }else{ console.error("Member was unable to resolve"); } }); }else{ Member.new(member,this).then(_=>{ if(_){ this.member=_; } }); } this.perminfo??={channels:{}}; for(const thing of json.channels){ const temp=new Channel(thing,this); this.channels.push(temp); this.localuser.channelids.set(temp.id,temp); } this.headchannels=[]; for(const thing of this.channels){ const parent=thing.resolveparent(this); if(!parent){ this.headchannels.push(thing); } } this.prevchannel=this.localuser.channelids.get(this.perminfo.prevchannel); } get perminfo(){ return this.localuser.perminfo.guilds[this.id]; } set perminfo(e){ this.localuser.perminfo.guilds[this.id]=e; } notisetting(settings){ this.message_notifications=settings.message_notifications; } setnotifcation(){ let noti=this.message_notifications; const notiselect=new Dialog( ["vdiv", ["radio","select notifications type", ["all","only mentions","none"], function(e:"all"|"only mentions"|"none"){ noti=["all","only mentions","none"].indexOf(e); }, noti ], ["button","","submit",_=>{ // fetch(this.info.api+`/users/@me/guilds/${this.id}/settings/`,{ method: "PATCH", headers: this.headers, body: JSON.stringify({ message_notifications: noti }) }); this.message_notifications=noti; }] ]); notiselect.show(); } confirmleave(){ const full= new Dialog([ "vdiv", ["title", "Are you sure you want to leave?" ], ["hdiv", ["button", "", "Yes, I'm sure", _=>{ this.leave().then(_=>{ full.hide(); }); } ], ["button", "", "Nevermind", _=>{ full.hide(); } ] ] ]); full.show(); } async leave(){ return fetch(this.info.api+"/users/@me/guilds/"+this.id,{ method: "DELETE", headers: this.headers }); } printServers(){ let build=""; for(const thing of this.headchannels){ build+=(thing.name+":"+thing.position)+"\n"; for(const thingy of thing.children){ build+=(" "+thingy.name+":"+thingy.position)+"\n"; } } console.log(build); } calculateReorder(){ let position=-1; const build:{id:string,position:number|undefined,parent_id:string|undefined}[]=[]; for(const thing of this.headchannels){ const thisthing:{id:string,position:number|undefined,parent_id:string|undefined}={id: thing.id,position: undefined,parent_id: undefined}; if(thing.position<=position){ thing.position=(thisthing.position=position+1); } position=thing.position; console.log(position); if(thing.move_id&&thing.move_id!==thing.parent_id){ thing.parent_id=thing.move_id; thisthing.parent_id=thing.parent?.id; thing.move_id=undefined; } if(thisthing.position||thisthing.parent_id){ build.push(thisthing); } if(thing.children.length>0){ const things=thing.calculateReorder(); for(const thing of things){ build.push(thing); } } } console.log(build); this.printServers(); if(build.length===0){ return; } const serverbug=false; if(serverbug){ for(const thing of build){ console.log(build,thing); fetch(this.info.api+"/guilds/"+this.id+"/channels",{ method: "PATCH", headers: this.headers, body: JSON.stringify([thing]) }); } }else{ fetch(this.info.api+"/guilds/"+this.id+"/channels",{ method: "PATCH", headers: this.headers, body: JSON.stringify(build) }); } } get localuser(){ return this.owner; } get info(){ return this.owner.info; } sortchannels(){ this.headchannels.sort((a,b)=>{ return a.position-b.position; }); } static generateGuildIcon(guild:Guild|(invitejson["guild"] & {info:{cdn:string}})){ const divy=document.createElement("div"); divy.classList.add("servernoti"); const noti=document.createElement("div"); noti.classList.add("unread"); divy.append(noti); if(guild instanceof Guild){ guild.localuser.guildhtml.set(guild.id,divy); } let icon:string|null if(guild instanceof Guild){ icon=guild.properties.icon; }else{ icon=guild.icon; } if(icon!==null){ const img=document.createElement("img"); img.classList.add("pfp","servericon"); img.src=guild.info.cdn+"/icons/"+guild.id+"/"+icon+".png"; divy.appendChild(img); if(guild instanceof Guild){ img.onclick=()=>{ console.log(guild.loadGuild); guild.loadGuild(); guild.loadChannel(); }; Guild.contextmenu.bindContextmenu(img,guild,undefined); } }else{ const div=document.createElement("div"); let name:string if(guild instanceof Guild){ name=guild.properties.name; }else{ name=guild.name; } const build=name.replace(/'s /g, " ").replace(/\w+/g, word=>word[0]).replace(/\s/g, ""); div.textContent=build; div.classList.add("blankserver","servericon"); divy.appendChild(div); if(guild instanceof Guild){ div.onclick=()=>{ guild.loadGuild(); guild.loadChannel(); }; Guild.contextmenu.bindContextmenu(div,guild,undefined); } } return divy; } generateGuildIcon(){ return Guild.generateGuildIcon(this); } confirmDelete(){ let confirmname=""; const full= new Dialog([ "vdiv", ["title", "Are you sure you want to delete "+this.properties.name+"?" ], ["textbox", "Name of server:", "", function(this:HTMLInputElement){ confirmname=this.value; } ], ["hdiv", ["button", "", "Yes, I'm sure", _=>{ console.log(confirmname); if(confirmname!==this.properties.name){ return; } this.delete().then(_=>{ full.hide(); }); } ], ["button", "", "Nevermind", _=>{ full.hide(); } ] ] ]); full.show(); } async delete(){ return fetch(this.info.api+"/guilds/"+this.id+"/delete",{ method: "POST", headers: this.headers, }); } unreads(html?:HTMLElement|undefined){ if(html){ this.html=html; }else{ html=this.html; } let read=true; for(const thing of this.channels){ if(thing.hasunreads){ console.log(thing); read=false; break; } } if(!html){ return; } if(read){ html.children[0].classList.remove("notiunread"); }else{ html.children[0].classList.add("notiunread"); } } getHTML(){ //this.printServers(); this.sortchannels(); this.printServers(); const build=document.createElement("div"); for(const thing of this.headchannels){ build.appendChild(thing.createguildHTML(this.isAdmin())); } return build; } isAdmin(){ return this.member.isAdmin(); } async markAsRead(){ const build:{read_states:{channel_id:string,message_id:string|null|undefined,read_state_type:number}[]}={read_states: []}; for(const thing of this.channels){ if(thing.hasunreads){ build.read_states.push({channel_id: thing.id,message_id: thing.lastmessageid,read_state_type: 0}); thing.lastreadmessageid=thing.lastmessageid; if(!thing.myhtml)continue; thing.myhtml.classList.remove("cunread"); } } this.unreads(); fetch(this.info.api+"/read-states/ack-bulk",{ method: "POST", headers: this.headers, body: JSON.stringify(build) }); } hasRole(r:Role|string){ console.log("this should run"); if(r instanceof Role){ r=r.id; } return this.member.hasRole(r); } loadChannel(ID?:string|undefined){ if(ID){ const channel=this.localuser.channelids.get(ID); if(channel){ channel.getHTML(); return; } } if(this.prevchannel){ console.log(this.prevchannel); this.prevchannel.getHTML(); return; } for(const thing of this.channels){ if(thing.children.length===0){ thing.getHTML(); return; } } } loadGuild(){ this.localuser.loadGuild(this.id); } updateChannel(json:channeljson){ const channel=this.localuser.channelids.get(json.id); if(channel){ channel.updateChannel(json); this.headchannels=[]; for(const thing of this.channels){ thing.children=[]; } this.headchannels=[]; for(const thing of this.channels){ const parent=thing.resolveparent(this); if(!parent){ this.headchannels.push(thing); } } this.printServers(); } } createChannelpac(json:channeljson){ const thischannel=new Channel(json,this); this.localuser.channelids.set(json.id,thischannel); this.channels.push(thischannel); thischannel.resolveparent(this); if(!thischannel.parent){ this.headchannels.push(thischannel); } this.calculateReorder(); this.printServers(); return thischannel; } createchannels(func=this.createChannel){ let name=""; let category=0; const channelselect=new Dialog( ["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(this:HTMLInputElement){ name=this.value; }], ["button","","submit",function(){ console.log(name,category); func(name,category); channelselect.hide(); }] ]); channelselect.show(); } createcategory(){ let name=""; const category=4; const channelselect=new Dialog( ["vdiv", ["textbox","Name of category","",function(this:HTMLInputElement){ name=this.value; }], ["button","","submit",()=>{ console.log(name,category); this.createChannel(name,category); channelselect.hide(); }] ]); channelselect.show(); } delChannel(json:channeljson){ const channel=this.localuser.channelids.get(json.id); this.localuser.channelids.delete(json.id); if(!channel) return; 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){ console.log(thing.id); if(thing!==channel){ build.push(thing) }else{ console.log("fail"); if(thing.parent){ thing.parent.delChannel(json); } } } this.channels=build; */ this.printServers(); } createChannel(name:string,type:number){ fetch(this.info.api+"/guilds/"+this.id+"/channels",{ method: "POST", headers: this.headers, body: JSON.stringify({name, type}) }); } async createRole(name:string){ const fetched=await fetch(this.info.api+"/guilds/"+this.id+"roles",{ method: "POST", headers: this.headers, body: JSON.stringify({ name, color: 0, permissions: "0" }) }); const json=await fetched.json(); const role=new Role(json,this); this.roleids.set(role.id,role); this.roles.push(role); return role; } async updateRolePermissions(id:string,perms:Permissions){ const role=this.roleids[id]; role.permissions.allow=perms.allow; role.permissions.deny=perms.deny; await fetch(this.info.api+"/guilds/"+this.id+"/roles/"+role.id,{ method: "PATCH", headers: this.headers, body: JSON.stringify({ color: role.color, hoist: role.hoist, icon: role.icon, mentionable: role.mentionable, name: role.name, permissions: role.permissions.allow.toString(), unicode_emoji: role.unicode_emoji, }) }); } } Guild.setupcontextmenu(); export{ Guild };