make fermi build faster

This commit is contained in:
MathMan05
2026-01-15 18:50:38 -06:00
parent 059eb80d2b
commit 238d61e833
18 changed files with 1205 additions and 1182 deletions
+6
View File
@@ -18,6 +18,12 @@ if (urlMaybe && URL.canParse(urlMaybe)) {
}
let entryPoints: {sPath: string; newPath: string}[] = [];
async function bundleFiles() {
const filter = new Set<string>();
entryPoints = entryPoints.filter((_) => {
if (filter.has(_.sPath)) return false;
filter.add(_.sPath);
return true;
});
let mod = await swc.bundle(
entryPoints.map(({sPath}) => {
return {
+2 -1
View File
@@ -1,6 +1,7 @@
<!doctype html>
<html lang="en">
<head>
<meta name="404-page" id="404-page" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>It seems you're lost</title>
@@ -49,6 +50,6 @@
</div>
</div>
</div>
<script src="/404.js" type="module"></script>
<script src="/index.js" type="module"></script>
</body>
</html>
+30 -29
View File
@@ -1,37 +1,38 @@
import {I18n} from "./i18n";
import {setTheme, SW} from "./utils/utils";
if (document.getElementById("404-page")) {
await setTheme();
await I18n.done;
I18n.translatePage();
await setTheme();
await I18n.done;
I18n.translatePage();
const easterEvents = [
() => {
window.open("https://youtube.com/watch?v=dQw4w9WgXcQ");
},
() => {
window.open("https://youtube.com/watch?v=fC7oUOUEEi4");
},
() => {
alert(I18n[404].whatelse());
},
];
const easterEvents = [
() => {
window.open("https://youtube.com/watch?v=dQw4w9WgXcQ");
},
() => {
window.open("https://youtube.com/watch?v=fC7oUOUEEi4");
},
() => {
alert(I18n[404].whatelse());
},
];
const where = document.getElementById("whereever");
if (where) {
where.onclick = () => {
const event = easterEvents[Math.floor(Math.random() * easterEvents.length)];
event();
};
}
while (true) {
await new Promise((res) => setTimeout(res, 100));
const where = document.getElementById("whereever");
if (where) {
where.onclick = () => {
const event = easterEvents[Math.floor(Math.random() * easterEvents.length)];
event();
};
}
while (true) {
await new Promise((res) => setTimeout(res, 100));
if (SW.worker) {
const valid = await SW.isValid(window.location.href);
if (valid) {
window.location.reload();
if (SW.worker) {
const valid = await SW.isValid(window.location.href);
if (valid) {
window.location.reload();
}
break;
}
break;
}
}
+1 -1
View File
@@ -35,5 +35,5 @@
</p>
<button id="download">Download all sounds</button>
</body>
<script src="/audio/page.js" type="module"></script>
<script src="/index.js" type="module"></script>
</html>
+147 -146
View File
@@ -1,167 +1,167 @@
import {BinWrite} from "../utils/binaryUtils.js";
import {setTheme} from "../utils/utils.js";
import {Play} from "./play.js";
if (window.location.pathname.startsWith("/audio")) {
await setTheme();
const w = new BinWrite(2 ** 12);
w.writeStringNo("jasf");
w.write8(4);
await setTheme();
const w = new BinWrite(2 ** 12);
w.writeStringNo("jasf");
w.write8(4);
w.writeString8("sin");
w.write32Float(0);
w.writeString8("triangle");
w.write32Float(0);
w.writeString8("square");
w.write32Float(0);
w.writeString8("custom");
w.write32Float(150);
//return Math.sin(((t + 2) ** Math.cos(t * 4)) * Math.PI * 2 * freq);
//Math.sin((((t+2)**Math.cos((t*4)))*((Math.PI*2)*f)))
w.write8(4); //sin
w.write8(5); //times
{
w.write8(9); //Power
w.writeString8("sin");
w.write32Float(0);
w.writeString8("triangle");
w.write32Float(0);
w.writeString8("square");
w.write32Float(0);
w.writeString8("custom");
w.write32Float(150);
//return Math.sin(((t + 2) ** Math.cos(t * 4)) * Math.PI * 2 * freq);
//Math.sin((((t+2)**Math.cos((t*4)))*((Math.PI*2)*f)))
w.write8(4); //sin
w.write8(5); //times
{
w.write8(6); //adding
w.write8(9); //Power
{
w.write8(6); //adding
w.write8(1); //t
w.write8(0);
w.write32Float(2); //2
}
w.write8(13); //cos
w.write8(5); // times
w.write8(1); //t
w.write8(0);
w.write32Float(2); //2
w.write32Float(4); //4
}
{
w.write8(5); //times
w.write8(5); //times
w.write8(3); //PI
w.write8(0);
w.write32Float(2); //2
w.write8(2); //freq
}
w.write8(13); //cos
w.write8(5); // times
w.write8(1); //t
w.write8(0);
w.write32Float(4); //4
}
{
w.write8(5); //times
w.write8(5); //times
w.write8(3); //PI
w.write8(0);
w.write32Float(2); //2
w.write8(2); //freq
}
w.write16(5); //5 tracks
w.write16(5); //5 tracks
w.write16(1); //zip
w.write8(4);
w.write32Float(1);
w.write32Float(640);
w.write16(3); //beep
{
w.write8(1);
w.write16(1); //zip
w.write8(4);
w.write32Float(1);
w.write32Float(700);
w.write32Float(50);
w.write32Float(640);
w.write8(0);
w.write32Float(100);
w.write16(3); //beep
{
w.write8(1);
w.write32Float(1);
w.write32Float(700);
w.write32Float(50);
w.write8(1);
w.write32Float(1);
w.write32Float(700);
w.write32Float(50);
}
w.write8(0);
w.write32Float(100);
w.write16(5); //three
{
w.write8(1);
w.write32Float(1);
w.write32Float(800);
w.write32Float(50);
w.write8(1);
w.write32Float(1);
w.write32Float(700);
w.write32Float(50);
}
w.write8(0);
w.write32Float(50);
w.write16(5); //three
{
w.write8(1);
w.write32Float(1);
w.write32Float(800);
w.write32Float(50);
w.write8(1);
w.write32Float(1);
w.write32Float(1000);
w.write32Float(50);
w.write8(0);
w.write32Float(50);
w.write8(0);
w.write32Float(50);
w.write8(1);
w.write32Float(1);
w.write32Float(1000);
w.write32Float(50);
w.write8(1);
w.write32Float(1);
w.write32Float(1300);
w.write32Float(50);
}
w.write8(0);
w.write32Float(50);
w.write16(5); //square
{
w.write8(3);
w.write32Float(1);
w.write32Float(600);
w.write32Float(50);
w.write8(1);
w.write32Float(1);
w.write32Float(1300);
w.write32Float(50);
}
w.write8(0);
w.write32Float(50);
w.write16(5); //square
{
w.write8(3);
w.write32Float(1);
w.write32Float(600);
w.write32Float(50);
w.write8(3);
w.write32Float(1);
w.write32Float(800);
w.write32Float(50);
w.write8(0);
w.write32Float(50);
w.write8(0);
w.write32Float(50);
w.write8(3);
w.write32Float(1);
w.write32Float(800);
w.write32Float(50);
w.write8(3);
w.write32Float(1);
w.write32Float(1000);
w.write32Float(50);
}
w.write16(5); //three
{
w.write8(1);
w.write32Float(1);
w.write32Float(600);
w.write32Float(75);
w.write8(0);
w.write32Float(50);
w.write8(0);
w.write32Float(75);
w.write8(3);
w.write32Float(1);
w.write32Float(1000);
w.write32Float(50);
}
w.write16(5); //three
{
w.write8(1);
w.write32Float(1);
w.write32Float(600);
w.write32Float(75);
w.write8(1);
w.write32Float(1);
w.write32Float(800);
w.write32Float(75);
w.write8(0);
w.write32Float(75);
w.write8(0);
w.write32Float(75);
w.write8(1);
w.write32Float(1);
w.write32Float(800);
w.write32Float(75);
w.write8(1);
w.write32Float(1);
w.write32Float(1000);
w.write32Float(50);
}
w.write8(0);
w.write32Float(75);
w.write16(5); //5 audio
w.write8(1);
w.write32Float(1);
w.write32Float(1000);
w.write32Float(50);
}
w.writeString8("zip");
w.write16(1);
w.write16(1);
w.write16(5); //5 audio
w.writeString8("beep");
w.write16(1);
w.write16(2);
w.writeString8("zip");
w.write16(1);
w.write16(1);
w.writeString8("three");
w.write16(1);
w.write16(3);
w.writeString8("beep");
w.write16(1);
w.write16(2);
w.writeString8("square");
w.write16(1);
w.write16(4);
w.writeString8("three");
w.write16(1);
w.write16(3);
w.writeString8("join");
w.write16(1);
w.write16(5);
const buff = w.getBuffer();
const play = new Play(buff);
/*
w.writeString8("square");
w.write16(1);
w.write16(4);
w.writeString8("join");
w.write16(1);
w.write16(5);
const buff = w.getBuffer();
const play = new Play(buff);
/*
const zip=play.audios.get("square");
if(zip){
setInterval(()=>{
@@ -171,21 +171,22 @@ if(zip){
console.log(play.voices[3][0].info.wave)
};
*/
console.log(play, buff);
document.onclick = () => {
play.play("join", 15);
};
const download = document.getElementById("download");
if (download) {
download.onclick = () => {
const blob = new Blob([buff], {type: "binary"});
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = "sounds.jasf";
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(downloadUrl);
console.log(play, buff);
document.onclick = () => {
play.play("join", 15);
};
const download = document.getElementById("download");
if (download) {
download.onclick = () => {
const blob = new Blob([buff], {type: "binary"});
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = "sounds.jasf";
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(downloadUrl);
};
}
}
+186 -184
View File
@@ -1,196 +1,198 @@
import {I18n} from "./i18n.js";
import {makeRegister} from "./register.js";
import {mobile} from "./utils/utils.js";
console.log(mobile);
const serverbox = document.getElementById("instancebox") as HTMLDivElement;
if (window.location.pathname === "/" || window.location.pathname.startsWith("/index")) {
console.log(mobile);
const serverbox = document.getElementById("instancebox") as HTMLDivElement;
(async () => {
await I18n.done;
const box1Items = document.getElementById("box1Items");
I18n.translatePage();
(async () => {
await I18n.done;
const box1Items = document.getElementById("box1Items");
I18n.translatePage();
if (box1Items) {
const items = I18n.htmlPages.box1Items().split("|");
let i = 0;
//@ts-ignore ts is being dumb here
for (const item of box1Items.children) {
(item as HTMLElement).textContent = items[i];
i++;
}
}
})();
const recent = document.getElementById("recentBlog");
if (recent) {
fetch("https://blog.fermi.chat/feed_json_created.json")
.then((_) => _.json())
.then(
(json: {
items: {
url: string;
title: string;
content_html: string;
}[];
}) => {
for (const thing of json.items.slice(0, 5)) {
const a = document.createElement("a");
a.href = thing.url;
a.textContent = thing.title;
recent.append(a);
}
},
);
}
fetch("/instances.json")
.then((_) => _.json())
.then(
async (
json: {
name: string;
description?: string;
descriptionLong?: string;
image?: string;
url?: string;
display?: boolean;
online?: boolean;
uptime: {alltime: number; daytime: number; weektime: number};
urls: {
wellknown: string;
api: string;
cdn: string;
gateway: string;
login?: string;
};
}[],
) => {
await I18n.done;
console.warn(json);
for (const instance of json) {
if (instance.display === false) {
continue;
}
const div = document.createElement("div");
div.classList.add("flexltr", "instance");
if (instance.image) {
const img = document.createElement("img");
img.alt = I18n.home.icon(instance.name);
img.src = instance.image;
div.append(img);
}
const statbox = document.createElement("div");
statbox.classList.add("flexttb", "flexgrow");
{
const textbox = document.createElement("div");
textbox.classList.add("flexttb", "instancetextbox");
const title = document.createElement("h2");
title.innerText = instance.name;
if (instance.online !== undefined) {
const status = document.createElement("span");
status.innerText = instance.online ? "Online" : "Offline";
status.classList.add("instanceStatus");
title.append(status);
}
textbox.append(title);
if (instance.description || instance.descriptionLong) {
const p = document.createElement("p");
if (instance.descriptionLong) {
p.innerText = instance.descriptionLong;
} else if (instance.description) {
p.innerText = instance.description;
}
textbox.append(p);
}
statbox.append(textbox);
}
if (instance.uptime) {
const stats = document.createElement("div");
stats.classList.add("flexltr");
const span = document.createElement("span");
span.innerText = I18n.home.uptimeStats(
Math.round(instance.uptime.alltime * 100) + "",
Math.round(instance.uptime.weektime * 100) + "",
Math.round(instance.uptime.daytime * 100) + "",
);
stats.append(span);
statbox.append(stats);
}
div.append(statbox);
div.onclick = (_) => {
if (instance.online !== false) {
makeRegister(true, instance.name);
} else {
alert(I18n.home.warnOffiline());
}
};
serverbox.append(div);
}
},
);
const slides = document.getElementById("ScreenshotSlides");
if (slides) {
const images = Array.from(slides.getElementsByTagName("img"));
const left = slides.getElementsByClassName("leftArrow").item(0) as HTMLElement;
const right = slides.getElementsByClassName("rightArrow").item(0) as HTMLElement;
let index = 0;
let timeout: NodeJS.Timeout | undefined = setTimeout(() => {});
function slideShow() {
let cleared = false;
if (timeout !== undefined) {
cleared = true;
clearTimeout(timeout);
}
let i = 0;
for (const img of images) {
if (i !== index) {
img.classList.add("hidden");
} else {
img.classList.remove("hidden");
}
i++;
}
const count = document.getElementById("slideCount");
if (count) {
if (count.children.length !== images.length) {
count.innerHTML = "";
for (let i = 0; i < images.length; i++) {
const dot = document.createElement("span");
const outer = document.createElement("div");
outer.onclick = () => {
index = i;
slideShow();
};
outer.append(dot);
count.append(outer);
}
}
if (box1Items) {
const items = I18n.htmlPages.box1Items().split("|");
let i = 0;
for (const child of Array.from(count.children)) {
if (i === index) {
child.classList.add("selected");
} else {
child.classList.remove("selected");
}
//@ts-ignore ts is being dumb here
for (const item of box1Items.children) {
(item as HTMLElement).textContent = items[i];
i++;
}
}
timeout = setTimeout(
() => {
index = (index + 1) % images.length;
timeout = undefined;
slideShow();
},
cleared ? 15000 : 30000,
);
})();
const recent = document.getElementById("recentBlog");
if (recent) {
fetch("https://blog.fermi.chat/feed_json_created.json")
.then((_) => _.json())
.then(
(json: {
items: {
url: string;
title: string;
content_html: string;
}[];
}) => {
for (const thing of json.items.slice(0, 5)) {
const a = document.createElement("a");
a.href = thing.url;
a.textContent = thing.title;
recent.append(a);
}
},
);
}
slideShow();
left.onclick = () => {
index = (index - 1 + images.length) % images.length;
fetch("/instances.json")
.then((_) => _.json())
.then(
async (
json: {
name: string;
description?: string;
descriptionLong?: string;
image?: string;
url?: string;
display?: boolean;
online?: boolean;
uptime: {alltime: number; daytime: number; weektime: number};
urls: {
wellknown: string;
api: string;
cdn: string;
gateway: string;
login?: string;
};
}[],
) => {
await I18n.done;
console.warn(json);
for (const instance of json) {
if (instance.display === false) {
continue;
}
const div = document.createElement("div");
div.classList.add("flexltr", "instance");
if (instance.image) {
const img = document.createElement("img");
img.alt = I18n.home.icon(instance.name);
img.src = instance.image;
div.append(img);
}
const statbox = document.createElement("div");
statbox.classList.add("flexttb", "flexgrow");
{
const textbox = document.createElement("div");
textbox.classList.add("flexttb", "instancetextbox");
const title = document.createElement("h2");
title.innerText = instance.name;
if (instance.online !== undefined) {
const status = document.createElement("span");
status.innerText = instance.online ? "Online" : "Offline";
status.classList.add("instanceStatus");
title.append(status);
}
textbox.append(title);
if (instance.description || instance.descriptionLong) {
const p = document.createElement("p");
if (instance.descriptionLong) {
p.innerText = instance.descriptionLong;
} else if (instance.description) {
p.innerText = instance.description;
}
textbox.append(p);
}
statbox.append(textbox);
}
if (instance.uptime) {
const stats = document.createElement("div");
stats.classList.add("flexltr");
const span = document.createElement("span");
span.innerText = I18n.home.uptimeStats(
Math.round(instance.uptime.alltime * 100) + "",
Math.round(instance.uptime.weektime * 100) + "",
Math.round(instance.uptime.daytime * 100) + "",
);
stats.append(span);
statbox.append(stats);
}
div.append(statbox);
div.onclick = (_) => {
if (instance.online !== false) {
makeRegister(true, instance.name);
} else {
alert(I18n.home.warnOffiline());
}
};
serverbox.append(div);
}
},
);
const slides = document.getElementById("ScreenshotSlides");
if (slides) {
const images = Array.from(slides.getElementsByTagName("img"));
const left = slides.getElementsByClassName("leftArrow").item(0) as HTMLElement;
const right = slides.getElementsByClassName("rightArrow").item(0) as HTMLElement;
let index = 0;
let timeout: NodeJS.Timeout | undefined = setTimeout(() => {});
function slideShow() {
let cleared = false;
if (timeout !== undefined) {
cleared = true;
clearTimeout(timeout);
}
let i = 0;
for (const img of images) {
if (i !== index) {
img.classList.add("hidden");
} else {
img.classList.remove("hidden");
}
i++;
}
const count = document.getElementById("slideCount");
if (count) {
if (count.children.length !== images.length) {
count.innerHTML = "";
for (let i = 0; i < images.length; i++) {
const dot = document.createElement("span");
const outer = document.createElement("div");
outer.onclick = () => {
index = i;
slideShow();
};
outer.append(dot);
count.append(outer);
}
}
let i = 0;
for (const child of Array.from(count.children)) {
if (i === index) {
child.classList.add("selected");
} else {
child.classList.remove("selected");
}
i++;
}
}
timeout = setTimeout(
() => {
index = (index + 1) % images.length;
timeout = undefined;
slideShow();
},
cleared ? 15000 : 30000,
);
}
slideShow();
};
right.onclick = () => {
index = (index + 1) % images.length;
slideShow();
};
left.onclick = () => {
index = (index - 1 + images.length) % images.length;
slideShow();
};
right.onclick = () => {
index = (index + 1) % images.length;
slideShow();
};
}
}
+1 -1
View File
@@ -105,5 +105,5 @@
</div>
</div>
</body>
<script src="/home.js" type="module"></script>
<script src="/index.js" type="module"></script>
</html>
+411 -401
View File
@@ -9,428 +9,438 @@ import {I18n} from "./i18n.js";
import "./utils/pollyfills.js";
import {makeLogin} from "./login.js";
import {Hover} from "./hover.js";
import "./templatePage.js";
import "./more.js";
import "./recover.js";
import "./home.js";
import "./invite.js";
import "./oauth2/auth.js";
import "./audio/page.js";
import "./404.js";
if (window.location.pathname === "/app") {
window.location.pathname = "/channels/@me";
}
let templateID = new URLSearchParams(window.location.search).get("templateID");
await I18n.done;
Localuser.loadFont();
I18n.translatePage();
const userInfoElement = document.getElementById("userinfo") as HTMLDivElement;
userInfoElement.addEventListener("click", (event) => {
event.stopImmediatePropagation();
const rect = userInfoElement.getBoundingClientRect();
Localuser.userMenu.makemenu(rect.x, rect.top - 10 - window.innerHeight, thisUser);
});
const switchAccountsElement = document.getElementById("switchaccounts") as HTMLDivElement;
switchAccountsElement.addEventListener("click", async (event) => {
event.stopImmediatePropagation();
Localuser.showAccountSwitcher(thisUser);
});
let thisUser: Localuser;
function regSwap(l: Localuser) {
l.onswap = (l) => {
thisUser = l;
regSwap(l);
};
l.fileExtange = (img, html) => {
const blobArr: Blob[] = [];
const htmlArr = imagesHtml;
let i = 0;
for (const file of images) {
const img = imagesHtml.get(file);
if (!img) continue;
if (pasteImageElement.contains(img)) {
pasteImageElement.removeChild(img);
blobArr.push(images[i]);
} else {
i++;
}
}
images = img;
imagesHtml = html;
for (const file of images) {
const img = imagesHtml.get(file);
if (!img) throw new Error("Image without HTML, exiting");
pasteImageElement.append(img);
}
return [blobArr, htmlArr];
};
}
const loaddesc = document.getElementById("load-desc") as HTMLSpanElement;
try {
const current = sessionStorage.getItem("currentuser") || Localuser.users.currentuser;
if (!Localuser.users.users[current]) {
thisUser = new Localuser(await new Promise<Specialuser>((res) => makeLogin(true, "", res)));
} else {
thisUser = new Localuser(Localuser.users.users[current]);
}
regSwap(thisUser);
thisUser.initwebsocket().then(() => {
thisUser.loaduser();
thisUser.init();
const loading = document.getElementById("loading") as HTMLDivElement;
loading.classList.add("doneloading");
loading.classList.remove("loading");
loaddesc.textContent = I18n.loaded();
console.log("done loading");
if (templateID) {
thisUser.passTemplateID(templateID);
}
});
} catch (e) {
console.error(e);
loaddesc.textContent = I18n.accountNotStart();
thisUser = new Localuser(-1);
}
//TODO move this to the channel/guild class, this is a weird spot
const menu = new Contextmenu<void, void>("create rightclick");
menu.addButton(
I18n.channel.createChannel(),
() => {
if (thisUser.lookingguild) {
thisUser.lookingguild.createchannels();
}
},
{visible: () => thisUser.isAdmin()},
);
menu.addButton(
I18n.channel.createCatagory(),
() => {
if (thisUser.lookingguild) {
thisUser.lookingguild.createcategory();
}
},
{visible: () => thisUser.isAdmin()},
);
const channelw = document.getElementById("channelw");
console.log(channelw);
if (channelw)
channelw.addEventListener("keypress", (e) => {
if (e.ctrlKey || e.altKey || e.metaKey || e.metaKey) return;
let owner = e.target as HTMLElement;
while (owner !== channelw) {
if (owner.tagName === "input" || owner.contentEditable !== "false") {
return;
}
owner = owner.parentElement as HTMLElement;
}
typebox.markdown.boxupdate(Infinity);
});
menu.bindContextmenu(document.getElementById("channels") as HTMLDivElement);
const pasteImageElement = document.getElementById("pasteimage") as HTMLDivElement;
let replyingTo: Message | null = null;
window.addEventListener("popstate", (e) => {
if (e.state instanceof Object) {
thisUser.goToState(e.state);
}
//console.log(e.state,"state:3")
});
let nonceMap = new Map<string, string>();
//@ts-expect-error unused right now, not needed
function getNonce(id: string) {
const nonce = nonceMap.get(id) || Math.floor(Math.random() * 1000000000) + "";
nonceMap.set(id, nonce);
return nonce;
}
async function handleEnter(event: KeyboardEvent): Promise<void> {
if (event.key === "Escape") {
while (images.length) {
const elm = imagesHtml.get(images.pop() as Blob) as HTMLElement;
if (pasteImageElement.contains(elm)) pasteImageElement.removeChild(elm);
}
if (thisUser.channelfocus) {
thisUser.channelfocus?.replyingto?.div?.classList.remove("replying");
thisUser.channelfocus.replyingto = null;
thisUser.channelfocus.makereplybox();
}
}
if (thisUser.handleKeyUp(event)) {
return;
}
const channel = thisUser.channelfocus;
if (!channel) return;
const content = MarkDown.gatherBoxText(typebox);
if (content === "" && event.key === "ArrowUp") {
channel.editLast();
return;
}
channel.typingstart();
if (event.key === "Enter" && !event.shiftKey) {
if (!channel.canMessageRightNow()) return;
if (channel.curCommand) {
channel.submitCommand();
return;
}
event.preventDefault();
replyingTo = thisUser.channelfocus ? thisUser.channelfocus.replyingto : null;
if (replyingTo?.div) {
replyingTo.div.classList.remove("replying");
}
if (thisUser.channelfocus) {
thisUser.channelfocus.replyingto = null;
thisUser.channelfocus.makereplybox();
}
const attachments = images.filter((_) => document.contains(imagesHtml.get(_) || null));
while (images.length) {
const elm = imagesHtml.get(images.pop() as Blob) as HTMLElement;
if (pasteImageElement.contains(elm)) pasteImageElement.removeChild(elm);
}
typebox.innerHTML = "";
typebox.markdown.txt = [];
try {
await new Promise<void>((mres, rej) =>
channel.sendMessage(
content,
{
attachments,
embeds: [], // Add an empty array for the embeds property
replyingto: replyingTo,
sticker_ids: [],
//nonce: getNonce(channel.id),
},
(res) => {
if (res === "Ok") {
mres();
} else {
rej();
}
},
),
);
} catch {
images = attachments;
for (const file of images) {
const img = imagesHtml.get(file);
if (!img) continue;
pasteImageElement.append(img);
}
channel.replyingto = replyingTo;
channel.makereplybox();
typebox.textContent = content;
typebox.markdown.txt = content.split("");
typebox.markdown.boxupdate(Infinity);
}
nonceMap.delete(channel.id);
}
}
export interface CustomHTMLDivElement extends HTMLDivElement {
markdown: MarkDown;
}
if (window.location.pathname.startsWith("/channels")) {
let templateID = new URLSearchParams(window.location.search).get("templateID");
await I18n.done;
Localuser.loadFont();
const typebox = document.getElementById("typebox") as CustomHTMLDivElement;
const markdown = new MarkDown("", thisUser);
typebox.markdown = markdown;
typebox.addEventListener("keyup", handleEnter);
typebox.addEventListener("keydown", (event) => {
thisUser.keydown(event);
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
I18n.translatePage();
const userInfoElement = document.getElementById("userinfo") as HTMLDivElement;
userInfoElement.addEventListener("click", (event) => {
event.stopImmediatePropagation();
}
});
markdown.giveBox(typebox);
{
const searchBox = document.getElementById("searchBox") as CustomHTMLDivElement;
const markdown = new MarkDown("", thisUser);
searchBox.markdown = markdown;
const searchX = document.getElementById("searchX") as HTMLElement;
searchBox.addEventListener("keydown", (event) => {
if (event.key === "Enter") {
event.preventDefault();
thisUser.mSearch(markdown.rawString);
}
const rect = userInfoElement.getBoundingClientRect();
Localuser.userMenu.makemenu(rect.x, rect.top - 10 - window.innerHeight, thisUser);
});
searchBox.addEventListener("keyup", () => {
if (searchBox.textContent === "") {
setTimeout(() => (searchBox.innerHTML = ""), 0);
searchX.classList.add("svg-search");
searchX.classList.remove("svg-plainx");
searchBox.parentElement!.classList.remove("searching");
const switchAccountsElement = document.getElementById("switchaccounts") as HTMLDivElement;
switchAccountsElement.addEventListener("click", async (event) => {
event.stopImmediatePropagation();
Localuser.showAccountSwitcher(thisUser);
});
let thisUser: Localuser;
function regSwap(l: Localuser) {
l.onswap = (l) => {
thisUser = l;
regSwap(l);
};
l.fileExtange = (img, html) => {
const blobArr: Blob[] = [];
const htmlArr = imagesHtml;
let i = 0;
for (const file of images) {
const img = imagesHtml.get(file);
if (!img) continue;
if (pasteImageElement.contains(img)) {
pasteImageElement.removeChild(img);
blobArr.push(images[i]);
} else {
i++;
}
}
images = img;
imagesHtml = html;
for (const file of images) {
const img = imagesHtml.get(file);
if (!img) throw new Error("Image without HTML, exiting");
pasteImageElement.append(img);
}
return [blobArr, htmlArr];
};
}
const loaddesc = document.getElementById("load-desc") as HTMLSpanElement;
try {
const current = sessionStorage.getItem("currentuser") || Localuser.users.currentuser;
if (!Localuser.users.users[current]) {
thisUser = new Localuser(await new Promise<Specialuser>((res) => makeLogin(true, "", res)));
} else {
searchX.classList.remove("svg-search");
searchX.classList.add("svg-plainx");
searchBox.parentElement!.classList.add("searching");
thisUser = new Localuser(Localuser.users.users[current]);
}
});
const sideContainDiv = document.getElementById("sideContainDiv") as HTMLElement;
searchBox.onclick = () => {
sideContainDiv.classList.remove("hideSearchDiv");
};
searchX.onclick = () => {
if (searchX.classList.contains("svg-plainx")) {
markdown.txt = [];
searchBox.innerHTML = "";
searchX.classList.add("svg-search");
searchBox.parentElement!.classList.remove("searching");
searchX.classList.remove("svg-plainx");
thisUser.mSearch("");
} else {
searchBox.parentElement!.classList.add("searching");
regSwap(thisUser);
thisUser.initwebsocket().then(() => {
thisUser.loaduser();
thisUser.init();
const loading = document.getElementById("loading") as HTMLDivElement;
loading.classList.add("doneloading");
loading.classList.remove("loading");
loaddesc.textContent = I18n.loaded();
console.log("done loading");
if (templateID) {
thisUser.passTemplateID(templateID);
}
});
} catch (e) {
console.error(e);
loaddesc.textContent = I18n.accountNotStart();
thisUser = new Localuser(-1);
}
//TODO move this to the channel/guild class, this is a weird spot
const menu = new Contextmenu<void, void>("create rightclick");
menu.addButton(
I18n.channel.createChannel(),
() => {
if (thisUser.lookingguild) {
thisUser.lookingguild.createchannels();
}
},
{visible: () => thisUser.isAdmin()},
);
menu.addButton(
I18n.channel.createCatagory(),
() => {
if (thisUser.lookingguild) {
thisUser.lookingguild.createcategory();
}
},
{visible: () => thisUser.isAdmin()},
);
const channelw = document.getElementById("channelw");
console.log(channelw);
if (channelw)
channelw.addEventListener("keypress", (e) => {
if (e.ctrlKey || e.altKey || e.metaKey || e.metaKey) return;
let owner = e.target as HTMLElement;
while (owner !== channelw) {
if (owner.tagName === "input" || owner.contentEditable !== "false") {
return;
}
owner = owner.parentElement as HTMLElement;
}
typebox.markdown.boxupdate(Infinity);
});
menu.bindContextmenu(document.getElementById("channels") as HTMLDivElement);
const pasteImageElement = document.getElementById("pasteimage") as HTMLDivElement;
let replyingTo: Message | null = null;
window.addEventListener("popstate", (e) => {
if (e.state instanceof Object) {
thisUser.goToState(e.state);
}
};
markdown.giveBox(searchBox);
markdown.setCustomBox((e) => {
const span = document.createElement("span");
span.textContent = e.replace("\n", "");
return span;
//console.log(e.state,"state:3")
});
}
let images: Blob[] = [];
let imagesHtml = new WeakMap<Blob, HTMLElement>();
document.addEventListener("paste", async (e: ClipboardEvent) => {
if (!thisUser.channelfocus) return;
if (!e.clipboardData) return;
for (const file of Array.from(e.clipboardData.files)) {
const fileInstance = File.initFromBlob(file);
e.preventDefault();
const html = fileInstance.upHTML(images, imagesHtml, file);
pasteImageElement.appendChild(html);
images.push(file);
imagesHtml.set(file, html);
let nonceMap = new Map<string, string>();
//@ts-expect-error unused right now, not needed
function getNonce(id: string) {
const nonce = nonceMap.get(id) || Math.floor(Math.random() * 1000000000) + "";
nonceMap.set(id, nonce);
return nonce;
}
});
await setTheme();
function userSettings(): void {
thisUser.showusersettings();
}
(document.getElementById("settings") as HTMLImageElement).onclick = userSettings;
const memberListToggle = document.getElementById("memberlisttoggle") as HTMLInputElement;
memberListToggle.checked = !localStorage.getItem("memberNotChecked");
memberListToggle.onchange = () => {
if (!memberListToggle.checked) {
localStorage.setItem("memberNotChecked", "true");
} else {
localStorage.removeItem("memberNotChecked");
}
};
if (mobile) {
const channelWrapper = document.getElementById("channelw") as HTMLDivElement;
channelWrapper.onclick = () => {
const toggle = document.getElementById("maintoggle") as HTMLInputElement;
toggle.checked = true;
};
memberListToggle.checked = false;
}
let dragendtimeout = setTimeout(() => {});
document.addEventListener("dragover", (e) => {
clearTimeout(dragendtimeout);
const data = e.dataTransfer;
const bg = document.getElementById("gimmefile") as HTMLDivElement;
if (data) {
const isfile = data.types.includes("Files") || data.types.includes("application/x-moz-file");
if (!isfile) {
bg.hidden = true;
async function handleEnter(event: KeyboardEvent): Promise<void> {
if (event.key === "Escape") {
while (images.length) {
const elm = imagesHtml.get(images.pop() as Blob) as HTMLElement;
if (pasteImageElement.contains(elm)) pasteImageElement.removeChild(elm);
}
if (thisUser.channelfocus) {
thisUser.channelfocus?.replyingto?.div?.classList.remove("replying");
thisUser.channelfocus.replyingto = null;
thisUser.channelfocus.makereplybox();
}
}
if (thisUser.handleKeyUp(event)) {
return;
}
e.preventDefault();
bg.hidden = false;
//console.log(data.types,data)
} else {
bg.hidden = true;
const channel = thisUser.channelfocus;
if (!channel) return;
const content = MarkDown.gatherBoxText(typebox);
if (content === "" && event.key === "ArrowUp") {
channel.editLast();
return;
}
channel.typingstart();
if (event.key === "Enter" && !event.shiftKey) {
if (!channel.canMessageRightNow()) return;
if (channel.curCommand) {
channel.submitCommand();
return;
}
event.preventDefault();
replyingTo = thisUser.channelfocus ? thisUser.channelfocus.replyingto : null;
if (replyingTo?.div) {
replyingTo.div.classList.remove("replying");
}
if (thisUser.channelfocus) {
thisUser.channelfocus.replyingto = null;
thisUser.channelfocus.makereplybox();
}
const attachments = images.filter((_) => document.contains(imagesHtml.get(_) || null));
while (images.length) {
const elm = imagesHtml.get(images.pop() as Blob) as HTMLElement;
if (pasteImageElement.contains(elm)) pasteImageElement.removeChild(elm);
}
typebox.innerHTML = "";
typebox.markdown.txt = [];
try {
await new Promise<void>((mres, rej) =>
channel.sendMessage(
content,
{
attachments,
embeds: [], // Add an empty array for the embeds property
replyingto: replyingTo,
sticker_ids: [],
//nonce: getNonce(channel.id),
},
(res) => {
if (res === "Ok") {
mres();
} else {
rej();
}
},
),
);
} catch {
images = attachments;
for (const file of images) {
const img = imagesHtml.get(file);
if (!img) continue;
pasteImageElement.append(img);
}
channel.replyingto = replyingTo;
channel.makereplybox();
typebox.textContent = content;
typebox.markdown.txt = content.split("");
typebox.markdown.boxupdate(Infinity);
}
nonceMap.delete(channel.id);
}
}
});
document.addEventListener("dragleave", (_) => {
dragendtimeout = setTimeout(() => {
const typebox = document.getElementById("typebox") as CustomHTMLDivElement;
const markdown = new MarkDown("", thisUser);
typebox.markdown = markdown;
typebox.addEventListener("keyup", handleEnter);
typebox.addEventListener("keydown", (event) => {
thisUser.keydown(event);
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
event.stopImmediatePropagation();
}
});
markdown.giveBox(typebox);
{
const searchBox = document.getElementById("searchBox") as CustomHTMLDivElement;
const markdown = new MarkDown("", thisUser);
searchBox.markdown = markdown;
const searchX = document.getElementById("searchX") as HTMLElement;
searchBox.addEventListener("keydown", (event) => {
if (event.key === "Enter") {
event.preventDefault();
thisUser.mSearch(markdown.rawString);
}
});
searchBox.addEventListener("keyup", () => {
if (searchBox.textContent === "") {
setTimeout(() => (searchBox.innerHTML = ""), 0);
searchX.classList.add("svg-search");
searchX.classList.remove("svg-plainx");
searchBox.parentElement!.classList.remove("searching");
} else {
searchX.classList.remove("svg-search");
searchX.classList.add("svg-plainx");
searchBox.parentElement!.classList.add("searching");
}
});
const sideContainDiv = document.getElementById("sideContainDiv") as HTMLElement;
searchBox.onclick = () => {
sideContainDiv.classList.remove("hideSearchDiv");
};
searchX.onclick = () => {
if (searchX.classList.contains("svg-plainx")) {
markdown.txt = [];
searchBox.innerHTML = "";
searchX.classList.add("svg-search");
searchBox.parentElement!.classList.remove("searching");
searchX.classList.remove("svg-plainx");
thisUser.mSearch("");
} else {
searchBox.parentElement!.classList.add("searching");
}
};
markdown.giveBox(searchBox);
markdown.setCustomBox((e) => {
const span = document.createElement("span");
span.textContent = e.replace("\n", "");
return span;
});
}
let images: Blob[] = [];
let imagesHtml = new WeakMap<Blob, HTMLElement>();
document.addEventListener("paste", async (e: ClipboardEvent) => {
if (!thisUser.channelfocus) return;
if (!e.clipboardData) return;
for (const file of Array.from(e.clipboardData.files)) {
const fileInstance = File.initFromBlob(file);
e.preventDefault();
const html = fileInstance.upHTML(images, imagesHtml, file);
pasteImageElement.appendChild(html);
images.push(file);
imagesHtml.set(file, html);
}
});
await setTheme();
function userSettings(): void {
thisUser.showusersettings();
}
(document.getElementById("settings") as HTMLImageElement).onclick = userSettings;
const memberListToggle = document.getElementById("memberlisttoggle") as HTMLInputElement;
memberListToggle.checked = !localStorage.getItem("memberNotChecked");
memberListToggle.onchange = () => {
if (!memberListToggle.checked) {
localStorage.setItem("memberNotChecked", "true");
} else {
localStorage.removeItem("memberNotChecked");
}
};
if (mobile) {
const channelWrapper = document.getElementById("channelw") as HTMLDivElement;
channelWrapper.onclick = () => {
const toggle = document.getElementById("maintoggle") as HTMLInputElement;
toggle.checked = true;
};
memberListToggle.checked = false;
}
let dragendtimeout = setTimeout(() => {});
document.addEventListener("dragover", (e) => {
clearTimeout(dragendtimeout);
const data = e.dataTransfer;
const bg = document.getElementById("gimmefile") as HTMLDivElement;
if (data) {
const isfile = data.types.includes("Files") || data.types.includes("application/x-moz-file");
if (!isfile) {
bg.hidden = true;
return;
}
e.preventDefault();
bg.hidden = false;
//console.log(data.types,data)
} else {
bg.hidden = true;
}
});
document.addEventListener("dragleave", (_) => {
dragendtimeout = setTimeout(() => {
const bg = document.getElementById("gimmefile") as HTMLDivElement;
bg.hidden = true;
}, 1000);
});
document.addEventListener("dragenter", (e) => {
e.preventDefault();
});
document.addEventListener("drop", (e) => {
const data = e.dataTransfer;
const bg = document.getElementById("gimmefile") as HTMLDivElement;
bg.hidden = true;
}, 1000);
});
document.addEventListener("dragenter", (e) => {
e.preventDefault();
});
document.addEventListener("drop", (e) => {
const data = e.dataTransfer;
const bg = document.getElementById("gimmefile") as HTMLDivElement;
bg.hidden = true;
if (!thisUser.channelfocus) {
e.preventDefault();
return;
}
if (data) {
const isfile = data.types.includes("Files") || data.types.includes("application/x-moz-file");
if (isfile) {
if (!thisUser.channelfocus) {
e.preventDefault();
console.log(data.files);
for (const file of Array.from(data.files)) {
const fileInstance = File.initFromBlob(file);
const html = fileInstance.upHTML(images, imagesHtml, file);
pasteImageElement.appendChild(html);
images.push(file);
imagesHtml.set(file, html);
return;
}
if (data) {
const isfile = data.types.includes("Files") || data.types.includes("application/x-moz-file");
if (isfile) {
e.preventDefault();
console.log(data.files);
for (const file of Array.from(data.files)) {
const fileInstance = File.initFromBlob(file);
const html = fileInstance.upHTML(images, imagesHtml, file);
pasteImageElement.appendChild(html);
images.push(file);
imagesHtml.set(file, html);
}
}
}
});
const pinnedM = document.getElementById("pinnedM") as HTMLElement;
pinnedM.onclick = (e) => {
thisUser.pinnedClick(pinnedM.getBoundingClientRect());
e.preventDefault();
e.stopImmediatePropagation();
};
(document.getElementById("upload") as HTMLElement).onclick = () => {
const input = document.createElement("input");
input.type = "file";
input.click();
input.multiple = true;
console.log("clicked");
if (!thisUser.channelfocus) return;
input.onchange = () => {
if (input.files) {
for (const file of Array.from(input.files)) {
const fileInstance = File.initFromBlob(file);
const html = fileInstance.upHTML(images, imagesHtml, file);
pasteImageElement.appendChild(html);
images.push(file);
imagesHtml.set(file, html);
}
}
};
};
const emojiTB = document.getElementById("emojiTB") as HTMLElement;
emojiTB.onmousedown = (e) => e.stopImmediatePropagation();
emojiTB.onclick = (e) => {
e.preventDefault();
e.stopImmediatePropagation();
thisUser.TBEmojiMenu(emojiTB.getBoundingClientRect());
};
const gifTB = document.getElementById("gifTB") as HTMLElement;
gifTB.onmousedown = (e) => e.stopImmediatePropagation();
gifTB.onclick = (e) => {
e.preventDefault();
e.stopImmediatePropagation();
thisUser.makeGifBox(gifTB.getBoundingClientRect());
};
const stickerTB = document.getElementById("stickerTB") as HTMLElement;
stickerTB.onmousedown = (e) => e.stopImmediatePropagation();
stickerTB.onclick = (e) => {
e.preventDefault();
e.stopImmediatePropagation();
thisUser.makeStickerBox(stickerTB.getBoundingClientRect());
};
const updateIcon = document.getElementById("updateIcon");
if (updateIcon) {
new Hover(() => updateIcon.textContent || "").addEvent(updateIcon);
updateIcon.onclick = () => {
window.location.reload();
};
}
});
const pinnedM = document.getElementById("pinnedM") as HTMLElement;
pinnedM.onclick = (e) => {
thisUser.pinnedClick(pinnedM.getBoundingClientRect());
e.preventDefault();
e.stopImmediatePropagation();
};
(document.getElementById("upload") as HTMLElement).onclick = () => {
const input = document.createElement("input");
input.type = "file";
input.click();
input.multiple = true;
console.log("clicked");
if (!thisUser.channelfocus) return;
input.onchange = () => {
if (input.files) {
for (const file of Array.from(input.files)) {
const fileInstance = File.initFromBlob(file);
const html = fileInstance.upHTML(images, imagesHtml, file);
pasteImageElement.appendChild(html);
images.push(file);
imagesHtml.set(file, html);
}
}
};
};
const emojiTB = document.getElementById("emojiTB") as HTMLElement;
emojiTB.onmousedown = (e) => e.stopImmediatePropagation();
emojiTB.onclick = (e) => {
e.preventDefault();
e.stopImmediatePropagation();
thisUser.TBEmojiMenu(emojiTB.getBoundingClientRect());
};
const gifTB = document.getElementById("gifTB") as HTMLElement;
gifTB.onmousedown = (e) => e.stopImmediatePropagation();
gifTB.onclick = (e) => {
e.preventDefault();
e.stopImmediatePropagation();
thisUser.makeGifBox(gifTB.getBoundingClientRect());
};
const stickerTB = document.getElementById("stickerTB") as HTMLElement;
stickerTB.onmousedown = (e) => e.stopImmediatePropagation();
stickerTB.onclick = (e) => {
e.preventDefault();
e.stopImmediatePropagation();
thisUser.makeStickerBox(stickerTB.getBoundingClientRect());
};
const updateIcon = document.getElementById("updateIcon");
if (updateIcon) {
new Hover(() => updateIcon.textContent || "").addEvent(updateIcon);
updateIcon.onclick = () => {
window.location.reload();
};
}
+1 -1
View File
@@ -32,6 +32,6 @@
<button id="AcceptInvite">Accept Invite</button>
</div>
</div>
<script src="/invite.js" type="module"></script>
<script src="/index.js" type="module"></script>
</body>
</html>
+114 -114
View File
@@ -2,126 +2,126 @@ import {I18n} from "./i18n.js";
import {AccountSwitcher} from "./utils/switcher.js";
import {createImg, getapiurls} from "./utils/utils.js";
import {getBulkUsers, Specialuser} from "./utils/utils.js";
if (window.location.pathname.startsWith("/invite"))
(async () => {
const users = getBulkUsers();
const well = new URLSearchParams(window.location.search).get("instance");
const joinable: Specialuser[] = [];
(async () => {
const users = getBulkUsers();
const well = new URLSearchParams(window.location.search).get("instance");
const joinable: Specialuser[] = [];
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (well && user.serverurls.wellknown.includes(well)) {
joinable.push(user);
}
console.log(user);
}
}
let urls: {api: string; cdn: string} | undefined;
if (!joinable.length && well) {
const out = await getapiurls(well);
if (out) {
urls = out;
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (user.serverurls.api.includes(out.api)) {
joinable.push(user);
}
console.log(user);
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (well && user.serverurls.wellknown.includes(well)) {
joinable.push(user);
}
console.log(user);
}
}
let urls: {api: string; cdn: string} | undefined;
if (!joinable.length && well) {
const out = await getapiurls(well);
if (out) {
urls = out;
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (user.serverurls.api.includes(out.api)) {
joinable.push(user);
}
console.log(user);
}
}
} else {
throw new Error("Someone needs to handle the case where the servers don't exist");
}
} else {
throw new Error("Someone needs to handle the case where the servers don't exist");
urls = joinable[0].serverurls;
}
await I18n.done;
if (!joinable.length) {
document.getElementById("AcceptInvite")!.textContent = I18n.htmlPages.noAccount();
}
} else {
urls = joinable[0].serverurls;
}
await I18n.done;
if (!joinable.length) {
document.getElementById("AcceptInvite")!.textContent = I18n.htmlPages.noAccount();
}
const code = window.location.pathname.split("/")[2];
let guildinfo: any;
const code = window.location.pathname.split("/")[2];
let guildinfo: any;
fetch(`${urls!.api}/invites/${code}`, {
method: "GET",
})
.then((response) => response.json())
.then((json) => {
if (json.code === 404) {
document.getElementById("AcceptInvite")?.remove();
document.getElementById("invitename")!.textContent = I18n.invite.notFound();
document.getElementById("invitedescription")!.textContent = "";
return;
}
const guildjson = json.guild;
guildinfo = guildjson;
document.getElementById("invitename")!.textContent = guildjson.name;
document.getElementById("invitedescription")!.textContent = I18n.invite.longInvitedBy(
json.inviter.username,
guildjson.name,
);
if (guildjson.discovery_splash) {
const img = createImg(
`${urls!.cdn}/discovery-splashes/${guildjson.id}/${guildjson.discovery_splash}.png`,
);
img.classList.add("inviteBG");
document.body.prepend(img);
document.getElementById("invitebody")?.classList.add("moreShadow");
}
if (guildjson.banner) {
const img = createImg(`${urls!.cdn}/banners/${guildjson.id}/${guildjson.banner}.png`);
document.getElementById("inviteBanner")!.append(img);
}
if (guildjson.icon) {
const img = document.createElement("img");
img.src = `${urls!.cdn}/icons/${guildjson.id}/${guildjson.icon}.png`;
img.classList.add("inviteGuild");
document.getElementById("inviteimg")!.append(img);
} else {
const txt = guildjson.name
.replace(/'s /g, " ")
.replace(/\w+/g, (word: any[]) => word[0])
.replace(/\s/g, "");
const div = document.createElement("div");
div.textContent = txt;
div.classList.add("inviteGuild");
document.getElementById("inviteimg")!.append(div);
}
});
async function showAccounts() {
console.log("showing!");
const user = await new AccountSwitcher(
(user) => {
return !!(well && user.serverurls.wellknown.includes(well));
},
{
loginText: () => I18n.login.login(),
createOpt: true,
loginurl: "/login?" + new URLSearchParams([["goback", window.location.href]]),
registerurl: "/register?" + new URLSearchParams([["goback", window.location.href]]),
},
).show();
fetch(`${urls!.api}/invites/${code}`, {
method: "POST",
headers: {
Authorization: user.token,
},
}).then(() => {
users.currentuser = user.uid;
sessionStorage.setItem("currentuser", user.uid);
localStorage.setItem("userinfos", JSON.stringify(users));
window.location.href = "/channels/" + guildinfo.id;
});
}
method: "GET",
})
.then((response) => response.json())
.then((json) => {
if (json.code === 404) {
document.getElementById("AcceptInvite")?.remove();
document.getElementById("invitename")!.textContent = I18n.invite.notFound();
document.getElementById("invitedescription")!.textContent = "";
return;
}
const guildjson = json.guild;
guildinfo = guildjson;
document.getElementById("invitename")!.textContent = guildjson.name;
document.getElementById("invitedescription")!.textContent = I18n.invite.longInvitedBy(
json.inviter.username,
guildjson.name,
);
if (guildjson.discovery_splash) {
const img = createImg(
`${urls!.cdn}/discovery-splashes/${guildjson.id}/${guildjson.discovery_splash}.png`,
);
img.classList.add("inviteBG");
document.body.prepend(img);
document.getElementById("invitebody")?.classList.add("moreShadow");
}
if (guildjson.banner) {
const img = createImg(`${urls!.cdn}/banners/${guildjson.id}/${guildjson.banner}.png`);
document.getElementById("inviteBanner")!.append(img);
}
if (guildjson.icon) {
const img = document.createElement("img");
img.src = `${urls!.cdn}/icons/${guildjson.id}/${guildjson.icon}.png`;
img.classList.add("inviteGuild");
document.getElementById("inviteimg")!.append(img);
} else {
const txt = guildjson.name
.replace(/'s /g, " ")
.replace(/\w+/g, (word: any[]) => word[0])
.replace(/\s/g, "");
const div = document.createElement("div");
div.textContent = txt;
div.classList.add("inviteGuild");
document.getElementById("inviteimg")!.append(div);
}
});
document.getElementById("AcceptInvite")!.addEventListener("click", (e) => {
e.stopImmediatePropagation();
showAccounts();
});
})();
async function showAccounts() {
console.log("showing!");
const user = await new AccountSwitcher(
(user) => {
return !!(well && user.serverurls.wellknown.includes(well));
},
{
loginText: () => I18n.login.login(),
createOpt: true,
loginurl: "/login?" + new URLSearchParams([["goback", window.location.href]]),
registerurl: "/register?" + new URLSearchParams([["goback", window.location.href]]),
},
).show();
fetch(`${urls!.api}/invites/${code}`, {
method: "POST",
headers: {
Authorization: user.token,
},
}).then(() => {
users.currentuser = user.uid;
sessionStorage.setItem("currentuser", user.uid);
localStorage.setItem("userinfos", JSON.stringify(users));
window.location.href = "/channels/" + guildinfo.id;
});
}
document.getElementById("AcceptInvite")!.addEventListener("click", (e) => {
e.stopImmediatePropagation();
showAccounts();
});
})();
+1 -1
View File
@@ -22,6 +22,6 @@
</style>
</head>
<body class="no-theme">
<script src="/login.js" type="module"></script>
<script src="/index.js" type="module"></script>
</body>
</html>
+195 -194
View File
@@ -44,209 +44,210 @@ type botjsonfetch = {
};
authorized: boolean;
};
if (window.location.pathname.startsWith("oauth2")) {
const users = getBulkUsers();
const params = new URLSearchParams(window.location.search);
const well = params.get("instance");
const permstr = params.get("permissions");
const joinable: Specialuser[] = [];
const users = getBulkUsers();
const params = new URLSearchParams(window.location.search);
const well = params.get("instance");
const permstr = params.get("permissions");
const joinable: Specialuser[] = [];
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (well && user.serverurls.wellknown.includes(well)) {
joinable.push(user);
}
console.log(user);
}
}
let urls: {api: string; cdn: string} | undefined;
if (!joinable.length && well) {
const out = await getapiurls(well);
if (out) {
urls = out;
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (user.serverurls.api.includes(out.api)) {
joinable.push(user);
}
console.log(user);
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (well && user.serverurls.wellknown.includes(well)) {
joinable.push(user);
}
console.log(user);
}
}
let urls: {api: string; cdn: string} | undefined;
if (!joinable.length && well) {
const out = await getapiurls(well);
if (out) {
urls = out;
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (user.serverurls.api.includes(out.api)) {
joinable.push(user);
}
console.log(user);
}
}
} else {
throw new Error("Someone needs to handle the case where the servers don't exist");
}
} else {
throw new Error("Someone needs to handle the case where the servers don't exist");
urls = joinable[0].serverurls;
}
} else {
urls = joinable[0].serverurls;
}
if (!joinable.length) {
document.getElementById("AcceptInvite")!.textContent = "Create an account to invite the bot";
}
await I18n.done;
function showGuilds(user: Specialuser) {
if (!urls) return;
fetch(urls.api + "/oauth2/authorize/" + window.location.search, {
headers: {
Authorization: user.token,
},
})
.then((_) => _.json())
.then((json: botjsonfetch) => {
const guilds: botjsonfetch["guilds"] = [];
for (const guild of json.guilds) {
const permisions = new Permissions(guild.permissions);
if (permisions.hasPermission("MANAGE_GUILD")) {
guilds.push(guild);
}
}
const dialog = document.createElement("dialog");
dialog.classList.add("flexttb", "accountSwitcher");
const h1 = document.createElement("h1");
dialog.append(h1);
h1.textContent = "Invite to server:";
const select = document.createElement("select");
const selectSpan = document.createElement("span");
selectSpan.classList.add("selectspan");
const selectArrow = document.createElement("span");
selectArrow.classList.add("svgicon", "svg-category", "selectarrow");
for (const guild of guilds) {
const option = document.createElement("option");
option.textContent = guild.name;
option.value = guild.id;
select.append(option);
}
selectSpan.append(select);
selectSpan.append(selectArrow);
dialog.append(selectSpan);
const button = document.createElement("button");
button.textContent = "Invite";
dialog.append(button);
button.onclick = () => {
const id = select.value;
const params2 = new URLSearchParams("");
params2.set("client_id", params.get("client_id") as string);
fetch(urls.api + "/oauth2/authorize?" + params2.toString(), {
method: "POST",
body: JSON.stringify({
authorize: true,
guild_id: id,
permissions: permstr,
}),
headers: {
"Content-type": "application/json; charset=UTF-8",
Authorization: user.token,
},
}).then((req) => {
if (req.ok) {
alert("Bot added successfully");
}
});
};
document.body.append(dialog);
});
}
function showAccounts(): void {
const table = document.createElement("dialog");
for (const user of joinable) {
console.log(user.pfpsrc);
const userinfo = document.createElement("div");
userinfo.classList.add("flexltr", "switchtable");
const pfp = document.createElement("img");
pfp.src = user.pfpsrc;
pfp.classList.add("pfp");
userinfo.append(pfp);
const userDiv = document.createElement("div");
userDiv.classList.add("userinfo");
userDiv.textContent = user.username;
userDiv.append(document.createElement("br"));
const span = document.createElement("span");
span.textContent = user.serverurls.wellknown.replace("https://", "").replace("http://", "");
span.classList.add("serverURL");
userDiv.append(span);
userinfo.append(userDiv);
table.append(userinfo);
userinfo.addEventListener("click", () => {
table.remove();
showGuilds(user);
});
}
const td = document.createElement("div");
td.classList.add("switchtable");
td.textContent = "Login or create an account ⇌";
td.addEventListener("click", () => {
const l = new URLSearchParams("?");
l.set("goback", window.location.href);
l.set("instance", well!);
window.location.href = "/login?" + l.toString();
});
if (!joinable.length) {
const l = new URLSearchParams("?");
l.set("goback", window.location.href);
l.set("instance", well!);
window.location.href = "/login?" + l.toString();
document.getElementById("AcceptInvite")!.textContent = "Create an account to invite the bot";
}
table.append(td);
table.classList.add("flexttb", "accountSwitcher");
console.log(table);
document.body.append(table);
}
const user = joinable[0];
if (user) {
fetch(urls.api + "/oauth2/authorize/" + window.location.search, {
headers: {
Authorization: user.token,
},
})
.then((_) => _.json())
.then((json: botjsonfetch) => {
const title = document.getElementById("invitename");
if (title) {
title.textContent = `Invite ${json.bot.username} to your servers`;
}
const desc = document.getElementById("invitedescription");
if (desc) {
desc.textContent = json.application.description;
}
const pfp = document.getElementById("inviteimg") as HTMLImageElement;
if (json.bot.avatar !== null) {
pfp.src = `${urls.cdn}/avatars/${json.bot.id}/${json.bot.avatar}.png`;
} else {
const int = Number((BigInt(json.bot.id) >> 22n) % 6n);
pfp.src = `${urls.cdn}/embed/avatars/${int}.png`;
}
const perms = document.getElementById("permissions") as HTMLDivElement;
if (perms && permstr) {
perms.children[0].textContent = I18n.htmlPages.idpermissions();
const permisions = new Permissions(permstr);
for (const perm of Permissions.info()) {
if (permisions.hasPermission(perm.name, false)) {
const div = document.createElement("div");
const h2 = document.createElement("h2");
h2.textContent = perm.readableName;
div.append(h2, perm.description);
div.classList.add("flexttb");
perms.append(div);
await I18n.done;
function showGuilds(user: Specialuser) {
if (!urls) return;
fetch(urls.api + "/oauth2/authorize/" + window.location.search, {
headers: {
Authorization: user.token,
},
})
.then((_) => _.json())
.then((json: botjsonfetch) => {
const guilds: botjsonfetch["guilds"] = [];
for (const guild of json.guilds) {
const permisions = new Permissions(guild.permissions);
if (permisions.hasPermission("MANAGE_GUILD")) {
guilds.push(guild);
}
}
}
const dialog = document.createElement("dialog");
dialog.classList.add("flexttb", "accountSwitcher");
const h1 = document.createElement("h1");
dialog.append(h1);
h1.textContent = "Invite to server:";
const select = document.createElement("select");
const selectSpan = document.createElement("span");
selectSpan.classList.add("selectspan");
const selectArrow = document.createElement("span");
selectArrow.classList.add("svgicon", "svg-category", "selectarrow");
for (const guild of guilds) {
const option = document.createElement("option");
option.textContent = guild.name;
option.value = guild.id;
select.append(option);
}
selectSpan.append(select);
selectSpan.append(selectArrow);
dialog.append(selectSpan);
const button = document.createElement("button");
button.textContent = "Invite";
dialog.append(button);
button.onclick = () => {
const id = select.value;
const params2 = new URLSearchParams("");
params2.set("client_id", params.get("client_id") as string);
fetch(urls.api + "/oauth2/authorize?" + params2.toString(), {
method: "POST",
body: JSON.stringify({
authorize: true,
guild_id: id,
permissions: permstr,
}),
headers: {
"Content-type": "application/json; charset=UTF-8",
Authorization: user.token,
},
}).then((req) => {
if (req.ok) {
alert("Bot added successfully");
}
});
};
document.body.append(dialog);
});
}
function showAccounts(): void {
const table = document.createElement("dialog");
for (const user of joinable) {
console.log(user.pfpsrc);
const userinfo = document.createElement("div");
userinfo.classList.add("flexltr", "switchtable");
const pfp = document.createElement("img");
pfp.src = user.pfpsrc;
pfp.classList.add("pfp");
userinfo.append(pfp);
const userDiv = document.createElement("div");
userDiv.classList.add("userinfo");
userDiv.textContent = user.username;
userDiv.append(document.createElement("br"));
const span = document.createElement("span");
span.textContent = user.serverurls.wellknown.replace("https://", "").replace("http://", "");
span.classList.add("serverURL");
userDiv.append(span);
userinfo.append(userDiv);
table.append(userinfo);
userinfo.addEventListener("click", () => {
table.remove();
showGuilds(user);
});
}
const td = document.createElement("div");
td.classList.add("switchtable");
td.textContent = "Login or create an account ⇌";
td.addEventListener("click", () => {
const l = new URLSearchParams("?");
l.set("goback", window.location.href);
l.set("instance", well!);
window.location.href = "/login?" + l.toString();
});
}
const AcceptInvite = document.getElementById("AcceptInvite");
if (AcceptInvite) {
AcceptInvite.addEventListener("click", showAccounts);
AcceptInvite.textContent = I18n.htmlPages.addBot();
if (!joinable.length) {
const l = new URLSearchParams("?");
l.set("goback", window.location.href);
l.set("instance", well!);
window.location.href = "/login?" + l.toString();
}
table.append(td);
table.classList.add("flexttb", "accountSwitcher");
console.log(table);
document.body.append(table);
}
const user = joinable[0];
if (user) {
fetch(urls.api + "/oauth2/authorize/" + window.location.search, {
headers: {
Authorization: user.token,
},
})
.then((_) => _.json())
.then((json: botjsonfetch) => {
const title = document.getElementById("invitename");
if (title) {
title.textContent = `Invite ${json.bot.username} to your servers`;
}
const desc = document.getElementById("invitedescription");
if (desc) {
desc.textContent = json.application.description;
}
const pfp = document.getElementById("inviteimg") as HTMLImageElement;
if (json.bot.avatar !== null) {
pfp.src = `${urls.cdn}/avatars/${json.bot.id}/${json.bot.avatar}.png`;
} else {
const int = Number((BigInt(json.bot.id) >> 22n) % 6n);
pfp.src = `${urls.cdn}/embed/avatars/${int}.png`;
}
const perms = document.getElementById("permissions") as HTMLDivElement;
if (perms && permstr) {
perms.children[0].textContent = I18n.htmlPages.idpermissions();
const permisions = new Permissions(permstr);
for (const perm of Permissions.info()) {
if (permisions.hasPermission(perm.name, false)) {
const div = document.createElement("div");
const h2 = document.createElement("h2");
h2.textContent = perm.readableName;
div.append(h2, perm.description);
div.classList.add("flexttb");
perms.append(div);
}
}
}
});
}
const AcceptInvite = document.getElementById("AcceptInvite");
if (AcceptInvite) {
AcceptInvite.addEventListener("click", showAccounts);
AcceptInvite.textContent = I18n.htmlPages.addBot();
}
}
+1 -1
View File
@@ -31,6 +31,6 @@
<button id="AcceptInvite">Add to server</button>
</div>
</div>
<script type="module" src="/oauth2/auth.js"></script>
<script type="module" src="/index.js"></script>
</body>
</html>
+9 -8
View File
@@ -89,11 +89,12 @@ function makeMenu1() {
});
d.show(false);
}
if (
window.location.href.split("#").length == 2 &&
new URLSearchParams(window.location.href.split("#")[1]).has("token")
) {
makeMenu2();
} else {
makeMenu1();
}
if (window.location.pathname.startsWith("/reset"))
if (
window.location.href.split("#").length == 2 &&
new URLSearchParams(window.location.href.split("#")[1]).has("token")
) {
makeMenu2();
} else {
makeMenu1();
}
+1 -1
View File
@@ -24,6 +24,6 @@
</head>
<body class="no-theme">
<h1 style="display: none">Register for a Spacebar instance!</h1>
<script src="/register.js" type="module"></script>
<script src="/index.js" type="module"></script>
</body>
</html>
+1 -1
View File
@@ -22,6 +22,6 @@
</style>
</head>
<body class="no-theme">
<script src="/recover.js" type="module"></script>
<script src="/index.js" type="module"></script>
</body>
</html>
+1 -1
View File
@@ -30,6 +30,6 @@
<button id="usetemplate">Use template</button>
</div>
</div>
<script src="/templatePage.js" type="module"></script>
<script src="/index.js" type="module"></script>
</body>
</html>
+97 -97
View File
@@ -2,109 +2,109 @@ import {I18n} from "./i18n.js";
import {templateSkim} from "./jsontypes.js";
import {getapiurls} from "./utils/utils.js";
import {getBulkUsers, Specialuser} from "./utils/utils.js";
if (window.location.pathname.startsWith("/template"))
(async () => {
const users = getBulkUsers();
const well = new URLSearchParams(window.location.search).get("instance");
const joinable: Specialuser[] = [];
(async () => {
const users = getBulkUsers();
const well = new URLSearchParams(window.location.search).get("instance");
const joinable: Specialuser[] = [];
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (well && user.serverurls.wellknown.includes(well)) {
joinable.push(user);
}
console.log(user);
}
}
let urls: {api: string; cdn: string} | undefined;
if (!joinable.length && well) {
const out = await getapiurls(well);
if (out) {
urls = out;
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (user.serverurls.api.includes(out.api)) {
joinable.push(user);
}
console.log(user);
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (well && user.serverurls.wellknown.includes(well)) {
joinable.push(user);
}
console.log(user);
}
}
let urls: {api: string; cdn: string} | undefined;
if (!joinable.length && well) {
const out = await getapiurls(well);
if (out) {
urls = out;
for (const key in users.users) {
if (Object.prototype.hasOwnProperty.call(users.users, key)) {
const user: Specialuser = users.users[key];
if (user.serverurls.api.includes(out.api)) {
joinable.push(user);
}
console.log(user);
}
}
} else {
throw new Error("Someone needs to handle the case where the servers don't exist");
}
} else {
throw new Error("Someone needs to handle the case where the servers don't exist");
urls = joinable[0].serverurls;
}
} else {
urls = joinable[0].serverurls;
}
await I18n.done;
if (!joinable.length) {
document.getElementById("usetemplate")!.textContent = I18n.htmlPages.noAccount();
}
const code = window.location.pathname.split("/")[2];
fetch(`${urls!.api}/guilds/templates/${code}`, {
method: "GET",
headers: {
Authorization: joinable[0].token,
},
})
.then((response) => response.json())
.then((json) => {
const template = json as templateSkim;
document.getElementById("templatename")!.textContent = I18n.useTemplate(template.name);
document.getElementById("templatedescription")!.textContent = template.description;
});
function showAccounts(): void {
const table = document.createElement("dialog");
for (const user of joinable) {
console.log(user.pfpsrc);
const userinfo = document.createElement("div");
userinfo.classList.add("flexltr", "switchtable");
const pfp = document.createElement("img");
pfp.src = user.pfpsrc;
pfp.classList.add("pfp");
userinfo.append(pfp);
const userDiv = document.createElement("div");
userDiv.classList.add("userinfo");
userDiv.textContent = user.username;
userDiv.append(document.createElement("br"));
const span = document.createElement("span");
span.textContent = user.serverurls.wellknown.replace("https://", "").replace("http://", "");
span.classList.add("serverURL");
userDiv.append(span);
userinfo.append(userDiv);
table.append(userinfo);
userinfo.addEventListener("click", () => {
const search = new URLSearchParams();
search.set("templateID", code);
sessionStorage.setItem("currentuser", user.uid);
window.location.assign("/channels/@me?" + search);
});
}
await I18n.done;
if (!joinable.length) {
const l = new URLSearchParams("?");
l.set("goback", window.location.href);
l.set("instance", well!);
window.location.href = "/login?" + l.toString();
document.getElementById("usetemplate")!.textContent = I18n.htmlPages.noAccount();
}
table.classList.add("flexttb", "accountSwitcher");
console.log(table);
document.body.append(table);
}
const code = window.location.pathname.split("/")[2];
document.getElementById("usetemplate")!.addEventListener("click", showAccounts);
document.getElementById("usetemplate")!.textContent = I18n.useTemplateButton();
})();
fetch(`${urls!.api}/guilds/templates/${code}`, {
method: "GET",
headers: {
Authorization: joinable[0].token,
},
})
.then((response) => response.json())
.then((json) => {
const template = json as templateSkim;
document.getElementById("templatename")!.textContent = I18n.useTemplate(template.name);
document.getElementById("templatedescription")!.textContent = template.description;
});
function showAccounts(): void {
const table = document.createElement("dialog");
for (const user of joinable) {
console.log(user.pfpsrc);
const userinfo = document.createElement("div");
userinfo.classList.add("flexltr", "switchtable");
const pfp = document.createElement("img");
pfp.src = user.pfpsrc;
pfp.classList.add("pfp");
userinfo.append(pfp);
const userDiv = document.createElement("div");
userDiv.classList.add("userinfo");
userDiv.textContent = user.username;
userDiv.append(document.createElement("br"));
const span = document.createElement("span");
span.textContent = user.serverurls.wellknown.replace("https://", "").replace("http://", "");
span.classList.add("serverURL");
userDiv.append(span);
userinfo.append(userDiv);
table.append(userinfo);
userinfo.addEventListener("click", () => {
const search = new URLSearchParams();
search.set("templateID", code);
sessionStorage.setItem("currentuser", user.uid);
window.location.assign("/channels/@me?" + search);
});
}
if (!joinable.length) {
const l = new URLSearchParams("?");
l.set("goback", window.location.href);
l.set("instance", well!);
window.location.href = "/login?" + l.toString();
}
table.classList.add("flexttb", "accountSwitcher");
console.log(table);
document.body.append(table);
}
document.getElementById("usetemplate")!.addEventListener("click", showAccounts);
document.getElementById("usetemplate")!.textContent = I18n.useTemplateButton();
})();