list bans of guilds

This commit is contained in:
MathMan05 2025-04-14 13:34:39 -05:00
parent bdbee6894d
commit 5b5d15c99c
8 changed files with 224 additions and 33 deletions

View file

@ -14,6 +14,8 @@ import {
rolesjson,
emojipjson,
extendedProperties,
banObj,
addInfoBan,
} from "./jsontypes.js";
import {User} from "./user.js";
import {I18n} from "./i18n.js";
@ -21,6 +23,7 @@ import {Emoji} from "./emoji.js";
import {webhookMenu} from "./webhooks.js";
import {createImg} from "./utils/utils.js";
import {Sticker} from "./sticker.js";
import {ProgessiveDecodeJSON} from "./utils/progessiveLoad.js";
class Guild extends SnowFlake {
owner!: Localuser;
@ -423,9 +426,133 @@ class Guild extends SnowFlake {
genDiv();
emoji.addHTMLArea(containdiv);
}
const banMenu = settings.addButton(I18n.guild.bans());
const makeBanMenu = () => {
const banDiv = document.createElement("div");
const bansp = ProgessiveDecodeJSON<banObj[]>(this.info.api + "/guilds/" + this.id + "/bans", {
headers: this.headers,
});
const createBanHTML = (ban: banObj) => {
const div = document.createElement("div");
div.classList.add("flexltr", "bandiv");
let src: string;
if (ban.user.avatar !== null) {
src = `${this.info.cdn}/avatars/${ban.user.id}/${ban.user.avatar}.png`;
} else {
const int = Number((BigInt(ban.user.id) >> 22n) % 6n);
src = `${this.info.cdn}/embed/avatars/${int}.png`;
}
const img = createImg(src);
img.classList.add("pfp");
const divUserRes = document.createElement("div");
divUserRes.classList.add("flexttb");
const username = document.createElement("span");
username.textContent = ban.user.username;
divUserRes.append(username);
if (ban.reason) {
const reason = document.createElement("span");
reason.innerText = ban.reason;
divUserRes.append(I18n.guild.banReason(ban.reason));
}
div.append(img, divUserRes);
div.onclick = async (_) => {
const opt = banMenu.addSubOptions(ban.user.username);
opt.addHTMLArea(img.cloneNode(true) as HTMLElement);
opt.addText(ban.user.username);
if (ban.reason) opt.addText(I18n.guild.banReason(ban.reason));
//FIXME the API sends back the wrong responce, so I don't have this info
/*
const moreInfo = (await (
await fetch(this.info.api + "/guilds/" + this.id + "/bans/" + ban.user.id, {
headers: this.headers,
})
).json()) as addInfoBan;
const userWhoBanned = await User.resolve(moreInfo.executor_id, this.localuser);
opt.addHTMLArea(userWhoBanned.createWidget(this));
//*/
opt.addButtonInput("", I18n.user.unban(ban.user.username), async () => {
bansArr = bansArr.filter((_) => _ !== ban);
await fetch(this.info.api + "/guilds/" + this.id + "/bans/" + ban.user.id, {
headers: this.headers,
method: "DELETE",
});
loadPage(currentPage);
banMenu.returnFromSub();
});
};
return div;
};
let bansArr: banObj[] = [];
let onpage = 0;
async function loadArr() {
let bansArr2: banObj[] = [];
let waiting = false;
async function addHTML() {
if (waiting) return;
waiting = true;
await new Promise((res) => setTimeout(res, 0));
waiting = false;
banDiv.append(...bansArr2.map((ban) => createBanHTML(ban)));
bansArr2 = [];
}
while (!(await bansp).done) {
const ban = await (await (await bansp).getNext()).getWhole();
bansArr.push(ban);
if (onpage < 50) {
bansArr2.push(ban);
addHTML();
onpage++;
} else {
next.disabled = false;
}
}
}
let currentPage = 0;
function loadPage(page = 0) {
banDiv.innerHTML = "";
for (onpage = 0; onpage < 50; onpage++) {
const ban = bansArr[onpage + page * 50];
if (!ban) break;
banDiv.append(createBanHTML(ban));
}
if (onpage === 50 && bansArr[onpage + page * 50]) {
next.disabled = false;
} else {
next.disabled = true;
}
}
const pageNav = document.createElement("div");
const back = document.createElement("button");
back.textContent = I18n.search.back();
back.disabled = !currentPage;
back.onclick = () => {
back.disabled = !(currentPage - 1);
next.disabled = false;
loadPage(--currentPage);
};
const next = document.createElement("button");
next.textContent = I18n.search.next();
next.disabled = true;
pageNav.append(back, next);
banMenu.addHTMLArea(pageNav);
next.onclick = () => {
loadPage(++currentPage);
back.disabled = false;
};
loadArr();
loadPage(currentPage);
return banDiv;
};
banMenu.addHTMLArea(makeBanMenu);
const widgetMenu = settings.addButton(I18n.widget());
(async () => {
const widgetMenu = settings.addButton(I18n.widget());
const cur = (await (
await fetch(this.info.api + "/guilds/" + this.id + "/widget", {
headers: this.headers,

View file

@ -121,6 +121,23 @@ type readyjson = {
};
};
};
interface banObj {
reason: string | null;
user: {
username: string;
discriminator: string;
id: string;
avatar: string | null;
public_flags: number;
};
}
interface addInfoBan {
id: string;
user_id: string;
guild_id: string;
executor_id: string;
reason?: string | undefined;
}
type mainuserjson = userjson & {
flags: number;
mfa_enabled?: boolean;
@ -819,4 +836,6 @@ export {
webhookInfo,
webhookType,
stickerJson,
banObj,
addInfoBan,
};

View file

@ -660,7 +660,7 @@ class HtmlArea implements OptionsElement<void> {
}
generateHTML(): HTMLElement {
if (this.html instanceof Function) {
return this.html();
return (this.html = this.html());
} else {
return this.html;
}

View file

@ -48,6 +48,17 @@ body {
align-items: center;
}
}
.bandiv {
padding: 10px;
align-items: center;
margin-bottom: 8px;
background: var(--secondary-bg);
border-radius: 6px;
cursor: pointer;
div {
margin-left: 8px;
}
}
.flexltr {
min-height: 0;
display: flex;

View file

@ -475,7 +475,30 @@ class User extends SnowFlake {
}
return pfp;
}
createWidget(guild: Guild) {
const div = document.createElement("div");
div.classList.add("flexltr", "createdWebhook");
//TODO make sure this is something I can actually do here
const name = document.createElement("b");
name.textContent = this.name;
const nameBox = document.createElement("div");
nameBox.classList.add("flexttb");
nameBox.append(name);
const pfp = this.buildpfp(undefined, div);
div.append(pfp, nameBox);
Member.resolveMember(this, guild).then((_) => {
if (_) {
name.textContent = _.name;
pfp.src = _.getpfpsrc();
} else {
const notFound = document.createElement("span");
notFound.textContent = I18n.webhooks.notFound();
nameBox.append(notFound);
}
});
this.bind(div, guild);
return div;
}
async buildstatuspfp(guild: Guild | void | Member | null): Promise<HTMLDivElement> {
const div = document.createElement("div");
div.classList.add("pfpDiv");
@ -554,6 +577,25 @@ class User extends SnowFlake {
const json = await fetch(localuser.info.api.toString() + "/users/" + id + "/profile", {
headers: localuser.headers,
}).then((res) => res.json());
if (json.code === 404) {
return new User(
{
id: "0",
public_flags: 0,
username: I18n.friends.notfound(),
avatar: null,
discriminator: "0000",
bio: "",
bot: false,
premium_type: 0,
premium_since: "",
accent_color: 0,
theme_colors: "",
badge_ids: [],
},
localuser,
);
}
return new User(json.user, localuser);
}

View file

@ -44,17 +44,29 @@ export class ProgressiveArray {
}
decoder = new TextDecoder();
backChar?: string;
chars = "";
curchar = 0;
async getChar() {
if (this.backChar) {
const temp = this.backChar;
delete this.backChar;
return temp;
}
let char = "";
while (!char) {
char = this.decoder.decode((await this.get8BitArray(1)).buffer, {stream: true});
let char: string;
if ((char = this.chars[this.curchar])) {
this.curchar++;
return char;
}
return char;
let chars = "";
while (!chars) {
const buflen = (this.cbuff?.length || 0) - this.index;
chars = this.decoder.decode((await this.get8BitArray(buflen <= 0 ? 1 : buflen)).buffer, {
stream: true,
});
}
this.chars = chars;
this.curchar = 1;
return chars[0];
}
putBackChar(char: string) {
this.backChar = char;

View file

@ -146,30 +146,9 @@ async function webhookMenu(
form.addText(I18n.webhooks.createdBy());
try {
const div = document.createElement("div");
div.classList.add("flexltr", "createdWebhook");
//TODO make sure this is something I can actually do here
const user = new User(hook.user, guild.localuser);
const name = document.createElement("b");
name.textContent = user.name;
const nameBox = document.createElement("div");
nameBox.classList.add("flexttb");
nameBox.append(name);
const pfp = user.buildpfp(undefined, div);
div.append(pfp, nameBox);
const div = user.createWidget(guild);
form.addHTMLArea(div);
Member.resolveMember(user, guild).then((_) => {
if (_) {
name.textContent = _.name;
pfp.src = _.getpfpsrc();
} else {
const notFound = document.createElement("span");
notFound.textContent = I18n.webhooks.notFound();
nameBox.append(notFound);
}
});
user.bind(div, guild);
} catch {}
form.addButtonInput("", I18n.webhooks.deleteWebhook(), () => {
const d = new Dialog("areYouSureDelete");
@ -191,9 +170,6 @@ async function webhookMenu(
d.show();
});
};
console.log(hook);
webhooks.addHTMLArea(div);
};
regenArea();

View file

@ -245,6 +245,9 @@
"nevermind": "Nevermind",
"submit": "submit",
"guild": {
"bannedBy": "Banned by:",
"banReason": "Ban reason: $1",
"bans": "Bans",
"ruleId": "Rules Channel:",
"community": "Community",
"creating": "Creating guild",
@ -498,7 +501,8 @@
"removeRole": "Remove roles",
"editServerProfile": "Edit server profile",
"instanceBan": "Instance ban",
"confirmInstBan": "Are you sure you want to instance ban $1?"
"confirmInstBan": "Are you sure you want to instance ban $1?",
"unban": "Unban $1"
},
"login": {
"checking": "Checking Instance",