From 1a3ce1e3ff2b3d1c8e393760c422b866819ce2c0 Mon Sep 17 00:00:00 2001
From: TomatoCake <60300461+DEVTomatoCake@users.noreply.github.com>
Date: Sat, 20 Jul 2024 19:19:23 +0200
Subject: [PATCH 01/10] implement very basic connections & applications
---
webpage/index.html | 7 +-
webpage/index.ts | 11 ++
webpage/localuser.ts | 260 ++++++++++++++++++++++++++++++++++++++++++-
webpage/style.css | 39 +++++--
4 files changed, 303 insertions(+), 14 deletions(-)
diff --git a/webpage/index.html b/webpage/index.html
index 07b70b1..c970952 100644
--- a/webpage/index.html
+++ b/webpage/index.html
@@ -37,7 +37,12 @@
diff --git a/webpage/index.ts b/webpage/index.ts
index a5d367e..3c21fa6 100644
--- a/webpage/index.ts
+++ b/webpage/index.ts
@@ -245,6 +245,17 @@ function userSettings(){
thisuser.usersettings.show();
}
document.getElementById("settings").onclick=userSettings;
+
+function userConnections(){
+ thisuser.userConnections.show();
+}
+document.getElementById("connections").onclick=userConnections;
+
+function devPortal(){
+ thisuser.devPortal.show();
+}
+document.getElementById("dev-portal").onclick=devPortal;
+
let triggered=false;
document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{
const messagecontainer=document.getElementById("messagecontainer")
diff --git a/webpage/localuser.ts b/webpage/localuser.ts
index 9ca8b11..87cf0c5 100644
--- a/webpage/localuser.ts
+++ b/webpage/localuser.ts
@@ -19,6 +19,8 @@ class Localuser{
info;
headers:{"Content-type":string,Authorization:string};
usersettings:Fullscreen;
+ userConnections:Fullscreen;
+ devPortal:Fullscreen;
ready;
guilds:Guild[];
guildids:{ [key: string]: Guild };
@@ -671,6 +673,262 @@ class Localuser{
newprouns=null;
newbio=null;
}.bind(this))
- }
+
+ const connectionContainer=document.createElement("div");
+ connectionContainer.id="connection-container";
+ this.userConnections=new Fullscreen(
+ ["html",
+ connectionContainer
+ ], () => {}, async () => {
+ connectionContainer.innerHTML="";
+
+ const res=await fetch(this.info.api.toString()+"/v9/connections", {
+ headers: this.headers
+ });
+ const json=await res.json();
+
+ Object.keys(json).sort(key => json[key].enabled ? -1 : 1).forEach(key => {
+ const connection=json[key];
+
+ const container=document.createElement("div");
+ container.textContent=key.charAt(0).toUpperCase() + key.slice(1);
+
+ if (connection.enabled) {
+ container.addEventListener("click", async () => {
+ const connectionRes=await fetch(this.info.api.toString()+"/v9/connections/" + key + "/authorize", {
+ headers: this.headers
+ });
+ const connectionJSON=await connectionRes.json();
+ window.open(connectionJSON.url, "_blank", "noopener noreferrer");
+ })
+ } else {
+ container.classList.add("disabled")
+ container.title="This connection has been disabled server-side."
+ }
+
+ connectionContainer.appendChild(container);
+ })
+ }
+ );
+
+ let appName="";
+ const appListContainer=document.createElement("div");
+ appListContainer.id="app-list-container";
+ this.devPortal=new Fullscreen(
+ ["vdiv",
+ ["hdiv",
+ ["textbox", "Name:", appName, event => {
+ appName=event.target.value;
+ }],
+ ["button",
+ "",
+ "Create application",
+ async () => {
+ if (appName.trim().length == 0) return alert("Please enter a name for the application.");
+
+ const res=await fetch(this.info.api.toString()+"/v9/applications", {
+ method: "POST",
+ headers: this.headers,
+ body: JSON.stringify({
+ name: appName
+ })
+ });
+ const json=await res.json();
+ this.manageApplication(json.id);
+ this.devPortal.hide();
+ }
+ ]
+ ],
+ ["html",
+ appListContainer
+ ]
+ ], () => {}, async () => {
+ appListContainer.innerHTML="";
+
+ const res=await fetch(this.info.api.toString()+"/v9/applications", {
+ headers: this.headers
+ });
+ const json=await res.json();
+
+ json.forEach(application => {
+ const container=document.createElement("div");
+
+ if (application.cover_image) {
+ const cover=document.createElement("img");
+ cover.crossOrigin="anonymous";
+ cover.src=this.info.cdn.toString()+"/app-icons/" + application.id + "/" + application.cover_image + ".png?size=256";
+ cover.alt="";
+ cover.loading="lazy";
+ container.appendChild(cover);
+ }
+
+ const name=document.createElement("h2");
+ name.textContent=application.name + (application.bot ? " (Bot)" : "");
+ container.appendChild(name);
+
+ container.addEventListener("click", async () => {
+ this.devPortal.hide();
+ this.manageApplication(application.id);
+ });
+ appListContainer.appendChild(container);
+ })
+ }
+ )
+ }
+ async manageApplication(appId="") {
+ const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
+ headers: this.headers
+ });
+ const json=await res.json();
+
+ const fields: any={};
+ const appDialog=new Fullscreen(
+ ["vdiv",
+ ["title",
+ "Editing " + json.name
+ ],
+ ["hdiv",
+ ["textbox", "Application name:", json.name, event => {
+ fields.name=event.target.value;
+ }],
+ ["mdbox", "Description:", json.description, event => {
+ fields.description=event.target.value;
+ }],
+ ["vdiv",
+ json.icon ? ["img", this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.icon + ".png?size=128", [128, 128]] : ["text", "No icon"],
+ ["fileupload", "Application icon:", event => {
+ const reader=new FileReader();
+ reader.readAsDataURL(event.target.files[0]);
+ reader.onload=() => {
+ fields.icon=reader.result;
+ }
+ }]
+ ]
+ ],
+ ["hdiv",
+ ["textbox", "Privacy policy URL:", json.privacy_policy_url || "", event => {
+ fields.privacy_policy_url=event.target.value;
+ }],
+ ["textbox", "Terms of Service URL:", json.terms_of_service_url || "", event => {
+ fields.terms_of_service_url=event.target.value;
+ }]
+ ],
+ ["hdiv",
+ ["checkbox", "Make bot publicly inviteable?", json.bot_public, event => {
+ fields.bot_public=event.target.checked;
+ }],
+ ["checkbox", "Require code grant to invite the bot?", json.bot_require_code_grant, event => {
+ fields.bot_require_code_grant=event.target.checked;
+ }]
+ ],
+ ["hdiv",
+ ["button",
+ "",
+ "Save changes",
+ async () => {
+ const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
+ method: "PATCH",
+ headers: this.headers,
+ body: JSON.stringify(fields)
+ });
+ if (updateRes.ok) appDialog.hide();
+ else {
+ const updateJSON=await updateRes.json();
+ alert("An error occurred: " + updateJSON.message);
+ }
+ }
+ ],
+ ["button",
+ "",
+ (json.bot ? "Manage" : "Add") + " bot",
+ async () => {
+ if (!json.bot) {
+ if (!confirm("Are you sure you want to add a bot to this application? There's no going back.")) return;
+
+ const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", {
+ method: "POST",
+ headers: this.headers
+ });
+ const updateJSON=await updateRes.json();
+ alert("Bot token:\n" + updateJSON.token);
+ }
+
+ appDialog.hide();
+ this.manageBot(appId);
+ }
+ ]
+ ]
+ ]
+ )
+ appDialog.show();
+ }
+ async manageBot(appId="") {
+ const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
+ headers: this.headers
+ });
+ const json=await res.json();
+ if (!json.bot) return alert("For some reason, this application doesn't have a bot (yet).");
+
+ const fields: any={
+ username: json.bot.username,
+ avatar: json.bot.avatar ? (this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.bot.avatar + ".png?size=256") : ""
+ };
+ const botDialog=new Fullscreen(
+ ["vdiv",
+ ["title",
+ "Editing bot: " + json.bot.username
+ ],
+ ["hdiv",
+ ["textbox", "Bot username:", json.bot.username, event => {
+ fields.username=event.target.value
+ }],
+ ["vdiv",
+ fields.avatar ? ["img", fields.avatar, [128, 128]] : ["text", "No avatar"],
+ ["fileupload", "Bot avatar:", event => {
+ const reader=new FileReader();
+ reader.readAsDataURL(event.target.files[0]);
+ reader.onload=() => {
+ fields.avatar=reader.result;
+ }
+ }]
+ ]
+ ],
+ ["hdiv",
+ ["button",
+ "",
+ "Save changes",
+ async () => {
+ const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", {
+ method: "PATCH",
+ headers: this.headers,
+ body: JSON.stringify(fields)
+ });
+ if (updateRes.ok) botDialog.hide();
+ else {
+ const updateJSON=await updateRes.json();
+ alert("An error occurred: " + updateJSON.message);
+ }
+ }
+ ],
+ ["button",
+ "",
+ "Reset token",
+ async () => {
+ if (!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it.")) return;
+
+ const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot/reset", {
+ method: "POST",
+ headers: this.headers
+ });
+ const updateJSON=await updateRes.json();
+ alert("New token:\n" + updateJSON.token);
+ botDialog.hide();
+ }
+ ]
+ ]
+ ]
+ );
+ botDialog.show();
+ }
}
export {Localuser};
diff --git a/webpage/style.css b/webpage/style.css
index b92af19..d3d03c7 100644
--- a/webpage/style.css
+++ b/webpage/style.css
@@ -699,22 +699,20 @@ textarea {
flex-shrink: 1;
}
-#settings {
+#user-actions {
+ display: flex;
+ flex-wrap: wrap;
+}
+#user-actions h2 {
cursor: pointer;
user-select: none;
- border-radius: .3in;
- transition: background 1s;
+ border-radius: .1in;
+ transition: color .5s;
text-align: center;
- font-size: .25in;
- width: .3in;
- height: .3in;
overflow: visible;
}
-
-#settings:hover {
- background-color: var(--settings-hover);
- cursor: pointer;
- user-select: none;
+#user-actions h2:hover, #user-actions h2:focus {
+ color: var(--timestamp-color);
}
#userinfo {
@@ -1352,4 +1350,21 @@ span {
width: 100%;
flex-direction: row;
max-height:100in;
-}
\ No newline at end of file
+}
+
+#connection-container, #app-list-container {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ max-width: 700px;
+}
+#connection-container div, #app-list-container div {
+ padding: 5px 10px;
+ border-radius: 5px;
+ background-color: var(--textarea-bg);
+ cursor: pointer;
+}
+#connection-container .disabled {
+ background-color: var(--embed-fallback);
+ cursor: not-allowed;
+}
From 36fc3fecc24b27f5acf1f1e60ad414ba9a5e667d Mon Sep 17 00:00:00 2001
From: MathMan05
Date: Sat, 20 Jul 2024 18:31:12 -0500
Subject: [PATCH 02/10] fixed uploading pfps
---
.dist/localuser.js | 6 +++---
webpage/localuser.ts | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.dist/localuser.js b/.dist/localuser.js
index 3df2641..d650a46 100644
--- a/.dist/localuser.js
+++ b/.dist/localuser.js
@@ -506,7 +506,7 @@ class Localuser {
reader.readAsDataURL(file);
console.log(this.headers);
reader.onload = () => {
- fetch(this.info.api.toString() + "/v9/users/@me", {
+ fetch(this.info.api.toString() + "/users/@me", {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({
@@ -517,7 +517,7 @@ class Localuser {
};
}
updatepronouns(pronouns) {
- fetch(this.info.api.toString() + "/v9/users/@me/profile", {
+ fetch(this.info.api.toString() + "/users/@me/profile", {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({
@@ -600,7 +600,7 @@ class Localuser {
newbio = this.value;
regen();
}],
- ["button", "update user content:", "submit", function () {
+ ["button", "update user content:", "submit", () => {
if (file !== null) {
this.updatepfp(file);
}
diff --git a/webpage/localuser.ts b/webpage/localuser.ts
index 551a978..f3470cb 100644
--- a/webpage/localuser.ts
+++ b/webpage/localuser.ts
@@ -531,7 +531,7 @@ class Localuser{
reader.readAsDataURL(file);
console.log(this.headers);
reader.onload = ()=>{
- fetch(this.info.api.toString()+"/v9/users/@me",{
+ fetch(this.info.api.toString()+"/users/@me",{
method:"PATCH",
headers:this.headers,
body:JSON.stringify({
@@ -543,7 +543,7 @@ class Localuser{
}
updatepronouns(pronouns:string):void{
- fetch(this.info.api.toString()+"/v9/users/@me/profile",{
+ fetch(this.info.api.toString()+"/users/@me/profile",{
method:"PATCH",
headers:this.headers,
body:JSON.stringify({
@@ -626,7 +626,7 @@ class Localuser{
newbio=this.value;
regen();
}],
- ["button","update user content:","submit",function(){
+ ["button","update user content:","submit",()=>{
if(file!==null){
this.updatepfp(file);
}
From ec5b86b276343a3d57e7dfcf0bb3639693641b4c Mon Sep 17 00:00:00 2001
From: MathMan05
Date: Sat, 20 Jul 2024 19:05:23 -0500
Subject: [PATCH 03/10] make MarkDown into a class and fixed emojis
---
.dist/channel.js | 5 +-
.dist/embed.js | 20 +-
.dist/markdown.js | 882 ++++++++++++++++++++++---------------------
.dist/message.js | 12 +-
.dist/user.js | 8 +-
webpage/channel.ts | 6 +-
webpage/embed.ts | 20 +-
webpage/localuser.ts | 2 +-
webpage/markdown.ts | 819 +++++++++++++++++++++-------------------
webpage/message.ts | 13 +-
webpage/style.css | 8 +
webpage/user.ts | 10 +-
12 files changed, 957 insertions(+), 848 deletions(-)
diff --git a/.dist/channel.js b/.dist/channel.js
index 16635a2..3efee21 100644
--- a/.dist/channel.js
+++ b/.dist/channel.js
@@ -3,7 +3,6 @@ import { Message } from "./message.js";
import { Voice } from "./audio.js";
import { Contextmenu } from "./contextmenu.js";
import { Fullscreen } from "./fullscreen.js";
-import { markdown } from "./markdown.js";
import { Permissions } from "./permissions.js";
import { Settings, RoleList } from "./settings.js";
import { InfiniteScroller } from "./infiniteScroller.js";
@@ -745,10 +744,10 @@ class Channel {
if (!("Notification" in window)) {
}
else if (Notification.permission === "granted") {
- let noticontent = markdown(message.content).textContent;
+ let noticontent = message.content.textContent;
if (message.embeds[0]) {
noticontent ||= message.embeds[0].json.title;
- noticontent ||= markdown(message.embeds[0].json.description).textContent;
+ noticontent ||= message.content.textContent;
}
noticontent ||= "Blank Message";
let imgurl = null;
diff --git a/.dist/embed.js b/.dist/embed.js
index 6a755cd..e617bdb 100644
--- a/.dist/embed.js
+++ b/.dist/embed.js
@@ -1,5 +1,5 @@
import { Fullscreen } from "./fullscreen.js";
-import { markdown } from "./markdown.js";
+import { MarkDown } from "./markdown.js";
class Embed {
type;
owner;
@@ -27,6 +27,18 @@ class Embed {
return document.createElement("div"); //prevent errors by giving blank div
}
}
+ get message() {
+ return this.owner;
+ }
+ get channel() {
+ return this.message.channel;
+ }
+ get guild() {
+ return this.channel.guild;
+ }
+ get localuser() {
+ return this.guild.localuser;
+ }
generateRich() {
console.log(this.json);
const div = document.createElement("div");
@@ -55,7 +67,7 @@ class Embed {
embed.append(authorline);
}
const title = document.createElement("a");
- title.append(markdown(this.json.title));
+ title.append(new MarkDown(this.json.title, this.localuser).makeHTML());
if (this.json.url) {
title.href = this.json.url;
}
@@ -63,7 +75,7 @@ class Embed {
embed.append(title);
if (this.json.description) {
const p = document.createElement("p");
- p.append(markdown(this.json.description));
+ p.append(new MarkDown(this.json.description, this.channel).makeHTML());
embed.append(p);
}
embed.append(document.createElement("br"));
@@ -74,7 +86,7 @@ class Embed {
b.textContent = thing.name;
div.append(b);
const p = document.createElement("p");
- p.append(markdown(thing.value));
+ p.append(new MarkDown(thing.value, this.channel).makeHTML());
p.classList.add("embedp");
div.append(p);
if (thing.inline) {
diff --git a/.dist/markdown.js b/.dist/markdown.js
index 0e1febb..8111f5f 100644
--- a/.dist/markdown.js
+++ b/.dist/markdown.js
@@ -1,446 +1,476 @@
-export { markdown };
-function markdown(text, { keep = false, stdsize = false } = {}) {
- let txt;
- if ((typeof text) === (typeof "")) {
- txt = text.split("");
- }
- else {
- txt = text;
- }
- if (txt === undefined) {
- txt = [];
- }
- const span = document.createElement("span");
- let current = document.createElement("span");
- function appendcurrent() {
- if (current.innerHTML !== "") {
- span.append(current);
- current = document.createElement("span");
+export { MarkDown };
+class MarkDown {
+ txt;
+ keep;
+ stdsize;
+ owner;
+ info;
+ constructor(text, owner, { keep = false, stdsize = false } = {}) {
+ if ((typeof text) === (typeof "")) {
+ this.txt = text.split("");
}
+ else {
+ this.txt = text;
+ }
+ if (this.txt === undefined) {
+ this.txt = [];
+ }
+ this.info = owner.info;
+ this.keep = keep;
+ this.owner = owner;
+ this.stdsize = stdsize;
}
- for (let i = 0; i < txt.length; i++) {
- if (txt[i] === "\n" || i === 0) {
- const first = i === 0;
- if (first) {
- i--;
+ get rawString() {
+ return this.txt.concat("");
+ }
+ get textContent() {
+ return this.makeHTML().textContent;
+ }
+ makeHTML({ keep = this.keep, stdsize = this.stdsize } = {}) {
+ return this.markdown(this.txt, { keep: keep, stdsize: stdsize });
+ }
+ markdown(text, { keep = false, stdsize = false } = {}) {
+ let txt;
+ if ((typeof text) === (typeof "")) {
+ txt = text.split("");
+ }
+ else {
+ txt = text;
+ }
+ if (txt === undefined) {
+ txt = [];
+ }
+ const span = document.createElement("span");
+ let current = document.createElement("span");
+ function appendcurrent() {
+ if (current.innerHTML !== "") {
+ span.append(current);
+ current = document.createElement("span");
}
- let element = null;
- let keepys = "";
- if (txt[i + 1] === "#") {
- console.log("test");
- if (txt[i + 2] === "#") {
- if (txt[i + 3] === "#" && txt[i + 4] === " ") {
- element = document.createElement("h3");
- keepys = "### ";
- i += 5;
+ }
+ for (let i = 0; i < txt.length; i++) {
+ if (txt[i] === "\n" || i === 0) {
+ const first = i === 0;
+ if (first) {
+ i--;
+ }
+ let element = null;
+ let keepys = "";
+ if (txt[i + 1] === "#") {
+ console.log("test");
+ if (txt[i + 2] === "#") {
+ if (txt[i + 3] === "#" && txt[i + 4] === " ") {
+ element = document.createElement("h3");
+ keepys = "### ";
+ i += 5;
+ }
+ else if (txt[i + 3] === " ") {
+ element = document.createElement("h2");
+ element.classList.add("h2md");
+ keepys = "## ";
+ i += 4;
+ }
}
- else if (txt[i + 3] === " ") {
- element = document.createElement("h2");
- element.classList.add("h2md");
- keepys = "## ";
- i += 4;
+ else if (txt[i + 2] === " ") {
+ element = document.createElement("h1");
+ keepys = "# ";
+ i += 3;
}
}
- else if (txt[i + 2] === " ") {
- element = document.createElement("h1");
- keepys = "# ";
+ else if (txt[i + 1] === ">" && txt[i + 2] === " ") {
+ element = document.createElement("div");
+ const line = document.createElement("div");
+ line.classList.add("quoteline");
+ element.append(line);
+ element.classList.add("quote");
+ keepys = "> ";
i += 3;
}
- }
- else if (txt[i + 1] === ">" && txt[i + 2] === " ") {
- element = document.createElement("div");
- const line = document.createElement("div");
- line.classList.add("quoteline");
- element.append(line);
- element.classList.add("quote");
- keepys = "> ";
- i += 3;
- }
- if (keepys) {
- appendcurrent();
- if (!first && !stdsize) {
- span.appendChild(document.createElement("br"));
+ if (keepys) {
+ appendcurrent();
+ if (!first && !stdsize) {
+ span.appendChild(document.createElement("br"));
+ }
+ const build = [];
+ for (; txt[i] !== "\n" && txt[i] !== undefined; i++) {
+ build.push(txt[i]);
+ }
+ if (stdsize) {
+ element = document.createElement("span");
+ }
+ if (keep) {
+ element.append(keepys);
+ }
+ element.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
+ span.append(element);
+ i--;
+ continue;
}
- const build = [];
- for (; txt[i] !== "\n" && txt[i] !== undefined; i++) {
- build.push(txt[i]);
+ if (first) {
+ i++;
+ }
+ }
+ if (txt[i] === "\n") {
+ if (!stdsize) {
+ appendcurrent();
+ span.append(document.createElement("br"));
+ }
+ continue;
+ }
+ if (txt[i] === "`") {
+ let count = 1;
+ if (txt[i + 1] === "`") {
+ count++;
+ if (txt[i + 2] === "`") {
+ count++;
+ }
+ }
+ let build = "";
+ if (keep) {
+ build += "`".repeat(count);
+ }
+ let find = 0;
+ let j = i + count;
+ let init = true;
+ for (; txt[j] !== undefined && (txt[j] !== "\n" || count === 3) && find !== count; j++) {
+ if (txt[j] === "`") {
+ find++;
+ }
+ else {
+ if (find !== 0) {
+ build += "`".repeat(find);
+ find = 0;
+ }
+ if (init && count === 3) {
+ if (txt[j] === " " || txt[j] === "\n") {
+ init = false;
+ }
+ if (keep) {
+ build += txt[j];
+ }
+ continue;
+ }
+ build += txt[j];
+ }
}
if (stdsize) {
- element = document.createElement("span");
+ console.log(build);
+ build = build.replaceAll("\n", "");
+ console.log(build, JSON.stringify(build));
}
- if (keep) {
- element.append(keepys);
- }
- element.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
- span.append(element);
- i--;
- continue;
- }
- if (first) {
- i++;
- }
- }
- if (txt[i] === "\n") {
- if (!stdsize) {
- appendcurrent();
- span.append(document.createElement("br"));
- }
- continue;
- }
- if (txt[i] === "`") {
- let count = 1;
- if (txt[i + 1] === "`") {
- count++;
- if (txt[i + 2] === "`") {
- count++;
- }
- }
- let build = "";
- if (keep) {
- build += "`".repeat(count);
- }
- let find = 0;
- let j = i + count;
- let init = true;
- for (; txt[j] !== undefined && (txt[j] !== "\n" || count === 3) && find !== count; j++) {
- if (txt[j] === "`") {
- find++;
- }
- else {
- if (find !== 0) {
- build += "`".repeat(find);
- find = 0;
- }
- if (init && count === 3) {
- if (txt[j] === " " || txt[j] === "\n") {
- init = false;
- }
- if (keep) {
- build += txt[j];
- }
- continue;
- }
- build += txt[j];
- }
- }
- if (stdsize) {
- console.log(build);
- build = build.replaceAll("\n", "");
- console.log(build, JSON.stringify(build));
- }
- if (find === count) {
- appendcurrent();
- i = j;
- if (keep) {
- build += "`".repeat(find);
- }
- if (count !== 3 && !stdsize) {
- const samp = document.createElement("samp");
- samp.textContent = build;
- span.appendChild(samp);
- }
- else {
- const pre = document.createElement("pre");
- if (build[build.length - 1] === "\n") {
- build = build.substring(0, build.length - 1);
- }
- if (txt[i] === "\n") {
- i++;
- }
- pre.textContent = build;
- span.appendChild(pre);
- }
- i--;
- continue;
- }
- }
- if (txt[i] === "*") {
- let count = 1;
- if (txt[i + 1] === "*") {
- count++;
- if (txt[i + 2] === "*") {
- count++;
- }
- }
- let build = [];
- let find = 0;
- let j = i + count;
- for (; txt[j] !== undefined && find !== count; j++) {
- if (txt[j] === "*") {
- find++;
- }
- else {
- build.push(txt[j]);
- if (find !== 0) {
- build = build.concat(new Array(find).fill("*"));
- find = 0;
- }
- }
- }
- if (find === count && (count != 1 || txt[i + 1] !== " ")) {
- appendcurrent();
- i = j;
- const stars = "*".repeat(count);
- if (count === 1) {
- const i = document.createElement("i");
- if (keep) {
- i.append(stars);
- }
- i.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
- if (keep) {
- i.append(stars);
- }
- span.appendChild(i);
- }
- else if (count === 2) {
- const b = document.createElement("b");
- if (keep) {
- b.append(stars);
- }
- b.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
- if (keep) {
- b.append(stars);
- }
- span.appendChild(b);
- }
- else {
- const b = document.createElement("b");
- const i = document.createElement("i");
- if (keep) {
- b.append(stars);
- }
- b.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
- if (keep) {
- b.append(stars);
- }
- i.appendChild(b);
- span.appendChild(i);
- }
- i--;
- continue;
- }
- }
- if (txt[i] === "_") {
- let count = 1;
- if (txt[i + 1] === "_") {
- count++;
- if (txt[i + 2] === "_") {
- count++;
- }
- }
- let build = [];
- let find = 0;
- let j = i + count;
- for (; txt[j] !== undefined && find !== count; j++) {
- if (txt[j] === "_") {
- find++;
- }
- else {
- build.push(txt[j]);
- if (find !== 0) {
- build = build.concat(new Array(find).fill("_"));
- find = 0;
- }
- }
- }
- if (find === count && (count != 1 || (txt[j + 1] === " " || txt[j + 1] === "\n" || txt[j + 1] === undefined))) {
- appendcurrent();
- i = j;
- const underscores = "_".repeat(count);
- if (count === 1) {
- const i = document.createElement("i");
- if (keep) {
- i.append(underscores);
- }
- i.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
- if (keep) {
- i.append(underscores);
- }
- span.appendChild(i);
- }
- else if (count === 2) {
- const u = document.createElement("u");
- if (keep) {
- u.append(underscores);
- }
- u.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
- if (keep) {
- u.append(underscores);
- }
- span.appendChild(u);
- }
- else {
- const u = document.createElement("u");
- const i = document.createElement("i");
- if (keep) {
- i.append(underscores);
- }
- i.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
- if (keep) {
- i.append(underscores);
- }
- u.appendChild(i);
- span.appendChild(u);
- }
- i--;
- continue;
- }
- }
- if (txt[i] === "~" && txt[i + 1] === "~") {
- let count = 2;
- let build = [];
- let find = 0;
- let j = i + 2;
- for (; txt[j] !== undefined && find !== count; j++) {
- if (txt[j] === "~") {
- find++;
- }
- else {
- build.push(txt[j]);
- if (find !== 0) {
- build = build.concat(new Array(find).fill("~"));
- find = 0;
- }
- }
- }
- if (find === count) {
- appendcurrent();
- i = j;
- const tildes = "~~";
- if (count === 2) {
- const s = document.createElement("s");
- if (keep) {
- s.append(tildes);
- }
- s.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
- if (keep) {
- s.append(tildes);
- }
- span.appendChild(s);
- }
- continue;
- }
- }
- if (txt[i] === "|" && txt[i + 1] === "|") {
- let count = 2;
- let build = [];
- let find = 0;
- let j = i + 2;
- for (; txt[j] !== undefined && find !== count; j++) {
- if (txt[j] === "|") {
- find++;
- }
- else {
- build.push(txt[j]);
- if (find !== 0) {
- build = build.concat(new Array(find).fill("~"));
- find = 0;
- }
- }
- }
- if (find === count) {
- appendcurrent();
- i = j;
- const pipes = "||";
- if (count === 2) {
- const j = document.createElement("j");
- if (keep) {
- j.append(pipes);
- }
- j.appendChild(markdown(build, { keep: keep, stdsize: stdsize }));
- j.classList.add("spoiler");
- j.onclick = markdown.unspoil;
- if (keep) {
- j.append(pipes);
- }
- span.appendChild(j);
- }
- continue;
- }
- }
- if (txt[i] === "<" && txt[i + 1] === "t" && txt[i + 2] === ":") {
- let found = false;
- const build = ["<", "t", ":"];
- let j = i + 3;
- for (; txt[j] !== void 0; j++) {
- build.push(txt[j]);
- if (txt[j] === ">") {
- found = true;
- break;
- }
- }
- if (found) {
- appendcurrent();
- i = j;
- const parts = build.join("").match(/^$/);
- const dateInput = new Date(Number.parseInt(parts[1]) * 1000);
- let time = "";
- if (Number.isNaN(dateInput.getTime()))
- time = build.join("");
- else {
- if (parts[3] === "d")
- time = dateInput.toLocaleString(void 0, { day: "2-digit", month: "2-digit", year: "numeric" });
- else if (parts[3] === "D")
- time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric" });
- else if (!parts[3] || parts[3] === "f")
- time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric" }) + " " +
- dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" });
- else if (parts[3] === "F")
- time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric", weekday: "long" }) + " " +
- dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" });
- else if (parts[3] === "t")
- time = dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" });
- else if (parts[3] === "T")
- time = dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit", second: "2-digit" });
- else if (parts[3] === "R")
- time = Math.round((Date.now() - (Number.parseInt(parts[1]) * 1000)) / 1000 / 60) + " minutes ago";
- }
- const timeElem = document.createElement("span");
- timeElem.classList.add("markdown-timestamp");
- timeElem.textContent = time;
- span.appendChild(timeElem);
- continue;
- }
- }
- if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) {
- let found = false;
- const build = txt[i + 1] === "a" ? ["<", "a", ":"] : ["<", ":"];
- let j = i + build.length;
- for (; txt[j] !== void 0; j++) {
- build.push(txt[j]);
- if (txt[j] === ">") {
- found = true;
- break;
- }
- }
- if (found) {
- const parts = build.join("").match(/^<(a)?:\w+:(\d{10,30})>$/);
- if (parts && parts[2]) {
+ if (find === count) {
appendcurrent();
i = j;
- console.log(typeof txt, txt);
- const isEmojiOnly = txt.join("").trim() === build.join("").trim();
- const emojiElem = document.createElement("img");
- emojiElem.classList.add("md-emoji");
- emojiElem.width = isEmojiOnly ? 48 : 22;
- emojiElem.height = isEmojiOnly ? 48 : 22;
- emojiElem.crossOrigin = "anonymous";
- //emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32";
- //must uncomment later
- emojiElem.alt = "";
- emojiElem.loading = "lazy";
- span.appendChild(emojiElem);
+ if (keep) {
+ build += "`".repeat(find);
+ }
+ if (count !== 3 && !stdsize) {
+ const samp = document.createElement("samp");
+ samp.textContent = build;
+ span.appendChild(samp);
+ }
+ else {
+ const pre = document.createElement("pre");
+ if (build[build.length - 1] === "\n") {
+ build = build.substring(0, build.length - 1);
+ }
+ if (txt[i] === "\n") {
+ i++;
+ }
+ pre.textContent = build;
+ span.appendChild(pre);
+ }
+ i--;
continue;
}
}
+ if (txt[i] === "*") {
+ let count = 1;
+ if (txt[i + 1] === "*") {
+ count++;
+ if (txt[i + 2] === "*") {
+ count++;
+ }
+ }
+ let build = [];
+ let find = 0;
+ let j = i + count;
+ for (; txt[j] !== undefined && find !== count; j++) {
+ if (txt[j] === "*") {
+ find++;
+ }
+ else {
+ build.push(txt[j]);
+ if (find !== 0) {
+ build = build.concat(new Array(find).fill("*"));
+ find = 0;
+ }
+ }
+ }
+ if (find === count && (count != 1 || txt[i + 1] !== " ")) {
+ appendcurrent();
+ i = j;
+ const stars = "*".repeat(count);
+ if (count === 1) {
+ const i = document.createElement("i");
+ if (keep) {
+ i.append(stars);
+ }
+ i.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
+ if (keep) {
+ i.append(stars);
+ }
+ span.appendChild(i);
+ }
+ else if (count === 2) {
+ const b = document.createElement("b");
+ if (keep) {
+ b.append(stars);
+ }
+ b.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
+ if (keep) {
+ b.append(stars);
+ }
+ span.appendChild(b);
+ }
+ else {
+ const b = document.createElement("b");
+ const i = document.createElement("i");
+ if (keep) {
+ b.append(stars);
+ }
+ b.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
+ if (keep) {
+ b.append(stars);
+ }
+ i.appendChild(b);
+ span.appendChild(i);
+ }
+ i--;
+ continue;
+ }
+ }
+ if (txt[i] === "_") {
+ let count = 1;
+ if (txt[i + 1] === "_") {
+ count++;
+ if (txt[i + 2] === "_") {
+ count++;
+ }
+ }
+ let build = [];
+ let find = 0;
+ let j = i + count;
+ for (; txt[j] !== undefined && find !== count; j++) {
+ if (txt[j] === "_") {
+ find++;
+ }
+ else {
+ build.push(txt[j]);
+ if (find !== 0) {
+ build = build.concat(new Array(find).fill("_"));
+ find = 0;
+ }
+ }
+ }
+ if (find === count && (count != 1 || (txt[j + 1] === " " || txt[j + 1] === "\n" || txt[j + 1] === undefined))) {
+ appendcurrent();
+ i = j;
+ const underscores = "_".repeat(count);
+ if (count === 1) {
+ const i = document.createElement("i");
+ if (keep) {
+ i.append(underscores);
+ }
+ i.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
+ if (keep) {
+ i.append(underscores);
+ }
+ span.appendChild(i);
+ }
+ else if (count === 2) {
+ const u = document.createElement("u");
+ if (keep) {
+ u.append(underscores);
+ }
+ u.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
+ if (keep) {
+ u.append(underscores);
+ }
+ span.appendChild(u);
+ }
+ else {
+ const u = document.createElement("u");
+ const i = document.createElement("i");
+ if (keep) {
+ i.append(underscores);
+ }
+ i.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
+ if (keep) {
+ i.append(underscores);
+ }
+ u.appendChild(i);
+ span.appendChild(u);
+ }
+ i--;
+ continue;
+ }
+ }
+ if (txt[i] === "~" && txt[i + 1] === "~") {
+ let count = 2;
+ let build = [];
+ let find = 0;
+ let j = i + 2;
+ for (; txt[j] !== undefined && find !== count; j++) {
+ if (txt[j] === "~") {
+ find++;
+ }
+ else {
+ build.push(txt[j]);
+ if (find !== 0) {
+ build = build.concat(new Array(find).fill("~"));
+ find = 0;
+ }
+ }
+ }
+ if (find === count) {
+ appendcurrent();
+ i = j;
+ const tildes = "~~";
+ if (count === 2) {
+ const s = document.createElement("s");
+ if (keep) {
+ s.append(tildes);
+ }
+ s.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
+ if (keep) {
+ s.append(tildes);
+ }
+ span.appendChild(s);
+ }
+ continue;
+ }
+ }
+ if (txt[i] === "|" && txt[i + 1] === "|") {
+ let count = 2;
+ let build = [];
+ let find = 0;
+ let j = i + 2;
+ for (; txt[j] !== undefined && find !== count; j++) {
+ if (txt[j] === "|") {
+ find++;
+ }
+ else {
+ build.push(txt[j]);
+ if (find !== 0) {
+ build = build.concat(new Array(find).fill("~"));
+ find = 0;
+ }
+ }
+ }
+ if (find === count) {
+ appendcurrent();
+ i = j;
+ const pipes = "||";
+ if (count === 2) {
+ const j = document.createElement("j");
+ if (keep) {
+ j.append(pipes);
+ }
+ j.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
+ j.classList.add("spoiler");
+ j.onclick = MarkDown.unspoil;
+ if (keep) {
+ j.append(pipes);
+ }
+ span.appendChild(j);
+ }
+ continue;
+ }
+ }
+ if (txt[i] === "<" && txt[i + 1] === "t" && txt[i + 2] === ":") {
+ let found = false;
+ const build = ["<", "t", ":"];
+ let j = i + 3;
+ for (; txt[j] !== void 0; j++) {
+ build.push(txt[j]);
+ if (txt[j] === ">") {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ appendcurrent();
+ i = j;
+ const parts = build.join("").match(/^$/);
+ const dateInput = new Date(Number.parseInt(parts[1]) * 1000);
+ let time = "";
+ if (Number.isNaN(dateInput.getTime()))
+ time = build.join("");
+ else {
+ if (parts[3] === "d")
+ time = dateInput.toLocaleString(void 0, { day: "2-digit", month: "2-digit", year: "numeric" });
+ else if (parts[3] === "D")
+ time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric" });
+ else if (!parts[3] || parts[3] === "f")
+ time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric" }) + " " +
+ dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" });
+ else if (parts[3] === "F")
+ time = dateInput.toLocaleString(void 0, { day: "numeric", month: "long", year: "numeric", weekday: "long" }) + " " +
+ dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" });
+ else if (parts[3] === "t")
+ time = dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit" });
+ else if (parts[3] === "T")
+ time = dateInput.toLocaleString(void 0, { hour: "2-digit", minute: "2-digit", second: "2-digit" });
+ else if (parts[3] === "R")
+ time = Math.round((Date.now() - (Number.parseInt(parts[1]) * 1000)) / 1000 / 60) + " minutes ago";
+ }
+ const timeElem = document.createElement("span");
+ timeElem.classList.add("markdown-timestamp");
+ timeElem.textContent = time;
+ span.appendChild(timeElem);
+ continue;
+ }
+ }
+ if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) {
+ let found = false;
+ const build = txt[i + 1] === "a" ? ["<", "a", ":"] : ["<", ":"];
+ let j = i + build.length;
+ for (; txt[j] !== void 0; j++) {
+ build.push(txt[j]);
+ if (txt[j] === ">") {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ const buildjoin = build.join("");
+ const parts = buildjoin.match(/^<(a)?:\w+:(\d{10,30})>$/);
+ if (parts && parts[2]) {
+ appendcurrent();
+ i = j;
+ console.log(typeof txt, txt);
+ const isEmojiOnly = txt.join("").trim() === buildjoin.trim();
+ console.log(isEmojiOnly, ":3");
+ const emojiElem = document.createElement("img");
+ emojiElem.classList.add("md-emoji");
+ emojiElem.classList.add(isEmojiOnly ? "bigemoji" : "smallemoji");
+ emojiElem.crossOrigin = "anonymous";
+ emojiElem.src = this.info.cdn.toString() + "emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32";
+ emojiElem.alt = buildjoin;
+ emojiElem.loading = "lazy";
+ span.appendChild(emojiElem);
+ continue;
+ }
+ }
+ }
+ current.textContent += txt[i];
}
- current.textContent += txt[i];
+ appendcurrent();
+ return span;
+ }
+ static unspoil(e) {
+ e.target.classList.remove("spoiler");
+ e.target.classList.add("unspoiled");
}
- appendcurrent();
- return span;
}
-markdown.unspoil = function (e) {
- //console.log("undone")
- e.target.classList.remove("spoiler");
- e.target.classList.add("unspoiled");
-};
diff --git a/.dist/message.js b/.dist/message.js
index 799f605..6dcaafb 100644
--- a/.dist/message.js
+++ b/.dist/message.js
@@ -1,7 +1,7 @@
import { Contextmenu } from "./contextmenu.js";
import { User } from "./user.js";
import { Member } from "./member.js";
-import { markdown } from "./markdown.js";
+import { MarkDown } from "./markdown.js";
import { Embed } from "./embed.js";
import { File } from "./file.js";
class Message {
@@ -33,7 +33,7 @@ class Message {
}
static setupcmenu() {
Message.contextmenu.addbutton("Copy raw text", function () {
- navigator.clipboard.writeText(this.content);
+ navigator.clipboard.writeText(this.content.rawString);
});
Message.contextmenu.addbutton("Reply", function (div) {
this.channel.setReplying(this);
@@ -63,6 +63,10 @@ class Message {
}
continue;
}
+ else if (thing === "content") {
+ this.content = new MarkDown(messagejson[thing], this.channel);
+ continue;
+ }
this[thing] = messagejson[thing];
}
for (const thing in this.embeds) {
@@ -204,7 +208,7 @@ class Message {
replyline.classList.add("replyflex");
this.channel.getmessage(this.message_reference.message_id).then(message => {
const author = message.author;
- reply.appendChild(markdown(message.content, { stdsize: true }));
+ reply.appendChild(message.content.makeHTML({ stdsize: true }));
minipfp.src = author.getpfpsrc();
author.bind(minipfp);
username.textContent = author.username;
@@ -266,7 +270,7 @@ class Message {
else {
div.classList.remove("topMessage");
}
- const messaged = markdown(this.content);
+ const messaged = this.content.makeHTML();
div["txt"] = messaged;
const messagedwrap = document.createElement("div");
messagedwrap.classList.add("flexttb");
diff --git a/.dist/user.js b/.dist/user.js
index 2323d78..401b8a9 100644
--- a/.dist/user.js
+++ b/.dist/user.js
@@ -1,6 +1,6 @@
//const usercache={};
import { Member } from "./member.js";
-import { markdown } from "./markdown.js";
+import { MarkDown } from "./markdown.js";
import { Contextmenu } from "./contextmenu.js";
class User {
static userids = {};
@@ -48,6 +48,10 @@ class User {
}
if (dontclone) {
for (const thing of Object.keys(userjson)) {
+ if (thing === "bio") {
+ this.bio = new MarkDown(userjson[thing], this.localuser);
+ continue;
+ }
this[thing] = userjson[thing];
}
this.hypotheticalpfp = false;
@@ -146,7 +150,7 @@ class User {
userbody.appendChild(pronounshtml);
const rule = document.createElement("hr");
userbody.appendChild(rule);
- const biohtml = markdown(this.bio);
+ const biohtml = this.bio.makeHTML();
userbody.appendChild(biohtml);
}
console.log(div);
diff --git a/webpage/channel.ts b/webpage/channel.ts
index ab9e615..1f1eca6 100644
--- a/webpage/channel.ts
+++ b/webpage/channel.ts
@@ -3,7 +3,7 @@ import { Message } from "./message.js";
import {Voice} from "./audio.js";
import {Contextmenu} from "./contextmenu.js";
import {Fullscreen} from "./fullscreen.js";
-import {markdown} from "./markdown.js";
+import {MarkDown} from "./markdown.js";
import {Guild} from "./guild.js";
import { Localuser } from "./localuser.js";
import { Permissions } from "./permissions.js";
@@ -744,10 +744,10 @@ class Channel{
if (!("Notification" in window)) {
} else if (Notification.permission === "granted") {
- let noticontent=markdown(message.content).textContent;
+ let noticontent=message.content.textContent;
if(message.embeds[0]){
noticontent||=message.embeds[0].json.title;
- noticontent||=markdown(message.embeds[0].json.description).textContent;
+ noticontent||=message.content.textContent;
}
noticontent||="Blank Message";
let imgurl=null;
diff --git a/webpage/embed.ts b/webpage/embed.ts
index a9c1494..ac5d60e 100644
--- a/webpage/embed.ts
+++ b/webpage/embed.ts
@@ -1,6 +1,6 @@
import {Fullscreen} from "./fullscreen.js";
import {Message} from "./message.js";
-import {markdown} from "./markdown.js";
+import {MarkDown} from "./markdown.js";
class Embed{
type:string;
@@ -29,6 +29,18 @@ class Embed{
return document.createElement("div");//prevent errors by giving blank div
}
}
+ get message(){
+ return this.owner;
+ }
+ get channel(){
+ return this.message.channel;
+ }
+ get guild(){
+ return this.channel.guild;
+ }
+ get localuser(){
+ return this.guild.localuser;
+ }
generateRich(){
console.log(this.json)
const div=document.createElement("div");
@@ -59,7 +71,7 @@ class Embed{
embed.append(authorline);
}
const title=document.createElement("a");
- title.append(markdown(this.json.title));
+ title.append(new MarkDown(this.json.title,this.localuser).makeHTML());
if(this.json.url){
title.href=this.json.url;
}
@@ -68,7 +80,7 @@ class Embed{
if(this.json.description){
const p=document.createElement("p");
- p.append(markdown(this.json.description));
+ p.append(new MarkDown(this.json.description,this.channel).makeHTML());
embed.append(p);
}
@@ -80,7 +92,7 @@ class Embed{
b.textContent=thing.name;
div.append(b);
const p=document.createElement("p")
- p.append(markdown(thing.value));
+ p.append(new MarkDown(thing.value,this.channel).makeHTML());
p.classList.add("embedp");
div.append(p);
diff --git a/webpage/localuser.ts b/webpage/localuser.ts
index f3470cb..a363c8b 100644
--- a/webpage/localuser.ts
+++ b/webpage/localuser.ts
@@ -4,7 +4,7 @@ import {Direct} from "./direct.js";
import {Voice} from "./audio.js";
import {User} from "./user.js";
import {Member} from "./member.js";
-import {markdown} from "./markdown.js";
+import {MarkDown} from "./markdown.js";
import {Fullscreen} from "./fullscreen.js";
import {setTheme, Specialuser} from "./login.js";
diff --git a/webpage/markdown.ts b/webpage/markdown.ts
index 128297d..3cf3a6e 100644
--- a/webpage/markdown.ts
+++ b/webpage/markdown.ts
@@ -1,413 +1,446 @@
-export {markdown};
-function markdown(text : string|string[],{keep=false,stdsize=false} = {}){
- let txt : string[];
- if((typeof text)===(typeof "")){
- txt=(text as string).split("");
- }else{
- txt=(text as string[]);
- }
- if(txt===undefined){
- txt=[];
- }
- const span=document.createElement("span");
- let current=document.createElement("span");
- function appendcurrent(){
- if(current.innerHTML!==""){
- span.append(current);
- current=document.createElement("span");
+import { Channel } from "./channel";
+import { Localuser } from "./localuser";
+
+export {MarkDown};
+class MarkDown{
+ txt : string[];
+ keep:boolean;
+ stdsize:boolean;
+ owner:Localuser|Channel;
+ info:Localuser["info"];
+ constructor(text : string|string[],owner:MarkDown["owner"],{keep=false,stdsize=false} = {}){
+ if((typeof text)===(typeof "")){
+ this.txt=(text as string).split("");
+ }else{
+ this.txt=(text as string[]);
}
-
+ if(this.txt===undefined){
+ this.txt=[];
+ }
+ this.info=owner.info;
+ this.keep=keep;
+ this.owner=owner;
+ this.stdsize=stdsize;
}
- for(let i=0;i"&&txt[i+2]===" "){
+ element=document.createElement("div");
+ const line=document.createElement("div");
+ line.classList.add("quoteline");
+ element.append(line);
+ element.classList.add("quote");
+ keepys="> ";
i+=3;
}
- }else if(txt[i+1]===">"&&txt[i+2]===" "){
- element=document.createElement("div");
- const line=document.createElement("div");
- line.classList.add("quoteline");
- element.append(line);
- element.classList.add("quote");
- keepys="> ";
- i+=3;
- }
- if(keepys){
- appendcurrent();
- if(!first&&!stdsize){
- span.appendChild(document.createElement("br"));
+ if(keepys){
+ appendcurrent();
+ if(!first&&!stdsize){
+ span.appendChild(document.createElement("br"));
+ }
+ const build=[];
+ for(;txt[i]!=="\n"&&txt[i]!==undefined;i++){
+ build.push(txt[i]);
+ }
+ if(stdsize){
+ element=document.createElement("span");
+ }
+ if(keep){
+ element.append(keepys);
+ }
+ element.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
+ span.append(element);
+ i--;
+ continue;
}
- const build=[];
- for(;txt[i]!=="\n"&&txt[i]!==undefined;i++){
- build.push(txt[i]);
+ if(first){
+ i++;
+ }
+ }
+ if(txt[i]==="\n"){
+
+ if(!stdsize){
+ appendcurrent();
+ span.append(document.createElement("br"));
+ }
+ continue;
+ }
+ if(txt[i]==="`"){
+ let count=1;
+ if(txt[i+1]==="`"){
+ count++;
+ if(txt[i+2]==="`"){
+ count++;
+ }
+ }
+ let build="";
+ if(keep){
+ build+="`".repeat(count);
+ }
+ let find=0;
+ let j=i+count;
+ let init=true;
+ for(;txt[j]!==undefined&&(txt[j]!=="\n"||count===3)&&find!==count;j++){
+ if(txt[j]==="`"){
+ find++;
+ }else{
+ if(find!==0){
+ build+="`".repeat(find);
+ find=0;
+ }
+ if(init&&count===3){
+ if(txt[j]===" "||txt[j]==="\n"){
+ init=false;
+ }
+ if(keep){
+ build+=txt[j];
+ }
+ continue;
+ }
+ build+=txt[j];
+ }
}
if(stdsize){
- element=document.createElement("span");
+ console.log(build);
+ build=build.replaceAll("\n","");
+ console.log(build,JSON.stringify(build));
}
- if(keep){
- element.append(keepys);
- }
- element.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
- span.append(element);
- i--;
- continue;
- }
- if(first){
- i++;
- }
- }
- if(txt[i]==="\n"){
-
- if(!stdsize){
- appendcurrent();
- span.append(document.createElement("br"));
- }
- continue;
- }
- if(txt[i]==="`"){
- let count=1;
- if(txt[i+1]==="`"){
- count++;
- if(txt[i+2]==="`"){
- count++;
- }
- }
- let build="";
- if(keep){
- build+="`".repeat(count);
- }
- let find=0;
- let j=i+count;
- let init=true;
- for(;txt[j]!==undefined&&(txt[j]!=="\n"||count===3)&&find!==count;j++){
- if(txt[j]==="`"){
- find++;
- }else{
- if(find!==0){
- build+="`".repeat(find);
- find=0;
- }
- if(init&&count===3){
- if(txt[j]===" "||txt[j]==="\n"){
- init=false;
- }
- if(keep){
- build+=txt[j];
- }
- continue;
- }
- build+=txt[j];
- }
- }
- if(stdsize){
- console.log(build);
- build=build.replaceAll("\n","");
- console.log(build,JSON.stringify(build));
- }
- if(find===count){
- appendcurrent();
- i=j;
- if(keep){
- build+="`".repeat(find);
- }
- if(count!==3&&!stdsize){
- const samp=document.createElement("samp");
- samp.textContent=build;
- span.appendChild(samp);
- }else{
- const pre=document.createElement("pre");
- if(build[build.length-1]==="\n"){
- build=build.substring(0,build.length-1);
- }
- if(txt[i]==="\n"){
- i++
- }
- pre.textContent=build;
- span.appendChild(pre);
- }
- i--;
- continue;
- }
- }
-
- if(txt[i]==="*"){
- let count=1;
- if(txt[i+1]==="*"){
- count++;
- if(txt[i+2]==="*"){
- count++;
- }
- }
- let build=[];
- let find=0;
- let j=i+count;
- for(;txt[j]!==undefined&&find!==count;j++){
-
- if(txt[j]==="*"){
- find++;
- }else{
- build.push(txt[j]);
- if(find!==0){
- build=build.concat(new Array(find).fill("*"));
- find=0;
- }
- }
- }
- if(find===count&&(count!=1||txt[i+1]!==" ")){
- appendcurrent();
- i=j;
-
- const stars="*".repeat(count);
- if(count===1){
- const i=document.createElement("i");
- if(keep){i.append(stars)}
- i.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
- if(keep){i.append(stars)}
- span.appendChild(i);
- }else if(count===2){
- const b=document.createElement("b");
- if(keep){b.append(stars)}
- b.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
- if(keep){b.append(stars)}
- span.appendChild(b);
- }else{
- const b=document.createElement("b");
- const i=document.createElement("i");
- if(keep){b.append(stars)}
- b.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
- if(keep){b.append(stars)}
- i.appendChild(b);
- span.appendChild(i);
- }
- i--
- continue;
- }
- }
-
- if(txt[i]==="_"){
- let count=1;
- if(txt[i+1]==="_"){
- count++;
- if(txt[i+2]==="_"){
- count++;
- }
- }
- let build=[];
- let find=0;
- let j=i+count;
- for(;txt[j]!==undefined&&find!==count;j++){
-
- if(txt[j]==="_"){
- find++;
- }else{
- build.push(txt[j]);
- if(find!==0){
- build=build.concat(new Array(find).fill("_"));
- find=0;
- }
- }
- }
- if(find===count&&(count!=1||(txt[j+1]===" "||txt[j+1]==="\n"||txt[j+1]===undefined))){
- appendcurrent();
- i=j;
- const underscores="_".repeat(count);
- if(count===1){
- const i=document.createElement("i");
- if(keep){i.append(underscores)}
- i.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
- if(keep){i.append(underscores)}
- span.appendChild(i);
- }else if(count===2){
- const u=document.createElement("u");
- if(keep){u.append(underscores)}
- u.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
- if(keep){u.append(underscores)}
- span.appendChild(u);
- }else{
- const u=document.createElement("u");
- const i=document.createElement("i");
- if(keep){i.append(underscores)}
- i.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
- if(keep){i.append(underscores)}
- u.appendChild(i)
- span.appendChild(u);
- }
- i--;
- continue;
- }
- }
-
- if(txt[i]==="~"&&txt[i+1]==="~"){
- let count=2;
- let build=[];
- let find=0;
- let j=i+2;
- for(;txt[j]!==undefined&&find!==count;j++){
- if(txt[j]==="~"){
- find++;
- }else{
- build.push(txt[j]);
- if(find!==0){
- build=build.concat(new Array(find).fill("~"));
- find=0;
- }
- }
- }
- if(find===count){
- appendcurrent();
- i=j;
- const tildes="~~";
- if(count===2){
- const s=document.createElement("s");
- if(keep){s.append(tildes)}
- s.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
- if(keep){s.append(tildes)}
- span.appendChild(s);
- }
- continue;
- }
- }
- if(txt[i]==="|"&&txt[i+1]==="|"){
- let count=2;
- let build=[];
- let find=0;
- let j=i+2;
- for(;txt[j]!==undefined&&find!==count;j++){
- if(txt[j]==="|"){
- find++;
- }else{
- build.push(txt[j]);
- if(find!==0){
- build=build.concat(new Array(find).fill("~"));
- find=0;
- }
- }
- }
- if(find===count){
- appendcurrent();
- i=j;
- const pipes="||";
- if(count===2){
- const j=document.createElement("j");
- if(keep){j.append(pipes)}
- j.appendChild(markdown(build,{keep:keep,stdsize:stdsize}));
- j.classList.add("spoiler");
- j.onclick=markdown.unspoil;
- if(keep){j.append(pipes)}
- span.appendChild(j);
- }
- continue;
- }
- }
-
- if (txt[i]==="<" && txt[i + 1]==="t" && txt[i + 2]===":") {
- let found=false;
- const build=["<","t",":"];
- let j = i+3;
- for (; txt[j] !== void 0; j++) {
- build.push(txt[j]);
-
- if (txt[j]===">") {
- found=true;
- break;
- }
- }
-
- if (found) {
- appendcurrent();
- i=j;
-
- const parts=build.join("").match(/^$/);
- const dateInput=new Date(Number.parseInt(parts[1]) * 1000);
- let time="";
- if (Number.isNaN(dateInput.getTime())) time=build.join("");
- else {
- if (parts[3]==="d") time=dateInput.toLocaleString(void 0, {day: "2-digit", month: "2-digit", year: "numeric"});
- else if (parts[3]==="D") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric"});
- else if (!parts[3] || parts[3]==="f") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric"}) + " " +
- dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"});
- else if (parts[3]==="F") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric", weekday: "long"}) + " " +
- dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"});
- else if (parts[3]==="t") time=dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"});
- else if (parts[3]==="T") time=dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit", second: "2-digit"});
- else if (parts[3]==="R") time=Math.round((Date.now() - (Number.parseInt(parts[1]) * 1000))/1000/60) + " minutes ago";
- }
-
- const timeElem=document.createElement("span");
- timeElem.classList.add("markdown-timestamp");
- timeElem.textContent=time;
- span.appendChild(timeElem);
- continue;
- }
- }
-
- if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) {
- let found=false;
- const build = txt[i + 1] === "a" ? ["<","a",":"] : ["<",":"];
- let j = i+build.length;
- for (; txt[j] !== void 0; j++) {
- build.push(txt[j]);
-
- if (txt[j]===">") {
- found=true;
- break;
- }
- }
-
- if (found) {
- const parts=build.join("").match(/^<(a)?:\w+:(\d{10,30})>$/);
- if (parts && parts[2]) {
+ if(find===count){
appendcurrent();
i=j;
- console.log(typeof txt,txt);
- const isEmojiOnly = txt.join("").trim()===build.join("").trim();
-
- const emojiElem=document.createElement("img");
- emojiElem.classList.add("md-emoji");
- emojiElem.width=isEmojiOnly ? 48 : 22;
- emojiElem.height=isEmojiOnly ? 48 : 22;
- emojiElem.crossOrigin="anonymous";
- //emojiElem.src=this.info.cdn.toString() + "/emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32";
- //must uncomment later
- emojiElem.alt="";
- emojiElem.loading="lazy";
- span.appendChild(emojiElem);
-
+ if(keep){
+ build+="`".repeat(find);
+ }
+ if(count!==3&&!stdsize){
+ const samp=document.createElement("samp");
+ samp.textContent=build;
+ span.appendChild(samp);
+ }else{
+ const pre=document.createElement("pre");
+ if(build[build.length-1]==="\n"){
+ build=build.substring(0,build.length-1);
+ }
+ if(txt[i]==="\n"){
+ i++
+ }
+ pre.textContent=build;
+ span.appendChild(pre);
+ }
+ i--;
continue;
}
}
+
+ if(txt[i]==="*"){
+ let count=1;
+ if(txt[i+1]==="*"){
+ count++;
+ if(txt[i+2]==="*"){
+ count++;
+ }
+ }
+ let build=[];
+ let find=0;
+ let j=i+count;
+ for(;txt[j]!==undefined&&find!==count;j++){
+
+ if(txt[j]==="*"){
+ find++;
+ }else{
+ build.push(txt[j]);
+ if(find!==0){
+ build=build.concat(new Array(find).fill("*"));
+ find=0;
+ }
+ }
+ }
+ if(find===count&&(count!=1||txt[i+1]!==" ")){
+ appendcurrent();
+ i=j;
+
+ const stars="*".repeat(count);
+ if(count===1){
+ const i=document.createElement("i");
+ if(keep){i.append(stars)}
+ i.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
+ if(keep){i.append(stars)}
+ span.appendChild(i);
+ }else if(count===2){
+ const b=document.createElement("b");
+ if(keep){b.append(stars)}
+ b.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
+ if(keep){b.append(stars)}
+ span.appendChild(b);
+ }else{
+ const b=document.createElement("b");
+ const i=document.createElement("i");
+ if(keep){b.append(stars)}
+ b.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
+ if(keep){b.append(stars)}
+ i.appendChild(b);
+ span.appendChild(i);
+ }
+ i--
+ continue;
+ }
+ }
+
+ if(txt[i]==="_"){
+ let count=1;
+ if(txt[i+1]==="_"){
+ count++;
+ if(txt[i+2]==="_"){
+ count++;
+ }
+ }
+ let build=[];
+ let find=0;
+ let j=i+count;
+ for(;txt[j]!==undefined&&find!==count;j++){
+
+ if(txt[j]==="_"){
+ find++;
+ }else{
+ build.push(txt[j]);
+ if(find!==0){
+ build=build.concat(new Array(find).fill("_"));
+ find=0;
+ }
+ }
+ }
+ if(find===count&&(count!=1||(txt[j+1]===" "||txt[j+1]==="\n"||txt[j+1]===undefined))){
+ appendcurrent();
+ i=j;
+ const underscores="_".repeat(count);
+ if(count===1){
+ const i=document.createElement("i");
+ if(keep){i.append(underscores)}
+ i.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
+ if(keep){i.append(underscores)}
+ span.appendChild(i);
+ }else if(count===2){
+ const u=document.createElement("u");
+ if(keep){u.append(underscores)}
+ u.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
+ if(keep){u.append(underscores)}
+ span.appendChild(u);
+ }else{
+ const u=document.createElement("u");
+ const i=document.createElement("i");
+ if(keep){i.append(underscores)}
+ i.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
+ if(keep){i.append(underscores)}
+ u.appendChild(i)
+ span.appendChild(u);
+ }
+ i--;
+ continue;
+ }
+ }
+
+ if(txt[i]==="~"&&txt[i+1]==="~"){
+ let count=2;
+ let build=[];
+ let find=0;
+ let j=i+2;
+ for(;txt[j]!==undefined&&find!==count;j++){
+ if(txt[j]==="~"){
+ find++;
+ }else{
+ build.push(txt[j]);
+ if(find!==0){
+ build=build.concat(new Array(find).fill("~"));
+ find=0;
+ }
+ }
+ }
+ if(find===count){
+ appendcurrent();
+ i=j;
+ const tildes="~~";
+ if(count===2){
+ const s=document.createElement("s");
+ if(keep){s.append(tildes)}
+ s.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
+ if(keep){s.append(tildes)}
+ span.appendChild(s);
+ }
+ continue;
+ }
+ }
+ if(txt[i]==="|"&&txt[i+1]==="|"){
+ let count=2;
+ let build=[];
+ let find=0;
+ let j=i+2;
+ for(;txt[j]!==undefined&&find!==count;j++){
+ if(txt[j]==="|"){
+ find++;
+ }else{
+ build.push(txt[j]);
+ if(find!==0){
+ build=build.concat(new Array(find).fill("~"));
+ find=0;
+ }
+ }
+ }
+ if(find===count){
+ appendcurrent();
+ i=j;
+ const pipes="||";
+ if(count===2){
+ const j=document.createElement("j");
+ if(keep){j.append(pipes)}
+ j.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
+ j.classList.add("spoiler");
+ j.onclick=MarkDown.unspoil;
+ if(keep){j.append(pipes)}
+ span.appendChild(j);
+ }
+ continue;
+ }
+ }
+
+ if (txt[i]==="<" && txt[i + 1]==="t" && txt[i + 2]===":") {
+ let found=false;
+ const build=["<","t",":"];
+ let j = i+3;
+ for (; txt[j] !== void 0; j++) {
+ build.push(txt[j]);
+
+ if (txt[j]===">") {
+ found=true;
+ break;
+ }
+ }
+
+ if (found) {
+ appendcurrent();
+ i=j;
+
+ const parts=build.join("").match(/^$/);
+ const dateInput=new Date(Number.parseInt(parts[1]) * 1000);
+ let time="";
+ if (Number.isNaN(dateInput.getTime())) time=build.join("");
+ else {
+ if (parts[3]==="d") time=dateInput.toLocaleString(void 0, {day: "2-digit", month: "2-digit", year: "numeric"});
+ else if (parts[3]==="D") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric"});
+ else if (!parts[3] || parts[3]==="f") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric"}) + " " +
+ dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"});
+ else if (parts[3]==="F") time=dateInput.toLocaleString(void 0, {day: "numeric", month: "long", year: "numeric", weekday: "long"}) + " " +
+ dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"});
+ else if (parts[3]==="t") time=dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit"});
+ else if (parts[3]==="T") time=dateInput.toLocaleString(void 0, {hour: "2-digit", minute: "2-digit", second: "2-digit"});
+ else if (parts[3]==="R") time=Math.round((Date.now() - (Number.parseInt(parts[1]) * 1000))/1000/60) + " minutes ago";
+ }
+
+ const timeElem=document.createElement("span");
+ timeElem.classList.add("markdown-timestamp");
+ timeElem.textContent=time;
+ span.appendChild(timeElem);
+ continue;
+ }
+ }
+
+ if (txt[i] === "<" && (txt[i + 1] === ":" || (txt[i + 1] === "a" && txt[i + 2] === ":"))) {
+ let found=false;
+ const build = txt[i + 1] === "a" ? ["<","a",":"] : ["<",":"];
+ let j = i+build.length;
+ for (; txt[j] !== void 0; j++) {
+ build.push(txt[j]);
+
+ if (txt[j]===">") {
+ found=true;
+ break;
+ }
+ }
+
+ if (found) {
+ const buildjoin=build.join("");
+ const parts=buildjoin.match(/^<(a)?:\w+:(\d{10,30})>$/);
+ if (parts && parts[2]) {
+ appendcurrent();
+ i=j;
+ console.log(typeof txt,txt);
+ const isEmojiOnly = txt.join("").trim()===buildjoin.trim();
+ console.log(isEmojiOnly,":3");
+
+ const emojiElem=document.createElement("img");
+ emojiElem.classList.add("md-emoji");
+ emojiElem.classList.add(isEmojiOnly ? "bigemoji" : "smallemoji");
+ emojiElem.crossOrigin="anonymous";
+ emojiElem.src=this.info.cdn.toString() + "emojis/" + parts[2] + "." + (parts[1] ? "gif" : "png") + "?size=32";
+
+ emojiElem.alt=buildjoin;
+ emojiElem.loading="lazy";
+ span.appendChild(emojiElem);
+
+ continue;
+ }
+ }
+ }
+
+ current.textContent+=txt[i];
}
-
- current.textContent+=txt[i];
+ appendcurrent();
+ return span;
+ }
+ static unspoil(e:any) : void{
+ e.target.classList.remove("spoiler")
+ e.target.classList.add("unspoiled")
}
- appendcurrent();
- return span;
-}
-markdown.unspoil=function(e:any) : void{
- //console.log("undone")
- e.target.classList.remove("spoiler")
- e.target.classList.add("unspoiled")
}
diff --git a/webpage/message.ts b/webpage/message.ts
index 91eb35b..a16ac7b 100644
--- a/webpage/message.ts
+++ b/webpage/message.ts
@@ -1,7 +1,7 @@
import {Contextmenu} from "./contextmenu.js";
import {User} from "./user.js";
import {Member} from "./member.js";
-import {markdown} from "./markdown.js";
+import {MarkDown} from "./markdown.js";
import {Embed} from "./embed.js";
import { Channel } from "./channel.js";
import {Localuser} from "./localuser.js";
@@ -21,7 +21,7 @@ class Message{
message_reference;
type:number;
timestamp:number;
- content:string;
+ content:MarkDown;
static del:Promise;
static resolve:Function;
div:HTMLDivElement;
@@ -37,7 +37,7 @@ class Message{
}
static setupcmenu(){
Message.contextmenu.addbutton("Copy raw text",function(){
- navigator.clipboard.writeText(this.content);
+ navigator.clipboard.writeText(this.content.rawString);
});
Message.contextmenu.addbutton("Reply",function(this:Message,div:HTMLDivElement){
this.channel.setReplying(this);
@@ -67,6 +67,9 @@ class Message{
this.attachments.push(new File(thing,this));
}
continue;
+ }else if(thing==="content"){
+ this.content=new MarkDown(messagejson[thing],this.channel);
+ continue;
}
this[thing]=messagejson[thing];
}
@@ -210,7 +213,7 @@ class Message{
replyline.classList.add("replyflex")
this.channel.getmessage(this.message_reference.message_id).then(message=>{
const author=message.author;
- reply.appendChild(markdown(message.content,{stdsize:true}));
+ reply.appendChild(message.content.makeHTML({stdsize:true}));
minipfp.src=author.getpfpsrc()
author.bind(minipfp);
username.textContent=author.username;
@@ -271,7 +274,7 @@ class Message{
}else{
div.classList.remove("topMessage");
}
- const messaged=markdown(this.content);
+ const messaged=this.content.makeHTML();
div["txt"]=messaged;
const messagedwrap=document.createElement("div");
messagedwrap.classList.add("flexttb")
diff --git a/webpage/style.css b/webpage/style.css
index 6f5fc92..31d8555 100644
--- a/webpage/style.css
+++ b/webpage/style.css
@@ -1359,3 +1359,11 @@ span {
.sizeupdown{
height:4in;
}
+.bigemoji{
+ width:48px;
+ height:48px;
+}
+.smallemoji{
+ width:22px;
+ height:22px;
+}
\ No newline at end of file
diff --git a/webpage/user.ts b/webpage/user.ts
index dadf121..d62433b 100644
--- a/webpage/user.ts
+++ b/webpage/user.ts
@@ -1,6 +1,6 @@
//const usercache={};
import {Member} from "./member.js";
-import {markdown} from "./markdown.js";
+import {MarkDown} from "./markdown.js";
import {Contextmenu} from "./contextmenu.js";
import {Localuser} from "./localuser.js";
import {Guild} from "./guild.js";
@@ -12,7 +12,7 @@ class User{
id:string;
avatar:string;
username:string;
- bio:string;
+ bio:MarkDown;
discriminator:string;
pronouns:string;
bot:boolean;
@@ -49,6 +49,10 @@ class User{
if(!owner){console.error("missing localuser")}
if(dontclone){
for(const thing of Object.keys(userjson)){
+ if(thing==="bio"){
+ this.bio=new MarkDown(userjson[thing],this.localuser);
+ continue;
+ }
this[thing]=userjson[thing];
}
this.hypotheticalpfp=false;
@@ -152,7 +156,7 @@ class User{
const rule=document.createElement("hr");
userbody.appendChild(rule);
- const biohtml=markdown(this.bio);
+ const biohtml=this.bio.makeHTML();
userbody.appendChild(biohtml);
}
console.log(div);
From 95a651396d8e4730b717a9330a778fc2f71e9d3a Mon Sep 17 00:00:00 2001
From: MathMan05
Date: Sat, 20 Jul 2024 19:06:08 -0500
Subject: [PATCH 04/10] got rid of uneeded logs
---
.dist/markdown.js | 2 --
webpage/markdown.ts | 2 --
2 files changed, 4 deletions(-)
diff --git a/.dist/markdown.js b/.dist/markdown.js
index 8111f5f..c98a848 100644
--- a/.dist/markdown.js
+++ b/.dist/markdown.js
@@ -449,9 +449,7 @@ class MarkDown {
if (parts && parts[2]) {
appendcurrent();
i = j;
- console.log(typeof txt, txt);
const isEmojiOnly = txt.join("").trim() === buildjoin.trim();
- console.log(isEmojiOnly, ":3");
const emojiElem = document.createElement("img");
emojiElem.classList.add("md-emoji");
emojiElem.classList.add(isEmojiOnly ? "bigemoji" : "smallemoji");
diff --git a/webpage/markdown.ts b/webpage/markdown.ts
index 3cf3a6e..8896749 100644
--- a/webpage/markdown.ts
+++ b/webpage/markdown.ts
@@ -414,9 +414,7 @@ class MarkDown{
if (parts && parts[2]) {
appendcurrent();
i=j;
- console.log(typeof txt,txt);
const isEmojiOnly = txt.join("").trim()===buildjoin.trim();
- console.log(isEmojiOnly,":3");
const emojiElem=document.createElement("img");
emojiElem.classList.add("md-emoji");
From f2ce41d48aa671ca6a401b93ac024b9aeb40f1ba Mon Sep 17 00:00:00 2001
From: TomatoCake <60300461+DEVTomatoCake@users.noreply.github.com>
Date: Sun, 21 Jul 2024 10:59:38 +0200
Subject: [PATCH 05/10] thanks git for yeeting my changes
---
webpage/index.ts | 29 +++++++++--------------------
1 file changed, 9 insertions(+), 20 deletions(-)
diff --git a/webpage/index.ts b/webpage/index.ts
index b3db4ee..6f37235 100644
--- a/webpage/index.ts
+++ b/webpage/index.ts
@@ -183,26 +183,15 @@ function userSettings(){
thisuser.usersettings.show();
}
document.getElementById("settings").onclick=userSettings;
-let triggered=false;
-document.getElementById("messagecontainer").addEventListener("scroll",(e)=>{
- const messagecontainer=document.getElementById("messagecontainer")
- if(messagecontainer.scrollTop<2000){
- if(!triggered){
- thisuser.lookingguild.prevchannel.grabmoremessages().then(()=>{
- triggered=false;
- if(messagecontainer.scrollTop===0){
- messagecontainer.scrollTop=1;
- }
- });
- }
- triggered=true;
- }else{
- if(Math.abs(messagecontainer.scrollHeight-messagecontainer.scrollTop-messagecontainer.clientHeight) < 3){
- thisuser.lookingguild.prevchannel.readbottom();
- }
- }
- //
-})
+function userConnections(){
+ thisuser.userConnections.show();
+}
+document.getElementById("connections").onclick=userConnections;
+function devPortal(){
+ thisuser.devPortal.show();
+}
+document.getElementById("dev-portal").onclick=devPortal;
+
if(mobile){
document.getElementById("channelw").onclick=function(){
(document.getElementById("channels").parentNode as HTMLElement).classList.add("collapse");
From 02f53fb1e5384766b545a2df8cca2c7ed18f22a4 Mon Sep 17 00:00:00 2001
From: MathMan05
Date: Sun, 21 Jul 2024 15:55:44 -0500
Subject: [PATCH 06/10] Implements a markdown box
---
.dist/embed.js | 2 +-
.dist/index.js | 10 +++--
.dist/localuser.js | 6 ++-
.dist/markdown.js | 89 +++++++++++++++++++++++++++++++++++++--
.dist/message.js | 4 +-
webpage/embed.ts | 2 +-
webpage/index.html | 2 +-
webpage/index.ts | 12 ++++--
webpage/localuser.ts | 6 ++-
webpage/markdown.ts | 99 +++++++++++++++++++++++++++++++++++++++++---
webpage/message.ts | 4 +-
webpage/style.css | 15 +++++--
12 files changed, 221 insertions(+), 30 deletions(-)
diff --git a/.dist/embed.js b/.dist/embed.js
index e617bdb..76fcbf3 100644
--- a/.dist/embed.js
+++ b/.dist/embed.js
@@ -67,7 +67,7 @@ class Embed {
embed.append(authorline);
}
const title = document.createElement("a");
- title.append(new MarkDown(this.json.title, this.localuser).makeHTML());
+ title.append(new MarkDown(this.json.title, this.channel).makeHTML());
if (this.json.url) {
title.href = this.json.url;
}
diff --git a/.dist/index.js b/.dist/index.js
index 7421acd..7894e2b 100644
--- a/.dist/index.js
+++ b/.dist/index.js
@@ -109,7 +109,7 @@ async function enter(event) {
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
if (channel.editing) {
- channel.editing.edit((typebox).value);
+ channel.editing.edit(markdown.rawString);
channel.editing = null;
}
else {
@@ -119,7 +119,7 @@ async function enter(event) {
replyingto.div.classList.remove("replying");
}
thisuser.channelfocus.replyingto = null;
- channel.sendMessage(typebox.value, {
+ channel.sendMessage(markdown.rawString, {
attachments: images,
replyingto: replying,
});
@@ -129,11 +129,14 @@ async function enter(event) {
images.pop();
pasteimage.removeChild(imageshtml.pop());
}
- typebox.value = "";
+ typebox.innerHTML = "";
return;
}
}
const typebox = document.getElementById("typebox");
+const markdown = new MarkDown("", thisuser);
+markdown.giveBox(typebox);
+typebox["markdown"] = markdown;
typebox.addEventListener("keyup", enter);
typebox.addEventListener("keydown", event => {
if (event.key === "Enter" && !event.shiftKey)
@@ -149,6 +152,7 @@ function getguildinfo() {
const images = [];
const imageshtml = [];
import { File } from "./file.js";
+import { MarkDown } from "./markdown.js";
document.addEventListener('paste', async (e) => {
Array.from(e.clipboardData.files).forEach(async (f) => {
const file = File.initFromBlob(f);
diff --git a/.dist/localuser.js b/.dist/localuser.js
index d650a46..dbb8daa 100644
--- a/.dist/localuser.js
+++ b/.dist/localuser.js
@@ -84,7 +84,9 @@ class Localuser {
outoffocus() {
document.getElementById("servers").textContent = "";
document.getElementById("channels").textContent = "";
- this.channelfocus.infinite.delete();
+ if (this.channelfocus) {
+ this.channelfocus.infinite.delete();
+ }
this.lookingguild = null;
this.channelfocus = null;
}
@@ -594,7 +596,7 @@ class Localuser {
newprouns = this.value;
regen();
}],
- ["mdbox", "Bio:", this.user.bio, function (e) {
+ ["mdbox", "Bio:", this.user.bio.rawString, function (e) {
console.log(this.value);
hypouser.bio = this.value;
newbio = this.value;
diff --git a/.dist/markdown.js b/.dist/markdown.js
index c98a848..1cd0b1e 100644
--- a/.dist/markdown.js
+++ b/.dist/markdown.js
@@ -21,7 +21,7 @@ class MarkDown {
this.stdsize = stdsize;
}
get rawString() {
- return this.txt.concat("");
+ return this.txt.join("");
}
get textContent() {
return this.makeHTML().textContent;
@@ -103,7 +103,8 @@ class MarkDown {
}
element.appendChild(this.markdown(build, { keep: keep, stdsize: stdsize }));
span.append(element);
- i--;
+ i -= 1;
+ console.log(txt[i]);
continue;
}
if (first) {
@@ -335,7 +336,7 @@ class MarkDown {
}
if (find === count) {
appendcurrent();
- i = j;
+ i = j - 1;
const tildes = "~~";
if (count === 2) {
const s = document.createElement("s");
@@ -370,7 +371,7 @@ class MarkDown {
}
if (find === count) {
appendcurrent();
- i = j;
+ i = j - 1;
const pipes = "||";
if (count === 2) {
const j = document.createElement("j");
@@ -471,4 +472,84 @@ class MarkDown {
e.target.classList.remove("spoiler");
e.target.classList.add("unspoiled");
}
+ giveBox(box) {
+ box.onkeydown = _ => {
+ //console.log(_);
+ };
+ let prevcontent = "";
+ box.onkeyup = _ => {
+ const content = MarkDown.gatherBoxText(box);
+ if (content !== prevcontent) {
+ prevcontent = content;
+ this.txt = content.split("");
+ this.boxupdate(box);
+ }
+ };
+ box.onpaste = _ => {
+ console.log(_.clipboardData.types);
+ const data = _.clipboardData.getData("text");
+ document.execCommand('insertHTML', false, data);
+ _.preventDefault();
+ box.onkeyup(new KeyboardEvent("_"));
+ };
+ }
+ boxupdate(box) {
+ var restore = saveCaretPosition(box);
+ box.innerHTML = "";
+ box.append(this.makeHTML({ keep: true }));
+ restore();
+ }
+ static gatherBoxText(element) {
+ const children = element.childNodes;
+ if (element.tagName.toLowerCase() === "img") {
+ return element.alt;
+ }
+ if (element.tagName.toLowerCase() === "br") {
+ return "\n";
+ }
+ if (children.length !== 0) {
+ let build = "";
+ for (const thing of children) {
+ if (thing instanceof Text) {
+ const text = thing.textContent;
+ build += text;
+ continue;
+ }
+ const text = this.gatherBoxText(thing);
+ if (text) {
+ build += text;
+ }
+ }
+ return build;
+ }
+ }
+}
+//solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div
+function saveCaretPosition(context) {
+ var selection = window.getSelection();
+ var range = selection.getRangeAt(0);
+ range.setStart(context, 0);
+ var len = range.toString().length;
+ return function restore() {
+ var pos = getTextNodeAtPosition(context, len);
+ selection.removeAllRanges();
+ var range = new Range();
+ range.setStart(pos.node, pos.position);
+ selection.addRange(range);
+ };
+}
+function getTextNodeAtPosition(root, index) {
+ const NODE_TYPE = NodeFilter.SHOW_TEXT;
+ var treeWalker = document.createTreeWalker(root, NODE_TYPE, function next(elem) {
+ if (index > elem.textContent.length) {
+ index -= elem.textContent.length;
+ return NodeFilter.FILTER_REJECT;
+ }
+ return NodeFilter.FILTER_ACCEPT;
+ });
+ var c = treeWalker.nextNode();
+ return {
+ node: c ? c : root,
+ position: index
+ };
}
diff --git a/.dist/message.js b/.dist/message.js
index 6dcaafb..78c8519 100644
--- a/.dist/message.js
+++ b/.dist/message.js
@@ -43,7 +43,9 @@ class Message {
});
Message.contextmenu.addbutton("Edit", function () {
this.channel.editing = this;
- document.getElementById("typebox").value = this.content;
+ const markdown = (document.getElementById("typebox"))["markdown"];
+ markdown.txt = this.content.rawString;
+ markdown.boxupdate(document.getElementById("typebox"));
}, null, _ => { return _.author.id === _.localuser.user.id; });
Message.contextmenu.addbutton("Delete message", function () {
this.delete();
diff --git a/webpage/embed.ts b/webpage/embed.ts
index ac5d60e..b17de58 100644
--- a/webpage/embed.ts
+++ b/webpage/embed.ts
@@ -71,7 +71,7 @@ class Embed{
embed.append(authorline);
}
const title=document.createElement("a");
- title.append(new MarkDown(this.json.title,this.localuser).makeHTML());
+ title.append(new MarkDown(this.json.title,this.channel).makeHTML());
if(this.json.url){
title.href=this.json.url;
}
diff --git a/webpage/index.html b/webpage/index.html
index 07b70b1..88f3c67 100644
--- a/webpage/index.html
+++ b/webpage/index.html
@@ -53,7 +53,7 @@
-
+
typing
diff --git a/webpage/index.ts b/webpage/index.ts
index 48fce30..25526b3 100644
--- a/webpage/index.ts
+++ b/webpage/index.ts
@@ -122,7 +122,7 @@ async function enter(event){
if(event.key === "Enter"&&!event.shiftKey){
event.preventDefault();
if(channel.editing){
- channel.editing.edit((typebox).value);
+ channel.editing.edit(markdown.rawString);
channel.editing=null;
}else{
replyingto= thisuser.channelfocus.replyingto;
@@ -131,7 +131,7 @@ async function enter(event){
replyingto.div.classList.remove("replying");
}
thisuser.channelfocus.replyingto=null;
- channel.sendMessage(typebox.value,{
+ channel.sendMessage(markdown.rawString,{
attachments:images,
replyingto:replying,
})
@@ -141,12 +141,15 @@ async function enter(event){
images.pop();
pasteimage.removeChild(imageshtml.pop());
}
- typebox.value="";
+ typebox.innerHTML="";
return;
}
}
-const typebox=document.getElementById("typebox") as HTMLInputElement;
+const typebox=document.getElementById("typebox") as HTMLDivElement;
+const markdown=new MarkDown("",thisuser);
+markdown.giveBox(typebox);
+typebox["markdown"]=markdown;
typebox.addEventListener("keyup",enter);
typebox.addEventListener("keydown",event=>{
if(event.key === "Enter"&&!event.shiftKey) event.preventDefault();
@@ -166,6 +169,7 @@ const images:Blob[]=[];
const imageshtml=[];
import { File } from "./file.js";
+import { MarkDown } from "./markdown.js";
document.addEventListener('paste', async (e) => {
Array.from(e.clipboardData.files).forEach(async (f) => {
const file=File.initFromBlob(f);
diff --git a/webpage/localuser.ts b/webpage/localuser.ts
index a363c8b..284601b 100644
--- a/webpage/localuser.ts
+++ b/webpage/localuser.ts
@@ -91,7 +91,9 @@ class Localuser{
outoffocus():void{
document.getElementById("servers").textContent="";
document.getElementById("channels").textContent="";
- this.channelfocus.infinite.delete();
+ if(this.channelfocus){
+ this.channelfocus.infinite.delete();
+ }
this.lookingguild=null;
this.channelfocus=null;
}
@@ -620,7 +622,7 @@ class Localuser{
newprouns=this.value;
regen();
}],
- ["mdbox","Bio:",this.user.bio,function(e){
+ ["mdbox","Bio:",this.user.bio.rawString,function(e){
console.log(this.value);
hypouser.bio=this.value;
newbio=this.value;
diff --git a/webpage/markdown.ts b/webpage/markdown.ts
index 8896749..bfbc07b 100644
--- a/webpage/markdown.ts
+++ b/webpage/markdown.ts
@@ -23,7 +23,7 @@ class MarkDown{
this.stdsize=stdsize;
}
get rawString(){
- return this.txt.concat("");
+ return this.txt.join("");
}
get textContent(){
return this.makeHTML().textContent;
@@ -103,7 +103,8 @@ class MarkDown{
}
element.appendChild(this.markdown(build,{keep:keep,stdsize:stdsize}));
span.append(element);
- i--;
+ i-=1;
+ console.log(txt[i]);
continue;
}
if(first){
@@ -309,7 +310,7 @@ class MarkDown{
}
if(find===count){
appendcurrent();
- i=j;
+ i=j-1;
const tildes="~~";
if(count===2){
const s=document.createElement("s");
@@ -339,7 +340,7 @@ class MarkDown{
}
if(find===count){
appendcurrent();
- i=j;
+ i=j-1;
const pipes="||";
if(count===2){
const j=document.createElement("j");
@@ -437,8 +438,94 @@ class MarkDown{
return span;
}
static unspoil(e:any) : void{
- e.target.classList.remove("spoiler")
- e.target.classList.add("unspoiled")
+ e.target.classList.remove("spoiler");
+ e.target.classList.add("unspoiled");
+ }
+ giveBox(box:HTMLDivElement){
+ box.onkeydown=_=>{
+ //console.log(_);
+ };
+ let prevcontent="";
+ box.onkeyup=_=>{
+ const content=MarkDown.gatherBoxText(box);
+ if(content!==prevcontent){
+ prevcontent=content;
+ this.txt=content.split("");
+ this.boxupdate(box);
+ }
+ };
+ box.onpaste=_=>{
+ console.log(_.clipboardData.types)
+ const data=_.clipboardData.getData("text");
+
+ document.execCommand('insertHTML', false, data);
+ _.preventDefault();
+ box.onkeyup(new KeyboardEvent("_"))
+ }
+ }
+ boxupdate(box:HTMLElement){
+ var restore = saveCaretPosition(box);
+ box.innerHTML="";
+ box.append(this.makeHTML({keep:true}))
+ restore();
+ }
+ static gatherBoxText(element:HTMLElement){
+ const children=element.childNodes;
+ if(element.tagName.toLowerCase()==="img"){
+ return (element as HTMLImageElement).alt;
+ }
+ if(element.tagName.toLowerCase()==="br"){
+ return "\n";
+ }
+ if(children.length!==0){
+ let build="";
+ for(const thing of children){
+
+ if(thing instanceof Text){
+
+ const text=thing.textContent;
+ build+=text;
+ continue;
+ }
+ const text=this.gatherBoxText(thing as HTMLElement);
+ if(text){
+ build+=text;
+ }
+ }
+ return build;
+ }
}
}
+//solution from https://stackoverflow.com/questions/4576694/saving-and-restoring-caret-position-for-contenteditable-div
+function saveCaretPosition(context){
+ var selection = window.getSelection();
+ var range = selection.getRangeAt(0);
+ range.setStart( context, 0 );
+ var len = range.toString().length;
+
+ return function restore(){
+ var pos = getTextNodeAtPosition(context, len);
+ selection.removeAllRanges();
+ var range = new Range();
+ range.setStart(pos.node ,pos.position);
+ selection.addRange(range);
+
+ }
+}
+
+function getTextNodeAtPosition(root, index){
+ const NODE_TYPE = NodeFilter.SHOW_TEXT;
+ var treeWalker = document.createTreeWalker(root, NODE_TYPE, function next(elem) {
+ if(index > elem.textContent.length){
+ index -= elem.textContent.length;
+ return NodeFilter.FILTER_REJECT
+ }
+ return NodeFilter.FILTER_ACCEPT;
+ });
+ var c = treeWalker.nextNode();
+ return {
+ node: c? c: root,
+ position: index
+ };
+}
diff --git a/webpage/message.ts b/webpage/message.ts
index a16ac7b..b287411 100644
--- a/webpage/message.ts
+++ b/webpage/message.ts
@@ -47,7 +47,9 @@ class Message{
});
Message.contextmenu.addbutton("Edit",function(){
this.channel.editing=this;
- (document.getElementById("typebox") as HTMLInputElement).value=this.content;
+ const markdown=(document.getElementById("typebox"))["markdown"] as MarkDown;
+ markdown.txt=this.content.rawString;
+ markdown.boxupdate(document.getElementById("typebox"));
},null,_=>{return _.author.id===_.localuser.user.id});
Message.contextmenu.addbutton("Delete message",function(){
this.delete();
diff --git a/webpage/style.css b/webpage/style.css
index 31d8555..8e064cb 100644
--- a/webpage/style.css
+++ b/webpage/style.css
@@ -146,6 +146,7 @@ h1,
h2,
h3 {
margin: 0;
+ display: inline-block;
}
h2 {
@@ -329,15 +330,17 @@ div {
#typebox {
font-family: "acumin-pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 16px;
+ /* font-size: 16px; */
padding: 3px;
border-radius: .25cm;
width: 100%;
- height: .5in;
+ min-height: .5in;
z-index: -100;
max-width: 99%;
display: flex;
max-height: fit-content;
+ max-height: 1.5in;
+ overflow-y: scroll;
}
p {
@@ -598,7 +601,11 @@ textarea {
resize: none;
height: 1.5in;
}
-
+#typebox{
+ color: var(--primary-text);
+ background: var(--textarea-bg);
+ border: 1px solid;
+}
.channels {
overflow: auto;
transition: height .2s ease-in-out;
@@ -1366,4 +1373,4 @@ span {
.smallemoji{
width:22px;
height:22px;
-}
\ No newline at end of file
+}
From b6804c643a3ca413dbef55a583b84d67e9925e4d Mon Sep 17 00:00:00 2001
From: MathMan05
Date: Sun, 21 Jul 2024 16:03:48 -0500
Subject: [PATCH 07/10] changes
---
.dist/index.js | 8 ++
.dist/localuser.js | 239 +++++++++++++++++++++++++++++++++++++++++++
webpage/localuser.ts | 2 +-
3 files changed, 248 insertions(+), 1 deletion(-)
diff --git a/.dist/index.js b/.dist/index.js
index 7894e2b..a139f22 100644
--- a/.dist/index.js
+++ b/.dist/index.js
@@ -168,6 +168,14 @@ function userSettings() {
thisuser.usersettings.show();
}
document.getElementById("settings").onclick = userSettings;
+function userConnections() {
+ thisuser.userConnections.show();
+}
+document.getElementById("connections").onclick = userConnections;
+function devPortal() {
+ thisuser.devPortal.show();
+}
+document.getElementById("dev-portal").onclick = devPortal;
if (mobile) {
document.getElementById("channelw").onclick = function () {
document.getElementById("channels").parentNode.classList.add("collapse");
diff --git a/.dist/localuser.js b/.dist/localuser.js
index dbb8daa..db9bb47 100644
--- a/.dist/localuser.js
+++ b/.dist/localuser.js
@@ -14,6 +14,8 @@ class Localuser {
info;
headers;
usersettings;
+ userConnections;
+ devPortal;
ready;
guilds;
guildids;
@@ -633,6 +635,243 @@ class Localuser {
newprouns = null;
newbio = null;
}.bind(this));
+ const connectionContainer = document.createElement("div");
+ connectionContainer.id = "connection-container";
+ this.userConnections = new Fullscreen(["html",
+ connectionContainer
+ ], () => { }, async () => {
+ connectionContainer.innerHTML = "";
+ const res = await fetch(this.info.api.toString() + "/v9/connections", {
+ headers: this.headers
+ });
+ const json = await res.json();
+ Object.keys(json).sort(key => json[key].enabled ? -1 : 1).forEach(key => {
+ const connection = json[key];
+ const container = document.createElement("div");
+ container.textContent = key.charAt(0).toUpperCase() + key.slice(1);
+ if (connection.enabled) {
+ container.addEventListener("click", async () => {
+ const connectionRes = await fetch(this.info.api.toString() + "/v9/connections/" + key + "/authorize", {
+ headers: this.headers
+ });
+ const connectionJSON = await connectionRes.json();
+ window.open(connectionJSON.url, "_blank", "noopener noreferrer");
+ });
+ }
+ else {
+ container.classList.add("disabled");
+ container.title = "This connection has been disabled server-side.";
+ }
+ connectionContainer.appendChild(container);
+ });
+ });
+ let appName = "";
+ const appListContainer = document.createElement("div");
+ appListContainer.id = "app-list-container";
+ this.devPortal = new Fullscreen(["vdiv",
+ ["hdiv",
+ ["textbox", "Name:", appName, event => {
+ appName = event.target.value;
+ }],
+ ["button",
+ "",
+ "Create application",
+ async () => {
+ if (appName.trim().length == 0)
+ return alert("Please enter a name for the application.");
+ const res = await fetch(this.info.api.toString() + "/v9/applications", {
+ method: "POST",
+ headers: this.headers,
+ body: JSON.stringify({
+ name: appName
+ })
+ });
+ const json = await res.json();
+ this.manageApplication(json.id);
+ this.devPortal.hide();
+ }
+ ]
+ ],
+ ["html",
+ appListContainer
+ ]
+ ], () => { }, async () => {
+ appListContainer.innerHTML = "";
+ const res = await fetch(this.info.api.toString() + "/v9/applications", {
+ headers: this.headers
+ });
+ const json = await res.json();
+ json.forEach(application => {
+ const container = document.createElement("div");
+ if (application.cover_image) {
+ const cover = document.createElement("img");
+ cover.crossOrigin = "anonymous";
+ cover.src = this.info.cdn.toString() + "/app-icons/" + application.id + "/" + application.cover_image + ".png?size=256";
+ cover.alt = "";
+ cover.loading = "lazy";
+ container.appendChild(cover);
+ }
+ const name = document.createElement("h2");
+ name.textContent = application.name + (application.bot ? " (Bot)" : "");
+ container.appendChild(name);
+ container.addEventListener("click", async () => {
+ this.devPortal.hide();
+ this.manageApplication(application.id);
+ });
+ appListContainer.appendChild(container);
+ });
+ });
+ }
+ async manageApplication(appId = "") {
+ const res = await fetch(this.info.api.toString() + "/v9/applications/" + appId, {
+ headers: this.headers
+ });
+ const json = await res.json();
+ const fields = {};
+ const appDialog = new Fullscreen(["vdiv",
+ ["title",
+ "Editing " + json.name
+ ],
+ ["vdiv",
+ ["textbox", "Application name:", json.name, event => {
+ fields.name = event.target.value;
+ }],
+ ["mdbox", "Description:", json.description, event => {
+ fields.description = event.target.value;
+ }],
+ ["vdiv",
+ json.icon ? ["img", this.info.cdn.toString() + "/app-icons/" + appId + "/" + json.icon + ".png?size=128", [128, 128]] : ["text", "No icon"],
+ ["fileupload", "Application icon:", event => {
+ const reader = new FileReader();
+ reader.readAsDataURL(event.target.files[0]);
+ reader.onload = () => {
+ fields.icon = reader.result;
+ };
+ }]
+ ]
+ ],
+ ["hdiv",
+ ["textbox", "Privacy policy URL:", json.privacy_policy_url || "", event => {
+ fields.privacy_policy_url = event.target.value;
+ }],
+ ["textbox", "Terms of Service URL:", json.terms_of_service_url || "", event => {
+ fields.terms_of_service_url = event.target.value;
+ }]
+ ],
+ ["hdiv",
+ ["checkbox", "Make bot publicly inviteable?", json.bot_public, event => {
+ fields.bot_public = event.target.checked;
+ }],
+ ["checkbox", "Require code grant to invite the bot?", json.bot_require_code_grant, event => {
+ fields.bot_require_code_grant = event.target.checked;
+ }]
+ ],
+ ["hdiv",
+ ["button",
+ "",
+ "Save changes",
+ async () => {
+ const updateRes = await fetch(this.info.api.toString() + "/v9/applications/" + appId, {
+ method: "PATCH",
+ headers: this.headers,
+ body: JSON.stringify(fields)
+ });
+ if (updateRes.ok)
+ appDialog.hide();
+ else {
+ const updateJSON = await updateRes.json();
+ alert("An error occurred: " + updateJSON.message);
+ }
+ }
+ ],
+ ["button",
+ "",
+ (json.bot ? "Manage" : "Add") + " bot",
+ async () => {
+ if (!json.bot) {
+ if (!confirm("Are you sure you want to add a bot to this application? There's no going back."))
+ return;
+ const updateRes = await fetch(this.info.api.toString() + "/v9/applications/" + appId + "/bot", {
+ method: "POST",
+ headers: this.headers
+ });
+ const updateJSON = await updateRes.json();
+ alert("Bot token:\n" + updateJSON.token);
+ }
+ appDialog.hide();
+ this.manageBot(appId);
+ }
+ ]
+ ]
+ ]);
+ appDialog.show();
+ }
+ async manageBot(appId = "") {
+ const res = await fetch(this.info.api.toString() + "/v9/applications/" + appId, {
+ headers: this.headers
+ });
+ const json = await res.json();
+ if (!json.bot)
+ return alert("For some reason, this application doesn't have a bot (yet).");
+ const fields = {
+ username: json.bot.username,
+ avatar: json.bot.avatar ? (this.info.cdn.toString() + "/app-icons/" + appId + "/" + json.bot.avatar + ".png?size=256") : ""
+ };
+ const botDialog = new Fullscreen(["vdiv",
+ ["title",
+ "Editing bot: " + json.bot.username
+ ],
+ ["hdiv",
+ ["textbox", "Bot username:", json.bot.username, event => {
+ fields.username = event.target.value;
+ }],
+ ["vdiv",
+ fields.avatar ? ["img", fields.avatar, [128, 128]] : ["text", "No avatar"],
+ ["fileupload", "Bot avatar:", event => {
+ const reader = new FileReader();
+ reader.readAsDataURL(event.target.files[0]);
+ reader.onload = () => {
+ fields.avatar = reader.result;
+ };
+ }]
+ ]
+ ],
+ ["hdiv",
+ ["button",
+ "",
+ "Save changes",
+ async () => {
+ const updateRes = await fetch(this.info.api.toString() + "/v9/applications/" + appId + "/bot", {
+ method: "PATCH",
+ headers: this.headers,
+ body: JSON.stringify(fields)
+ });
+ if (updateRes.ok)
+ botDialog.hide();
+ else {
+ const updateJSON = await updateRes.json();
+ alert("An error occurred: " + updateJSON.message);
+ }
+ }
+ ],
+ ["button",
+ "",
+ "Reset token",
+ async () => {
+ if (!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it."))
+ return;
+ const updateRes = await fetch(this.info.api.toString() + "/v9/applications/" + appId + "/bot/reset", {
+ method: "POST",
+ headers: this.headers
+ });
+ const updateJSON = await updateRes.json();
+ alert("New token:\n" + updateJSON.token);
+ botDialog.hide();
+ }
+ ]
+ ]
+ ]);
+ botDialog.show();
}
}
export { Localuser };
diff --git a/webpage/localuser.ts b/webpage/localuser.ts
index e3246c2..62a742e 100644
--- a/webpage/localuser.ts
+++ b/webpage/localuser.ts
@@ -775,7 +775,7 @@ class Localuser{
["title",
"Editing " + json.name
],
- ["hdiv",
+ ["vdiv",
["textbox", "Application name:", json.name, event => {
fields.name=event.target.value;
}],
From 14d1c69c7d50f9e606d20ac73e1f9ff8f18c5519 Mon Sep 17 00:00:00 2001
From: MathMan05
Date: Sun, 21 Jul 2024 16:14:56 -0500
Subject: [PATCH 08/10] fixed indents
---
webpage/localuser.ts | 478 +++++++++++++++++++++----------------------
1 file changed, 239 insertions(+), 239 deletions(-)
diff --git a/webpage/localuser.ts b/webpage/localuser.ts
index 62a742e..e1ce1a5 100644
--- a/webpage/localuser.ts
+++ b/webpage/localuser.ts
@@ -662,261 +662,261 @@ class Localuser{
newbio=null;
}.bind(this))
- const connectionContainer=document.createElement("div");
- connectionContainer.id="connection-container";
- this.userConnections=new Fullscreen(
- ["html",
- connectionContainer
- ], () => {}, async () => {
- connectionContainer.innerHTML="";
+ const connectionContainer=document.createElement("div");
+ connectionContainer.id="connection-container";
+ this.userConnections=new Fullscreen(
+ ["html",
+ connectionContainer
+ ], () => {}, async () => {
+ connectionContainer.innerHTML="";
- const res=await fetch(this.info.api.toString()+"/v9/connections", {
- headers: this.headers
- });
- const json=await res.json();
+ const res=await fetch(this.info.api.toString()+"/v9/connections", {
+ headers: this.headers
+ });
+ const json=await res.json();
- Object.keys(json).sort(key => json[key].enabled ? -1 : 1).forEach(key => {
- const connection=json[key];
+ Object.keys(json).sort(key => json[key].enabled ? -1 : 1).forEach(key => {
+ const connection=json[key];
- const container=document.createElement("div");
- container.textContent=key.charAt(0).toUpperCase() + key.slice(1);
+ const container=document.createElement("div");
+ container.textContent=key.charAt(0).toUpperCase() + key.slice(1);
- if (connection.enabled) {
- container.addEventListener("click", async () => {
- const connectionRes=await fetch(this.info.api.toString()+"/v9/connections/" + key + "/authorize", {
- headers: this.headers
- });
- const connectionJSON=await connectionRes.json();
- window.open(connectionJSON.url, "_blank", "noopener noreferrer");
- })
- } else {
- container.classList.add("disabled")
- container.title="This connection has been disabled server-side."
- }
+ if (connection.enabled) {
+ container.addEventListener("click", async () => {
+ const connectionRes=await fetch(this.info.api.toString()+"/v9/connections/" + key + "/authorize", {
+ headers: this.headers
+ });
+ const connectionJSON=await connectionRes.json();
+ window.open(connectionJSON.url, "_blank", "noopener noreferrer");
+ })
+ } else {
+ container.classList.add("disabled")
+ container.title="This connection has been disabled server-side."
+ }
- connectionContainer.appendChild(container);
- })
- }
- );
+ connectionContainer.appendChild(container);
+ })
+ }
+ );
- let appName="";
- const appListContainer=document.createElement("div");
- appListContainer.id="app-list-container";
- this.devPortal=new Fullscreen(
- ["vdiv",
- ["hdiv",
- ["textbox", "Name:", appName, event => {
- appName=event.target.value;
- }],
- ["button",
- "",
- "Create application",
- async () => {
- if (appName.trim().length == 0) return alert("Please enter a name for the application.");
+ let appName="";
+ const appListContainer=document.createElement("div");
+ appListContainer.id="app-list-container";
+ this.devPortal=new Fullscreen(
+ ["vdiv",
+ ["hdiv",
+ ["textbox", "Name:", appName, event => {
+ appName=event.target.value;
+ }],
+ ["button",
+ "",
+ "Create application",
+ async () => {
+ if (appName.trim().length == 0) return alert("Please enter a name for the application.");
- const res=await fetch(this.info.api.toString()+"/v9/applications", {
- method: "POST",
- headers: this.headers,
- body: JSON.stringify({
- name: appName
- })
- });
- const json=await res.json();
- this.manageApplication(json.id);
- this.devPortal.hide();
- }
- ]
- ],
- ["html",
- appListContainer
- ]
- ], () => {}, async () => {
- appListContainer.innerHTML="";
+ const res=await fetch(this.info.api.toString()+"/v9/applications", {
+ method: "POST",
+ headers: this.headers,
+ body: JSON.stringify({
+ name: appName
+ })
+ });
+ const json=await res.json();
+ this.manageApplication(json.id);
+ this.devPortal.hide();
+ }
+ ]
+ ],
+ ["html",
+ appListContainer
+ ]
+ ], () => {}, async () => {
+ appListContainer.innerHTML="";
- const res=await fetch(this.info.api.toString()+"/v9/applications", {
- headers: this.headers
- });
- const json=await res.json();
+ const res=await fetch(this.info.api.toString()+"/v9/applications", {
+ headers: this.headers
+ });
+ const json=await res.json();
- json.forEach(application => {
- const container=document.createElement("div");
+ json.forEach(application => {
+ const container=document.createElement("div");
- if (application.cover_image) {
- const cover=document.createElement("img");
- cover.crossOrigin="anonymous";
- cover.src=this.info.cdn.toString()+"/app-icons/" + application.id + "/" + application.cover_image + ".png?size=256";
- cover.alt="";
- cover.loading="lazy";
- container.appendChild(cover);
- }
+ if (application.cover_image) {
+ const cover=document.createElement("img");
+ cover.crossOrigin="anonymous";
+ cover.src=this.info.cdn.toString()+"/app-icons/" + application.id + "/" + application.cover_image + ".png?size=256";
+ cover.alt="";
+ cover.loading="lazy";
+ container.appendChild(cover);
+ }
- const name=document.createElement("h2");
- name.textContent=application.name + (application.bot ? " (Bot)" : "");
- container.appendChild(name);
+ const name=document.createElement("h2");
+ name.textContent=application.name + (application.bot ? " (Bot)" : "");
+ container.appendChild(name);
- container.addEventListener("click", async () => {
- this.devPortal.hide();
- this.manageApplication(application.id);
- });
- appListContainer.appendChild(container);
- })
- }
- )
- }
- async manageApplication(appId="") {
- const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
- headers: this.headers
- });
- const json=await res.json();
+ container.addEventListener("click", async () => {
+ this.devPortal.hide();
+ this.manageApplication(application.id);
+ });
+ appListContainer.appendChild(container);
+ })
+ }
+ )
+ }
+ async manageApplication(appId="") {
+ const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
+ headers: this.headers
+ });
+ const json=await res.json();
- const fields: any={};
- const appDialog=new Fullscreen(
- ["vdiv",
- ["title",
- "Editing " + json.name
- ],
- ["vdiv",
- ["textbox", "Application name:", json.name, event => {
- fields.name=event.target.value;
- }],
- ["mdbox", "Description:", json.description, event => {
- fields.description=event.target.value;
- }],
- ["vdiv",
- json.icon ? ["img", this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.icon + ".png?size=128", [128, 128]] : ["text", "No icon"],
- ["fileupload", "Application icon:", event => {
- const reader=new FileReader();
- reader.readAsDataURL(event.target.files[0]);
- reader.onload=() => {
- fields.icon=reader.result;
- }
- }]
- ]
- ],
- ["hdiv",
- ["textbox", "Privacy policy URL:", json.privacy_policy_url || "", event => {
- fields.privacy_policy_url=event.target.value;
- }],
- ["textbox", "Terms of Service URL:", json.terms_of_service_url || "", event => {
- fields.terms_of_service_url=event.target.value;
- }]
- ],
- ["hdiv",
- ["checkbox", "Make bot publicly inviteable?", json.bot_public, event => {
- fields.bot_public=event.target.checked;
- }],
- ["checkbox", "Require code grant to invite the bot?", json.bot_require_code_grant, event => {
- fields.bot_require_code_grant=event.target.checked;
- }]
- ],
- ["hdiv",
- ["button",
- "",
- "Save changes",
- async () => {
- const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
- method: "PATCH",
- headers: this.headers,
- body: JSON.stringify(fields)
- });
- if (updateRes.ok) appDialog.hide();
- else {
- const updateJSON=await updateRes.json();
- alert("An error occurred: " + updateJSON.message);
- }
- }
- ],
- ["button",
- "",
- (json.bot ? "Manage" : "Add") + " bot",
- async () => {
- if (!json.bot) {
- if (!confirm("Are you sure you want to add a bot to this application? There's no going back.")) return;
+ const fields: any={};
+ const appDialog=new Fullscreen(
+ ["vdiv",
+ ["title",
+ "Editing " + json.name
+ ],
+ ["vdiv",
+ ["textbox", "Application name:", json.name, event => {
+ fields.name=event.target.value;
+ }],
+ ["mdbox", "Description:", json.description, event => {
+ fields.description=event.target.value;
+ }],
+ ["vdiv",
+ json.icon ? ["img", this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.icon + ".png?size=128", [128, 128]] : ["text", "No icon"],
+ ["fileupload", "Application icon:", event => {
+ const reader=new FileReader();
+ reader.readAsDataURL(event.target.files[0]);
+ reader.onload=() => {
+ fields.icon=reader.result;
+ }
+ }]
+ ]
+ ],
+ ["hdiv",
+ ["textbox", "Privacy policy URL:", json.privacy_policy_url || "", event => {
+ fields.privacy_policy_url=event.target.value;
+ }],
+ ["textbox", "Terms of Service URL:", json.terms_of_service_url || "", event => {
+ fields.terms_of_service_url=event.target.value;
+ }]
+ ],
+ ["hdiv",
+ ["checkbox", "Make bot publicly inviteable?", json.bot_public, event => {
+ fields.bot_public=event.target.checked;
+ }],
+ ["checkbox", "Require code grant to invite the bot?", json.bot_require_code_grant, event => {
+ fields.bot_require_code_grant=event.target.checked;
+ }]
+ ],
+ ["hdiv",
+ ["button",
+ "",
+ "Save changes",
+ async () => {
+ const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
+ method: "PATCH",
+ headers: this.headers,
+ body: JSON.stringify(fields)
+ });
+ if (updateRes.ok) appDialog.hide();
+ else {
+ const updateJSON=await updateRes.json();
+ alert("An error occurred: " + updateJSON.message);
+ }
+ }
+ ],
+ ["button",
+ "",
+ (json.bot ? "Manage" : "Add") + " bot",
+ async () => {
+ if (!json.bot) {
+ if (!confirm("Are you sure you want to add a bot to this application? There's no going back.")) return;
- const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", {
- method: "POST",
- headers: this.headers
- });
- const updateJSON=await updateRes.json();
- alert("Bot token:\n" + updateJSON.token);
- }
+ const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", {
+ method: "POST",
+ headers: this.headers
+ });
+ const updateJSON=await updateRes.json();
+ alert("Bot token:\n" + updateJSON.token);
+ }
- appDialog.hide();
- this.manageBot(appId);
- }
- ]
- ]
- ]
- )
- appDialog.show();
- }
- async manageBot(appId="") {
- const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
- headers: this.headers
- });
- const json=await res.json();
- if (!json.bot) return alert("For some reason, this application doesn't have a bot (yet).");
+ appDialog.hide();
+ this.manageBot(appId);
+ }
+ ]
+ ]
+ ]
+ )
+ appDialog.show();
+ }
+ async manageBot(appId="") {
+ const res=await fetch(this.info.api.toString()+"/v9/applications/" + appId, {
+ headers: this.headers
+ });
+ const json=await res.json();
+ if (!json.bot) return alert("For some reason, this application doesn't have a bot (yet).");
- const fields: any={
- username: json.bot.username,
- avatar: json.bot.avatar ? (this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.bot.avatar + ".png?size=256") : ""
- };
- const botDialog=new Fullscreen(
- ["vdiv",
- ["title",
- "Editing bot: " + json.bot.username
- ],
- ["hdiv",
- ["textbox", "Bot username:", json.bot.username, event => {
- fields.username=event.target.value
- }],
- ["vdiv",
- fields.avatar ? ["img", fields.avatar, [128, 128]] : ["text", "No avatar"],
- ["fileupload", "Bot avatar:", event => {
- const reader=new FileReader();
- reader.readAsDataURL(event.target.files[0]);
- reader.onload=() => {
- fields.avatar=reader.result;
- }
- }]
- ]
- ],
- ["hdiv",
- ["button",
- "",
- "Save changes",
- async () => {
- const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", {
- method: "PATCH",
- headers: this.headers,
- body: JSON.stringify(fields)
- });
- if (updateRes.ok) botDialog.hide();
- else {
- const updateJSON=await updateRes.json();
- alert("An error occurred: " + updateJSON.message);
- }
- }
- ],
- ["button",
- "",
- "Reset token",
- async () => {
- if (!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it.")) return;
+ const fields: any={
+ username: json.bot.username,
+ avatar: json.bot.avatar ? (this.info.cdn.toString()+"/app-icons/" + appId + "/" + json.bot.avatar + ".png?size=256") : ""
+ };
+ const botDialog=new Fullscreen(
+ ["vdiv",
+ ["title",
+ "Editing bot: " + json.bot.username
+ ],
+ ["hdiv",
+ ["textbox", "Bot username:", json.bot.username, event => {
+ fields.username=event.target.value
+ }],
+ ["vdiv",
+ fields.avatar ? ["img", fields.avatar, [128, 128]] : ["text", "No avatar"],
+ ["fileupload", "Bot avatar:", event => {
+ const reader=new FileReader();
+ reader.readAsDataURL(event.target.files[0]);
+ reader.onload=() => {
+ fields.avatar=reader.result;
+ }
+ }]
+ ]
+ ],
+ ["hdiv",
+ ["button",
+ "",
+ "Save changes",
+ async () => {
+ const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot", {
+ method: "PATCH",
+ headers: this.headers,
+ body: JSON.stringify(fields)
+ });
+ if (updateRes.ok) botDialog.hide();
+ else {
+ const updateJSON=await updateRes.json();
+ alert("An error occurred: " + updateJSON.message);
+ }
+ }
+ ],
+ ["button",
+ "",
+ "Reset token",
+ async () => {
+ if (!confirm("Are you sure you want to reset the bot token? Your bot will stop working until you update it.")) return;
- const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot/reset", {
- method: "POST",
- headers: this.headers
- });
- const updateJSON=await updateRes.json();
- alert("New token:\n" + updateJSON.token);
- botDialog.hide();
- }
- ]
- ]
- ]
- );
- botDialog.show();
- }
+ const updateRes=await fetch(this.info.api.toString()+"/v9/applications/" + appId + "/bot/reset", {
+ method: "POST",
+ headers: this.headers
+ });
+ const updateJSON=await updateRes.json();
+ alert("New token:\n" + updateJSON.token);
+ botDialog.hide();
+ }
+ ]
+ ]
+ ]
+ );
+ botDialog.show();
+ }
}
export {Localuser};
From 7eb3ff6cab9c13955a1863e806623c8c0ba11404 Mon Sep 17 00:00:00 2001
From: MathMan05
Date: Tue, 23 Jul 2024 23:01:45 -0500
Subject: [PATCH 09/10] snowflake and cleaning up classes
---
.dist/channel.js | 135 ++++++++++++++++++++------------
.dist/direct.js | 25 +++---
.dist/guild.js | 39 ++++------
.dist/localuser.js | 181 +++++++++++++++++++++----------------------
.dist/member.js | 30 +++----
.dist/message.js | 22 ++++--
.dist/role.js | 5 ++
.dist/settings.js | 9 ++-
.dist/snowflake.js | 51 ++++++++++++
.dist/user.js | 19 +++--
webpage/channel.ts | 156 ++++++++++++++++++++++---------------
webpage/direct.ts | 25 +++---
webpage/guild.ts | 43 +++++-----
webpage/localuser.ts | 44 +++++------
webpage/member.ts | 30 +++----
webpage/message.ts | 23 ++++--
webpage/role.ts | 7 +-
webpage/settings.ts | 13 ++--
webpage/snowflake.ts | 53 +++++++++++++
webpage/style.css | 14 ++++
webpage/user.ts | 21 +++--
21 files changed, 584 insertions(+), 361 deletions(-)
create mode 100644 .dist/snowflake.js
create mode 100644 webpage/snowflake.ts
diff --git a/.dist/channel.js b/.dist/channel.js
index 3efee21..ab677cf 100644
--- a/.dist/channel.js
+++ b/.dist/channel.js
@@ -6,7 +6,7 @@ import { Fullscreen } from "./fullscreen.js";
import { Permissions } from "./permissions.js";
import { Settings, RoleList } from "./settings.js";
import { InfiniteScroller } from "./infiniteScroller.js";
-Settings;
+import { SnowFlake } from "./snowflake.js";
class Channel {
editing;
type;
@@ -35,8 +35,8 @@ class Channel {
static contextmenu = new Contextmenu("channel menu");
replyingto;
infinite;
- idToPrev = {};
- idToNext = {};
+ idToPrev = new Map();
+ idToNext = new Map();
static setupcontextmenu() {
this.contextmenu.addbutton("Copy channel id", function () {
console.log(this);
@@ -73,22 +73,24 @@ class Channel {
setUpInfiniteScroller() {
const ids = {};
this.infinite = new InfiniteScroller(async function (id, offset) {
+ const snowflake = SnowFlake.getSnowFlakeFromID(id, Message);
if (offset === 1) {
- if (this.idToPrev[id]) {
- return this.idToPrev[id];
+ if (this.idToPrev.get(snowflake)) {
+ return this.idToPrev.get(snowflake)?.id;
}
else {
- await this.grabmoremessages(id);
- return this.idToPrev[id];
+ await this.grabBefore(id);
+ return this.idToPrev.get(snowflake)?.id;
}
}
else {
- return this.idToNext[id];
+ return this.idToNext.get(snowflake)?.id;
}
}.bind(this), function (id) {
let res;
const promise = new Promise(_ => { res = _; });
- const html = this.messageids[id].buildhtml(this.messageids[this.idToPrev[id]], promise);
+ const snowflake = SnowFlake.getSnowFlakeFromID(id, Message);
+ const html = this.messageids.get(snowflake).buildhtml(this.messageids.get(this.idToPrev.get(snowflake)), promise);
ids[id] = res;
return html;
}.bind(this), async function (id) {
@@ -106,28 +108,27 @@ class Channel {
this.owner = owner;
this.headers = this.owner.headers;
this.name = JSON.name;
- this.id = JSON.id;
- this.parent_id = JSON.parent_id;
+ this.id = new SnowFlake(JSON.id, this);
+ this.parent_id = new SnowFlake(JSON.parent_id, undefined);
this.parent = null;
this.children = [];
this.guild_id = JSON.guild_id;
- this.messageids = {};
- this.permission_overwrites = {};
+ this.messageids = new Map();
+ this.permission_overwrites = new Map();
this.permission_overwritesar = [];
for (const thing of JSON.permission_overwrites) {
- console.log(thing);
if (thing.id === "1182819038095799904" || thing.id === "1182820803700625444") {
continue;
}
;
- this.permission_overwrites[thing.id] = new Permissions(thing.allow, thing.deny);
- this.permission_overwritesar.push([thing.id, this.permission_overwrites[thing.id]]);
+ this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny));
+ this.permission_overwritesar.push([thing.id, this.permission_overwrites.get(thing.id)]);
}
this.topic = JSON.topic;
this.nsfw = JSON.nsfw;
this.position = JSON.position;
this.lastreadmessageid = null;
- this.lastmessageid = JSON.last_message_id;
+ this.lastmessageid = SnowFlake.getSnowFlakeFromID(JSON.last_message_id, Message);
this.setUpInfiniteScroller();
}
isAdmin() {
@@ -143,7 +144,7 @@ class Channel {
return this.owner.info;
}
readStateInfo(json) {
- this.lastreadmessageid = json.last_message_id;
+ this.lastreadmessageid = SnowFlake.getSnowFlakeFromID(json.last_message_id, Message);
this.mentions = json.mention_count;
this.mentions ??= 0;
this.lastpin = json.last_pin_timestamp;
@@ -152,15 +153,15 @@ class Channel {
if (!this.hasPermission("VIEW_CHANNEL")) {
return false;
}
- return this.lastmessageid !== this.lastreadmessageid && this.type !== 4;
+ return this.lastmessageid !== this.lastreadmessageid && this.type !== 4 && !!this.lastmessageid.id;
}
hasPermission(name, member = this.guild.member) {
if (member.isAdmin()) {
return true;
}
for (const thing of member.roles) {
- if (this.permission_overwrites[thing.id]) {
- let perm = this.permission_overwrites[thing.id].getPermission(name);
+ if (this.permission_overwrites.get(thing.id.id)) {
+ let perm = this.permission_overwrites.get(thing.id.id).getPermission(name);
if (perm) {
return perm === 1;
}
@@ -181,7 +182,7 @@ class Channel {
this.children.sort((a, b) => { return a.position - b.position; });
}
resolveparent(guild) {
- this.parent = guild.channelids[this.parent_id];
+ this.parent = guild.channelids[this.parent_id?.id];
this.parent ??= null;
if (this.parent !== null) {
this.parent.children.push(this);
@@ -343,7 +344,7 @@ class Channel {
if (!this.hasunreads) {
return;
}
- fetch(this.info.api.toString() + "/v9/channels/" + this.id + "/messages/" + this.lastmessageid + "/ack", {
+ fetch(this.info.api.toString() + "/channels/" + this.id + "/messages/" + this.lastmessageid + "/ack", {
method: "POST",
headers: this.headers,
body: JSON.stringify({})
@@ -433,8 +434,8 @@ class Channel {
["textbox", "Channel name:", this.name, function () { name = this.value; }],
["mdbox", "Channel topic:", this.topic, function () { topic = this.value; }],
["checkbox", "NSFW Channel", this.nsfw, function () { nsfw = this.checked; }],
- ["button", "", "submit", function () {
- fetch(this.info.api.toString() + "/v9/channels/" + thisid, {
+ ["button", "", "submit", () => {
+ fetch(this.info.api.toString() + "/channels/" + thisid, {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({
@@ -457,7 +458,7 @@ class Channel {
console.log(full);
}
deleteChannel() {
- fetch(this.info.api.toString() + "/v9/channels/" + this.id, {
+ fetch(this.info.api.toString() + "/channels/" + this.id, {
method: "DELETE",
headers: this.headers
});
@@ -495,11 +496,12 @@ class Channel {
}
}
async getmessage(id) {
- if (this.messageids[id]) {
- return this.messageids[id];
+ const snowflake = SnowFlake.getSnowFlakeFromID(id, Message);
+ if (snowflake.getObject()) {
+ return snowflake.getObject();
}
else {
- const gety = await fetch(this.info.api.toString() + "/v9/channels/" + this.id + "/messages?limit=1&around=" + id, { headers: this.headers });
+ const gety = await fetch(this.info.api.toString() + "/channels/" + this.id + "/messages?limit=1&around=" + id, { headers: this.headers });
const json = await gety.json();
return new Message(json[0], this);
}
@@ -527,8 +529,9 @@ class Channel {
history.pushState(null, null, "/channels/" + this.guild_id + "/" + this.id);
document.getElementById("channelname").textContent = "#" + this.name;
console.log(this);
- document.getElementById("typebox").disabled = !this.canMessage;
+ document.getElementById("typebox").contentEditable = "" + this.canMessage;
}
+ lastmessage;
async putmessages() {
if (this.allthewayup) {
return;
@@ -545,12 +548,15 @@ class Channel {
for (const thing of response) {
const message = new Message(thing, this);
if (prev) {
- this.idToNext[message.id] = prev.id;
- this.idToPrev[prev.id] = message.id;
+ this.idToNext.set(message.id, prev.id);
+ this.idToPrev.set(prev.id, message.id);
+ }
+ else {
+ this.lastmessage = message;
}
prev = message;
- if (this.messageids[message.id] === undefined) {
- this.messageids[message.id] = message;
+ if (this.messageids.get(message.id) === undefined) {
+ this.messageids.set(message.id, message);
}
}
}
@@ -563,7 +569,7 @@ class Channel {
}
this.children = build;
}
- async grabmoremessages(id) {
+ async grabBefore(id) {
if (this.allthewayup) {
return;
}
@@ -574,7 +580,7 @@ class Channel {
if (response.length === 0) {
this.allthewayup = true;
}
- let previd = id;
+ let previd = SnowFlake.getSnowFlakeFromID(id, Message);
for (const i in response) {
let messager;
if (!next) {
@@ -590,11 +596,11 @@ class Channel {
next = undefined;
console.log("ohno", +i + 1);
}
- if (this.messageids[messager.id] === undefined) {
- this.idToNext[messager.id] = previd;
- this.idToPrev[previd] = messager.id;
+ if (this.messageids.get(messager.id) === undefined) {
+ this.idToNext.set(messager.id, previd);
+ this.idToPrev.set(previd, messager.id);
previd = messager.id;
- this.messageids[messager.id] = messager;
+ this.messageids.set(messager.id, messager);
}
else {
console.log("How???");
@@ -611,17 +617,47 @@ class Channel {
buildmessages() {
const messages = document.getElementById("channelw");
messages.innerHTML = "";
- messages.append(this.infinite.getDiv(this.lastmessageid));
+ let id;
+ if (this.messageids.get(this.lastreadmessageid)) {
+ id = this.lastreadmessageid;
+ }
+ else if (this.lastmessage.id) {
+ id = this.goBackIds(this.lastmessage.id, 50);
+ console.log("shouldn't");
+ }
+ messages.append(this.infinite.getDiv(id.id));
+ }
+ goBackIds(id, back) {
+ while (back !== 0) {
+ const nextid = this.idToPrev.get(id);
+ if (nextid) {
+ id = nextid;
+ console.log(id);
+ back--;
+ }
+ else {
+ break;
+ }
+ }
+ return id;
}
updateChannel(JSON) {
this.type = JSON.type;
this.name = JSON.name;
- this.parent_id = JSON.parent_id;
+ this.parent_id = new SnowFlake(JSON.parent_id, undefined);
this.parent = null;
this.children = [];
this.guild_id = JSON.guild_id;
- this.messageids = {};
- this.permission_overwrites = JSON.permission_overwrites;
+ this.messageids = new Map();
+ this.permission_overwrites = new Map();
+ for (const thing of JSON.permission_overwrites) {
+ if (thing.id === "1182819038095799904" || thing.id === "1182820803700625444") {
+ continue;
+ }
+ ;
+ this.permission_overwrites.set(thing.id, new Permissions(thing.allow, thing.deny));
+ this.permission_overwritesar.push([thing.id, this.permission_overwrites.get(thing.id)]);
+ }
this.topic = JSON.topic;
this.nsfw = JSON.nsfw;
}
@@ -706,10 +742,11 @@ class Channel {
return;
}
const messagez = new Message(messagep.d, this);
- this.idToNext[this.lastmessageid] = messagez.id;
- this.idToPrev[messagez.id] = this.lastmessageid;
+ console.log(this.lastmessageid, messagez.id, ":3");
+ this.idToNext.set(this.lastmessageid, messagez.id);
+ this.idToPrev.set(messagez.id, this.lastmessageid);
this.lastmessageid = messagez.id;
- this.messageids[messagez.id] = messagez;
+ this.messageids.set(messagez.id, messagez);
if (messagez.author === this.localuser.user) {
this.lastreadmessageid = messagez.id;
if (this.myhtml) {
@@ -789,11 +826,11 @@ class Channel {
})
});
const perm = new Permissions("0", "0");
- this.permission_overwrites[role.id] = perm;
+ this.permission_overwrites.set(role.id.id, perm);
this.permission_overwritesar.push([role.id, perm]);
}
async updateRolePermissions(id, perms) {
- const permission = this.permission_overwrites[id];
+ const permission = this.permission_overwrites.get(id);
permission.allow = perms.allow;
permission.deny = perms.deny;
await fetch(this.info.api.toString() + "/channels/" + this.id + "/permissions/" + id, {
diff --git a/.dist/direct.js b/.dist/direct.js
index e8a9620..87cd5fd 100644
--- a/.dist/direct.js
+++ b/.dist/direct.js
@@ -2,6 +2,7 @@ import { Guild } from "./guild.js";
import { Channel } from "./channel.js";
import { Message } from "./message.js";
import { User } from "./user.js";
+import { SnowFlake } from "./snowflake.js";
class Direct extends Guild {
constructor(JSON, owner) {
super(-1, owner, null);
@@ -14,16 +15,16 @@ class Direct extends Guild {
this.headers = this.localuser.headers;
this.channels = [];
this.channelids = {};
- this.id = "@me";
+ this.id = new SnowFlake("@me", this);
this.properties = {};
this.roles = [];
- this.roleids = {};
+ this.roleids = new Map();
this.prevchannel = undefined;
this.properties.name = "Direct Messages";
for (const thing of JSON) {
const temp = new Group(thing, this);
this.channels.push(temp);
- this.channelids[temp.id] = temp;
+ this.channelids[temp.id.id] = temp;
}
this.headchannels = this.channels;
}
@@ -36,7 +37,7 @@ class Direct extends Guild {
}
sortchannels() {
this.headchannels.sort((a, b) => {
- const result = (BigInt(a.lastmessageid) - BigInt(b.lastmessageid));
+ const result = (a.lastmessageid.getUnixTime() - b.lastmessageid.getUnixTime());
return Number(-result);
});
}
@@ -72,15 +73,15 @@ class Group extends Channel {
this.user = this.localuser.user;
}
this.name ??= this.localuser.user.username;
- this.id = JSON.id;
+ this.id = new SnowFlake(JSON.id, this);
this.parent_id = null;
this.parent = null;
this.children = [];
this.guild_id = "@me";
- this.messageids = {};
- this.permission_overwrites = {};
- this.lastmessageid = JSON.last_message_id;
- this.lastmessageid ??= "0";
+ this.messageids = new Map();
+ this.permission_overwrites = new Map();
+ this.lastmessageid = SnowFlake.getSnowFlakeFromID(JSON.last_message_id, Message);
+ this.lastmessageid ??= new SnowFlake("0", undefined);
this.mentions = 0;
this.setUpInfiniteScroller();
}
@@ -116,10 +117,10 @@ class Group extends Channel {
}
messageCreate(messagep) {
const messagez = new Message(messagep.d, this);
- this.idToNext[this.lastmessageid] = messagez.id;
- this.idToPrev[messagez.id] = this.lastmessageid;
+ this.idToNext.set(this.lastmessageid, messagez.id);
+ this.idToPrev.set(messagez.id, this.lastmessageid);
this.lastmessageid = messagez.id;
- this.messageids[messagez.id] = messagez;
+ this.messageids.set(messagez.id, messagez);
if (messagez.author === this.localuser.user) {
this.lastreadmessageid = messagez.id;
if (this.myhtml) {
diff --git a/.dist/guild.js b/.dist/guild.js
index ff6b29d..1290ae2 100644
--- a/.dist/guild.js
+++ b/.dist/guild.js
@@ -4,6 +4,7 @@ import { Role } from "./role.js";
import { Fullscreen } from "./fullscreen.js";
import { Member } from "./member.js";
import { Settings, RoleList } from "./settings.js";
+import { SnowFlake } from "./snowflake.js";
class Guild {
owner;
headers;
@@ -67,30 +68,30 @@ class Guild {
s1.options.push(new RoleList(permlist, this, this.updateRolePermissions.bind(this)));
settings.show();
}
- constructor(JSON, owner, member) {
- if (JSON === -1) {
+ constructor(json, owner, member) {
+ if (json === -1) {
return;
}
this.owner = owner;
this.headers = this.owner.headers;
this.channels = [];
this.channelids = {};
- this.id = JSON.id;
- this.properties = JSON.properties;
+ this.id = new SnowFlake(json.id, this);
+ this.properties = json.properties;
this.roles = [];
- this.roleids = {};
+ this.roleids = new Map();
this.prevchannel = undefined;
this.message_notifications = 0;
- for (const roley of JSON.roles) {
+ for (const roley of json.roles) {
const roleh = new Role(roley, this);
this.roles.push(roleh);
- this.roleids[roleh.id] = roleh;
+ this.roleids.set(roleh.id, roleh);
}
Member.resolve(member, this).then(_ => this.member = _);
- for (const thing of JSON.channels) {
+ for (const thing of json.channels) {
const temp = new Channel(thing, this);
this.channels.push(temp);
- this.channelids[temp.id] = temp;
+ this.channelids[temp.id.id] = temp;
}
this.headchannels = [];
for (const thing of this.channels) {
@@ -118,7 +119,7 @@ class Guild {
headers: this.headers,
body: JSON.stringify({
"guilds": {
- [this.id]: {
+ [this.id.id]: {
"message_notifications": noti
}
}
@@ -237,7 +238,7 @@ class Guild {
const noti = document.createElement("div");
noti.classList.add("unread");
divy.append(noti);
- this.localuser.guildhtml[this.id] = divy;
+ this.localuser.guildhtml[this.id.id] = divy;
if (this.properties.icon != null) {
const img = document.createElement("img");
img.classList.add("pfp", "servericon");
@@ -366,16 +367,10 @@ class Guild {
body: JSON.stringify(build)
});
}
- getRole(ID) {
- if (!this.roleids[ID]) {
- console.error(`role id ${ID} does not exist`, this.roleids);
- }
- return this.roleids[ID];
- }
hasRole(r) {
console.log("this should run");
- if ((typeof r) !== (typeof "")) {
- r = r.id;
+ if (r instanceof Role) {
+ r = r.id.id;
}
return this.member.hasRole(r);
}
@@ -397,10 +392,10 @@ class Guild {
}
}
loadGuild() {
- this.localuser.loadGuild(this.id);
+ this.localuser.loadGuild(this.id.id);
}
updateChannel(JSON) {
- this.channelids[JSON.id].updateChannel(JSON);
+ SnowFlake.getSnowFlakeFromID(JSON.id, Channel).getObject().updateChannel(JSON);
this.headchannels = [];
for (const thing of this.channels) {
thing.children = [];
@@ -507,7 +502,7 @@ class Guild {
});
const json = await fetched.json();
const role = new Role(json, this);
- this.roleids[role.id] = role;
+ this.roleids[role.id.id] = role;
this.roles.push(role);
return role;
}
diff --git a/.dist/localuser.js b/.dist/localuser.js
index db9bb47..5284388 100644
--- a/.dist/localuser.js
+++ b/.dist/localuser.js
@@ -4,6 +4,8 @@ import { Voice } from "./audio.js";
import { User } from "./user.js";
import { Fullscreen } from "./fullscreen.js";
import { setTheme } from "./login.js";
+import { SnowFlake } from "./snowflake.js";
+import { Message } from "./message.js";
const wsCodesRetry = new Set([4000, 4003, 4005, 4007, 4008, 4009]);
class Localuser {
packets;
@@ -43,14 +45,14 @@ class Localuser {
this.initialized = true;
this.ready = ready;
this.guilds = [];
- this.guildids = {};
+ this.guildids = new Map();
this.user = new User(ready.d.user, this);
this.userinfo.username = this.user.username;
this.userinfo.pfpsrc = this.user.getpfpsrc();
this.status = this.ready.d.user_settings.status;
this.channelfocus = null;
this.lookingguild = null;
- this.guildhtml = {};
+ this.guildhtml = new Map();
const members = {};
for (const thing of ready.d.merged_members) {
members[thing[0].guild_id] = thing[0];
@@ -58,12 +60,12 @@ class Localuser {
for (const thing of ready.d.guilds) {
const temp = new Guild(thing, this, members[thing.id]);
this.guilds.push(temp);
- this.guildids[temp.id] = temp;
+ this.guildids[temp.id.id] = temp;
}
{
const temp = new Direct(ready.d.private_channels, this);
this.guilds.push(temp);
- this.guildids[temp.id] = temp;
+ this.guildids[temp.id.id] = temp;
}
console.log(ready.d.user_guild_settings.entries);
for (const thing of ready.d.user_guild_settings.entries) {
@@ -79,7 +81,7 @@ class Localuser {
continue;
}
const guildid = guild.id;
- this.guildids[guildid].channelids[thing.channel_id].readStateInfo(thing);
+ this.guildids[guildid.id].channelids[thing.channel_id].readStateInfo(thing);
}
this.typing = [];
}
@@ -97,7 +99,7 @@ class Localuser {
clearInterval(this.wsinterval);
this.outoffocus();
this.guilds = [];
- this.guildids = {};
+ this.guildids = new Map();
this.ws.close(4000);
}
async initwebsocket() {
@@ -128,90 +130,85 @@ class Localuser {
}));
});
this.ws.addEventListener('message', (event) => {
- try {
- const temp = JSON.parse(event.data);
- console.log(temp);
- if (temp.op == 0) {
- switch (temp.t) {
- case "MESSAGE_CREATE":
- if (this.initialized) {
- this.messageCreate(temp);
+ const temp = JSON.parse(event.data);
+ console.log(temp);
+ if (temp.op == 0) {
+ switch (temp.t) {
+ case "MESSAGE_CREATE":
+ if (this.initialized) {
+ this.messageCreate(temp);
+ }
+ break;
+ case "MESSAGE_DELETE":
+ console.log(temp.d);
+ SnowFlake.getSnowFlakeFromID(temp.d.id, Message).getObject().deleteEvent();
+ break;
+ case "READY":
+ this.gottenReady(temp);
+ this.genusersettings();
+ returny();
+ break;
+ case "MESSAGE_UPDATE":
+ const message = SnowFlake.getSnowFlakeFromID(temp.d.id, Message).getObject();
+ message.giveData(temp.d);
+ break;
+ case "TYPING_START":
+ if (this.initialized) {
+ this.typingStart(temp);
+ }
+ break;
+ case "USER_UPDATE":
+ if (this.initialized) {
+ const users = SnowFlake.getSnowFlakeFromID(temp.d.id, User).getObject();
+ console.log(users, temp.d.id);
+ if (users) {
+ users.userupdate(temp.d);
}
+ }
+ break;
+ case "CHANNEL_UPDATE":
+ if (this.initialized) {
+ this.updateChannel(temp.d);
+ }
+ break;
+ case "CHANNEL_CREATE":
+ if (this.initialized) {
+ this.createChannel(temp.d);
+ }
+ break;
+ case "CHANNEL_DELETE":
+ if (this.initialized) {
+ this.delChannel(temp.d);
+ }
+ break;
+ case "GUILD_DELETE":
+ {
+ const guildy = this.guildids[temp.d.id];
+ delete this.guildids[temp.d.id];
+ this.guilds.splice(this.guilds.indexOf(guildy), 1);
+ guildy.html.remove();
break;
- case "MESSAGE_DELETE":
- console.log(temp.d);
- this.guildids[temp.d.guild_id].channelids[temp.d.channel_id].messageids[temp.d.id].deleteEvent();
- break;
- case "READY":
- this.gottenReady(temp);
- this.genusersettings();
- returny();
- break;
- case "MESSAGE_UPDATE":
- const message = this.resolveChannelFromID(temp.d.channel_id).messageids[temp.d.id];
- message.giveData(temp.d);
- break;
- case "TYPING_START":
- if (this.initialized) {
- this.typingStart(temp);
- }
- break;
- case "USER_UPDATE":
- if (this.initialized) {
- const users = User.userids[temp.d.id];
- console.log(users, temp.d.id);
- if (users) {
- users.userupdate(temp.d);
- }
- }
- break;
- case "CHANNEL_UPDATE":
- if (this.initialized) {
- this.updateChannel(temp.d);
- }
- break;
- case "CHANNEL_CREATE":
- if (this.initialized) {
- this.createChannel(temp.d);
- }
- break;
- case "CHANNEL_DELETE":
- if (this.initialized) {
- this.delChannel(temp.d);
- }
- break;
- case "GUILD_DELETE":
- {
- const guildy = this.guildids[temp.d.id];
- delete this.guildids[temp.d.id];
- this.guilds.splice(this.guilds.indexOf(guildy), 1);
- guildy.html.remove();
- break;
- }
- case "GUILD_CREATE":
- {
- const guildy = new Guild(temp.d, this, this.user);
- this.guilds.push(guildy);
- this.guildids[guildy.id] = guildy;
- document.getElementById("servers").insertBefore(guildy.generateGuildIcon(), document.getElementById("bottomseparator"));
- }
- }
- }
- else if (temp.op === 10) {
- console.log("heartbeat down");
- this.wsinterval = setInterval(_ => {
- if (this.connectionSucceed === 0)
- this.connectionSucceed = Date.now();
- this.ws.send(JSON.stringify({ op: 1, d: this.packets }));
- }, temp.d.heartbeat_interval);
- this.packets = 1;
- }
- else if (temp.op != 11) {
- this.packets++;
+ }
+ case "GUILD_CREATE":
+ {
+ const guildy = new Guild(temp.d, this, this.user);
+ this.guilds.push(guildy);
+ this.guildids[guildy.id.id] = guildy;
+ document.getElementById("servers").insertBefore(guildy.generateGuildIcon(), document.getElementById("bottomseparator"));
+ }
}
}
- catch (error) {
- console.error(error);
+ else if (temp.op === 10) {
+ console.log("heartbeat down");
+ this.wsinterval = setInterval(_ => {
+ if (this.connectionSucceed === 0)
+ this.connectionSucceed = Date.now();
+ this.ws.send(JSON.stringify({ op: 1, d: this.packets }));
+ }, temp.d.heartbeat_interval);
+ this.packets = 1;
+ }
+ else if (temp.op != 11) {
+ this.packets++;
}
});
this.ws.addEventListener("close", event => {
@@ -253,15 +250,15 @@ class Localuser {
return undefined;
}
updateChannel(JSON) {
- this.guildids[JSON.guild_id].updateChannel(JSON);
- if (JSON.guild_id === this.lookingguild.id) {
+ SnowFlake.getSnowFlakeFromID(JSON.guild_id, Guild).getObject().updateChannel(JSON);
+ if (JSON.guild_id === this.lookingguild.id.id) {
this.loadGuild(JSON.guild_id);
}
}
createChannel(JSON) {
JSON.guild_id ??= "@me";
- this.guildids[JSON.guild_id].createChannelpac(JSON);
- if (JSON.guild_id === this.lookingguild.id) {
+ SnowFlake.getSnowFlakeFromID(JSON.guild_id, Guild).getObject().createChannelpac(JSON);
+ if (JSON.guild_id === this.lookingguild.id.id) {
this.loadGuild(JSON.guild_id);
}
}
@@ -469,10 +466,10 @@ class Localuser {
unreads() {
console.log(this.guildhtml);
for (const thing of this.guilds) {
- if (thing.id === "@me") {
+ if (thing.id.id === "@me") {
continue;
}
- thing.unreads(this.guildhtml[thing.id]);
+ thing.unreads(this.guildhtml[thing.id.id]);
}
}
typingStart(typing) {
diff --git a/.dist/member.js b/.dist/member.js
index 7143cbf..dbbbd4b 100644
--- a/.dist/member.js
+++ b/.dist/member.js
@@ -1,6 +1,8 @@
import { User } from "./user.js";
+import { Role } from "./role.js";
import { Guild } from "./guild.js";
import { Contextmenu } from "./contextmenu.js";
+import { SnowFlake } from "./snowflake.js";
class Member {
static already = {};
owner;
@@ -39,7 +41,7 @@ class Member {
}
if (thing === "roles") {
for (const strrole of membery["roles"]) {
- const role = this.guild.getRole(strrole);
+ const role = SnowFlake.getSnowFlakeFromID(strrole, Role).getObject();
this.roles.push(role);
}
continue;
@@ -67,50 +69,50 @@ class Member {
console.error(guild);
}
let user;
- let id = "";
+ let id;
if (unkown instanceof User) {
user = unkown;
id = user.id;
}
else if (typeof unkown === typeof "") {
- id = unkown;
+ id = new SnowFlake(unkown, undefined);
}
else {
return new Member(unkown, guild);
}
- if (guild.id === "@me") {
+ if (guild.id.id === "@me") {
return null;
}
- if (!Member.already[guild.id]) {
- Member.already[guild.id] = {};
+ if (!Member.already[guild.id.id]) {
+ Member.already[guild.id.id] = {};
}
- else if (Member.already[guild.id][id]) {
- const memb = Member.already[guild.id][id];
+ else if (Member.already[guild.id.id][id]) {
+ const memb = Member.already[guild.id.id][id];
if (memb instanceof Promise) {
return await memb;
}
return memb;
}
- const promoise = fetch(guild.info.api.toString() + "/v9/users/" + id + "/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id=" + guild.id, { headers: guild.headers }).then(_ => _.json()).then(json => {
+ const promoise = fetch(guild.info.api.toString() + "/users/" + id + "/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id=" + guild.id, { headers: guild.headers }).then(_ => _.json()).then(json => {
const memb = new Member(json, guild);
- Member.already[guild.id][id] = memb;
+ Member.already[guild.id.id][id] = memb;
console.log("resolved");
return memb;
});
- Member.already[guild.id][id] = promoise;
+ Member.already[guild.id.id][id] = promoise;
try {
return await promoise;
}
catch (_) {
const memb = new Member(user, guild, true);
- Member.already[guild.id][id] = memb;
+ Member.already[guild.id.id][id] = memb;
return memb;
}
}
hasRole(ID) {
console.log(this.roles, ID);
for (const thing of this.roles) {
- if (thing.id === ID) {
+ if (thing.id.id === ID) {
return true;
}
}
@@ -131,7 +133,7 @@ class Member {
return true;
}
}
- return this.guild.properties.owner_id === this.user.id;
+ return this.guild.properties.owner_id === this.user.id.id;
}
bind(html) {
if (html.tagName === "SPAN") {
diff --git a/.dist/message.js b/.dist/message.js
index 78c8519..5ed5d0c 100644
--- a/.dist/message.js
+++ b/.dist/message.js
@@ -4,6 +4,7 @@ import { Member } from "./member.js";
import { MarkDown } from "./markdown.js";
import { Embed } from "./embed.js";
import { File } from "./file.js";
+import { SnowFlake } from "./snowflake.js";
class Message {
static contextmenu = new Contextmenu("message menu");
owner;
@@ -39,7 +40,7 @@ class Message {
this.channel.setReplying(this);
});
Message.contextmenu.addbutton("Copy message id", function () {
- navigator.clipboard.writeText(this.id);
+ navigator.clipboard.writeText(this.id.id);
});
Message.contextmenu.addbutton("Edit", function () {
this.channel.editing = this;
@@ -69,6 +70,10 @@ class Message {
this.content = new MarkDown(messagejson[thing], this.channel);
continue;
}
+ else if (thing === "id") {
+ this.id = new SnowFlake(messagejson.id, this);
+ continue;
+ }
this[thing] = messagejson[thing];
}
for (const thing in this.embeds) {
@@ -132,14 +137,14 @@ class Message {
return build;
}
async edit(content) {
- return await fetch(this.info.api.toString() + "/channels/" + this.channel.id + "/messages/" + this.id, {
+ return await fetch(this.info.api.toString() + "/channels/" + this.channel.id + "/messages/" + this.id.id, {
method: "PATCH",
headers: this.headers,
body: JSON.stringify({ content: content })
});
}
delete() {
- fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id}`, {
+ fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id.id}`, {
headers: this.headers,
method: "DELETE",
});
@@ -149,19 +154,22 @@ class Message {
this.div.innerHTML = "";
this.div = null;
}
- const prev = this.channel.idToPrev[this.id];
- const next = this.channel.idToNext[this.id];
+ const prev = this.channel.idToPrev[this.id.id];
+ const next = this.channel.idToNext[this.id.id];
this.channel.idToNext[prev] = next;
this.channel.idToPrev[next] = prev;
- delete this.channel.messageids[this.id];
+ delete this.channel.messageids[this.id.id];
const regen = this.channel.messageids[prev];
if (regen) {
regen.generateMessage();
}
+ if (this.channel.lastmessage === this) {
+ this.channel.lastmessage = this.channel.messageids[prev];
+ }
}
generateMessage(premessage = null) {
if (!premessage) {
- premessage = this.channel.messageids[this.channel.idToNext[this.id]];
+ premessage = this.channel.messageids[this.channel.idToNext[this.id.id]];
}
const div = this.div;
if (this === this.channel.replyingto) {
diff --git a/.dist/role.js b/.dist/role.js
index 32a1bbb..58c5b11 100644
--- a/.dist/role.js
+++ b/.dist/role.js
@@ -1,5 +1,6 @@
export { Role };
import { Permissions } from "./permissions.js";
+import { SnowFlake } from "./snowflake.js";
class Role {
permissions;
owner;
@@ -16,6 +17,10 @@ class Role {
this.headers = owner.headers;
this.info = owner.info;
for (const thing of Object.keys(JSON)) {
+ if (thing === "id") {
+ this.id = new SnowFlake(JSON.id, this);
+ continue;
+ }
this[thing] = JSON[thing];
}
this.permissions = new Permissions(JSON.permissions);
diff --git a/.dist/settings.js b/.dist/settings.js
index 18d032a..9d1fe94 100644
--- a/.dist/settings.js
+++ b/.dist/settings.js
@@ -1,4 +1,6 @@
import { Permissions } from "./permissions.js";
+import { SnowFlake } from "./snowflake.js";
+import { Role } from "./role.js";
class Buttons {
name;
buttons;
@@ -154,16 +156,17 @@ class RoleList extends Buttons {
options.addPermissionToggle(thing, this.permission); //
}
for (const i of permissions) {
- this.buttons.push([guild.getRole(i[0]).name, i[0]]); //
+ console.log(i);
+ this.buttons.push([i[0].getObject().name, i[0].id]); //
}
this.options = options;
}
handleString(str) {
this.curid = str;
- const perm = this.permissions.find(_ => _[0] === str)[1];
+ const perm = this.permissions.find(_ => _[0].id === str)[1];
this.permission.deny = perm.deny;
this.permission.allow = perm.allow;
- this.options.name = this.guild.getRole(str).name;
+ this.options.name = SnowFlake.getSnowFlakeFromID(str, Role).getObject().name;
this.options.haschanged = false;
return this.options.generateHTML();
}
diff --git a/.dist/snowflake.js b/.dist/snowflake.js
new file mode 100644
index 0000000..0f394b8
--- /dev/null
+++ b/.dist/snowflake.js
@@ -0,0 +1,51 @@
+class SnowFlake {
+ id;
+ static SnowFlakes = new Map();
+ static FinalizationRegistry = new FinalizationRegistry((id) => {
+ SnowFlake.SnowFlakes.delete(id);
+ });
+ obj;
+ constructor(id, obj) {
+ if (!obj) {
+ this.id = id;
+ return;
+ }
+ if (!SnowFlake.SnowFlakes.get(obj.constructor)) {
+ SnowFlake.SnowFlakes.set(obj.constructor, new Map());
+ }
+ if (SnowFlake.SnowFlakes.get(obj.constructor).get(id)) {
+ const snowflake = SnowFlake.SnowFlakes.get(obj.constructor).get(id).deref();
+ snowflake.obj = obj;
+ return snowflake;
+ }
+ this.id = id;
+ SnowFlake.SnowFlakes.get(obj.constructor).set(id, new WeakRef(this));
+ SnowFlake.FinalizationRegistry.register(this, id);
+ this.obj = obj;
+ }
+ static getSnowFlakeFromID(id, type) {
+ if (!SnowFlake.SnowFlakes.get(type)) {
+ SnowFlake.SnowFlakes.set(type, new Map());
+ }
+ const snowflake = SnowFlake.SnowFlakes.get(type).get(id);
+ if (snowflake) {
+ return snowflake.deref();
+ }
+ {
+ const snowflake = new SnowFlake(id, undefined);
+ SnowFlake.SnowFlakes.get(type).set(id, new WeakRef(snowflake));
+ SnowFlake.FinalizationRegistry.register(snowflake, id);
+ return snowflake;
+ }
+ }
+ getUnixTime() {
+ return Number((BigInt(this.id) >> 22n) + 1420070400000n);
+ }
+ toString() {
+ return this.id;
+ }
+ getObject() {
+ return this.obj;
+ }
+}
+export { SnowFlake };
diff --git a/.dist/user.js b/.dist/user.js
index 401b8a9..2b2c1fc 100644
--- a/.dist/user.js
+++ b/.dist/user.js
@@ -2,6 +2,7 @@
import { Member } from "./member.js";
import { MarkDown } from "./markdown.js";
import { Contextmenu } from "./contextmenu.js";
+import { SnowFlake } from "./snowflake.js";
class User {
static userids = {};
owner;
@@ -16,12 +17,12 @@ class User {
static contextmenu = new Contextmenu("User Menu");
static setUpContextMenu() {
this.contextmenu.addbutton("Copy user id", function () {
- navigator.clipboard.writeText(this.id);
+ navigator.clipboard.writeText(this.id.id);
});
this.contextmenu.addbutton("Message user", function () {
fetch(this.info.api.toString() + "/v9/users/@me/channels", { method: "POST",
- body: JSON.stringify({ "recipients": [this.id] }),
- headers: this.headers
+ body: JSON.stringify({ "recipients": [this.id.id] }),
+ headers: this.localuser.headers
});
});
}
@@ -52,6 +53,10 @@ class User {
this.bio = new MarkDown(userjson[thing], this.localuser);
continue;
}
+ if (thing === "id") {
+ this.id = new SnowFlake(userjson[thing], this);
+ continue;
+ }
this[thing] = userjson[thing];
}
this.hypotheticalpfp = false;
@@ -67,7 +72,7 @@ class User {
const pfp = document.createElement('img');
pfp.src = this.getpfpsrc();
pfp.classList.add("pfp");
- pfp.classList.add("userid:" + this.id);
+ pfp.classList.add("userid:" + this.id.id);
return pfp;
}
userupdate(json) {
@@ -77,7 +82,7 @@ class User {
}
}
bind(html, guild = null) {
- if (guild && guild.id !== "@me") {
+ if (guild && guild.id.id !== "@me") {
Member.resolve(this, guild).then(_ => {
_.bind(html);
}).catch(_ => {
@@ -96,7 +101,7 @@ class User {
this.hypotheticalpfp = false;
const src = this.getpfpsrc();
console.log(src);
- for (const thing of document.getElementsByClassName("userid:" + this.id)) {
+ for (const thing of document.getElementsByClassName("userid:" + this.id.id)) {
thing.src = src;
}
}
@@ -105,7 +110,7 @@ class User {
return this.avatar;
}
if (this.avatar != null) {
- return this.info.cdn.toString() + "avatars/" + this.id + "/" + this.avatar + ".png";
+ return this.info.cdn.toString() + "avatars/" + this.id.id + "/" + this.avatar + ".png";
}
else {
return this.info.cdn.toString() + "embed/avatars/3.png";
diff --git a/webpage/channel.ts b/webpage/channel.ts
index 1f1eca6..0fb5a13 100644
--- a/webpage/channel.ts
+++ b/webpage/channel.ts
@@ -3,14 +3,14 @@ import { Message } from "./message.js";
import {Voice} from "./audio.js";
import {Contextmenu} from "./contextmenu.js";
import {Fullscreen} from "./fullscreen.js";
-import {MarkDown} from "./markdown.js";
import {Guild} from "./guild.js";
import { Localuser } from "./localuser.js";
import { Permissions } from "./permissions.js";
import { Settings, RoleList } from "./settings.js";
import { Role } from "./role.js";
-import {InfiniteScroller} from "./infiniteScroller.js"
-Settings;
+import {InfiniteScroller} from "./infiniteScroller.js";
+import { SnowFlake } from "./snowflake.js";
+
declare global {
interface NotificationOptions {
image?: string
@@ -22,30 +22,30 @@ class Channel{
owner:Guild;
headers:Localuser["headers"];
name:string;
- id:string;
- parent_id:string;
+ id:SnowFlake;
+ parent_id:SnowFlake;
parent:Channel;
children:Channel[];
guild_id:string;
- messageids:{[key : string]:Message};
- permission_overwrites:{[key:string]:Permissions};
- permission_overwritesar:[string,Permissions][]
+ messageids:Map,Message>;
+ permission_overwrites:Map;
+ permission_overwritesar:[SnowFlake,Permissions][]
topic:string;
nsfw:boolean;
position:number;
- lastreadmessageid:string;
- lastmessageid:string;
+ lastreadmessageid:SnowFlake;
+ lastmessageid:SnowFlake;
mentions:number;
lastpin:string;
- move_id:string;
+ move_id:SnowFlake;
typing:number;
message_notifications:number;
allthewayup:boolean;
static contextmenu=new Contextmenu("channel menu");
replyingto:Message;
infinite:InfiniteScroller;
- idToPrev:{[key:string]:string}={};
- idToNext:{[key:string]:string}={};
+ idToPrev:Map,SnowFlake>=new Map();
+ idToNext:Map,SnowFlake>=new Map();
static setupcontextmenu(){
this.contextmenu.addbutton("Copy channel id",function(){
console.log(this)
@@ -87,26 +87,28 @@ class Channel{
}
setUpInfiniteScroller(){
const ids:{[key:string]:Function}={};
- this.infinite=new InfiniteScroller(async function(id:string,offset:number){
+ this.infinite=new InfiniteScroller(async function(this:Channel,id:string,offset:number):Promise{
+ const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake;
if(offset===1){
- if(this.idToPrev[id]){
- return this.idToPrev[id];
+ if(this.idToPrev.get(snowflake)){
+ return this.idToPrev.get(snowflake)?.id;
}else{
- await this.grabmoremessages(id);
- return this.idToPrev[id];
+ await this.grabBefore(id);
+ return this.idToPrev.get(snowflake)?.id;
}
}else{
- return this.idToNext[id];
+ return this.idToNext.get(snowflake)?.id;
}
}.bind(this),
function(this:Channel,id:string){
let res:Function;
const promise=new Promise(_=>{res=_;}) as Promise;
- const html=this.messageids[id].buildhtml(this.messageids[this.idToPrev[id]],promise);
+ const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake;
+ const html=this.messageids.get(snowflake).buildhtml(this.messageids.get(this.idToPrev.get(snowflake)),promise);
ids[id]=res;
return html;
}.bind(this),
- async function(id:string){
+ async function(this:Channel,id:string){
ids[id]();
delete ids[id];
return true;
@@ -125,26 +127,25 @@ class Channel{
this.owner=owner;
this.headers=this.owner.headers;
this.name=JSON.name;
- this.id=JSON.id;
- this.parent_id=JSON.parent_id;
+ this.id=new SnowFlake(JSON.id,this);
+ this.parent_id=new SnowFlake(JSON.parent_id,undefined);
this.parent=null;
this.children=[];
this.guild_id=JSON.guild_id;
- this.messageids={};
- this.permission_overwrites={};
+ this.messageids=new Map();
+ this.permission_overwrites=new Map();
this.permission_overwritesar=[];
for(const thing of JSON.permission_overwrites){
- console.log(thing);
if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;};
- this.permission_overwrites[thing.id]=new Permissions(thing.allow,thing.deny);
- this.permission_overwritesar.push([thing.id,this.permission_overwrites[thing.id]]);
+ this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny));
+ this.permission_overwritesar.push([thing.id,this.permission_overwrites.get(thing.id)]);
}
this.topic=JSON.topic;
this.nsfw=JSON.nsfw;
this.position=JSON.position;
this.lastreadmessageid=null;
- this.lastmessageid=JSON.last_message_id;
+ this.lastmessageid=SnowFlake.getSnowFlakeFromID(JSON.last_message_id,Message);
this.setUpInfiniteScroller();
}
isAdmin(){
@@ -160,22 +161,22 @@ class Channel{
return this.owner.info;
}
readStateInfo(json){
- this.lastreadmessageid=json.last_message_id;
+ this.lastreadmessageid=SnowFlake.getSnowFlakeFromID(json.last_message_id,Message);
this.mentions=json.mention_count;
this.mentions??=0;
this.lastpin=json.last_pin_timestamp;
}
get hasunreads():boolean{
if(!this.hasPermission("VIEW_CHANNEL")){return false;}
- return this.lastmessageid!==this.lastreadmessageid&&this.type!==4;
+ return this.lastmessageid!==this.lastreadmessageid&&this.type!==4&&!!this.lastmessageid.id;
}
hasPermission(name:string,member=this.guild.member):boolean{
if(member.isAdmin()){
return true;
}
for(const thing of member.roles){
- if(this.permission_overwrites[thing.id]){
- let perm=this.permission_overwrites[thing.id].getPermission(name);
+ if(this.permission_overwrites.get(thing.id.id)){
+ let perm=this.permission_overwrites.get(thing.id.id).getPermission(name);
if(perm){
return perm===1;
}
@@ -196,7 +197,7 @@ class Channel{
this.children.sort((a,b)=>{return a.position-b.position});
}
resolveparent(guild:Guild){
- this.parent=guild.channelids[this.parent_id];
+ this.parent=guild.channelids[this.parent_id?.id];
this.parent??=null;
if(this.parent!==null){
this.parent.children.push(this);
@@ -354,7 +355,7 @@ class Channel{
if(!this.hasunreads){
return;
}
- fetch(this.info.api.toString()+"/v9/channels/"+this.id+"/messages/"+this.lastmessageid+"/ack",{
+ fetch(this.info.api.toString()+"/channels/"+this.id+"/messages/"+this.lastmessageid+"/ack",{
method:"POST",
headers:this.headers,
body:JSON.stringify({})
@@ -445,8 +446,8 @@ class Channel{
["textbox","Channel name:",this.name,function(){name=this.value}],
["mdbox","Channel topic:",this.topic,function(){topic=this.value}],
["checkbox","NSFW Channel",this.nsfw,function(){nsfw=this.checked}],
- ["button","","submit",function(){
- fetch(this.info.api.toString()+"/v9/channels/"+thisid,{
+ ["button","","submit",()=>{
+ fetch(this.info.api.toString()+"/channels/"+thisid,{
method:"PATCH",
headers:this.headers,
body:JSON.stringify({
@@ -470,7 +471,7 @@ class Channel{
console.log(full)
}
deleteChannel(){
- fetch(this.info.api.toString()+"/v9/channels/"+this.id,{
+ fetch(this.info.api.toString()+"/channels/"+this.id,{
method:"DELETE",
headers:this.headers
})
@@ -508,10 +509,11 @@ class Channel{
}
}
async getmessage(id:string):Promise{
- if(this.messageids[id]){
- return this.messageids[id];
+ const snowflake=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake;
+ if(snowflake.getObject()){
+ return snowflake.getObject();
}else{
- const gety=await fetch(this.info.api.toString()+"/v9/channels/"+this.id+"/messages?limit=1&around="+id,{headers:this.headers})
+ const gety=await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=1&around="+id,{headers:this.headers})
const json=await gety.json();
return new Message(json[0],this);
}
@@ -539,13 +541,15 @@ class Channel{
history.pushState(null, null,"/channels/"+this.guild_id+"/"+this.id);
document.getElementById("channelname").textContent="#"+this.name;
console.log(this);
- (document.getElementById("typebox") as HTMLInputElement).disabled=!this.canMessage;
+ (document.getElementById("typebox") as HTMLInputElement).contentEditable=""+this.canMessage;
}
+ lastmessage:Message;
async putmessages(){
if(this.allthewayup){return};
const j=await fetch(this.info.api.toString()+"/channels/"+this.id+"/messages?limit=100",{
headers: this.headers,
- })
+ });
+
const response=await j.json();
if(response.length!==100){
this.allthewayup=true;
@@ -554,12 +558,14 @@ class Channel{
for(const thing of response){
const message=new Message(thing,this);
if(prev){
- this.idToNext[message.id]=prev.id;
- this.idToPrev[prev.id]=message.id;
+ this.idToNext.set(message.id,prev.id);
+ this.idToPrev.set(prev.id,message.id);
+ }else{
+ this.lastmessage=message;
}
prev=message;
- if(this.messageids[message.id]===undefined){
- this.messageids[message.id]=message;
+ if(this.messageids.get(message.id)===undefined){
+ this.messageids.set(message.id,message);
}
}
}
@@ -572,7 +578,7 @@ class Channel{
}
this.children=build;
}
- async grabmoremessages(id:string){
+ async grabBefore(id:string){
if(this.allthewayup){
return;
}
@@ -584,7 +590,7 @@ class Channel{
if(response.length===0){
this.allthewayup=true;
}
- let previd=id;
+ let previd=SnowFlake.getSnowFlakeFromID(id,Message) as SnowFlake;
for(const i in response){
let messager:Message;
if(!next){
@@ -598,11 +604,11 @@ class Channel{
next=undefined;
console.log("ohno",+i+1);
}
- if(this.messageids[messager.id]===undefined){
- this.idToNext[messager.id]=previd;
- this.idToPrev[previd]=messager.id;
+ if(this.messageids.get(messager.id)===undefined){
+ this.idToNext.set(messager.id,previd);
+ this.idToPrev.set(previd,messager.id);
previd=messager.id;
- this.messageids[messager.id]=messager;
+ this.messageids.set(messager.id,messager);
}else{
console.log("How???")
}
@@ -618,17 +624,42 @@ class Channel{
buildmessages(){
const messages=document.getElementById("channelw");
messages.innerHTML="";
- messages.append(this.infinite.getDiv(this.lastmessageid));
+ let id:SnowFlake;
+ if(this.messageids.get(this.lastreadmessageid)){
+ id=this.lastreadmessageid;
+ }else if(this.lastmessage.id){
+ id=this.goBackIds(this.lastmessage.id,50);
+ console.log("shouldn't")
+ }
+ messages.append(this.infinite.getDiv(id.id));
+ }
+ private goBackIds(id:SnowFlake,back:number):SnowFlake{
+ while(back!==0){
+ const nextid=this.idToPrev.get(id);
+ if(nextid){
+ id=nextid;
+ console.log(id);
+ back--;
+ }else{
+ break;
+ }
+ }
+ return id;
}
updateChannel(JSON){
this.type=JSON.type;
this.name=JSON.name;
- this.parent_id=JSON.parent_id;
+ this.parent_id=new SnowFlake(JSON.parent_id,undefined);
this.parent=null;
this.children=[];
this.guild_id=JSON.guild_id;
- this.messageids={};
- this.permission_overwrites=JSON.permission_overwrites;
+ this.messageids=new Map();
+ this.permission_overwrites=new Map();
+ for(const thing of JSON.permission_overwrites){
+ if(thing.id==="1182819038095799904"||thing.id==="1182820803700625444"){continue;};
+ this.permission_overwrites.set(thing.id,new Permissions(thing.allow,thing.deny));
+ this.permission_overwritesar.push([thing.id,this.permission_overwrites.get(thing.id)]);
+ }
this.topic=JSON.topic;
this.nsfw=JSON.nsfw;
}
@@ -707,10 +738,11 @@ class Channel{
messageCreate(messagep:any):void{
if(!this.hasPermission("VIEW_CHANNEL")){return}
const messagez=new Message(messagep.d,this);
- this.idToNext[this.lastmessageid]=messagez.id;
- this.idToPrev[messagez.id]=this.lastmessageid;
+ console.log(this.lastmessageid,messagez.id,":3");
+ this.idToNext.set(this.lastmessageid,messagez.id);
+ this.idToPrev.set(messagez.id,this.lastmessageid);
this.lastmessageid=messagez.id;
- this.messageids[messagez.id]=messagez;
+ this.messageids.set(messagez.id,messagez);
if(messagez.author===this.localuser.user){
this.lastreadmessageid=messagez.id;
if(this.myhtml){
@@ -785,11 +817,11 @@ class Channel{
})
})
const perm=new Permissions("0","0");
- this.permission_overwrites[role.id]=perm;
+ this.permission_overwrites.set(role.id.id,perm);
this.permission_overwritesar.push([role.id,perm]);
}
async updateRolePermissions(id:string,perms:Permissions){
- const permission=this.permission_overwrites[id];
+ const permission=this.permission_overwrites.get(id);
permission.allow=perms.allow;
permission.deny=perms.deny;
await fetch(this.info.api.toString()+"/channels/"+this.id+"/permissions/"+id,{
diff --git a/webpage/direct.ts b/webpage/direct.ts
index 3d4ad35..2f9ce66 100644
--- a/webpage/direct.ts
+++ b/webpage/direct.ts
@@ -4,6 +4,7 @@ import { Message } from "./message.js";
import { Localuser } from "./localuser.js";
import {User} from "./user.js";
import { Member } from "./member.js";
+import { SnowFlake } from "./snowflake.js";
class Direct extends Guild{
constructor(JSON,owner:Localuser){
@@ -17,16 +18,16 @@ class Direct extends Guild{
this.headers=this.localuser.headers;
this.channels=[];
this.channelids={};
- this.id="@me";
+ this.id=new SnowFlake("@me",this);
this.properties={};
this.roles=[];
- this.roleids={};
+ this.roleids=new Map();
this.prevchannel=undefined;
this.properties.name="Direct Messages";
for(const thing of JSON){
const temp=new Group(thing,this);
this.channels.push(temp);
- this.channelids[temp.id]=temp;
+ this.channelids[temp.id.id]=temp;
}
this.headchannels=this.channels;
}
@@ -39,7 +40,7 @@ class Direct extends Guild{
}
sortchannels(){
this.headchannels.sort((a,b)=>{
- const result=(BigInt(a.lastmessageid)-BigInt(b.lastmessageid));
+ const result=(a.lastmessageid.getUnixTime()-b.lastmessageid.getUnixTime());
return Number(-result);
});
}
@@ -74,15 +75,15 @@ class Group extends Channel{
this.user=this.localuser.user;
}
this.name??=this.localuser.user.username;
- this.id=JSON.id;
+ this.id=new SnowFlake(JSON.id,this);
this.parent_id=null;
this.parent=null;
this.children=[];
this.guild_id="@me";
- this.messageids={};
- this.permission_overwrites={};
- this.lastmessageid=JSON.last_message_id;
- this.lastmessageid??="0";
+ this.messageids=new Map();
+ this.permission_overwrites=new Map();
+ this.lastmessageid=SnowFlake.getSnowFlakeFromID(JSON.last_message_id,Message);
+ this.lastmessageid??=new SnowFlake("0",undefined);
this.mentions=0;
this.setUpInfiniteScroller();
}
@@ -118,10 +119,10 @@ class Group extends Channel{
}
messageCreate(messagep){
const messagez=new Message(messagep.d,this);
- this.idToNext[this.lastmessageid]=messagez.id;
- this.idToPrev[messagez.id]=this.lastmessageid;
+ this.idToNext.set(this.lastmessageid,messagez.id);
+ this.idToPrev.set(messagez.id,this.lastmessageid);
this.lastmessageid=messagez.id;
- this.messageids[messagez.id]=messagez;
+ this.messageids.set(messagez.id,messagez);
if(messagez.author===this.localuser.user){
this.lastreadmessageid=messagez.id;
if(this.myhtml){
diff --git a/webpage/guild.ts b/webpage/guild.ts
index e5a77ce..9b69c6a 100644
--- a/webpage/guild.ts
+++ b/webpage/guild.ts
@@ -6,15 +6,16 @@ import {Fullscreen} from "./fullscreen.js";
import {Member} from "./member.js";
import {Settings,RoleList} from "./settings.js";
import {Permissions} from "./permissions.js";
+import { SnowFlake } from "./snowflake.js";
class Guild{
owner:Localuser;
headers:Localuser["headers"];
channels:Channel[];
channelids:{[key:string]:Channel};
- id:string;
+ id:SnowFlake;
properties
roles:Role[];
- roleids:{[key:string]:Role};
+ roleids:Map,Role>;
prevchannel:Channel;
message_notifications:number;
headchannels:Channel[];
@@ -75,30 +76,30 @@ class Guild{
s1.options.push(new RoleList(permlist,this,this.updateRolePermissions.bind(this)));
settings.show();
}
- constructor(JSON,owner:Localuser,member){
- if(JSON===-1){
+ constructor(json,owner:Localuser,member){
+ if(json===-1){
return;
}
this.owner=owner;
this.headers=this.owner.headers;
this.channels=[];
this.channelids={};
- this.id=JSON.id;
- this.properties=JSON.properties;
+ this.id=new SnowFlake(json.id,this);
+ this.properties=json.properties;
this.roles=[];
- this.roleids={};
+ this.roleids=new Map();
this.prevchannel=undefined;
this.message_notifications=0;
- for(const roley of JSON.roles){
+ for(const roley of json.roles){
const roleh=new Role(roley,this);
this.roles.push(roleh)
- this.roleids[roleh.id]=roleh;
+ this.roleids.set(roleh.id,roleh);
}
Member.resolve(member,this).then(_=>this.member=_);
- for(const thing of JSON.channels){
+ for(const thing of json.channels){
const temp=new Channel(thing,this);
this.channels.push(temp);
- this.channelids[temp.id]=temp;
+ this.channelids[temp.id.id]=temp;
}
this.headchannels=[];
for(const thing of this.channels){
@@ -128,7 +129,7 @@ class Guild{
headers:this.headers,
body:JSON.stringify({
"guilds":{
- [this.id]:{
+ [this.id.id]:{
"message_notifications": noti
}
}
@@ -247,7 +248,7 @@ class Guild{
const noti=document.createElement("div");
noti.classList.add("unread");
divy.append(noti);
- this.localuser.guildhtml[this.id]=divy;
+ this.localuser.guildhtml[this.id.id]=divy;
if(this.properties.icon!=null){
const img=document.createElement("img");
img.classList.add("pfp","servericon");
@@ -373,16 +374,12 @@ class Guild{
body:JSON.stringify(build)
})
}
- getRole(ID:string):Role{
- if(!this.roleids[ID]){console.error(`role id ${ID} does not exist`,this.roleids)}
- return this.roleids[ID];
- }
hasRole(r:Role|string){
console.log("this should run");
- if((typeof r)!==(typeof "")){
- r=(r as Role).id;
+ if(r instanceof Role){
+ r=r.id.id;
}
- return this.member.hasRole(r as string);
+ return this.member.hasRole(r);
}
loadChannel(ID:string=undefined){
if(ID&&this.channelids[ID]){
@@ -402,10 +399,10 @@ class Guild{
}
}
loadGuild(){
- this.localuser.loadGuild(this.id);
+ this.localuser.loadGuild(this.id.id);
}
updateChannel(JSON){
- this.channelids[JSON.id].updateChannel(JSON);
+ SnowFlake.getSnowFlakeFromID(JSON.id,Channel).getObject().updateChannel(JSON);
this.headchannels=[];
for(const thing of this.channels){
thing.children=[];
@@ -516,7 +513,7 @@ class Guild{
})
const json=await fetched.json();
const role=new Role(json,this);
- this.roleids[role.id]=role;
+ this.roleids[role.id.id]=role;
this.roles.push(role);
return role;
}
diff --git a/webpage/localuser.ts b/webpage/localuser.ts
index e1ce1a5..c4f2744 100644
--- a/webpage/localuser.ts
+++ b/webpage/localuser.ts
@@ -7,6 +7,8 @@ import {Member} from "./member.js";
import {MarkDown} from "./markdown.js";
import {Fullscreen} from "./fullscreen.js";
import {setTheme, Specialuser} from "./login.js";
+import { SnowFlake } from "./snowflake.js";
+import { Message } from "./message.js";
const wsCodesRetry=new Set([4000,4003,4005,4007,4008,4009]);
@@ -23,12 +25,12 @@ class Localuser{
devPortal:Fullscreen;
ready;
guilds:Guild[];
- guildids:{ [key: string]: Guild };
+ guildids:Map;
user:User;
status:string;
channelfocus:Channel;
lookingguild:Guild;
- guildhtml:Record;
+ guildhtml:Map;
ws:WebSocket;
typing:[string,number][];
wsinterval:NodeJS.Timeout;
@@ -48,14 +50,14 @@ class Localuser{
this.initialized=true;
this.ready=ready;
this.guilds=[];
- this.guildids={};
+ this.guildids=new Map();
this.user=new User(ready.d.user,this);
this.userinfo.username=this.user.username;
this.userinfo.pfpsrc=this.user.getpfpsrc();
this.status=this.ready.d.user_settings.status;
this.channelfocus=null;
this.lookingguild=null;
- this.guildhtml={};
+ this.guildhtml=new Map();
const members={};
for(const thing of ready.d.merged_members){
members[thing[0].guild_id]=thing[0];
@@ -64,12 +66,12 @@ class Localuser{
for(const thing of ready.d.guilds){
const temp=new Guild(thing,this,members[thing.id]);
this.guilds.push(temp);
- this.guildids[temp.id]=temp;
+ this.guildids[temp.id.id]=temp;
}
{
const temp=new Direct(ready.d.private_channels,this);
this.guilds.push(temp);
- this.guildids[temp.id]=temp;
+ this.guildids[temp.id.id]=temp;
}
console.log(ready.d.user_guild_settings.entries);
@@ -86,7 +88,7 @@ class Localuser{
continue
}
const guildid=guild.id;
- this.guildids[guildid].channelids[thing.channel_id].readStateInfo(thing);
+ this.guildids[guildid.id].channelids[thing.channel_id].readStateInfo(thing);
}
this.typing=[];
}
@@ -104,7 +106,7 @@ class Localuser{
clearInterval(this.wsinterval);
this.outoffocus();
this.guilds=[];
- this.guildids={};
+ this.guildids=new Map();
this.ws.close(4000)
}
async initwebsocket():Promise{
@@ -138,7 +140,7 @@ class Localuser{
this.ws.addEventListener('message', (event) => {
- try{
+
const temp=JSON.parse(event.data);
console.log(temp)
if(temp.op==0){
@@ -150,7 +152,7 @@ class Localuser{
break;
case "MESSAGE_DELETE":
console.log(temp.d);
- this.guildids[temp.d.guild_id].channelids[temp.d.channel_id].messageids[temp.d.id].deleteEvent();
+ SnowFlake.getSnowFlakeFromID(temp.d.id,Message).getObject().deleteEvent();
break;
case "READY":
this.gottenReady(temp);
@@ -158,7 +160,7 @@ class Localuser{
returny();
break;
case "MESSAGE_UPDATE":
- const message=this.resolveChannelFromID(temp.d.channel_id).messageids[temp.d.id];
+ const message=SnowFlake.getSnowFlakeFromID(temp.d.id,Message).getObject();
message.giveData(temp.d);
break;
case "TYPING_START":
@@ -168,7 +170,7 @@ class Localuser{
break;
case "USER_UPDATE":
if(this.initialized){
- const users=User.userids[temp.d.id];
+ const users=SnowFlake.getSnowFlakeFromID(temp.d.id,User).getObject() as User;
console.log(users,temp.d.id)
if(users){
users.userupdate(temp.d);
@@ -202,7 +204,7 @@ class Localuser{
{
const guildy=new Guild(temp.d,this,this.user);
this.guilds.push(guildy);
- this.guildids[guildy.id]=guildy;
+ this.guildids[guildy.id.id]=guildy;
document.getElementById("servers").insertBefore(guildy.generateGuildIcon(),document.getElementById("bottomseparator"));
}
}
@@ -218,9 +220,7 @@ class Localuser{
}else if(temp.op!=11){
this.packets++
}
- }catch(error){
- console.error(error)
- }
+
});
@@ -264,15 +264,15 @@ class Localuser{
return undefined;
}
updateChannel(JSON):void{
- this.guildids[JSON.guild_id].updateChannel(JSON);
- if(JSON.guild_id===this.lookingguild.id){
+ SnowFlake.getSnowFlakeFromID(JSON.guild_id,Guild).getObject().updateChannel(JSON);
+ if(JSON.guild_id===this.lookingguild.id.id){
this.loadGuild(JSON.guild_id);
}
}
createChannel(JSON):void{
JSON.guild_id??="@me";
- this.guildids[JSON.guild_id].createChannelpac(JSON);
- if(JSON.guild_id===this.lookingguild.id){
+ SnowFlake.getSnowFlakeFromID(JSON.guild_id,Guild).getObject().createChannelpac(JSON);
+ if(JSON.guild_id===this.lookingguild.id.id){
this.loadGuild(JSON.guild_id);
}
}
@@ -497,8 +497,8 @@ class Localuser{
unreads():void{
console.log(this.guildhtml)
for(const thing of this.guilds){
- if(thing.id==="@me"){continue;}
- thing.unreads(this.guildhtml[thing.id]);
+ if(thing.id.id==="@me"){continue;}
+ thing.unreads(this.guildhtml[thing.id.id]);
}
}
typingStart(typing):void{
diff --git a/webpage/member.ts b/webpage/member.ts
index 2154cd7..c181d2e 100644
--- a/webpage/member.ts
+++ b/webpage/member.ts
@@ -2,6 +2,7 @@ import {User} from "./user.js";
import {Role} from "./role.js";
import {Guild} from "./guild.js";
import { Contextmenu } from "./contextmenu.js";
+import { SnowFlake } from "./snowflake.js";
class Member{
static already={};
@@ -38,7 +39,7 @@ class Member{
if(thing==="owner"){continue}
if(thing==="roles"){
for(const strrole of membery["roles"]){
- const role=this.guild.getRole(strrole);
+ const role=SnowFlake.getSnowFlakeFromID(strrole,Role).getObject();
this.roles.push(role);
}
continue;
@@ -65,44 +66,45 @@ class Member{
console.error(guild)
}
let user:User;
- let id="";
+ let id:SnowFlake;
if(unkown instanceof User){
user=unkown as User;
id=user.id;
}else if(typeof unkown===typeof ""){
- id=unkown as string;
+ id=new SnowFlake(unkown as string,undefined);
}else{
return new Member(unkown,guild);
}
- if(guild.id==="@me"){return null}
- if(!Member.already[guild.id]){
- Member.already[guild.id]={};
- }else if(Member.already[guild.id][id]){
- const memb=Member.already[guild.id][id]
+ if(guild.id.id==="@me"){return null}
+ if(!Member.already[guild.id.id]){
+ Member.already[guild.id.id]={};
+ }else if(Member.already[guild.id.id][id]){
+ const memb=Member.already[guild.id.id][id]
if(memb instanceof Promise){
return await memb;
}
return memb;
}
- const promoise= fetch(guild.info.api.toString()+"/v9/users/"+id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.id,{headers:guild.headers}).then(_=>_.json()).then(json=>{
+ const promoise= fetch(guild.info.api.toString()+"/users/"+id+"/profile?with_mutual_guilds=true&with_mutual_friends_count=true&guild_id="+guild.id,{headers:guild.headers}).then(_=>_.json()).then(json=>{
const memb=new Member(json,guild);
- Member.already[guild.id][id]=memb;
+ Member.already[guild.id.id][id]=memb;
console.log("resolved")
return memb
})
- Member.already[guild.id][id]=promoise;
+ Member.already[guild.id.id][id]=promoise;
try{
return await promoise
}catch(_){
+
const memb=new Member(user,guild,true);
- Member.already[guild.id][id]=memb;
+ Member.already[guild.id.id][id]=memb;
return memb;
}
}
hasRole(ID:string){
console.log(this.roles,ID);
for(const thing of this.roles){
- if(thing.id===ID){
+ if(thing.id.id===ID){
return true;
}
}
@@ -123,7 +125,7 @@ class Member{
return true;
}
}
- return this.guild.properties.owner_id===this.user.id;
+ return this.guild.properties.owner_id===this.user.id.id;
}
bind(html:HTMLElement){
if(html.tagName==="SPAN"){
diff --git a/webpage/message.ts b/webpage/message.ts
index b287411..6830793 100644
--- a/webpage/message.ts
+++ b/webpage/message.ts
@@ -7,6 +7,7 @@ import { Channel } from "./channel.js";
import {Localuser} from "./localuser.js";
import { Role } from "./role.js";
import {File} from "./file.js";
+import { SnowFlake } from "./snowflake.js";
class Message{
static contextmenu=new Contextmenu("message menu");
@@ -17,7 +18,7 @@ class Message{
mentions:User[];
mention_roles:Role[];
attachments:File[];//probably should be its own class tbh, should be Attachments[]
- id:string;
+ id:SnowFlake;
message_reference;
type:number;
timestamp:number;
@@ -43,7 +44,7 @@ class Message{
this.channel.setReplying(this);
});
Message.contextmenu.addbutton("Copy message id",function(){
- navigator.clipboard.writeText(this.id);
+ navigator.clipboard.writeText(this.id.id);
});
Message.contextmenu.addbutton("Edit",function(){
this.channel.editing=this;
@@ -72,6 +73,9 @@ class Message{
}else if(thing==="content"){
this.content=new MarkDown(messagejson[thing],this.channel);
continue;
+ }else if(thing ==="id"){
+ this.id=new SnowFlake(messagejson.id,this);
+ continue;
}
this[thing]=messagejson[thing];
}
@@ -135,14 +139,14 @@ class Message{
return build;
}
async edit(content){
- return await fetch(this.info.api.toString()+"/channels/"+this.channel.id+"/messages/"+this.id,{
+ return await fetch(this.info.api.toString()+"/channels/"+this.channel.id+"/messages/"+this.id.id,{
method: "PATCH",
headers: this.headers,
body:JSON.stringify({content:content})
});
}
delete(){
- fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id}`,{
+ fetch(`${this.info.api.toString()}/channels/${this.channel.id}/messages/${this.id.id}`,{
headers:this.headers,
method:"DELETE",
})
@@ -152,19 +156,22 @@ class Message{
this.div.innerHTML="";
this.div=null;
}
- const prev=this.channel.idToPrev[this.id];
- const next=this.channel.idToNext[this.id];
+ const prev=this.channel.idToPrev[this.id.id];
+ const next=this.channel.idToNext[this.id.id];
this.channel.idToNext[prev]=next;
this.channel.idToPrev[next]=prev;
- delete this.channel.messageids[this.id];
+ delete this.channel.messageids[this.id.id];
const regen=this.channel.messageids[prev]
if(regen){
regen.generateMessage();
}
+ if(this.channel.lastmessage===this){
+ this.channel.lastmessage=this.channel.messageids[prev];
+ }
}
generateMessage(premessage:Message=null){
if(!premessage){
- premessage=this.channel.messageids[this.channel.idToNext[this.id]];
+ premessage=this.channel.messageids[this.channel.idToNext[this.id.id]];
}
const div=this.div;
if(this===this.channel.replyingto){
diff --git a/webpage/role.ts b/webpage/role.ts
index 9a1145c..079df86 100644
--- a/webpage/role.ts
+++ b/webpage/role.ts
@@ -2,11 +2,12 @@ export {Role};
import {Permissions} from "./permissions.js";
import {Localuser} from "./localuser.js";
import {Guild} from "./guild.js";
+import { SnowFlake } from "./snowflake.js";
class Role{
permissions:Permissions;
owner:Guild;
color:number;
- id:string;
+ readonly id:SnowFlake;
name:string;
info:Guild["info"];
hoist:boolean;
@@ -18,6 +19,10 @@ class Role{
this.headers=owner.headers;
this.info=owner.info;
for(const thing of Object.keys(JSON)){
+ if(thing==="id"){
+ this.id=new SnowFlake(JSON.id,this);
+ continue;
+ }
this[thing]=JSON[thing];
}
this.permissions=new Permissions(JSON.permissions);
diff --git a/webpage/settings.ts b/webpage/settings.ts
index 1b2f095..1b2b54a 100644
--- a/webpage/settings.ts
+++ b/webpage/settings.ts
@@ -1,5 +1,7 @@
import { Permissions } from "./permissions.js";
import { Guild } from "./guild.js";
+import { SnowFlake } from "./snowflake.js";
+import { Role } from "./role.js";
class Buttons{
readonly name:string;
@@ -126,7 +128,7 @@ class PermissionToggle{
}
}
class RoleList extends Buttons{
- readonly permissions:[string,Permissions][];
+ readonly permissions:[SnowFlake,Permissions][];
permission:Permissions;
readonly guild:Guild;
readonly channel:boolean;
@@ -134,7 +136,7 @@ class RoleList extends Buttons{
readonly options:Options;
onchange:Function;
curid:string;
- constructor(permissions:[string,Permissions][],guild:Guild,onchange:Function,channel=false){
+ constructor(permissions:[SnowFlake,Permissions][],guild:Guild,onchange:Function,channel=false){
super("Roles");
this.guild=guild;
this.permissions=permissions;
@@ -150,16 +152,17 @@ class RoleList extends Buttons{
options.addPermissionToggle(thing,this.permission);//
}
for(const i of permissions){
- this.buttons.push([guild.getRole(i[0]).name,i[0]])//
+ console.log(i);
+ this.buttons.push([i[0].getObject().name,i[0].id])//
}
this.options=options;
}
handleString(str:string):HTMLElement{
this.curid=str;
- const perm=this.permissions.find(_=>_[0]===str)[1];
+ const perm=this.permissions.find(_=>_[0].id===str)[1];
this.permission.deny=perm.deny;
this.permission.allow=perm.allow;
- this.options.name=this.guild.getRole(str).name;
+ this.options.name=SnowFlake.getSnowFlakeFromID(str,Role).getObject().name;
this.options.haschanged=false;
return this.options.generateHTML();
}
diff --git a/webpage/snowflake.ts b/webpage/snowflake.ts
new file mode 100644
index 0000000..2da4c1a
--- /dev/null
+++ b/webpage/snowflake.ts
@@ -0,0 +1,53 @@
+class SnowFlake{
+ public readonly id:string;
+ private static readonly SnowFlakes:Map>>>=new Map();
+ private static readonly FinalizationRegistry=new FinalizationRegistry((id:string)=>{
+ SnowFlake.SnowFlakes.delete(id);
+ });
+ private obj:x;
+ constructor(id:string,obj:x){
+ if(!obj){
+ this.id=id;
+ return;
+ }
+ if(!SnowFlake.SnowFlakes.get(obj.constructor)){
+ SnowFlake.SnowFlakes.set(obj.constructor,new Map());
+ }
+ if(SnowFlake.SnowFlakes.get(obj.constructor).get(id)){
+ const snowflake=SnowFlake.SnowFlakes.get(obj.constructor).get(id).deref();
+ snowflake.obj=obj;
+ return snowflake;
+ }
+ this.id=id;
+ SnowFlake.SnowFlakes.get(obj.constructor).set(id,new WeakRef(this));
+ SnowFlake.FinalizationRegistry.register(this,id);
+ this.obj=obj;
+ }
+ static getSnowFlakeFromID(id:string,type:any):SnowFlake{
+ if(!SnowFlake.SnowFlakes.get(type)){
+ SnowFlake.SnowFlakes.set(type,new Map());
+ }
+ const snowflake=SnowFlake.SnowFlakes.get(type).get(id);
+ if(snowflake){
+ return snowflake.deref();
+ }
+ {
+ const snowflake=new SnowFlake(id,undefined);
+
+ SnowFlake.SnowFlakes.get(type).set(id,new WeakRef(snowflake));
+ SnowFlake.FinalizationRegistry.register(snowflake,id);
+
+ return snowflake;
+ }
+ }
+ getUnixTime():number{
+ return Number((BigInt(this.id)>>22n)+1420070400000n);
+ }
+ toString(){
+ return this.id;
+ }
+ getObject():x{
+ return this.obj;
+ }
+}
+export {SnowFlake};
diff --git a/webpage/style.css b/webpage/style.css
index eb1a459..a5691dc 100644
--- a/webpage/style.css
+++ b/webpage/style.css
@@ -115,12 +115,17 @@ samp {
}
.infosection {
+ hr{
+ width:100%;
+ }
display: inline-block;
background-color: var(--profile-info-bg);
border-radius: 10%;
padding: .3cm;
width: calc(100% - .6cm);
height: calc(100% - .75in);
+ display: flex;
+ flex-direction: column;
}
.profile {
@@ -1390,3 +1395,12 @@ span {
width:22px;
height:22px;
}
+#typebox[contenteditable=false]{
+
+ cursor:not-allowed;
+
+}
+#typebox[contenteditable=false]:before{
+ content:'You can\'t chat here';
+ color:color-mix(in hsl, var(--primary-bg),var(--primary-text));
+}
\ No newline at end of file
diff --git a/webpage/user.ts b/webpage/user.ts
index d62433b..85c3993 100644
--- a/webpage/user.ts
+++ b/webpage/user.ts
@@ -4,12 +4,13 @@ import {MarkDown} from "./markdown.js";
import {Contextmenu} from "./contextmenu.js";
import {Localuser} from "./localuser.js";
import {Guild} from "./guild.js";
+import { SnowFlake } from "./snowflake.js";
class User{
static userids={};
owner:Localuser;
hypotheticalpfp:boolean;
- id:string;
+ id:SnowFlake;
avatar:string;
username:string;
bio:MarkDown;
@@ -19,13 +20,13 @@ class User{
static contextmenu:Contextmenu=new Contextmenu("User Menu");
static setUpContextMenu(){
this.contextmenu.addbutton("Copy user id",function(){
- navigator.clipboard.writeText(this.id);
+ navigator.clipboard.writeText(this.id.id);
});
this.contextmenu.addbutton("Message user",function(){
fetch(this.info.api.toString()+"/v9/users/@me/channels",
{method:"POST",
- body:JSON.stringify({"recipients":[this.id]}),
- headers: this.headers
+ body:JSON.stringify({"recipients":[this.id.id]}),
+ headers: this.localuser.headers
});
})
}
@@ -53,6 +54,10 @@ class User{
this.bio=new MarkDown(userjson[thing],this.localuser);
continue;
}
+ if(thing === "id"){
+ this.id=new SnowFlake(userjson[thing],this);
+ continue;
+ }
this[thing]=userjson[thing];
}
this.hypotheticalpfp=false;
@@ -67,7 +72,7 @@ class User{
const pfp=document.createElement('img');
pfp.src=this.getpfpsrc();
pfp.classList.add("pfp");
- pfp.classList.add("userid:"+this.id);
+ pfp.classList.add("userid:"+this.id.id);
return pfp;
}
userupdate(json){
@@ -77,7 +82,7 @@ class User{
}
}
bind(html:HTMLElement,guild:Guild=null){
- if(guild&&guild.id!=="@me"){
+ if(guild&&guild.id.id!=="@me"){
Member.resolve(this,guild).then(_=>{
_.bind(html);
}).catch(_=>{
@@ -98,7 +103,7 @@ class User{
this.hypotheticalpfp=false;
const src=this.getpfpsrc();
console.log(src)
- for(const thing of document.getElementsByClassName("userid:"+this.id)){
+ for(const thing of document.getElementsByClassName("userid:"+this.id.id)){
(thing as HTMLImageElement).src=src;
}
}
@@ -107,7 +112,7 @@ class User{
return this.avatar;
}
if(this.avatar!=null){
- return this.info.cdn.toString()+"avatars/"+this.id+"/"+this.avatar+".png";
+ return this.info.cdn.toString()+"avatars/"+this.id.id+"/"+this.avatar+".png";
}else{
return this.info.cdn.toString()+"embed/avatars/3.png";
}
From 5e9405207b6f5fe957b8ec0de1c958381b1779fd Mon Sep 17 00:00:00 2001
From: MathMan05
Date: Tue, 23 Jul 2024 23:03:43 -0500
Subject: [PATCH 10/10] fixed bug where replying wouldn't work
---
.dist/channel.js | 6 +++---
webpage/channel.ts | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.dist/channel.js b/.dist/channel.js
index ab677cf..a2cfd00 100644
--- a/.dist/channel.js
+++ b/.dist/channel.js
@@ -693,9 +693,9 @@ class Channel {
if (replyingto) {
replyjson =
{
- "guild_id": replyingto.guild.id,
- "channel_id": replyingto.channel.id,
- "message_id": replyingto.id,
+ "guild_id": replyingto.guild.id.id,
+ "channel_id": replyingto.channel.id.id,
+ "message_id": replyingto.id.id,
};
}
;
diff --git a/webpage/channel.ts b/webpage/channel.ts
index 0fb5a13..21dd447 100644
--- a/webpage/channel.ts
+++ b/webpage/channel.ts
@@ -693,9 +693,9 @@ class Channel{
if(replyingto){
replyjson=
{
- "guild_id":replyingto.guild.id,
- "channel_id": replyingto.channel.id,
- "message_id": replyingto.id,
+ "guild_id":replyingto.guild.id.id,
+ "channel_id": replyingto.channel.id.id,
+ "message_id": replyingto.id.id,
};
};
if(attachments.length===0){