roles
This commit is contained in:
parent
e06d304064
commit
c8e3125c5d
10 changed files with 759 additions and 250 deletions
|
@ -61,7 +61,7 @@ class Channel extends SnowFlake{
|
|||
this.readbottom();
|
||||
});
|
||||
|
||||
this.contextmenu.addbutton("Settings[temp]", function(this: Channel){
|
||||
this.contextmenu.addbutton("Settings", function(this: Channel){
|
||||
this.generateSettings();
|
||||
});
|
||||
|
||||
|
@ -76,17 +76,6 @@ class Channel extends SnowFlake{
|
|||
}
|
||||
);
|
||||
|
||||
this.contextmenu.addbutton(
|
||||
"Edit channel",
|
||||
function(this: Channel){
|
||||
this.editChannel();
|
||||
},
|
||||
null,
|
||||
function(){
|
||||
return this.isAdmin();
|
||||
}
|
||||
);
|
||||
|
||||
this.contextmenu.addbutton(
|
||||
"Make invite",
|
||||
function(this: Channel){
|
||||
|
@ -205,15 +194,33 @@ class Channel extends SnowFlake{
|
|||
generateSettings(){
|
||||
this.sortPerms();
|
||||
const settings = new Settings("Settings for " + this.name);
|
||||
|
||||
const s1 = settings.addButton("roles");
|
||||
|
||||
{
|
||||
const gensettings=settings.addButton("Settings");
|
||||
const form=gensettings.addForm("",()=>{},{
|
||||
fetchURL:this.info.api + "/channels/" + this.id,
|
||||
method: "PATCH",
|
||||
headers: this.headers,
|
||||
});
|
||||
form.addTextInput("Name:","name",{initText:this.name});
|
||||
form.addMDInput("Topic:","topic",{initText:this.topic});
|
||||
form.addCheckboxInput("NSFW:","nsfw",{initState:this.nsfw});
|
||||
if(this.type!==4){
|
||||
const options=["voice", "text", "announcement"];
|
||||
form.addSelect("Type:","type",options,{
|
||||
defaultIndex:options.indexOf({0:"text", 2:"voice", 5:"announcement", 4:"category" }[this.type] as string)
|
||||
})
|
||||
}
|
||||
form.addPreprocessor((obj:any)=>{
|
||||
obj.type={text: 0, voice: 2, announcement: 5, category: 4 }[obj.type as string]
|
||||
})
|
||||
}
|
||||
const s1 = settings.addButton("Permisions");
|
||||
s1.options.push(
|
||||
new RoleList(
|
||||
this.permission_overwritesar,
|
||||
this.guild,
|
||||
this.updateRolePermissions.bind(this),
|
||||
true
|
||||
this
|
||||
)
|
||||
);
|
||||
settings.show();
|
||||
|
@ -739,68 +746,6 @@ class Channel extends SnowFlake{
|
|||
}),
|
||||
});
|
||||
}
|
||||
editChannel(){
|
||||
let name = this.name;
|
||||
let topic = this.topic;
|
||||
let nsfw = this.nsfw;
|
||||
const thisid = this.id;
|
||||
const thistype = this.type;
|
||||
const full = new Dialog([
|
||||
"hdiv",
|
||||
[
|
||||
"vdiv",
|
||||
[
|
||||
"textbox",
|
||||
"Channel name:",
|
||||
this.name,
|
||||
function(this: HTMLInputElement){
|
||||
name = this.value;
|
||||
},
|
||||
],
|
||||
[
|
||||
"mdbox",
|
||||
"Channel topic:",
|
||||
this.topic,
|
||||
function(this: HTMLTextAreaElement){
|
||||
topic = this.value;
|
||||
},
|
||||
],
|
||||
[
|
||||
"checkbox",
|
||||
"NSFW Channel",
|
||||
this.nsfw,
|
||||
function(this: HTMLInputElement){
|
||||
nsfw = this.checked;
|
||||
},
|
||||
],
|
||||
[
|
||||
"button",
|
||||
"",
|
||||
"submit",
|
||||
()=>{
|
||||
fetch(this.info.api + "/channels/" + thisid, {
|
||||
method: "PATCH",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify({
|
||||
name,
|
||||
type: thistype,
|
||||
topic,
|
||||
bitrate: 64000,
|
||||
user_limit: 0,
|
||||
nsfw,
|
||||
flags: 0,
|
||||
rate_limit_per_user: 0,
|
||||
}),
|
||||
});
|
||||
console.log(full);
|
||||
full.hide();
|
||||
},
|
||||
],
|
||||
],
|
||||
]);
|
||||
full.show();
|
||||
console.log(full);
|
||||
}
|
||||
deleteChannel(){
|
||||
fetch(this.info.api + "/channels/" + this.id, {
|
||||
method: "DELETE",
|
||||
|
@ -1231,12 +1176,11 @@ class Channel extends SnowFlake{
|
|||
|
||||
this.children = [];
|
||||
this.guild_id = json.guild_id;
|
||||
const oldover=this.permission_overwrites;
|
||||
this.permission_overwrites = new Map();
|
||||
this.permission_overwritesar=[];
|
||||
for(const thing of json.permission_overwrites){
|
||||
if(
|
||||
thing.id === "1182819038095799904" ||
|
||||
thing.id === "1182820803700625444"
|
||||
){
|
||||
if(thing.id === "1182819038095799904" || thing.id === "1182820803700625444"){
|
||||
continue;
|
||||
}
|
||||
this.permission_overwrites.set(
|
||||
|
@ -1251,9 +1195,26 @@ class Channel extends SnowFlake{
|
|||
}
|
||||
}
|
||||
}
|
||||
const nchange=[...new Set<string>().union(oldover).difference(this.permission_overwrites)];
|
||||
const pchange=[...new Set<string>().union(this.permission_overwrites).difference(oldover)];
|
||||
for(const thing of nchange){
|
||||
const role=this.guild.roleids.get(thing);
|
||||
if(role){
|
||||
this.croleUpdate(role,new Permissions("0"),false)
|
||||
}
|
||||
}
|
||||
for(const thing of pchange){
|
||||
const role=this.guild.roleids.get(thing);
|
||||
const perms=this.permission_overwrites.get(thing);
|
||||
if(role&&perms){
|
||||
this.croleUpdate(role,perms,true);
|
||||
}
|
||||
}
|
||||
console.log(pchange,nchange);
|
||||
this.topic = json.topic;
|
||||
this.nsfw = json.nsfw;
|
||||
}
|
||||
croleUpdate:(role:Role,perm:Permissions,added:boolean)=>unknown=()=>{};
|
||||
typingstart(){
|
||||
if(this.typing > Date.now()){
|
||||
return;
|
||||
|
@ -1366,16 +1327,14 @@ class Channel extends SnowFlake{
|
|||
return;
|
||||
}
|
||||
if(
|
||||
this.localuser.lookingguild?.prevchannel === this &&
|
||||
document.hasFocus()
|
||||
this.localuser.lookingguild?.prevchannel === this && document.hasFocus()
|
||||
){
|
||||
return;
|
||||
}
|
||||
if(this.notification === "all"){
|
||||
this.notify(messagez);
|
||||
}else if(
|
||||
this.notification === "mentions" &&
|
||||
messagez.mentionsuser(this.localuser.user)
|
||||
this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)
|
||||
){
|
||||
this.notify(messagez);
|
||||
}
|
||||
|
@ -1445,20 +1404,22 @@ class Channel extends SnowFlake{
|
|||
if(permission){
|
||||
permission.allow = perms.allow;
|
||||
permission.deny = perms.deny;
|
||||
await fetch(
|
||||
this.info.api + "/channels/" + this.id + "/permissions/" + id,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify({
|
||||
allow: permission.allow.toString(),
|
||||
deny: permission.deny.toString(),
|
||||
id,
|
||||
type: 0,
|
||||
}),
|
||||
}
|
||||
);
|
||||
}else{
|
||||
//this.permission_overwrites.set(id,perms);
|
||||
}
|
||||
await fetch(
|
||||
this.info.api + "/channels/" + this.id + "/permissions/" + id,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify({
|
||||
allow: perms.allow.toString(),
|
||||
deny: perms.deny.toString(),
|
||||
id,
|
||||
type: 0,
|
||||
}),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Channel.setupcontextmenu();
|
||||
|
|
|
@ -13,6 +13,7 @@ import{
|
|||
emojijson,
|
||||
memberjson,
|
||||
invitejson,
|
||||
rolesjson,
|
||||
}from"./jsontypes.js";
|
||||
import{ User }from"./user.js";
|
||||
|
||||
|
@ -114,16 +115,67 @@ class Guild extends SnowFlake{
|
|||
}
|
||||
form.addTextInput("Region:", "region", { initText: region });
|
||||
}
|
||||
const s1 = settings.addButton("roles");
|
||||
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))
|
||||
new RoleList(permlist, this, this.updateRolePermissions.bind(this),false)
|
||||
);
|
||||
settings.show();
|
||||
}
|
||||
roleUpdate:(role:Role,added:-1|0|1)=>unknown=()=>{};
|
||||
sortRoles(){
|
||||
this.roles.sort((a,b)=>(b.position-a.position));
|
||||
}
|
||||
async recalcRoles(){
|
||||
let position=this.roles.length;
|
||||
const map=this.roles.map(_=>{
|
||||
position--;
|
||||
return {id:_.id,position};
|
||||
})
|
||||
await fetch(this.info.api+"/guilds/"+this.id+"/roles",{
|
||||
method:"PATCH",
|
||||
body:JSON.stringify(map),
|
||||
headers:this.headers
|
||||
})
|
||||
}
|
||||
newRole(rolej:rolesjson){
|
||||
const role=new Role(rolej,this);
|
||||
this.roles.push(role);
|
||||
this.roleids.set(role.id, role);
|
||||
this.sortRoles();
|
||||
this.roleUpdate(role,1);
|
||||
}
|
||||
updateRole(rolej:rolesjson){
|
||||
const role=this.roleids.get(rolej.id) as Role;
|
||||
role.newJson(rolej);
|
||||
this.roleUpdate(role,0);
|
||||
}
|
||||
memberupdate(json:memberjson){
|
||||
let member:undefined|Member=undefined;
|
||||
for(const thing of this.members){
|
||||
if(thing.id===json.id){
|
||||
member=thing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!member) return;
|
||||
member.update(json);
|
||||
if(member===this.member){
|
||||
console.log(member);
|
||||
this.loadGuild();
|
||||
}
|
||||
}
|
||||
deleteRole(id:string){
|
||||
const role = this.roleids.get(id);
|
||||
if(!role) return;
|
||||
this.roleids.delete(id);
|
||||
this.roles.splice(this.roles.indexOf(role),1);
|
||||
this.roleUpdate(role,-1);
|
||||
}
|
||||
constructor(
|
||||
json: guildjson | -1,
|
||||
owner: Localuser,
|
||||
|
@ -153,6 +205,7 @@ class Guild extends SnowFlake{
|
|||
this.roles.push(roleh);
|
||||
this.roleids.set(roleh.id, roleh);
|
||||
}
|
||||
this.sortRoles();
|
||||
if(member instanceof User){
|
||||
Member.resolveMember(member, this).then(_=>{
|
||||
if(_){
|
||||
|
|
|
@ -478,7 +478,28 @@ roleCreate | {
|
|||
guild_id: string;
|
||||
emoji: emojijson;
|
||||
};
|
||||
s: 3;
|
||||
s: number;
|
||||
}|{
|
||||
op: 0,
|
||||
t: "GUILD_ROLE_UPDATE",
|
||||
d: {
|
||||
guild_id: string,
|
||||
role: rolesjson
|
||||
},
|
||||
"s": number
|
||||
}|{
|
||||
op: 0,
|
||||
t: "GUILD_ROLE_DELETE",
|
||||
d: {
|
||||
guild_id: string,
|
||||
role_id: string
|
||||
},
|
||||
s:number
|
||||
}|{
|
||||
op: 0,
|
||||
t: "GUILD_MEMBER_UPDATE",
|
||||
d: memberjson,
|
||||
"s": 3
|
||||
}|memberlistupdatejson|voiceupdate|voiceserverupdate;
|
||||
|
||||
|
||||
|
|
|
@ -354,149 +354,174 @@ class Localuser{
|
|||
if(temp.s)this.lastSequence = temp.s;
|
||||
if(temp.op == 0){
|
||||
switch(temp.t){
|
||||
case"MESSAGE_CREATE":
|
||||
if(this.initialized){
|
||||
this.messageCreate(temp);
|
||||
}
|
||||
break;
|
||||
case"MESSAGE_DELETE": {
|
||||
temp.d.guild_id ??= "@me";
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.id);
|
||||
if(!message)break;
|
||||
message.deleteEvent();
|
||||
break;
|
||||
}
|
||||
case"READY":
|
||||
await this.gottenReady(temp as readyjson);
|
||||
break;
|
||||
case"MESSAGE_UPDATE": {
|
||||
temp.d.guild_id ??= "@me";
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.id);
|
||||
if(!message)break;
|
||||
message.giveData(temp.d);
|
||||
break;
|
||||
}
|
||||
case"TYPING_START":
|
||||
if(this.initialized){
|
||||
this.typingStart(temp);
|
||||
}
|
||||
break;
|
||||
case"USER_UPDATE":
|
||||
if(this.initialized){
|
||||
const users = this.userMap.get(temp.d.id);
|
||||
if(users){
|
||||
users.userupdate(temp.d);
|
||||
case"MESSAGE_CREATE":
|
||||
if(this.initialized){
|
||||
this.messageCreate(temp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case"CHANNEL_UPDATE":
|
||||
if(this.initialized){
|
||||
this.updateChannel(temp.d);
|
||||
}
|
||||
break;
|
||||
case"CHANNEL_CREATE":
|
||||
if(this.initialized){
|
||||
this.createChannel(temp.d);
|
||||
}
|
||||
break;
|
||||
case"CHANNEL_DELETE":
|
||||
if(this.initialized){
|
||||
this.delChannel(temp.d);
|
||||
}
|
||||
break;
|
||||
case"GUILD_DELETE": {
|
||||
const guildy = this.guildids.get(temp.d.id);
|
||||
if(guildy){
|
||||
this.guildids.delete(temp.d.id);
|
||||
this.guilds.splice(this.guilds.indexOf(guildy), 1);
|
||||
guildy.html.remove();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case"GUILD_CREATE": {
|
||||
const guildy = new Guild(temp.d, this, this.user);
|
||||
this.guilds.push(guildy);
|
||||
this.guildids.set(guildy.id, guildy);
|
||||
(document.getElementById("servers") as HTMLDivElement).insertBefore(
|
||||
guildy.generateGuildIcon(),
|
||||
document.getElementById("bottomseparator")
|
||||
);
|
||||
break;
|
||||
}
|
||||
case"MESSAGE_REACTION_ADD":
|
||||
{
|
||||
break;
|
||||
case"MESSAGE_DELETE": {
|
||||
temp.d.guild_id ??= "@me";
|
||||
const guild = this.guildids.get(temp.d.guild_id);
|
||||
if(!guild)break;
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.message_id);
|
||||
const message = channel.messages.get(temp.d.id);
|
||||
if(!message)break;
|
||||
let thing: Member | { id: string };
|
||||
if(temp.d.member){
|
||||
thing = (await Member.new(temp.d.member, guild)) as Member;
|
||||
}else{
|
||||
thing = { id: temp.d.user_id };
|
||||
message.deleteEvent();
|
||||
break;
|
||||
}
|
||||
case"READY":
|
||||
await this.gottenReady(temp as readyjson);
|
||||
break;
|
||||
case"MESSAGE_UPDATE": {
|
||||
temp.d.guild_id ??= "@me";
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.id);
|
||||
if(!message)break;
|
||||
message.giveData(temp.d);
|
||||
break;
|
||||
}
|
||||
case"TYPING_START":
|
||||
if(this.initialized){
|
||||
this.typingStart(temp);
|
||||
}
|
||||
message.reactionAdd(temp.d.emoji, thing);
|
||||
break;
|
||||
case"USER_UPDATE":
|
||||
if(this.initialized){
|
||||
const users = this.userMap.get(temp.d.id);
|
||||
if(users){
|
||||
users.userupdate(temp.d);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case"CHANNEL_UPDATE":
|
||||
if(this.initialized){
|
||||
this.updateChannel(temp.d);
|
||||
}
|
||||
break;
|
||||
case"CHANNEL_CREATE":
|
||||
if(this.initialized){
|
||||
this.createChannel(temp.d);
|
||||
}
|
||||
break;
|
||||
case"CHANNEL_DELETE":
|
||||
if(this.initialized){
|
||||
this.delChannel(temp.d);
|
||||
}
|
||||
break;
|
||||
case"GUILD_DELETE": {
|
||||
const guildy = this.guildids.get(temp.d.id);
|
||||
if(guildy){
|
||||
this.guildids.delete(temp.d.id);
|
||||
this.guilds.splice(this.guilds.indexOf(guildy), 1);
|
||||
guildy.html.remove();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case"MESSAGE_REACTION_REMOVE":
|
||||
case"GUILD_CREATE": {
|
||||
const guildy = new Guild(temp.d, this, this.user);
|
||||
this.guilds.push(guildy);
|
||||
this.guildids.set(guildy.id, guildy);
|
||||
(document.getElementById("servers") as HTMLDivElement).insertBefore(
|
||||
guildy.generateGuildIcon(),
|
||||
document.getElementById("bottomseparator")
|
||||
);
|
||||
break;
|
||||
}
|
||||
case"MESSAGE_REACTION_ADD":
|
||||
{
|
||||
temp.d.guild_id ??= "@me";
|
||||
const guild = this.guildids.get(temp.d.guild_id);
|
||||
if(!guild)break;
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.message_id);
|
||||
if(!message)break;
|
||||
let thing: Member | { id: string };
|
||||
if(temp.d.member){
|
||||
thing = (await Member.new(temp.d.member, guild)) as Member;
|
||||
}else{
|
||||
thing = { id: temp.d.user_id };
|
||||
}
|
||||
message.reactionAdd(temp.d.emoji, thing);
|
||||
}
|
||||
break;
|
||||
case"MESSAGE_REACTION_REMOVE":
|
||||
{
|
||||
temp.d.guild_id ??= "@me";
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.message_id);
|
||||
if(!message)break;
|
||||
message.reactionRemove(temp.d.emoji, temp.d.user_id);
|
||||
}
|
||||
break;
|
||||
case"MESSAGE_REACTION_REMOVE_ALL":
|
||||
{
|
||||
temp.d.guild_id ??= "@me";
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.message_id);
|
||||
if(!message)break;
|
||||
message.reactionRemoveAll();
|
||||
}
|
||||
break;
|
||||
case"MESSAGE_REACTION_REMOVE_EMOJI":
|
||||
{
|
||||
temp.d.guild_id ??= "@me";
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.message_id);
|
||||
if(!message)break;
|
||||
message.reactionRemoveEmoji(temp.d.emoji);
|
||||
}
|
||||
break;
|
||||
case"GUILD_MEMBERS_CHUNK":
|
||||
this.gotChunk(temp.d);
|
||||
break;
|
||||
case"GUILD_MEMBER_LIST_UPDATE":
|
||||
{
|
||||
temp.d.guild_id ??= "@me";
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.message_id);
|
||||
if(!message)break;
|
||||
message.reactionRemove(temp.d.emoji, temp.d.user_id);
|
||||
}
|
||||
break;
|
||||
case"MESSAGE_REACTION_REMOVE_ALL":
|
||||
{
|
||||
temp.d.guild_id ??= "@me";
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.message_id);
|
||||
if(!message)break;
|
||||
message.reactionRemoveAll();
|
||||
}
|
||||
break;
|
||||
case"MESSAGE_REACTION_REMOVE_EMOJI":
|
||||
{
|
||||
temp.d.guild_id ??= "@me";
|
||||
const channel = this.channelids.get(temp.d.channel_id);
|
||||
if(!channel)break;
|
||||
const message = channel.messages.get(temp.d.message_id);
|
||||
if(!message)break;
|
||||
message.reactionRemoveEmoji(temp.d.emoji);
|
||||
}
|
||||
break;
|
||||
case"GUILD_MEMBERS_CHUNK":
|
||||
this.gotChunk(temp.d);
|
||||
break;
|
||||
case"GUILD_MEMBER_LIST_UPDATE":
|
||||
{
|
||||
this.memberListUpdate(temp)
|
||||
break;
|
||||
}
|
||||
case "VOICE_STATE_UPDATE":
|
||||
if(this.voiceFactory){
|
||||
this.voiceFactory.voiceStateUpdate(temp)
|
||||
this.memberListUpdate(temp)
|
||||
break;
|
||||
}
|
||||
case "VOICE_STATE_UPDATE":
|
||||
if(this.voiceFactory){
|
||||
this.voiceFactory.voiceStateUpdate(temp)
|
||||
}
|
||||
|
||||
break;
|
||||
case "VOICE_SERVER_UPDATE":
|
||||
if(this.voiceFactory){
|
||||
this.voiceFactory.voiceServerUpdate(temp)
|
||||
break;
|
||||
case "VOICE_SERVER_UPDATE":
|
||||
if(this.voiceFactory){
|
||||
this.voiceFactory.voiceServerUpdate(temp)
|
||||
}
|
||||
break;
|
||||
case "GUILD_ROLE_CREATE":{
|
||||
const guild=this.guildids.get(temp.d.guild_id);
|
||||
if(!guild) break;
|
||||
guild.newRole(temp.d.role);
|
||||
break;
|
||||
}
|
||||
case "GUILD_ROLE_UPDATE":{
|
||||
const guild=this.guildids.get(temp.d.guild_id);
|
||||
if(!guild) break;
|
||||
guild.updateRole(temp.d.role);
|
||||
break;
|
||||
}
|
||||
case "GUILD_ROLE_DELETE":{
|
||||
const guild=this.guildids.get(temp.d.guild_id);
|
||||
if(!guild) break;
|
||||
guild.deleteRole(temp.d.role_id);
|
||||
break;
|
||||
}
|
||||
case "GUILD_MEMBER_UPDATE":{
|
||||
const guild=this.guildids.get(temp.d.guild_id);
|
||||
if(!guild) break;
|
||||
guild.memberupdate(temp.d)
|
||||
break
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}else if(temp.op === 10){
|
||||
if(!this.ws)return;
|
||||
console.log("heartbeat down");
|
||||
|
|
|
@ -49,6 +49,32 @@ class Member extends SnowFlake{
|
|||
return this.guild.roles.indexOf(a) - this.guild.roles.indexOf(b);
|
||||
});
|
||||
}
|
||||
update(memberjson: memberjson){
|
||||
this.roles=[];
|
||||
for(const key of Object.keys(memberjson)){
|
||||
if(key === "guild" || key === "owner" || key === "user"){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key === "roles"){
|
||||
for(const strrole of memberjson.roles){
|
||||
const role = this.guild.roleids.get(strrole);
|
||||
if(!role)continue;
|
||||
this.roles.push(role);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(key === "presence"){
|
||||
this.getPresence(memberjson.presence);
|
||||
continue;
|
||||
}
|
||||
(this as any)[key] = (memberjson as any)[key];
|
||||
}
|
||||
|
||||
this.roles.sort((a, b)=>{
|
||||
return this.guild.roles.indexOf(a) - this.guild.roles.indexOf(b);
|
||||
});
|
||||
}
|
||||
get guild(){
|
||||
return this.owner;
|
||||
}
|
||||
|
@ -241,6 +267,24 @@ class Member extends SnowFlake{
|
|||
]);
|
||||
menu.show();
|
||||
}
|
||||
addRole(role:Role){
|
||||
const roles=this.roles.map(_=>_.id)
|
||||
roles.push(role.id);
|
||||
fetch(this.info.api+"/guilds/"+this.guild.id+"/members/"+this.id,{
|
||||
method:"PATCH",
|
||||
headers:this.guild.headers,
|
||||
body:JSON.stringify({roles})
|
||||
})
|
||||
}
|
||||
removeRole(role:Role){
|
||||
let roles=this.roles.map(_=>_.id)
|
||||
roles=roles.filter(_=>_!==role.id);
|
||||
fetch(this.info.api+"/guilds/"+this.guild.id+"/members/"+this.id,{
|
||||
method:"PATCH",
|
||||
headers:this.guild.headers,
|
||||
body:JSON.stringify({roles})
|
||||
})
|
||||
}
|
||||
banAPI(reason: string){
|
||||
const headers = structuredClone(this.guild.headers);
|
||||
(headers as any)["x-audit-log-reason"] = reason;
|
||||
|
|
|
@ -3,6 +3,7 @@ import{ Localuser }from"./localuser.js";
|
|||
import{ Guild }from"./guild.js";
|
||||
import{ SnowFlake }from"./snowflake.js";
|
||||
import{ rolesjson }from"./jsontypes.js";
|
||||
import{ Search }from"./search.js";
|
||||
class Role extends SnowFlake{
|
||||
permissions: Permissions;
|
||||
owner: Guild;
|
||||
|
@ -13,6 +14,7 @@ class Role extends SnowFlake{
|
|||
icon!: string;
|
||||
mentionable!: boolean;
|
||||
unicode_emoji!: string;
|
||||
position!:number;
|
||||
headers: Guild["headers"];
|
||||
constructor(json: rolesjson, owner: Guild){
|
||||
super(json.id);
|
||||
|
@ -27,6 +29,15 @@ class Role extends SnowFlake{
|
|||
this.permissions = new Permissions(json.permissions);
|
||||
this.owner = owner;
|
||||
}
|
||||
newJson(json: rolesjson){
|
||||
for(const thing of Object.keys(json)){
|
||||
if(thing === "id"||thing==="permissions"){
|
||||
continue;
|
||||
}
|
||||
(this as any)[thing] = (json as any)[thing];
|
||||
}
|
||||
this.permissions.allow=BigInt(json.permissions);
|
||||
}
|
||||
get guild(): Guild{
|
||||
return this.owner;
|
||||
}
|
||||
|
@ -39,6 +50,14 @@ class Role extends SnowFlake{
|
|||
}
|
||||
return`#${this.color.toString(16)}`;
|
||||
}
|
||||
canManage(){
|
||||
if(this.guild.member.hasPermission("MANAGE_ROLES")){
|
||||
let max=-Infinity;
|
||||
this.guild.member.roles.forEach(r=>max=Math.max(max,r.position))
|
||||
return this.position<=max||this.guild.properties.owner_id===this.guild.member.id;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export{ Role };
|
||||
import{ Options }from"./settings.js";
|
||||
|
@ -121,22 +140,25 @@ class PermissionToggle implements OptionsElement<number>{
|
|||
submit(){}
|
||||
}
|
||||
import{ OptionsElement, Buttons }from"./settings.js";
|
||||
import { Contextmenu } from "./contextmenu.js";
|
||||
import { Channel } from "./channel.js";
|
||||
class RoleList extends Buttons{
|
||||
readonly permissions: [Role, Permissions][];
|
||||
permissions: [Role, Permissions][];
|
||||
permission: Permissions;
|
||||
readonly guild: Guild;
|
||||
readonly channel: boolean;
|
||||
declare readonly buttons: [string, string][];
|
||||
readonly channel: false|Channel;
|
||||
declare buttons: [string, string][];
|
||||
readonly options: Options;
|
||||
onchange: Function;
|
||||
curid!: string;
|
||||
constructor(
|
||||
permissions: [Role, Permissions][],
|
||||
guild: Guild,
|
||||
onchange: Function,
|
||||
channel = false
|
||||
){
|
||||
super("Roles");
|
||||
curid?: string;
|
||||
get info(){
|
||||
return this.guild.info;
|
||||
}
|
||||
get headers(){
|
||||
return this.guild.headers;
|
||||
}
|
||||
constructor(permissions:[Role, Permissions][], guild:Guild, onchange:Function, channel:false|Channel){
|
||||
super("");
|
||||
this.guild = guild;
|
||||
this.permissions = permissions;
|
||||
this.channel = channel;
|
||||
|
@ -147,16 +169,237 @@ class RoleList extends Buttons{
|
|||
}else{
|
||||
this.permission = new Permissions("0");
|
||||
}
|
||||
this.makeguildmenus(options);
|
||||
for(const thing of Permissions.info){
|
||||
options.options.push(
|
||||
new PermissionToggle(thing, this.permission, options)
|
||||
);
|
||||
}
|
||||
for(const i of permissions){
|
||||
console.log(i);
|
||||
this.buttons.push([i[0].name, i[0].id]);
|
||||
}
|
||||
this.options = options;
|
||||
guild.roleUpdate=this.groleUpdate.bind(this);
|
||||
if(channel){
|
||||
channel.croleUpdate=this.croleUpdate.bind(this);
|
||||
}
|
||||
}
|
||||
private groleUpdate(role:Role,added:1|0|-1){
|
||||
if(!this.channel){
|
||||
if(added===1){
|
||||
this.permissions.push([role,role.permissions]);
|
||||
}
|
||||
}
|
||||
if(added===-1){
|
||||
this.permissions=this.permissions.filter(r=>r[0]!==role);
|
||||
}
|
||||
this.redoButtons();
|
||||
}
|
||||
private croleUpdate(role:Role,perm:Permissions,added:boolean){
|
||||
if(added){
|
||||
this.permissions.push([role,perm])
|
||||
}else{
|
||||
this.permissions=this.permissions.filter(r=>r[0]!==role);
|
||||
}
|
||||
this.redoButtons();
|
||||
}
|
||||
makeguildmenus(option:Options){
|
||||
option.addButtonInput("","Display settings",()=>{
|
||||
const role=this.guild.roleids.get(this.curid as string);
|
||||
if(!role) return;
|
||||
const form=option.addSubForm("Display settings",()=>{},{
|
||||
fetchURL:this.info.api+"/guilds/"+this.guild.id+"/roles/"+this.curid,
|
||||
method:"PATCH",
|
||||
headers:this.headers
|
||||
});
|
||||
form.addTextInput("Role Name:","name",{
|
||||
initText:role.name
|
||||
});
|
||||
form.addCheckboxInput("Hoisted:","hoist",{
|
||||
initState:role.hoist
|
||||
});
|
||||
form.addCheckboxInput("Allow anyone to ping this role:","mentionable",{
|
||||
initState:role.mentionable
|
||||
});
|
||||
const color="#"+role.color.toString(16).padStart(6,"0");
|
||||
form.addColorInput("Color","color",{
|
||||
initColor:color
|
||||
});
|
||||
form.addPreprocessor((obj:any)=>{
|
||||
obj.color=Number("0x"+obj.color.substring(1));
|
||||
console.log(obj.color);
|
||||
})
|
||||
})
|
||||
}
|
||||
static channelrolemenu=this.ChannelRoleMenu();
|
||||
static guildrolemenu=this.GuildRoleMenu();
|
||||
private static ChannelRoleMenu(){
|
||||
const menu=new Contextmenu<RoleList,Role>("role settings");
|
||||
menu.addbutton("Remove role",function(role){
|
||||
if(!this.channel) return;
|
||||
console.log(role);
|
||||
fetch(this.info.api+"/channels/"+this.channel.id+"/permissions/"+role.id,{
|
||||
method:"DELETE",
|
||||
headers:this.headers
|
||||
})
|
||||
},null);
|
||||
return menu;
|
||||
}
|
||||
private static GuildRoleMenu(){
|
||||
const menu=new Contextmenu<RoleList,Role>("role settings");
|
||||
menu.addbutton("Delete Role",function(role){
|
||||
if(!confirm("Are you sure you want to delete "+role.name+"?")) return;
|
||||
console.log(role);
|
||||
fetch(this.info.api+"/guilds/"+this.guild.id+"/roles/"+role.id,{
|
||||
method:"DELETE",
|
||||
headers:this.headers
|
||||
})
|
||||
},null);
|
||||
return menu;
|
||||
}
|
||||
redoButtons(){
|
||||
this.buttons=[];
|
||||
this.permissions.sort(([a],[b])=>b.position-a.position);
|
||||
for(const i of this.permissions){
|
||||
this.buttons.push([i[0].name, i[0].id]);
|
||||
}
|
||||
console.log("in here :P")
|
||||
if(!this.buttonList)return;
|
||||
console.log("in here :P");
|
||||
const elms=Array.from(this.buttonList.children);
|
||||
const div=elms[0] as HTMLDivElement;
|
||||
const div2=elms[1] as HTMLDivElement;
|
||||
console.log(div);
|
||||
div.innerHTML="";
|
||||
div.append(this.buttonListGen(div2));//not actually sure why the html is needed
|
||||
}
|
||||
buttonMap=new WeakMap<HTMLButtonElement,Role>();
|
||||
dragged?:HTMLButtonElement;
|
||||
buttonDragEvents(button:HTMLButtonElement,role:Role){
|
||||
this.buttonMap.set(button,role);
|
||||
button.addEventListener("dragstart", e=>{
|
||||
this.dragged = button;
|
||||
e.stopImmediatePropagation();
|
||||
});
|
||||
|
||||
button.addEventListener("dragend", ()=>{
|
||||
this.dragged = undefined;
|
||||
});
|
||||
|
||||
button.addEventListener("dragenter", event=>{
|
||||
console.log("enter");
|
||||
event.preventDefault();
|
||||
return true;
|
||||
});
|
||||
|
||||
button.addEventListener("dragover", event=>{
|
||||
event.preventDefault();
|
||||
return true;
|
||||
});
|
||||
|
||||
button.addEventListener("drop", _=>{
|
||||
const role2=this.buttonMap.get(this.dragged as HTMLButtonElement);
|
||||
if(!role2) return;
|
||||
const index2=this.guild.roles.indexOf(role2);
|
||||
this.guild.roles.splice(index2,1);
|
||||
const index=this.guild.roles.indexOf(role);
|
||||
this.guild.roles.splice(index+1,0,role2);
|
||||
this.guild.recalcRoles();
|
||||
console.log(role);
|
||||
});
|
||||
}
|
||||
buttonListGen(html:HTMLElement){
|
||||
const buttonTable=document.createElement("div");
|
||||
buttonTable.classList.add("flexttb");
|
||||
|
||||
const roleRow=document.createElement("div");
|
||||
roleRow.classList.add("flexltr");
|
||||
roleRow.append("Roles");
|
||||
const add=document.createElement("span");
|
||||
add.classList.add("svg-plus","svgicon","addrole");
|
||||
add.onclick=async (e)=>{
|
||||
const box=add.getBoundingClientRect();
|
||||
e.stopPropagation();
|
||||
if(this.channel){
|
||||
const roles:[Role,string[]][]=[];
|
||||
for(const role of this.guild.roles){
|
||||
if(this.permissions.find(r=>r[0]==role)){
|
||||
continue;
|
||||
}
|
||||
roles.push([role,[role.name]]);
|
||||
}
|
||||
const search=new Search(roles);
|
||||
|
||||
const found=await search.find(box.left,box.top);
|
||||
|
||||
|
||||
if(!found) return;
|
||||
console.log(found);
|
||||
this.onchange(found.id,new Permissions("0","0"));
|
||||
}else{
|
||||
const bar=document.createElement("input");
|
||||
bar.classList.add("fixedsearch");
|
||||
bar.style.left=(box.left^0)+"px";
|
||||
bar.style.top=(box.top^0)+"px";
|
||||
document.body.append(bar);
|
||||
if(Contextmenu.currentmenu != ""){
|
||||
Contextmenu.currentmenu.remove();
|
||||
}
|
||||
Contextmenu.currentmenu=bar;
|
||||
Contextmenu.keepOnScreen(bar);
|
||||
bar.onchange=()=>{
|
||||
bar.remove();
|
||||
console.log(bar.value)
|
||||
if(bar.value==="") return;
|
||||
fetch(this.info.api+`/guilds/${this.guild.id}/roles`,{
|
||||
method:"POST",
|
||||
headers:this.headers,
|
||||
body:JSON.stringify({
|
||||
color:0,
|
||||
name:bar.value,
|
||||
permissions:""
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
roleRow.append(add);
|
||||
|
||||
buttonTable.append(roleRow);
|
||||
for(const thing of this.buttons){
|
||||
const button = document.createElement("button");
|
||||
button.classList.add("SettingsButton");
|
||||
button.textContent = thing[0];
|
||||
const role=this.guild.roleids.get(thing[1]);
|
||||
if(role){
|
||||
if(!this.channel){
|
||||
if(role.canManage()){
|
||||
this.buttonDragEvents(button,role);
|
||||
button.draggable=true;
|
||||
RoleList.guildrolemenu.bindContextmenu(button,this,role)
|
||||
}
|
||||
}else{
|
||||
if(role.canManage()){
|
||||
RoleList.channelrolemenu.bindContextmenu(button,this,role)
|
||||
}
|
||||
}
|
||||
}
|
||||
button.onclick = _=>{
|
||||
this.generateHTMLArea(thing[1], html);
|
||||
if(this.warndiv){
|
||||
this.warndiv.remove();
|
||||
}
|
||||
};
|
||||
buttonTable.append(button);
|
||||
}
|
||||
return buttonTable;
|
||||
}
|
||||
|
||||
generateButtons(html:HTMLElement):HTMLDivElement{
|
||||
const div = document.createElement("div");
|
||||
div.classList.add("settingbuttons");
|
||||
div.append(this.buttonListGen(html));
|
||||
return div;
|
||||
}
|
||||
handleString(str: string): HTMLElement{
|
||||
this.curid = str;
|
||||
|
|
72
src/webpage/search.ts
Normal file
72
src/webpage/search.ts
Normal file
|
@ -0,0 +1,72 @@
|
|||
import { Contextmenu } from "./contextmenu.js";
|
||||
|
||||
class Search<E>{
|
||||
options:Map<string,E>;
|
||||
readonly keys:string[];
|
||||
constructor(options:[E,string[]][]){
|
||||
const map=options.flatMap(e=>{
|
||||
const val=e[1].map(f=>[f,e[0]]);
|
||||
return val as [string,E][];
|
||||
})
|
||||
this.options=new Map(map);
|
||||
this.keys=[...this.options.keys()];
|
||||
}
|
||||
generateList(str:string,max:number,res:(e:E)=>void){
|
||||
str=str.toLowerCase();
|
||||
const options=this.keys.filter(e=>{
|
||||
return e.toLowerCase().includes(str)
|
||||
});
|
||||
const div=document.createElement("div");
|
||||
div.classList.add("OptionList","flexttb");
|
||||
for(const option of options.slice(0, max)){
|
||||
const hoption=document.createElement("span");
|
||||
hoption.textContent=option;
|
||||
hoption.onclick=()=>{
|
||||
if(!this.options.has(option)) return;
|
||||
res(this.options.get(option) as E)
|
||||
}
|
||||
div.append(hoption);
|
||||
}
|
||||
return div;
|
||||
}
|
||||
async find(x:number,y:number,max=4):Promise<E|undefined>{
|
||||
return new Promise<E|undefined>((res)=>{
|
||||
|
||||
const container=document.createElement("div");
|
||||
container.classList.add("fixedsearch");
|
||||
console.log((x^0)+"",(y^0)+"");
|
||||
container.style.left=(x^0)+"px";
|
||||
container.style.top=(y^0)+"px";
|
||||
const remove=container.remove;
|
||||
container.remove=()=>{
|
||||
remove.call(container);
|
||||
res(undefined);
|
||||
}
|
||||
|
||||
function resolve(e:E){
|
||||
res(e);
|
||||
container.remove();
|
||||
}
|
||||
const bar=document.createElement("input");
|
||||
const options=document.createElement("div");
|
||||
const keydown=()=>{
|
||||
const html=this.generateList(bar.value,max,resolve);
|
||||
options.innerHTML="";
|
||||
options.append(html);
|
||||
}
|
||||
bar.oninput=keydown;
|
||||
keydown();
|
||||
bar.type="text";
|
||||
container.append(bar);
|
||||
container.append(options);
|
||||
document.body.append(container);
|
||||
if(Contextmenu.currentmenu != ""){
|
||||
Contextmenu.currentmenu.remove();
|
||||
}
|
||||
Contextmenu.currentmenu=container;
|
||||
Contextmenu.keepOnScreen(container);
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
export {Search};
|
|
@ -30,6 +30,15 @@ class Buttons implements OptionsElement<unknown>{
|
|||
this.buttonList = buttonList;
|
||||
const htmlarea = document.createElement("div");
|
||||
htmlarea.classList.add("flexgrow");
|
||||
const buttonTable = this.generateButtons(htmlarea);
|
||||
if(this.buttons[0]){
|
||||
this.generateHTMLArea(this.buttons[0][1], htmlarea);
|
||||
}
|
||||
buttonList.append(buttonTable);
|
||||
buttonList.append(htmlarea);
|
||||
return buttonList;
|
||||
}
|
||||
generateButtons(optionsArea:HTMLElement){
|
||||
const buttonTable = document.createElement("div");
|
||||
buttonTable.classList.add("settingbuttons");
|
||||
for(const thing of this.buttons){
|
||||
|
@ -37,24 +46,21 @@ class Buttons implements OptionsElement<unknown>{
|
|||
button.classList.add("SettingsButton");
|
||||
button.textContent = thing[0];
|
||||
button.onclick = _=>{
|
||||
this.generateHTMLArea(thing[1], htmlarea);
|
||||
this.generateHTMLArea(thing[1], optionsArea);
|
||||
if(this.warndiv){
|
||||
this.warndiv.remove();
|
||||
}
|
||||
};
|
||||
buttonTable.append(button);
|
||||
}
|
||||
this.generateHTMLArea(this.buttons[0][1], htmlarea);
|
||||
buttonList.append(buttonTable);
|
||||
buttonList.append(htmlarea);
|
||||
return buttonList;
|
||||
return buttonTable;
|
||||
}
|
||||
handleString(str: string): HTMLElement{
|
||||
const div = document.createElement("span");
|
||||
div.textContent = str;
|
||||
return div;
|
||||
}
|
||||
private generateHTMLArea(
|
||||
generateHTMLArea(
|
||||
buttonInfo: Options | string,
|
||||
htmlarea: HTMLElement
|
||||
){
|
||||
|
@ -1066,6 +1072,10 @@ class Form implements OptionsElement<object>{
|
|||
this.owner.changed();
|
||||
}
|
||||
}
|
||||
preprocessor:(obj:Object)=>void=()=>{};
|
||||
addPreprocessor(func:(obj:Object)=>void){
|
||||
this.preprocessor=func;
|
||||
}
|
||||
async submit(){
|
||||
if(this.options.subOptions){
|
||||
this.options.subOptions.submit();
|
||||
|
@ -1130,6 +1140,7 @@ class Form implements OptionsElement<object>{
|
|||
}
|
||||
console.log("middle2");
|
||||
await Promise.allSettled(promises);
|
||||
this.preprocessor(build);
|
||||
if(this.fetchURL !== ""){
|
||||
fetch(this.fetchURL, {
|
||||
method: this.method,
|
||||
|
|
|
@ -1934,3 +1934,28 @@ fieldset input[type="radio"] {
|
|||
width: 100%;
|
||||
}
|
||||
}
|
||||
.addrole{
|
||||
width:.1in;
|
||||
height: .1in;
|
||||
margin-left: .1in;
|
||||
margin-top: .04in;
|
||||
cursor: pointer;
|
||||
}
|
||||
.fixedsearch{
|
||||
position: absolute;
|
||||
background: var(--primary-bg);
|
||||
min-height: .2in;
|
||||
padding:.05in;
|
||||
border:solid .03in var(--black);
|
||||
border-radius:.05in;
|
||||
span{
|
||||
margin-top:.1in;
|
||||
width:100%;
|
||||
padding:.03in;
|
||||
border:solid .03in var(--black);
|
||||
box-sizing:border-box;
|
||||
border-radius:.05in;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import{ Localuser }from"./localuser.js";
|
|||
import{ Guild }from"./guild.js";
|
||||
import{ SnowFlake }from"./snowflake.js";
|
||||
import{ presencejson, userjson }from"./jsontypes.js";
|
||||
import { Role } from "./role.js";
|
||||
import { Search } from "./search.js";
|
||||
|
||||
class User extends SnowFlake{
|
||||
owner: Localuser;
|
||||
|
@ -174,6 +176,58 @@ class User extends SnowFlake{
|
|||
return us.hasPermission("BAN_MEMBERS") || false;
|
||||
}
|
||||
);
|
||||
this.contextmenu.addbutton(
|
||||
"Add roles",
|
||||
async function(this: User, member: Member | undefined,e){
|
||||
if(member){
|
||||
e.stopPropagation();
|
||||
const roles:[Role,string[]][]=[];
|
||||
for(const role of member.guild.roles){
|
||||
if(!role.canManage()||member.roles.indexOf(role)!==-1){
|
||||
continue;
|
||||
}
|
||||
roles.push([role,[role.name]]);
|
||||
}
|
||||
const search=new Search(roles);
|
||||
const result=await search.find(e.x,e.y);
|
||||
if(!result) return;
|
||||
member.addRole(result);
|
||||
}
|
||||
},
|
||||
null,
|
||||
member=>{
|
||||
if(!member)return false;
|
||||
const us = member.guild.member;
|
||||
console.log(us.hasPermission("MANAGE_ROLES"))
|
||||
return us.hasPermission("MANAGE_ROLES") || false;
|
||||
}
|
||||
);
|
||||
this.contextmenu.addbutton(
|
||||
"Remove roles",
|
||||
async function(this: User, member: Member | undefined,e){
|
||||
if(member){
|
||||
e.stopPropagation();
|
||||
const roles:[Role,string[]][]=[];
|
||||
for(const role of member.roles){
|
||||
if(!role.canManage()){
|
||||
continue;
|
||||
}
|
||||
roles.push([role,[role.name]]);
|
||||
}
|
||||
const search=new Search(roles);
|
||||
const result=await search.find(e.x,e.y);
|
||||
if(!result) return;
|
||||
member.removeRole(result);
|
||||
}
|
||||
},
|
||||
null,
|
||||
member=>{
|
||||
if(!member)return false;
|
||||
const us = member.guild.member;
|
||||
console.log(us.hasPermission("MANAGE_ROLES"))
|
||||
return us.hasPermission("MANAGE_ROLES") || false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static checkuser(user: User | userjson, owner: Localuser): User{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue