This commit is contained in:
MathMan05 2024-10-29 20:30:24 -05:00
parent e06d304064
commit c8e3125c5d
10 changed files with 759 additions and 250 deletions

View file

@ -61,7 +61,7 @@ class Channel extends SnowFlake{
this.readbottom(); this.readbottom();
}); });
this.contextmenu.addbutton("Settings[temp]", function(this: Channel){ this.contextmenu.addbutton("Settings", function(this: Channel){
this.generateSettings(); 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( this.contextmenu.addbutton(
"Make invite", "Make invite",
function(this: Channel){ function(this: Channel){
@ -205,15 +194,33 @@ class Channel extends SnowFlake{
generateSettings(){ generateSettings(){
this.sortPerms(); this.sortPerms();
const settings = new Settings("Settings for " + this.name); 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( s1.options.push(
new RoleList( new RoleList(
this.permission_overwritesar, this.permission_overwritesar,
this.guild, this.guild,
this.updateRolePermissions.bind(this), this.updateRolePermissions.bind(this),
true this
) )
); );
settings.show(); 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(){ deleteChannel(){
fetch(this.info.api + "/channels/" + this.id, { fetch(this.info.api + "/channels/" + this.id, {
method: "DELETE", method: "DELETE",
@ -1231,12 +1176,11 @@ class Channel extends SnowFlake{
this.children = []; this.children = [];
this.guild_id = json.guild_id; this.guild_id = json.guild_id;
const oldover=this.permission_overwrites;
this.permission_overwrites = new Map(); this.permission_overwrites = new Map();
this.permission_overwritesar=[];
for(const thing of json.permission_overwrites){ for(const thing of json.permission_overwrites){
if( if(thing.id === "1182819038095799904" || thing.id === "1182820803700625444"){
thing.id === "1182819038095799904" ||
thing.id === "1182820803700625444"
){
continue; continue;
} }
this.permission_overwrites.set( 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.topic = json.topic;
this.nsfw = json.nsfw; this.nsfw = json.nsfw;
} }
croleUpdate:(role:Role,perm:Permissions,added:boolean)=>unknown=()=>{};
typingstart(){ typingstart(){
if(this.typing > Date.now()){ if(this.typing > Date.now()){
return; return;
@ -1366,16 +1327,14 @@ class Channel extends SnowFlake{
return; return;
} }
if( if(
this.localuser.lookingguild?.prevchannel === this && this.localuser.lookingguild?.prevchannel === this && document.hasFocus()
document.hasFocus()
){ ){
return; return;
} }
if(this.notification === "all"){ if(this.notification === "all"){
this.notify(messagez); this.notify(messagez);
}else if( }else if(
this.notification === "mentions" && this.notification === "mentions" && messagez.mentionsuser(this.localuser.user)
messagez.mentionsuser(this.localuser.user)
){ ){
this.notify(messagez); this.notify(messagez);
} }
@ -1445,21 +1404,23 @@ class Channel extends SnowFlake{
if(permission){ if(permission){
permission.allow = perms.allow; permission.allow = perms.allow;
permission.deny = perms.deny; permission.deny = perms.deny;
}else{
//this.permission_overwrites.set(id,perms);
}
await fetch( await fetch(
this.info.api + "/channels/" + this.id + "/permissions/" + id, this.info.api + "/channels/" + this.id + "/permissions/" + id,
{ {
method: "PUT", method: "PUT",
headers: this.headers, headers: this.headers,
body: JSON.stringify({ body: JSON.stringify({
allow: permission.allow.toString(), allow: perms.allow.toString(),
deny: permission.deny.toString(), deny: perms.deny.toString(),
id, id,
type: 0, type: 0,
}), }),
} }
); );
} }
}
} }
Channel.setupcontextmenu(); Channel.setupcontextmenu();
export{ Channel }; export{ Channel };

View file

@ -13,6 +13,7 @@ import{
emojijson, emojijson,
memberjson, memberjson,
invitejson, invitejson,
rolesjson,
}from"./jsontypes.js"; }from"./jsontypes.js";
import{ User }from"./user.js"; import{ User }from"./user.js";
@ -114,16 +115,67 @@ class Guild extends SnowFlake{
} }
form.addTextInput("Region:", "region", { initText: region }); form.addTextInput("Region:", "region", { initText: region });
} }
const s1 = settings.addButton("roles"); const s1 = settings.addButton("Roles");
const permlist: [Role, Permissions][] = []; const permlist: [Role, Permissions][] = [];
for(const thing of this.roles){ for(const thing of this.roles){
permlist.push([thing, thing.permissions]); permlist.push([thing, thing.permissions]);
} }
s1.options.push( s1.options.push(
new RoleList(permlist, this, this.updateRolePermissions.bind(this)) new RoleList(permlist, this, this.updateRolePermissions.bind(this),false)
); );
settings.show(); 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( constructor(
json: guildjson | -1, json: guildjson | -1,
owner: Localuser, owner: Localuser,
@ -153,6 +205,7 @@ class Guild extends SnowFlake{
this.roles.push(roleh); this.roles.push(roleh);
this.roleids.set(roleh.id, roleh); this.roleids.set(roleh.id, roleh);
} }
this.sortRoles();
if(member instanceof User){ if(member instanceof User){
Member.resolveMember(member, this).then(_=>{ Member.resolveMember(member, this).then(_=>{
if(_){ if(_){

View file

@ -478,7 +478,28 @@ roleCreate | {
guild_id: string; guild_id: string;
emoji: emojijson; 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; }|memberlistupdatejson|voiceupdate|voiceserverupdate;

View file

@ -494,7 +494,32 @@ class Localuser{
this.voiceFactory.voiceServerUpdate(temp) this.voiceFactory.voiceServerUpdate(temp)
} }
break; 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
}
}
}else if(temp.op === 10){ }else if(temp.op === 10){

View file

@ -49,6 +49,32 @@ class Member extends SnowFlake{
return this.guild.roles.indexOf(a) - this.guild.roles.indexOf(b); 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(){ get guild(){
return this.owner; return this.owner;
} }
@ -241,6 +267,24 @@ class Member extends SnowFlake{
]); ]);
menu.show(); 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){ banAPI(reason: string){
const headers = structuredClone(this.guild.headers); const headers = structuredClone(this.guild.headers);
(headers as any)["x-audit-log-reason"] = reason; (headers as any)["x-audit-log-reason"] = reason;

View file

@ -3,6 +3,7 @@ import{ Localuser }from"./localuser.js";
import{ Guild }from"./guild.js"; import{ Guild }from"./guild.js";
import{ SnowFlake }from"./snowflake.js"; import{ SnowFlake }from"./snowflake.js";
import{ rolesjson }from"./jsontypes.js"; import{ rolesjson }from"./jsontypes.js";
import{ Search }from"./search.js";
class Role extends SnowFlake{ class Role extends SnowFlake{
permissions: Permissions; permissions: Permissions;
owner: Guild; owner: Guild;
@ -13,6 +14,7 @@ class Role extends SnowFlake{
icon!: string; icon!: string;
mentionable!: boolean; mentionable!: boolean;
unicode_emoji!: string; unicode_emoji!: string;
position!:number;
headers: Guild["headers"]; headers: Guild["headers"];
constructor(json: rolesjson, owner: Guild){ constructor(json: rolesjson, owner: Guild){
super(json.id); super(json.id);
@ -27,6 +29,15 @@ class Role extends SnowFlake{
this.permissions = new Permissions(json.permissions); this.permissions = new Permissions(json.permissions);
this.owner = owner; 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{ get guild(): Guild{
return this.owner; return this.owner;
} }
@ -39,6 +50,14 @@ class Role extends SnowFlake{
} }
return`#${this.color.toString(16)}`; 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 }; export{ Role };
import{ Options }from"./settings.js"; import{ Options }from"./settings.js";
@ -121,22 +140,25 @@ class PermissionToggle implements OptionsElement<number>{
submit(){} submit(){}
} }
import{ OptionsElement, Buttons }from"./settings.js"; import{ OptionsElement, Buttons }from"./settings.js";
import { Contextmenu } from "./contextmenu.js";
import { Channel } from "./channel.js";
class RoleList extends Buttons{ class RoleList extends Buttons{
readonly permissions: [Role, Permissions][]; permissions: [Role, Permissions][];
permission: Permissions; permission: Permissions;
readonly guild: Guild; readonly guild: Guild;
readonly channel: boolean; readonly channel: false|Channel;
declare readonly buttons: [string, string][]; declare buttons: [string, string][];
readonly options: Options; readonly options: Options;
onchange: Function; onchange: Function;
curid!: string; curid?: string;
constructor( get info(){
permissions: [Role, Permissions][], return this.guild.info;
guild: Guild, }
onchange: Function, get headers(){
channel = false return this.guild.headers;
){ }
super("Roles"); constructor(permissions:[Role, Permissions][], guild:Guild, onchange:Function, channel:false|Channel){
super("");
this.guild = guild; this.guild = guild;
this.permissions = permissions; this.permissions = permissions;
this.channel = channel; this.channel = channel;
@ -147,16 +169,237 @@ class RoleList extends Buttons{
}else{ }else{
this.permission = new Permissions("0"); this.permission = new Permissions("0");
} }
this.makeguildmenus(options);
for(const thing of Permissions.info){ for(const thing of Permissions.info){
options.options.push( options.options.push(
new PermissionToggle(thing, this.permission, options) new PermissionToggle(thing, this.permission, options)
); );
} }
for(const i of permissions){ for(const i of permissions){
console.log(i);
this.buttons.push([i[0].name, i[0].id]); this.buttons.push([i[0].name, i[0].id]);
} }
this.options = options; 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{ handleString(str: string): HTMLElement{
this.curid = str; this.curid = str;

72
src/webpage/search.ts Normal file
View 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};

View file

@ -30,6 +30,15 @@ class Buttons implements OptionsElement<unknown>{
this.buttonList = buttonList; this.buttonList = buttonList;
const htmlarea = document.createElement("div"); const htmlarea = document.createElement("div");
htmlarea.classList.add("flexgrow"); 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"); const buttonTable = document.createElement("div");
buttonTable.classList.add("settingbuttons"); buttonTable.classList.add("settingbuttons");
for(const thing of this.buttons){ for(const thing of this.buttons){
@ -37,24 +46,21 @@ class Buttons implements OptionsElement<unknown>{
button.classList.add("SettingsButton"); button.classList.add("SettingsButton");
button.textContent = thing[0]; button.textContent = thing[0];
button.onclick = _=>{ button.onclick = _=>{
this.generateHTMLArea(thing[1], htmlarea); this.generateHTMLArea(thing[1], optionsArea);
if(this.warndiv){ if(this.warndiv){
this.warndiv.remove(); this.warndiv.remove();
} }
}; };
buttonTable.append(button); buttonTable.append(button);
} }
this.generateHTMLArea(this.buttons[0][1], htmlarea); return buttonTable;
buttonList.append(buttonTable);
buttonList.append(htmlarea);
return buttonList;
} }
handleString(str: string): HTMLElement{ handleString(str: string): HTMLElement{
const div = document.createElement("span"); const div = document.createElement("span");
div.textContent = str; div.textContent = str;
return div; return div;
} }
private generateHTMLArea( generateHTMLArea(
buttonInfo: Options | string, buttonInfo: Options | string,
htmlarea: HTMLElement htmlarea: HTMLElement
){ ){
@ -1066,6 +1072,10 @@ class Form implements OptionsElement<object>{
this.owner.changed(); this.owner.changed();
} }
} }
preprocessor:(obj:Object)=>void=()=>{};
addPreprocessor(func:(obj:Object)=>void){
this.preprocessor=func;
}
async submit(){ async submit(){
if(this.options.subOptions){ if(this.options.subOptions){
this.options.subOptions.submit(); this.options.subOptions.submit();
@ -1130,6 +1140,7 @@ class Form implements OptionsElement<object>{
} }
console.log("middle2"); console.log("middle2");
await Promise.allSettled(promises); await Promise.allSettled(promises);
this.preprocessor(build);
if(this.fetchURL !== ""){ if(this.fetchURL !== ""){
fetch(this.fetchURL, { fetch(this.fetchURL, {
method: this.method, method: this.method,

View file

@ -1934,3 +1934,28 @@ fieldset input[type="radio"] {
width: 100%; 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;
}
}

View file

@ -5,6 +5,8 @@ import{ Localuser }from"./localuser.js";
import{ Guild }from"./guild.js"; import{ Guild }from"./guild.js";
import{ SnowFlake }from"./snowflake.js"; import{ SnowFlake }from"./snowflake.js";
import{ presencejson, userjson }from"./jsontypes.js"; import{ presencejson, userjson }from"./jsontypes.js";
import { Role } from "./role.js";
import { Search } from "./search.js";
class User extends SnowFlake{ class User extends SnowFlake{
owner: Localuser; owner: Localuser;
@ -174,6 +176,58 @@ class User extends SnowFlake{
return us.hasPermission("BAN_MEMBERS") || false; 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{ static checkuser(user: User | userjson, owner: Localuser): User{