inital member list support

This commit is contained in:
MathMan05 2024-09-30 15:47:52 -05:00
parent b2a31d7993
commit a1902a912f
8 changed files with 501 additions and 288 deletions

View file

@ -377,7 +377,10 @@ class Channel extends SnowFlake{
if(member.isAdmin()){
return true;
}
for(const thing of member.roles){
const roles=new Set(member.roles);
const everyone=this.guild.roles[this.guild.roles.length-1];
roles.add(everyone)
for(const thing of roles){
const premission = this.permission_overwrites.get(thing.id);
if(premission){
const perm = premission.getPermission(name);
@ -834,6 +837,7 @@ class Channel extends SnowFlake{
Channel.regenLoadingMessages();
loading.classList.add("loading");
this.rendertyping();
this.localuser.getSidePannel();
await this.putmessages();
await prom;
if(id !== Channel.genid){

View file

@ -34,6 +34,7 @@ class Guild extends SnowFlake{
html!: HTMLElement;
emojis!: emojijson[];
large!: boolean;
members=new Set<Member>();
static contextmenu = new Contextmenu<Guild, undefined>("guild menu");
static setupcontextmenu(){
Guild.contextmenu.addbutton("Copy Guild id", function(this: Guild){

View file

@ -56,6 +56,8 @@
<span id="channelname">Channel name</span>
<span id="channelTopic" hidden>Channel topic</span>
</div>
<div class="flexltr">
<div class="flexttb">
<div id="channelw">
<div id="loadingdiv">
</div>
@ -76,6 +78,10 @@
</div>
</div>
</div>
<div class="flexttb" id="sideDiv">
</div>
</div>
</div>
</div>
</body>

View file

@ -152,6 +152,7 @@ guild_id: string;
guild: {
id: string;
} | null;
presence?:presencejson
nick?: string;
roles: string[];
joined_at: string;
@ -469,7 +470,7 @@ guild_id: string;
emoji: emojijson;
};
s: 3;
};
}|memberlistupdatejson;
type memberChunk = {
guild_id: string;
nonce: string;
@ -479,6 +480,39 @@ chunk_index: number;
chunk_count: number;
not_found: string[];
};
type memberlistupdatejson={
op: 0,
s: number,
t: "GUILD_MEMBER_LIST_UPDATE",
d: {
ops: [
{
items:({
group:{
count:number,
id:string
}
}|{
member:memberjson
})[]
op: "SYNC",
range: [
number,
number
]
}
],
online_count: number,
member_count: number,
id: string,
guild_id: string,
groups: {
count: number,
id: string
}[]
}
}
export{
readyjson,
dirrectjson,
@ -498,4 +532,5 @@ export{
messageCreateJson,
memberChunk,
invitejson,
memberlistupdatejson
};

View file

@ -10,6 +10,7 @@ import{
guildjson,
mainuserjson,
memberjson,
memberlistupdatejson,
messageCreateJson,
presencejson,
readyjson,
@ -20,6 +21,7 @@ import{ Member }from"./member.js";
import{ Form, FormError, Options, Settings }from"./settings.js";
import{ MarkDown }from"./markdown.js";
import { Bot } from "./bot.js";
import { Role } from "./role.js";
const wsCodesRetry = new Set([4000, 4003, 4005, 4007, 4008, 4009]);
@ -479,7 +481,13 @@ class Localuser{
case"GUILD_MEMBERS_CHUNK":
this.gotChunk(temp.d);
break;
case"GUILD_MEMBER_LIST_UPDATE":
{
this.memberListUpdate(temp)
break;
}
}
}else if(temp.op === 10){
if(!this.ws)return;
console.log("heartbeat down");
@ -518,6 +526,108 @@ class Localuser{
}
return channel; // Add this line to return the 'channel' variable
}
async memberListUpdate(list:memberlistupdatejson){
const div=document.getElementById("sideDiv") as HTMLDivElement;
div.innerHTML="";
const counts=new Map<string,number>();
const guild=this.lookingguild;
if(!guild) return;
const channel=this.channelfocus;
if(!channel) return;
for(const thing of list.d.ops[0].items){
if("member" in thing){
await Member.new(thing.member,guild);
}else{
counts.set(thing.group.id,thing.group.count);
}
}
const elms:Map<Role|"offline"|"online",Member[]>=new Map([["offline",[]],["online",[]]]);
for(const role of guild.roles){
console.log(guild.roles);
if(role.hoist){
elms.set(role,[]);
}
}
const members=new Set(guild.members);
members.forEach((member)=>{
if(!channel.hasPermission("VIEW_CHANNEL",member)){
members.delete(member);
console.log(member)
return;
}
})
for(const [role, list] of elms){
members.forEach((member)=>{
if(role === "offline"){
if(member.user.status === "offline"){
list.push(member);
members.delete(member);
}
return;
}
if(role !== "online"&&member.hasRole(role.id)){
list.push(member);
members.delete(member);
}
});
if(!list.length) continue;
list.sort((a,b)=>{
return (a.name.toLowerCase()>b.name.toLowerCase())?1:-1;
});
}
const online=[...members];
online.sort((a,b)=>{
return (a.name.toLowerCase()>b.name.toLowerCase())?1:-1;
});
elms.set("online",online);
for(const [role, list] of elms){
if(!list.length) continue;
const category=document.createElement("div");
category.classList.add("memberList");
let title=document.createElement("h3");
if(role==="offline"){
title.textContent="Offline";
category.classList.add("offline");
}else if(role==="online"){
title.textContent="Online";
}else{
title.textContent=role.name;
}
category.append(title);
const membershtml=document.createElement("div");
membershtml.classList.add("flexttb");
for(const member of list){
const memberdiv=document.createElement("div");
const pfp=member.user.buildpfp();
const username=document.createElement("span");
username.textContent=member.name;
member.bind(username)
member.user.bind(memberdiv,member.guild,false);
memberdiv.append(pfp,username);
memberdiv.classList.add("flexltr");
membershtml.append(memberdiv);
}
category.append(membershtml);
div.prepend(category);
}
console.log(elms);
}
async getSidePannel(){
if(this.ws&&this.channelfocus){
this.ws.send(JSON.stringify({
d:{
channels:{[this.channelfocus.id]:[[0,99]]},
guild_id:this.channelfocus.guild.id
},
op:14
}))
}else{
console.log("false? :3")
}
}
gotoid: string | undefined;
async goToChannel(id: string){
const channel = this.channelids.get(id);

View file

@ -11,7 +11,6 @@ class Member extends SnowFlake{
user: User;
roles: Role[] = [];
nick!: string;
[key: string]: any;
private constructor(memberjson: memberjson, owner: Guild){
super(memberjson.id);
@ -23,9 +22,11 @@ private constructor(memberjson: memberjson, owner: Guild){
}else{
throw new Error("Missing user object of this member");
}
if(this.localuser.userMap.has(this?.id)){
this.user = this.localuser.userMap.get(this?.id) as User;
}
for(const key of Object.keys(memberjson)){
if(key === "guild" || key === "owner"){
if(key === "guild" || key === "owner" || key === "user"){
continue;
}
@ -37,11 +38,13 @@ private constructor(memberjson: memberjson, owner: Guild){
}
continue;
}
if(key === "presence"){
this.getPresence(memberjson.presence);
continue;
}
(this as any)[key] = (memberjson as any)[key];
}
if(this.localuser.userMap.has(this?.id)){
this.user = this.localuser.userMap.get(this?.id) as User;
}
this.roles.sort((a, b)=>{
return this.guild.roles.indexOf(a) - this.guild.roles.indexOf(b);
});
@ -72,15 +75,20 @@ static async new(
if(memb === undefined){
memb = new Member(memberjson, owner);
user.members.set(owner, memb);
owner.members.add(memb);
return memb;
}else if(memb instanceof Promise){
return await memb; //I should do something else, though for now this is "good enough"
}else{
if(memberjson.presence){
memb.getPresence(memberjson.presence);
}
return memb;
}
}else{
const memb = new Member(memberjson, owner);
user.members.set(owner, memb);
owner.members.add(memb);
return memb;
}
}

View file

@ -1379,6 +1379,7 @@ span {
width: 100%;
height: 100dvh;
align-content: space-around;
align-items: stretch;
}
.userflex{
display:flex;
@ -2219,3 +2220,51 @@ form div{
.mentionMD:hover{
background:color-mix(in srgb,var(--mention-md-bg),white 10%);
}
#sideDiv{
flex-grow:0;
flex-shrink:0;
width:2.5in;
box-shadow: -.02in 0 .04in black;
&:empty{
width:0in;
}
;
align-items: stretch;
/* overflow-x: hidden; */
overflow-y: unset;
scrollbar-width: none;
}
.memberList{
padding:.05in;
>div{
width: 100%;
>div{
width:100%;
padding:.04in .02in;
margin: .01in 0.0in;
border-radius:.1in;
&:hover{
background:var(--message-bg-hover);
}
flex-shrink: 1;
cursor: pointer;
box-sizing:border-box;
gap:.05in;
align-items: center;
}
img{
width:40px;
height:40px;
}
box-sizing: border-box;
}
}
.offline{
h3{
color:var(--primary-text)
}
>div{
opacity:.4;
}
}

View file

@ -27,7 +27,7 @@ class User extends SnowFlake{
badge_ids!: string[];
members: WeakMap<Guild, Member | undefined | Promise<Member | undefined>> =
new WeakMap();
private status!: string;
status!: string;
resolving: false | Promise<any> = false;
constructor(userjson: userjson, owner: Localuser, dontclone = false){